@baseplate-dev/fastify-generators 0.3.8 → 0.4.0

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 (431) hide show
  1. package/dist/constants/fastify-packages.d.ts +12 -11
  2. package/dist/constants/fastify-packages.d.ts.map +1 -1
  3. package/dist/constants/fastify-packages.js +12 -11
  4. package/dist/constants/fastify-packages.js.map +1 -1
  5. package/dist/generators/auth/auth-context/generated/ts-import-providers.d.ts +1 -2
  6. package/dist/generators/auth/auth-context/generated/ts-import-providers.d.ts.map +1 -1
  7. package/dist/generators/auth/auth-context/generated/ts-import-providers.js +1 -1
  8. package/dist/generators/auth/auth-context/generated/ts-import-providers.js.map +1 -1
  9. package/dist/generators/auth/auth-roles/generated/ts-import-providers.d.ts +1 -2
  10. package/dist/generators/auth/auth-roles/generated/ts-import-providers.d.ts.map +1 -1
  11. package/dist/generators/auth/auth-roles/generated/ts-import-providers.js +1 -1
  12. package/dist/generators/auth/auth-roles/generated/ts-import-providers.js.map +1 -1
  13. package/dist/generators/auth/index.d.ts +0 -1
  14. package/dist/generators/auth/index.d.ts.map +1 -1
  15. package/dist/generators/auth/index.js +0 -1
  16. package/dist/generators/auth/index.js.map +1 -1
  17. package/dist/generators/auth/password-hasher-service/generated/ts-import-providers.d.ts +1 -2
  18. package/dist/generators/auth/password-hasher-service/generated/ts-import-providers.d.ts.map +1 -1
  19. package/dist/generators/auth/password-hasher-service/generated/ts-import-providers.js +1 -1
  20. package/dist/generators/auth/password-hasher-service/generated/ts-import-providers.js.map +1 -1
  21. package/dist/generators/auth/user-session-types/generated/ts-import-providers.d.ts +1 -2
  22. package/dist/generators/auth/user-session-types/generated/ts-import-providers.d.ts.map +1 -1
  23. package/dist/generators/auth/user-session-types/generated/ts-import-providers.js +1 -1
  24. package/dist/generators/auth/user-session-types/generated/ts-import-providers.js.map +1 -1
  25. package/dist/generators/bull/bull-mq/generated/ts-import-providers.d.ts +1 -2
  26. package/dist/generators/bull/bull-mq/generated/ts-import-providers.d.ts.map +1 -1
  27. package/dist/generators/bull/bull-mq/generated/ts-import-providers.js +1 -1
  28. package/dist/generators/bull/bull-mq/generated/ts-import-providers.js.map +1 -1
  29. package/dist/generators/core/app-module-setup/generated/ts-import-providers.d.ts +1 -2
  30. package/dist/generators/core/app-module-setup/generated/ts-import-providers.d.ts.map +1 -1
  31. package/dist/generators/core/app-module-setup/generated/ts-import-providers.js +1 -1
  32. package/dist/generators/core/app-module-setup/generated/ts-import-providers.js.map +1 -1
  33. package/dist/generators/core/axios/generated/ts-import-providers.d.ts +1 -2
  34. package/dist/generators/core/axios/generated/ts-import-providers.d.ts.map +1 -1
  35. package/dist/generators/core/axios/generated/ts-import-providers.js +3 -1
  36. package/dist/generators/core/axios/generated/ts-import-providers.js.map +1 -1
  37. package/dist/generators/core/config-service/generated/ts-import-providers.d.ts +1 -2
  38. package/dist/generators/core/config-service/generated/ts-import-providers.d.ts.map +1 -1
  39. package/dist/generators/core/config-service/generated/ts-import-providers.js +3 -1
  40. package/dist/generators/core/config-service/generated/ts-import-providers.js.map +1 -1
  41. package/dist/generators/core/error-handler-service/generated/ts-import-providers.d.ts +1 -2
  42. package/dist/generators/core/error-handler-service/generated/ts-import-providers.d.ts.map +1 -1
  43. package/dist/generators/core/error-handler-service/generated/ts-import-providers.js +1 -1
  44. package/dist/generators/core/error-handler-service/generated/ts-import-providers.js.map +1 -1
  45. package/dist/generators/core/fastify/fastify.generator.js +1 -1
  46. package/dist/generators/core/fastify/fastify.generator.js.map +1 -1
  47. package/dist/generators/core/fastify-redis/generated/ts-import-providers.d.ts +1 -2
  48. package/dist/generators/core/fastify-redis/generated/ts-import-providers.d.ts.map +1 -1
  49. package/dist/generators/core/fastify-redis/generated/ts-import-providers.js +1 -1
  50. package/dist/generators/core/fastify-redis/generated/ts-import-providers.js.map +1 -1
  51. package/dist/generators/core/fastify-sentry/fastify-sentry.generator.js +1 -1
  52. package/dist/generators/core/fastify-sentry/generated/ts-import-providers.d.ts +1 -2
  53. package/dist/generators/core/fastify-sentry/generated/ts-import-providers.d.ts.map +1 -1
  54. package/dist/generators/core/fastify-sentry/generated/ts-import-providers.js +1 -1
  55. package/dist/generators/core/fastify-sentry/generated/ts-import-providers.js.map +1 -1
  56. package/dist/generators/core/logger-service/generated/ts-import-providers.d.ts +1 -2
  57. package/dist/generators/core/logger-service/generated/ts-import-providers.d.ts.map +1 -1
  58. package/dist/generators/core/logger-service/generated/ts-import-providers.js +3 -1
  59. package/dist/generators/core/logger-service/generated/ts-import-providers.js.map +1 -1
  60. package/dist/generators/core/readme/templates/package/README.md +4 -4
  61. package/dist/generators/core/request-context/generated/ts-import-providers.d.ts +1 -2
  62. package/dist/generators/core/request-context/generated/ts-import-providers.d.ts.map +1 -1
  63. package/dist/generators/core/request-context/generated/ts-import-providers.js +1 -1
  64. package/dist/generators/core/request-context/generated/ts-import-providers.js.map +1 -1
  65. package/dist/generators/core/request-service-context/generated/ts-import-providers.d.ts +1 -2
  66. package/dist/generators/core/request-service-context/generated/ts-import-providers.d.ts.map +1 -1
  67. package/dist/generators/core/request-service-context/generated/ts-import-providers.js +1 -1
  68. package/dist/generators/core/request-service-context/generated/ts-import-providers.js.map +1 -1
  69. package/dist/generators/core/service-context/generated/ts-import-providers.d.ts +1 -2
  70. package/dist/generators/core/service-context/generated/ts-import-providers.d.ts.map +1 -1
  71. package/dist/generators/core/service-context/generated/ts-import-providers.js +1 -1
  72. package/dist/generators/core/service-context/generated/ts-import-providers.js.map +1 -1
  73. package/dist/generators/core/service-file/service-file.generator.d.ts +7 -0
  74. package/dist/generators/core/service-file/service-file.generator.d.ts.map +1 -1
  75. package/dist/generators/core/service-file/service-file.generator.js +12 -2
  76. package/dist/generators/core/service-file/service-file.generator.js.map +1 -1
  77. package/dist/generators/pothos/pothos/generated/index.d.ts +3 -1
  78. package/dist/generators/pothos/pothos/generated/index.d.ts.map +1 -1
  79. package/dist/generators/pothos/pothos/generated/ts-import-providers.d.ts +1 -2
  80. package/dist/generators/pothos/pothos/generated/ts-import-providers.d.ts.map +1 -1
  81. package/dist/generators/pothos/pothos/generated/ts-import-providers.js +1 -1
  82. package/dist/generators/pothos/pothos/generated/ts-import-providers.js.map +1 -1
  83. package/dist/generators/pothos/pothos/generated/typed-templates.d.ts +6 -2
  84. package/dist/generators/pothos/pothos/generated/typed-templates.d.ts.map +1 -1
  85. package/dist/generators/pothos/pothos/generated/typed-templates.js +1 -0
  86. package/dist/generators/pothos/pothos/generated/typed-templates.js.map +1 -1
  87. package/dist/generators/pothos/pothos/pothos.generator.d.ts +3 -3
  88. package/dist/generators/pothos/pothos/pothos.generator.d.ts.map +1 -1
  89. package/dist/generators/pothos/pothos/pothos.generator.js +4 -0
  90. package/dist/generators/pothos/pothos/pothos.generator.js.map +1 -1
  91. package/dist/generators/pothos/pothos/templates/src/plugins/graphql/FieldWithInputPayloadPlugin/global-types.ts +3 -5
  92. package/dist/generators/pothos/pothos/templates/src/plugins/graphql/FieldWithInputPayloadPlugin/schema-builder.ts +9 -4
  93. package/dist/generators/pothos/pothos/templates/src/plugins/graphql/FieldWithInputPayloadPlugin/types.ts +6 -1
  94. package/dist/generators/pothos/pothos-auth/pothos-auth.generator.d.ts +1 -1
  95. package/dist/generators/pothos/pothos-enums-file/pothos-enums-file.generator.d.ts +1 -1
  96. package/dist/generators/pothos/pothos-prisma/generated/index.d.ts +36 -0
  97. package/dist/generators/pothos/pothos-prisma/generated/index.d.ts.map +1 -0
  98. package/dist/generators/pothos/pothos-prisma/generated/index.js +11 -0
  99. package/dist/generators/pothos/pothos-prisma/generated/index.js.map +1 -0
  100. package/dist/generators/pothos/pothos-prisma/generated/template-paths.d.ts +12 -0
  101. package/dist/generators/pothos/pothos-prisma/generated/template-paths.d.ts.map +1 -0
  102. package/dist/generators/pothos/pothos-prisma/generated/template-paths.js +22 -0
  103. package/dist/generators/pothos/pothos-prisma/generated/template-paths.js.map +1 -0
  104. package/dist/generators/pothos/pothos-prisma/generated/template-renderers.d.ts +18 -0
  105. package/dist/generators/pothos/pothos-prisma/generated/template-renderers.d.ts.map +1 -0
  106. package/dist/generators/pothos/pothos-prisma/generated/template-renderers.js +34 -0
  107. package/dist/generators/pothos/pothos-prisma/generated/template-renderers.js.map +1 -0
  108. package/dist/generators/pothos/pothos-prisma/generated/ts-import-providers.d.ts +30 -0
  109. package/dist/generators/pothos/pothos-prisma/generated/ts-import-providers.d.ts.map +1 -0
  110. package/dist/generators/pothos/pothos-prisma/generated/ts-import-providers.js +30 -0
  111. package/dist/generators/pothos/pothos-prisma/generated/ts-import-providers.js.map +1 -0
  112. package/dist/generators/pothos/pothos-prisma/generated/typed-templates.d.ts +4 -0
  113. package/dist/generators/pothos/pothos-prisma/generated/typed-templates.d.ts.map +1 -0
  114. package/dist/generators/pothos/pothos-prisma/generated/typed-templates.js +14 -0
  115. package/dist/generators/pothos/pothos-prisma/generated/typed-templates.js.map +1 -0
  116. package/dist/generators/pothos/pothos-prisma/index.d.ts +2 -0
  117. package/dist/generators/pothos/pothos-prisma/index.d.ts.map +1 -1
  118. package/dist/generators/pothos/pothos-prisma/index.js +1 -0
  119. package/dist/generators/pothos/pothos-prisma/index.js.map +1 -1
  120. package/dist/generators/pothos/pothos-prisma/pothos-prisma.generator.d.ts +34 -1
  121. package/dist/generators/pothos/pothos-prisma/pothos-prisma.generator.d.ts.map +1 -1
  122. package/dist/generators/pothos/pothos-prisma/pothos-prisma.generator.js +20 -6
  123. package/dist/generators/pothos/pothos-prisma/pothos-prisma.generator.js.map +1 -1
  124. package/dist/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.d.ts +2 -2
  125. package/dist/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.d.ts.map +1 -1
  126. package/dist/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.js +87 -50
  127. package/dist/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.js.map +1 -1
  128. package/dist/generators/pothos/pothos-scalar/generated/index.d.ts +9 -39
  129. package/dist/generators/pothos/pothos-scalar/generated/index.d.ts.map +1 -1
  130. package/dist/generators/pothos/pothos-scalar/generated/template-paths.d.ts +2 -0
  131. package/dist/generators/pothos/pothos-scalar/generated/template-paths.d.ts.map +1 -1
  132. package/dist/generators/pothos/pothos-scalar/generated/template-paths.js +2 -0
  133. package/dist/generators/pothos/pothos-scalar/generated/template-paths.js.map +1 -1
  134. package/dist/generators/pothos/pothos-scalar/generated/template-renderers.d.ts +6 -10
  135. package/dist/generators/pothos/pothos-scalar/generated/template-renderers.d.ts.map +1 -1
  136. package/dist/generators/pothos/pothos-scalar/generated/template-renderers.js +21 -6
  137. package/dist/generators/pothos/pothos-scalar/generated/template-renderers.js.map +1 -1
  138. package/dist/generators/pothos/pothos-scalar/generated/typed-templates.d.ts +9 -29
  139. package/dist/generators/pothos/pothos-scalar/generated/typed-templates.d.ts.map +1 -1
  140. package/dist/generators/pothos/pothos-scalar/generated/typed-templates.js +28 -14
  141. package/dist/generators/pothos/pothos-scalar/generated/typed-templates.js.map +1 -1
  142. package/dist/generators/pothos/pothos-scalar/pothos-scalar.generator.d.ts +2 -12
  143. package/dist/generators/pothos/pothos-scalar/pothos-scalar.generator.d.ts.map +1 -1
  144. package/dist/generators/pothos/pothos-scalar/pothos-scalar.generator.js +35 -11
  145. package/dist/generators/pothos/pothos-scalar/pothos-scalar.generator.js.map +1 -1
  146. package/dist/generators/pothos/pothos-scalar/templates/module/scalars/date-time.ts +21 -28
  147. package/dist/generators/pothos/pothos-scalar/templates/module/scalars/date.ts +13 -45
  148. package/dist/generators/pothos/pothos-scalar/templates/module/scalars/json-object.ts +28 -0
  149. package/dist/generators/pothos/pothos-scalar/templates/module/scalars/json.ts +23 -0
  150. package/dist/generators/pothos/pothos-scalar/templates/module/scalars/uuid.ts +13 -31
  151. package/dist/generators/pothos/pothos-sentry/pothos-sentry.generator.d.ts +1 -1
  152. package/dist/generators/prisma/_providers/index.d.ts +2 -0
  153. package/dist/generators/prisma/_providers/index.d.ts.map +1 -0
  154. package/dist/generators/prisma/_providers/index.js +2 -0
  155. package/dist/generators/prisma/_providers/index.js.map +1 -0
  156. package/dist/generators/prisma/_providers/prisma-generated-imports.d.ts +15 -0
  157. package/dist/generators/prisma/_providers/prisma-generated-imports.d.ts.map +1 -0
  158. package/dist/generators/prisma/_providers/prisma-generated-imports.js +10 -0
  159. package/dist/generators/prisma/_providers/prisma-generated-imports.js.map +1 -0
  160. package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.d.ts +124 -0
  161. package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.d.ts.map +1 -0
  162. package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.js +137 -0
  163. package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.js.map +1 -0
  164. package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.d.ts +82 -0
  165. package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.d.ts.map +1 -0
  166. package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.js +215 -0
  167. package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.js.map +1 -0
  168. package/dist/generators/prisma/_shared/build-data-helpers/index.d.ts +3 -0
  169. package/dist/generators/prisma/_shared/build-data-helpers/index.d.ts.map +1 -0
  170. package/dist/generators/prisma/_shared/build-data-helpers/index.js +3 -0
  171. package/dist/generators/prisma/_shared/build-data-helpers/index.js.map +1 -0
  172. package/dist/generators/prisma/_shared/crud-method/primary-key-input.d.ts +0 -9
  173. package/dist/generators/prisma/_shared/crud-method/primary-key-input.d.ts.map +1 -1
  174. package/dist/generators/prisma/_shared/crud-method/primary-key-input.js +0 -32
  175. package/dist/generators/prisma/_shared/crud-method/primary-key-input.js.map +1 -1
  176. package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.d.ts +26 -0
  177. package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.d.ts.map +1 -0
  178. package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.js +47 -0
  179. package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.js.map +1 -0
  180. package/dist/generators/prisma/_shared/field-definition-generators/types.d.ts +8 -0
  181. package/dist/generators/prisma/_shared/field-definition-generators/types.d.ts.map +1 -0
  182. package/dist/generators/prisma/_shared/field-definition-generators/types.js +2 -0
  183. package/dist/generators/prisma/_shared/field-definition-generators/types.js.map +1 -0
  184. package/dist/generators/prisma/data-utils/data-utils.generator.d.ts +109 -0
  185. package/dist/generators/prisma/data-utils/data-utils.generator.d.ts.map +1 -0
  186. package/dist/generators/prisma/data-utils/data-utils.generator.js +32 -0
  187. package/dist/generators/prisma/data-utils/data-utils.generator.js.map +1 -0
  188. package/dist/generators/prisma/data-utils/generated/index.d.ts +190 -0
  189. package/dist/generators/prisma/data-utils/generated/index.d.ts.map +1 -0
  190. package/dist/generators/prisma/data-utils/generated/index.js +11 -0
  191. package/dist/generators/prisma/data-utils/generated/index.js.map +1 -0
  192. package/dist/generators/prisma/data-utils/generated/template-paths.d.ts +17 -0
  193. package/dist/generators/prisma/data-utils/generated/template-paths.d.ts.map +1 -0
  194. package/dist/generators/prisma/data-utils/generated/template-paths.js +27 -0
  195. package/dist/generators/prisma/data-utils/generated/template-paths.js.map +1 -0
  196. package/dist/generators/prisma/data-utils/generated/template-renderers.d.ts +45 -0
  197. package/dist/generators/prisma/data-utils/generated/template-renderers.d.ts.map +1 -0
  198. package/dist/generators/prisma/data-utils/generated/template-renderers.js +47 -0
  199. package/dist/generators/prisma/data-utils/generated/template-renderers.js.map +1 -0
  200. package/dist/generators/prisma/data-utils/generated/ts-import-providers.d.ts +183 -0
  201. package/dist/generators/prisma/data-utils/generated/ts-import-providers.d.ts.map +1 -0
  202. package/dist/generators/prisma/data-utils/generated/ts-import-providers.js +72 -0
  203. package/dist/generators/prisma/data-utils/generated/ts-import-providers.js.map +1 -0
  204. package/dist/generators/prisma/data-utils/generated/typed-templates.d.ts +157 -0
  205. package/dist/generators/prisma/data-utils/generated/typed-templates.d.ts.map +1 -0
  206. package/dist/generators/prisma/data-utils/generated/typed-templates.js +125 -0
  207. package/dist/generators/prisma/data-utils/generated/typed-templates.js.map +1 -0
  208. package/dist/generators/prisma/data-utils/index.d.ts +4 -0
  209. package/dist/generators/prisma/data-utils/index.d.ts.map +1 -0
  210. package/dist/generators/prisma/data-utils/index.js +3 -0
  211. package/dist/generators/prisma/data-utils/index.js.map +1 -0
  212. package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/define-operations.ts +1030 -0
  213. package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.ts +782 -0
  214. package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-types.ts +164 -0
  215. package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-utils.ts +80 -0
  216. package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/relation-helpers.ts +196 -0
  217. package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts +372 -0
  218. package/dist/generators/prisma/index.d.ts +7 -6
  219. package/dist/generators/prisma/index.d.ts.map +1 -1
  220. package/dist/generators/prisma/index.js +7 -6
  221. package/dist/generators/prisma/index.js.map +1 -1
  222. package/dist/generators/prisma/prisma/generated/index.d.ts +19 -1
  223. package/dist/generators/prisma/prisma/generated/index.d.ts.map +1 -1
  224. package/dist/generators/prisma/prisma/generated/template-paths.d.ts +1 -0
  225. package/dist/generators/prisma/prisma/generated/template-paths.d.ts.map +1 -1
  226. package/dist/generators/prisma/prisma/generated/template-paths.js +1 -0
  227. package/dist/generators/prisma/prisma/generated/template-paths.js.map +1 -1
  228. package/dist/generators/prisma/prisma/generated/template-renderers.d.ts +7 -1
  229. package/dist/generators/prisma/prisma/generated/template-renderers.d.ts.map +1 -1
  230. package/dist/generators/prisma/prisma/generated/template-renderers.js +14 -1
  231. package/dist/generators/prisma/prisma/generated/template-renderers.js.map +1 -1
  232. package/dist/generators/prisma/prisma/generated/ts-import-providers.d.ts +7 -2
  233. package/dist/generators/prisma/prisma/generated/ts-import-providers.d.ts.map +1 -1
  234. package/dist/generators/prisma/prisma/generated/ts-import-providers.js +12 -2
  235. package/dist/generators/prisma/prisma/generated/ts-import-providers.js.map +1 -1
  236. package/dist/generators/prisma/prisma/generated/typed-templates.d.ts +13 -1
  237. package/dist/generators/prisma/prisma/generated/typed-templates.d.ts.map +1 -1
  238. package/dist/generators/prisma/prisma/generated/typed-templates.js +19 -2
  239. package/dist/generators/prisma/prisma/generated/typed-templates.js.map +1 -1
  240. package/dist/generators/prisma/prisma/prisma.generator.d.ts +21 -0
  241. package/dist/generators/prisma/prisma/prisma.generator.d.ts.map +1 -1
  242. package/dist/generators/prisma/prisma/prisma.generator.js +42 -8
  243. package/dist/generators/prisma/prisma/prisma.generator.js.map +1 -1
  244. package/dist/generators/prisma/prisma/templates/package/prisma.config.mts +7 -2
  245. package/dist/generators/prisma/prisma/templates/src/services/prisma.ts +5 -2
  246. package/dist/generators/prisma/prisma-data-create/index.d.ts +2 -0
  247. package/dist/generators/prisma/prisma-data-create/index.d.ts.map +1 -0
  248. package/dist/generators/prisma/prisma-data-create/index.js +2 -0
  249. package/dist/generators/prisma/prisma-data-create/index.js.map +1 -0
  250. package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.d.ts +73 -0
  251. package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.d.ts.map +1 -0
  252. package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.js +102 -0
  253. package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.js.map +1 -0
  254. package/dist/generators/prisma/prisma-data-delete/index.d.ts +2 -0
  255. package/dist/generators/prisma/prisma-data-delete/index.d.ts.map +1 -0
  256. package/dist/generators/prisma/prisma-data-delete/index.js +2 -0
  257. package/dist/generators/prisma/prisma-data-delete/index.js.map +1 -0
  258. package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.d.ts +72 -0
  259. package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.d.ts.map +1 -0
  260. package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.js +82 -0
  261. package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.js.map +1 -0
  262. package/dist/generators/prisma/prisma-data-nested-field/index.d.ts +2 -0
  263. package/dist/generators/prisma/prisma-data-nested-field/index.d.ts.map +1 -0
  264. package/dist/generators/prisma/prisma-data-nested-field/index.js +2 -0
  265. package/dist/generators/prisma/prisma-data-nested-field/index.js.map +1 -0
  266. package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.d.ts +16 -0
  267. package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.d.ts.map +1 -0
  268. package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.js +179 -0
  269. package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.js.map +1 -0
  270. package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.d.ts +95 -0
  271. package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.d.ts.map +1 -0
  272. package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.js +120 -0
  273. package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.js.map +1 -0
  274. package/dist/generators/prisma/prisma-data-service/index.d.ts +2 -0
  275. package/dist/generators/prisma/prisma-data-service/index.d.ts.map +1 -0
  276. package/dist/generators/prisma/prisma-data-service/index.js +2 -0
  277. package/dist/generators/prisma/prisma-data-service/index.js.map +1 -0
  278. package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.d.ts +117 -0
  279. package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.d.ts.map +1 -0
  280. package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.js +127 -0
  281. package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.js.map +1 -0
  282. package/dist/generators/prisma/prisma-data-update/index.d.ts +2 -0
  283. package/dist/generators/prisma/prisma-data-update/index.d.ts.map +1 -0
  284. package/dist/generators/prisma/prisma-data-update/index.js +2 -0
  285. package/dist/generators/prisma/prisma-data-update/index.js.map +1 -0
  286. package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.d.ts +73 -0
  287. package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.d.ts.map +1 -0
  288. package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.js +114 -0
  289. package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.js.map +1 -0
  290. package/dist/generators/prisma/prisma-field/prisma-field.generator.d.ts +6 -6
  291. package/dist/generators/stripe/fastify-stripe/generated/ts-import-providers.d.ts +1 -2
  292. package/dist/generators/stripe/fastify-stripe/generated/ts-import-providers.d.ts.map +1 -1
  293. package/dist/generators/stripe/fastify-stripe/generated/ts-import-providers.js +1 -1
  294. package/dist/generators/stripe/fastify-stripe/generated/ts-import-providers.js.map +1 -1
  295. package/dist/generators/vitest/prisma-vitest/generated/index.d.ts +20 -1
  296. package/dist/generators/vitest/prisma-vitest/generated/index.d.ts.map +1 -1
  297. package/dist/generators/vitest/prisma-vitest/generated/template-renderers.d.ts +6 -0
  298. package/dist/generators/vitest/prisma-vitest/generated/template-renderers.d.ts.map +1 -1
  299. package/dist/generators/vitest/prisma-vitest/generated/template-renderers.js +7 -1
  300. package/dist/generators/vitest/prisma-vitest/generated/template-renderers.js.map +1 -1
  301. package/dist/generators/vitest/prisma-vitest/generated/ts-import-providers.d.ts +1 -2
  302. package/dist/generators/vitest/prisma-vitest/generated/ts-import-providers.d.ts.map +1 -1
  303. package/dist/generators/vitest/prisma-vitest/generated/ts-import-providers.js +1 -1
  304. package/dist/generators/vitest/prisma-vitest/generated/ts-import-providers.js.map +1 -1
  305. package/dist/generators/vitest/prisma-vitest/generated/typed-templates.d.ts +14 -1
  306. package/dist/generators/vitest/prisma-vitest/generated/typed-templates.d.ts.map +1 -1
  307. package/dist/generators/vitest/prisma-vitest/generated/typed-templates.js +8 -2
  308. package/dist/generators/vitest/prisma-vitest/generated/typed-templates.js.map +1 -1
  309. package/dist/generators/vitest/prisma-vitest/prisma-vitest.generator.d.ts +16 -0
  310. package/dist/generators/vitest/prisma-vitest/prisma-vitest.generator.d.ts.map +1 -1
  311. package/dist/generators/vitest/prisma-vitest/prisma-vitest.generator.js +5 -10
  312. package/dist/generators/vitest/prisma-vitest/prisma-vitest.generator.js.map +1 -1
  313. package/dist/generators/vitest/prisma-vitest/templates/src/tests/helpers/db.test-helper.ts +3 -2
  314. package/dist/generators/vitest/prisma-vitest/templates/src/tests/helpers/prisma.test-helper.ts +1 -1
  315. package/dist/types/field-types.d.ts +1 -1
  316. package/dist/types/field-types.d.ts.map +1 -1
  317. package/dist/types/field-types.js +2 -0
  318. package/dist/types/field-types.js.map +1 -1
  319. package/dist/types/service-dto-kinds.d.ts +59 -0
  320. package/dist/types/service-dto-kinds.d.ts.map +1 -0
  321. package/dist/types/service-dto-kinds.js +53 -0
  322. package/dist/types/service-dto-kinds.js.map +1 -0
  323. package/dist/types/service-output.d.ts +25 -2
  324. package/dist/types/service-output.d.ts.map +1 -1
  325. package/dist/types/service-output.js +22 -2
  326. package/dist/types/service-output.js.map +1 -1
  327. package/dist/writers/pothos/input-types.d.ts +1 -1
  328. package/dist/writers/pothos/input-types.d.ts.map +1 -1
  329. package/dist/writers/pothos/input-types.js +7 -10
  330. package/dist/writers/pothos/input-types.js.map +1 -1
  331. package/dist/writers/pothos/resolvers.d.ts.map +1 -1
  332. package/dist/writers/pothos/resolvers.js +9 -6
  333. package/dist/writers/pothos/resolvers.js.map +1 -1
  334. package/dist/writers/pothos/scalars.d.ts.map +1 -1
  335. package/dist/writers/pothos/scalars.js +5 -0
  336. package/dist/writers/pothos/scalars.js.map +1 -1
  337. package/dist/writers/prisma-schema/fields.d.ts +3 -0
  338. package/dist/writers/prisma-schema/fields.d.ts.map +1 -1
  339. package/dist/writers/prisma-schema/fields.js +1 -0
  340. package/dist/writers/prisma-schema/fields.js.map +1 -1
  341. package/package.json +8 -6
  342. package/dist/generators/auth/prisma-password-transformer/index.d.ts +0 -2
  343. package/dist/generators/auth/prisma-password-transformer/index.d.ts.map +0 -1
  344. package/dist/generators/auth/prisma-password-transformer/index.js +0 -2
  345. package/dist/generators/auth/prisma-password-transformer/index.js.map +0 -1
  346. package/dist/generators/auth/prisma-password-transformer/prisma-password-transformer.generator.d.ts +0 -12
  347. package/dist/generators/auth/prisma-password-transformer/prisma-password-transformer.generator.d.ts.map +0 -1
  348. package/dist/generators/auth/prisma-password-transformer/prisma-password-transformer.generator.js +0 -48
  349. package/dist/generators/auth/prisma-password-transformer/prisma-password-transformer.generator.js.map +0 -1
  350. package/dist/generators/prisma/_shared/crud-method/data-method.d.ts +0 -31
  351. package/dist/generators/prisma/_shared/crud-method/data-method.d.ts.map +0 -1
  352. package/dist/generators/prisma/_shared/crud-method/data-method.js +0 -195
  353. package/dist/generators/prisma/_shared/crud-method/data-method.js.map +0 -1
  354. package/dist/generators/prisma/embedded-relation-transformer/embedded-relation-transformer.generator.d.ts +0 -50
  355. package/dist/generators/prisma/embedded-relation-transformer/embedded-relation-transformer.generator.d.ts.map +0 -1
  356. package/dist/generators/prisma/embedded-relation-transformer/embedded-relation-transformer.generator.js +0 -371
  357. package/dist/generators/prisma/embedded-relation-transformer/embedded-relation-transformer.generator.js.map +0 -1
  358. package/dist/generators/prisma/embedded-relation-transformer/index.d.ts +0 -2
  359. package/dist/generators/prisma/embedded-relation-transformer/index.d.ts.map +0 -1
  360. package/dist/generators/prisma/embedded-relation-transformer/index.js +0 -2
  361. package/dist/generators/prisma/embedded-relation-transformer/index.js.map +0 -1
  362. package/dist/generators/prisma/prisma-crud-create/index.d.ts +0 -2
  363. package/dist/generators/prisma/prisma-crud-create/index.d.ts.map +0 -1
  364. package/dist/generators/prisma/prisma-crud-create/index.js +0 -2
  365. package/dist/generators/prisma/prisma-crud-create/index.js.map +0 -1
  366. package/dist/generators/prisma/prisma-crud-create/prisma-crud-create.generator.d.ts +0 -48
  367. package/dist/generators/prisma/prisma-crud-create/prisma-crud-create.generator.d.ts.map +0 -1
  368. package/dist/generators/prisma/prisma-crud-create/prisma-crud-create.generator.js +0 -130
  369. package/dist/generators/prisma/prisma-crud-create/prisma-crud-create.generator.js.map +0 -1
  370. package/dist/generators/prisma/prisma-crud-delete/index.d.ts +0 -2
  371. package/dist/generators/prisma/prisma-crud-delete/index.d.ts.map +0 -1
  372. package/dist/generators/prisma/prisma-crud-delete/index.js +0 -2
  373. package/dist/generators/prisma/prisma-crud-delete/index.js.map +0 -1
  374. package/dist/generators/prisma/prisma-crud-delete/prisma-crud-delete.generator.d.ts +0 -38
  375. package/dist/generators/prisma/prisma-crud-delete/prisma-crud-delete.generator.d.ts.map +0 -1
  376. package/dist/generators/prisma/prisma-crud-delete/prisma-crud-delete.generator.js +0 -94
  377. package/dist/generators/prisma/prisma-crud-delete/prisma-crud-delete.generator.js.map +0 -1
  378. package/dist/generators/prisma/prisma-crud-service/index.d.ts +0 -2
  379. package/dist/generators/prisma/prisma-crud-service/index.d.ts.map +0 -1
  380. package/dist/generators/prisma/prisma-crud-service/index.js +0 -2
  381. package/dist/generators/prisma/prisma-crud-service/index.js.map +0 -1
  382. package/dist/generators/prisma/prisma-crud-service/prisma-crud-service.generator.d.ts +0 -20
  383. package/dist/generators/prisma/prisma-crud-service/prisma-crud-service.generator.d.ts.map +0 -1
  384. package/dist/generators/prisma/prisma-crud-service/prisma-crud-service.generator.js +0 -53
  385. package/dist/generators/prisma/prisma-crud-service/prisma-crud-service.generator.js.map +0 -1
  386. package/dist/generators/prisma/prisma-crud-update/index.d.ts +0 -2
  387. package/dist/generators/prisma/prisma-crud-update/index.d.ts.map +0 -1
  388. package/dist/generators/prisma/prisma-crud-update/index.js +0 -2
  389. package/dist/generators/prisma/prisma-crud-update/index.js.map +0 -1
  390. package/dist/generators/prisma/prisma-crud-update/prisma-crud-update.generator.d.ts +0 -48
  391. package/dist/generators/prisma/prisma-crud-update/prisma-crud-update.generator.d.ts.map +0 -1
  392. package/dist/generators/prisma/prisma-crud-update/prisma-crud-update.generator.js +0 -145
  393. package/dist/generators/prisma/prisma-crud-update/prisma-crud-update.generator.js.map +0 -1
  394. package/dist/generators/prisma/prisma-utils/generated/index.d.ts +0 -134
  395. package/dist/generators/prisma/prisma-utils/generated/index.d.ts.map +0 -1
  396. package/dist/generators/prisma/prisma-utils/generated/index.js +0 -11
  397. package/dist/generators/prisma/prisma-utils/generated/index.js.map +0 -1
  398. package/dist/generators/prisma/prisma-utils/generated/template-paths.d.ts +0 -17
  399. package/dist/generators/prisma/prisma-utils/generated/template-paths.d.ts.map +0 -1
  400. package/dist/generators/prisma/prisma-utils/generated/template-paths.js +0 -27
  401. package/dist/generators/prisma/prisma-utils/generated/template-paths.js.map +0 -1
  402. package/dist/generators/prisma/prisma-utils/generated/template-renderers.d.ts +0 -37
  403. package/dist/generators/prisma/prisma-utils/generated/template-renderers.d.ts.map +0 -1
  404. package/dist/generators/prisma/prisma-utils/generated/template-renderers.js +0 -43
  405. package/dist/generators/prisma/prisma-utils/generated/template-renderers.js.map +0 -1
  406. package/dist/generators/prisma/prisma-utils/generated/ts-import-providers.d.ts +0 -88
  407. package/dist/generators/prisma/prisma-utils/generated/ts-import-providers.d.ts.map +0 -1
  408. package/dist/generators/prisma/prisma-utils/generated/ts-import-providers.js +0 -54
  409. package/dist/generators/prisma/prisma-utils/generated/ts-import-providers.js.map +0 -1
  410. package/dist/generators/prisma/prisma-utils/generated/typed-templates.d.ts +0 -125
  411. package/dist/generators/prisma/prisma-utils/generated/typed-templates.d.ts.map +0 -1
  412. package/dist/generators/prisma/prisma-utils/generated/typed-templates.js +0 -104
  413. package/dist/generators/prisma/prisma-utils/generated/typed-templates.js.map +0 -1
  414. package/dist/generators/prisma/prisma-utils/index.d.ts +0 -4
  415. package/dist/generators/prisma/prisma-utils/index.d.ts.map +0 -1
  416. package/dist/generators/prisma/prisma-utils/index.js +0 -3
  417. package/dist/generators/prisma/prisma-utils/index.js.map +0 -1
  418. package/dist/generators/prisma/prisma-utils/prisma-utils.generator.d.ts +0 -61
  419. package/dist/generators/prisma/prisma-utils/prisma-utils.generator.d.ts.map +0 -1
  420. package/dist/generators/prisma/prisma-utils/prisma-utils.generator.js +0 -43
  421. package/dist/generators/prisma/prisma-utils/prisma-utils.generator.js.map +0 -1
  422. package/dist/generators/prisma/prisma-utils/templates/src/utils/crud-service-types.ts +0 -35
  423. package/dist/generators/prisma/prisma-utils/templates/src/utils/data-pipes.ts +0 -86
  424. package/dist/generators/prisma/prisma-utils/templates/src/utils/embedded-pipes/embedded-one-to-many.ts +0 -245
  425. package/dist/generators/prisma/prisma-utils/templates/src/utils/embedded-pipes/embedded-one-to-one.ts +0 -147
  426. package/dist/generators/prisma/prisma-utils/templates/src/utils/embedded-pipes/embedded-types.ts +0 -6
  427. package/dist/generators/prisma/prisma-utils/templates/src/utils/prisma-relations.ts +0 -24
  428. package/dist/providers/prisma/prisma-data-transformable.d.ts +0 -27
  429. package/dist/providers/prisma/prisma-data-transformable.d.ts.map +0 -1
  430. package/dist/providers/prisma/prisma-data-transformable.js +0 -2
  431. package/dist/providers/prisma/prisma-data-transformable.js.map +0 -1
@@ -0,0 +1,1030 @@
1
+ // @ts-nocheck
2
+
3
+ import type {
4
+ GetPayload,
5
+ ModelPropName,
6
+ ModelQuery,
7
+ WhereUniqueInput,
8
+ } from '$prismaTypes';
9
+ import type {
10
+ AnyFieldDefinition,
11
+ AnyOperationHooks,
12
+ DataOperationType,
13
+ InferFieldOutput,
14
+ InferFieldsCreateOutput,
15
+ InferFieldsOutput,
16
+ InferFieldsUpdateOutput,
17
+ InferInput,
18
+ InferInputSchema,
19
+ OperationContext,
20
+ OperationHooks,
21
+ PrismaTransaction,
22
+ TransactionalOperationContext,
23
+ } from '$types';
24
+ import type { Prisma } from '%prismaGeneratedImports';
25
+ import type { ServiceContext } from '%serviceContextImports';
26
+ import type { Result } from '@prisma/client/runtime/client';
27
+
28
+ import { makeGenericPrismaDelegate } from '$prismaUtils';
29
+ import { NotFoundError } from '%errorHandlerServiceImports';
30
+ import { prisma } from '%prismaImports';
31
+ import { z } from 'zod';
32
+
33
+ /**
34
+ * Invokes an array of hooks with the provided context.
35
+ *
36
+ * All hooks are executed in parallel using `Promise.all`. If no hooks are provided
37
+ * or the array is empty, this function returns immediately.
38
+ *
39
+ * @template TContext - The context type passed to each hook
40
+ * @param hooks - Optional array of async hook functions to invoke
41
+ * @param context - The context object passed to each hook
42
+ * @returns Promise that resolves when all hooks have completed
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * await invokeHooks(config.hooks?.beforeExecute, {
47
+ * operation: 'create',
48
+ * serviceContext: ctx,
49
+ * tx: transaction,
50
+ * });
51
+ * ```
52
+ */
53
+ export async function invokeHooks<TContext>(
54
+ hooks: ((ctx: TContext) => Promise<void>)[] | undefined,
55
+ context: TContext,
56
+ ): Promise<void> {
57
+ if (!hooks || hooks.length === 0) return;
58
+ await Promise.all(hooks.map((hook) => hook(context)));
59
+ }
60
+
61
+ type FieldDataOrFunction<TField extends AnyFieldDefinition> =
62
+ | InferFieldOutput<TField>
63
+ | ((tx: PrismaTransaction) => Promise<InferFieldOutput<TField>>);
64
+
65
+ /**
66
+ * Transforms field definitions into Prisma create/update data structures.
67
+ *
68
+ * This function processes each field definition by:
69
+ * 1. Validating the input value against the field's schema
70
+ * 2. Transforming the value into Prisma-compatible create/update data
71
+ * 3. Collecting hooks from each field for execution during the operation lifecycle
72
+ *
73
+ * The function supports both synchronous and asynchronous field transformations.
74
+ * If any field returns an async transformation function, the entire data object
75
+ * becomes async and will be resolved inside the transaction.
76
+ *
77
+ * @template TFields - Record of field definitions
78
+ * @param fields - Field definitions to process
79
+ * @param input - Input data to validate and transform
80
+ * @param options - Transformation options
81
+ * @param options.serviceContext - Service context with user, request info
82
+ * @param options.operation - Type of operation (create, update, upsert, delete)
83
+ * @param options.allowOptionalFields - Whether to allow undefined field values
84
+ * @param options.loadExisting - Function to load existing model data
85
+ * @returns Object containing transformed data and collected hooks
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const { data, hooks } = await transformFields(
90
+ * { name: scalarField(z.string()), email: scalarField(z.string().email()) },
91
+ * { name: 'John', email: 'john@example.com' },
92
+ * {
93
+ * serviceContext: ctx,
94
+ * operation: 'create',
95
+ * allowOptionalFields: false,
96
+ * loadExisting: () => Promise.resolve(undefined),
97
+ * },
98
+ * );
99
+ * ```
100
+ */
101
+ export async function transformFields<
102
+ TFields extends Record<string, AnyFieldDefinition>,
103
+ >(
104
+ fields: TFields,
105
+ input: InferInput<TFields>,
106
+ {
107
+ serviceContext,
108
+ operation,
109
+ allowOptionalFields,
110
+ loadExisting,
111
+ }: {
112
+ serviceContext: ServiceContext;
113
+ operation: DataOperationType;
114
+ allowOptionalFields: boolean;
115
+ loadExisting: () => Promise<object | undefined>;
116
+ },
117
+ ): Promise<{
118
+ data:
119
+ | InferFieldsOutput<TFields>
120
+ | ((tx: PrismaTransaction) => Promise<InferFieldsOutput<TFields>>);
121
+ hooks: AnyOperationHooks;
122
+ }> {
123
+ const hooks: Required<AnyOperationHooks> = {
124
+ beforeExecute: [],
125
+ afterExecute: [],
126
+ afterCommit: [],
127
+ };
128
+
129
+ const data = {} as {
130
+ [K in keyof TFields]: FieldDataOrFunction<TFields[K]>;
131
+ };
132
+
133
+ for (const [key, field] of Object.entries(fields)) {
134
+ const fieldKey = key as keyof typeof input;
135
+ const value = input[fieldKey];
136
+
137
+ if (allowOptionalFields && value === undefined) continue;
138
+
139
+ const result = await field.processInput(value, {
140
+ operation,
141
+ serviceContext,
142
+ fieldName: fieldKey as string,
143
+ loadExisting,
144
+ });
145
+
146
+ if (result.data) {
147
+ data[fieldKey as keyof TFields] = result.data as FieldDataOrFunction<
148
+ TFields[keyof TFields]
149
+ >;
150
+ }
151
+
152
+ if (result.hooks) {
153
+ hooks.beforeExecute.push(...(result.hooks.beforeExecute ?? []));
154
+ hooks.afterExecute.push(...(result.hooks.afterExecute ?? []));
155
+ hooks.afterCommit.push(...(result.hooks.afterCommit ?? []));
156
+ }
157
+ }
158
+
159
+ function splitCreateUpdateData(data: {
160
+ [K in keyof TFields]: InferFieldOutput<TFields[K]>;
161
+ }): {
162
+ create: InferFieldsCreateOutput<TFields>;
163
+ update: InferFieldsUpdateOutput<TFields>;
164
+ } {
165
+ const create = {} as InferFieldsCreateOutput<TFields>;
166
+ const update = {} as InferFieldsUpdateOutput<TFields>;
167
+ for (const [key, value] of Object.entries<
168
+ InferFieldOutput<TFields[keyof TFields]>
169
+ >(data)) {
170
+ if (value.create !== undefined) {
171
+ create[key as keyof TFields] =
172
+ value.create as InferFieldsCreateOutput<TFields>[keyof TFields];
173
+ }
174
+ if (value.update) {
175
+ update[key as keyof TFields] =
176
+ value.update as InferFieldsUpdateOutput<TFields>[keyof TFields];
177
+ }
178
+ }
179
+ return { create, update };
180
+ }
181
+
182
+ const transformedData = Object.values(data).some(
183
+ (value) => typeof value === 'function',
184
+ )
185
+ ? async (tx: PrismaTransaction) => {
186
+ const awaitedData = Object.fromEntries(
187
+ await Promise.all(
188
+ Object.entries(data).map(
189
+ async ([key, value]: [
190
+ keyof TFields,
191
+ FieldDataOrFunction<TFields[keyof TFields]>,
192
+ ]): Promise<
193
+ [keyof TFields, InferFieldOutput<TFields[keyof TFields]>]
194
+ > => [key, typeof value === 'function' ? await value(tx) : value],
195
+ ),
196
+ ),
197
+ ) as {
198
+ [K in keyof TFields]: InferFieldOutput<TFields[K]>;
199
+ };
200
+ return splitCreateUpdateData(awaitedData);
201
+ }
202
+ : splitCreateUpdateData(
203
+ data as { [K in keyof TFields]: InferFieldOutput<TFields[K]> },
204
+ );
205
+
206
+ return { data: transformedData, hooks };
207
+ }
208
+
209
+ /**
210
+ * =========================================
211
+ * Schema Generation Utilities
212
+ * =========================================
213
+ */
214
+
215
+ /**
216
+ * Generates a Zod schema for create operations from field definitions.
217
+ *
218
+ * Extracts the Zod schema from each field definition and combines them
219
+ * into a single object schema. This schema can be used for validation
220
+ * in GraphQL resolvers, REST endpoints, tRPC procedures, or OpenAPI documentation.
221
+ *
222
+ * @template TFields - Record of field definitions
223
+ * @param fields - Field definitions to extract schemas from
224
+ * @returns Zod object schema with all fields required
225
+ *
226
+ * @example
227
+ * ```typescript
228
+ * const fields = {
229
+ * name: scalarField(z.string()),
230
+ * email: scalarField(z.string().email()),
231
+ * };
232
+ *
233
+ * const schema = generateCreateSchema(fields);
234
+ * // schema is z.object({ name: z.string(), email: z.string().email() })
235
+ *
236
+ * // Use for validation
237
+ * const validated = schema.parse({ name: 'John', email: 'john@example.com' });
238
+ * ```
239
+ */
240
+ export function generateCreateSchema<
241
+ TFields extends Record<string, AnyFieldDefinition>,
242
+ >(fields: TFields): InferInputSchema<TFields> {
243
+ const shape = Object.fromEntries(
244
+ Object.entries(fields).map(([key, field]) => [key, field.schema]),
245
+ ) as {
246
+ [K in keyof TFields]: TFields[K]['schema'];
247
+ };
248
+
249
+ return z.object(shape) as InferInputSchema<TFields>;
250
+ }
251
+
252
+ /**
253
+ * =========================================
254
+ * Create Operation
255
+ * =========================================
256
+ */
257
+
258
+ /**
259
+ * Configuration for defining a create operation.
260
+ *
261
+ * Create operations insert new records into the database with support for:
262
+ * - Field-level validation and transformation
263
+ * - Authorization checks before creation
264
+ * - Computed fields based on raw input
265
+ * - Transaction management with lifecycle hooks
266
+ * - Nested relation creation
267
+ *
268
+ * @template TModelName - Prisma model name (e.g., 'user', 'post')
269
+ * @template TFields - Record of field definitions
270
+ * @template TPrepareResult - Type of data returned by prepareComputedFields
271
+ */
272
+ export interface CreateOperationConfig<
273
+ TModelName extends ModelPropName,
274
+ TFields extends Record<string, AnyFieldDefinition>,
275
+ TPrepareResult extends Record<string, unknown> | undefined = undefined,
276
+ > {
277
+ /**
278
+ * Prisma model name
279
+ */
280
+ model: TModelName;
281
+
282
+ /**
283
+ * Field definitions for the create operation
284
+ */
285
+ fields: TFields;
286
+
287
+ /**
288
+ * Optional authorization check before creating
289
+ */
290
+ authorize?: (
291
+ data: InferInput<TFields>,
292
+ ctx: OperationContext<GetPayload<TModelName>, { hasResult: false }>,
293
+ ) => Promise<void>;
294
+
295
+ /**
296
+ * Optional step to prepare computed fields based off the raw input
297
+ */
298
+ prepareComputedFields?: (
299
+ data: InferInput<TFields>,
300
+ ctx: OperationContext<GetPayload<TModelName>, { hasResult: false }>,
301
+ ) => TPrepareResult | Promise<TPrepareResult>;
302
+
303
+ /**
304
+ * Execute the create operation. This function receives validated field data
305
+ * and must return a Prisma create operation. It runs inside the transaction.
306
+ */
307
+ create: <TQueryArgs extends ModelQuery<TModelName>>(input: {
308
+ tx: PrismaTransaction;
309
+ data: InferFieldsCreateOutput<TFields> & TPrepareResult;
310
+ query: { include: NonNullable<TQueryArgs['include']> };
311
+ }) => Promise<
312
+ Result<
313
+ (typeof prisma)[TModelName],
314
+ // We type the query parameter to ensure that the user always includes ...query into the create call
315
+ { include: NonNullable<TQueryArgs['include']> },
316
+ 'create'
317
+ >
318
+ >;
319
+
320
+ /**
321
+ * Optional hooks for the operation
322
+ */
323
+ hooks?: OperationHooks<GetPayload<TModelName>>;
324
+ }
325
+
326
+ /**
327
+ * Input parameters for executing a create operation.
328
+ *
329
+ * @template TModelName - Prisma model name
330
+ * @template TFields - Record of field definitions
331
+ * @template TQueryArgs - Prisma query arguments (select/include)
332
+ */
333
+ export interface CreateOperationInput<
334
+ TModelName extends ModelPropName,
335
+ TFields extends Record<string, AnyFieldDefinition>,
336
+ TQueryArgs extends ModelQuery<TModelName>,
337
+ > {
338
+ /** Data to create the new record with */
339
+ data: InferInput<TFields>;
340
+ /** Optional Prisma query arguments to shape the returned data */
341
+ query?: TQueryArgs;
342
+ /** Service context containing user info, request details, etc. */
343
+ context: ServiceContext;
344
+ /**
345
+ * Skip Zod validation if data has already been validated (avoids double validation).
346
+ * Set to true when validation happened at a higher layer (e.g., GraphQL input type validation).
347
+ */
348
+ skipValidation?: boolean;
349
+ }
350
+
351
+ type CreateOperationFunction<
352
+ TModelName extends ModelPropName,
353
+ TFields extends Record<string, AnyFieldDefinition>,
354
+ > = (<TQueryArgs extends ModelQuery<TModelName>>(
355
+ input: CreateOperationInput<TModelName, TFields, TQueryArgs>,
356
+ ) => Promise<GetPayload<TModelName, TQueryArgs>>) & {
357
+ $dataSchema: InferInputSchema<TFields>;
358
+ };
359
+
360
+ /**
361
+ * Defines a type-safe create operation for a Prisma model.
362
+ *
363
+ * Creates a reusable function for inserting new records with built-in:
364
+ * - Input validation via field definitions
365
+ * - Authorization checks
366
+ * - Computed field preparation
367
+ * - Transaction management
368
+ * - Hook execution at each lifecycle phase
369
+ *
370
+ * @template TModelName - Prisma model name
371
+ * @template TFields - Record of field definitions
372
+ * @template TPrepareResult - Type of prepared computed fields
373
+ * @param config - Operation configuration
374
+ * @returns Async function that executes the create operation
375
+ *
376
+ * @example
377
+ * ```typescript
378
+ * const createUser = defineCreateOperation({
379
+ * model: 'user',
380
+ * fields: {
381
+ * name: scalarField(z.string()),
382
+ * email: scalarField(z.string().email()),
383
+ * },
384
+ * authorize: async (data, ctx) => {
385
+ * // Check if user has permission to create
386
+ * },
387
+ * create: ({ tx, data, query }) =>
388
+ * tx.user.create({
389
+ * data: {
390
+ * name: data.name,
391
+ * email: data.email,
392
+ * },
393
+ * ...query,
394
+ * }),
395
+ * });
396
+ *
397
+ * // Usage
398
+ * const user = await createUser({
399
+ * data: { name: 'John', email: 'john@example.com' },
400
+ * context: serviceContext,
401
+ * });
402
+ * ```
403
+ */
404
+ export function defineCreateOperation<
405
+ TModelName extends Prisma.TypeMap['meta']['modelProps'],
406
+ TFields extends Record<string, AnyFieldDefinition>,
407
+ TPrepareResult extends Record<string, unknown> | undefined = Record<
408
+ string,
409
+ never
410
+ >,
411
+ >(
412
+ config: CreateOperationConfig<TModelName, TFields, TPrepareResult>,
413
+ ): CreateOperationFunction<TModelName, TFields> {
414
+ const dataSchema = generateCreateSchema(config.fields);
415
+
416
+ const createOperation = async <TQueryArgs extends ModelQuery<TModelName>>({
417
+ data,
418
+ query,
419
+ context,
420
+ skipValidation,
421
+ }: CreateOperationInput<TModelName, TFields, TQueryArgs>): Promise<
422
+ GetPayload<TModelName, TQueryArgs>
423
+ > => {
424
+ // Throw error if query select is provided since we will not necessarily have a full result to return
425
+ if (query?.select) {
426
+ throw new Error(
427
+ 'Query select is not supported for create operations. Use include instead.',
428
+ );
429
+ }
430
+
431
+ // Validate data unless skipValidation is true (e.g., when GraphQL already validated)
432
+ const validatedData = skipValidation ? data : dataSchema.parse(data);
433
+
434
+ const baseOperationContext: OperationContext<
435
+ GetPayload<TModelName>,
436
+ { hasResult: false }
437
+ > = {
438
+ operation: 'create' as const,
439
+ serviceContext: context,
440
+ loadExisting: () => Promise.resolve(undefined),
441
+ result: undefined,
442
+ };
443
+
444
+ // Authorization
445
+ if (config.authorize) {
446
+ await config.authorize(validatedData, baseOperationContext);
447
+ }
448
+
449
+ // Step 1: Transform fields (OUTSIDE TRANSACTION)
450
+ const [{ data: fieldsData, hooks: fieldsHooks }, preparedData] =
451
+ await Promise.all([
452
+ transformFields(config.fields, validatedData, {
453
+ operation: 'create',
454
+ serviceContext: context,
455
+ allowOptionalFields: false,
456
+ loadExisting: () => Promise.resolve(undefined),
457
+ }),
458
+ config.prepareComputedFields
459
+ ? config.prepareComputedFields(validatedData, baseOperationContext)
460
+ : Promise.resolve(undefined as TPrepareResult),
461
+ ]);
462
+
463
+ const allHooks: AnyOperationHooks = {
464
+ beforeExecute: [
465
+ ...(config.hooks?.beforeExecute ?? []),
466
+ ...(fieldsHooks.beforeExecute ?? []),
467
+ ],
468
+ afterExecute: [
469
+ ...(config.hooks?.afterExecute ?? []),
470
+ ...(fieldsHooks.afterExecute ?? []),
471
+ ],
472
+ afterCommit: [
473
+ ...(config.hooks?.afterCommit ?? []),
474
+ ...(fieldsHooks.afterCommit ?? []),
475
+ ],
476
+ };
477
+
478
+ // Execute in transaction
479
+ return prisma
480
+ .$transaction(async (tx) => {
481
+ const txContext: TransactionalOperationContext<
482
+ GetPayload<TModelName>,
483
+ { hasResult: false }
484
+ > = {
485
+ ...baseOperationContext,
486
+ tx,
487
+ };
488
+
489
+ // Run beforeExecute hooks
490
+ await invokeHooks(allHooks.beforeExecute, txContext);
491
+
492
+ // Run all async create data transformations
493
+ const awaitedFieldsData =
494
+ typeof fieldsData === 'function' ? await fieldsData(tx) : fieldsData;
495
+
496
+ const result = await config.create({
497
+ tx,
498
+ data: { ...awaitedFieldsData.create, ...preparedData },
499
+ query: (query ?? {}) as {
500
+ include: NonNullable<TQueryArgs['include']>;
501
+ },
502
+ });
503
+
504
+ // Run afterExecute hooks
505
+ await invokeHooks(allHooks.afterExecute, {
506
+ ...txContext,
507
+ result,
508
+ });
509
+
510
+ return result;
511
+ })
512
+ .then(async (result) => {
513
+ // Run afterCommit hooks (outside transaction)
514
+ await invokeHooks(allHooks.afterCommit, {
515
+ ...baseOperationContext,
516
+ result,
517
+ });
518
+ return result as GetPayload<TModelName, TQueryArgs>;
519
+ });
520
+ };
521
+ createOperation.$dataSchema = dataSchema;
522
+ return createOperation;
523
+ }
524
+
525
+ /**
526
+ * =========================================
527
+ * Update Operation
528
+ * =========================================
529
+ */
530
+
531
+ /**
532
+ * Configuration for defining an update operation.
533
+ *
534
+ * Update operations modify existing database records with support for:
535
+ * - Partial updates (only specified fields are updated)
536
+ * - Authorization checks before modification
537
+ * - Pre-transaction preparation step for heavy I/O
538
+ * - Field-level validation and transformation
539
+ * - Transaction management with lifecycle hooks
540
+ *
541
+ * @template TModelName - Prisma model name (e.g., 'user', 'post')
542
+ * @template TFields - Record of field definitions
543
+ * @template TPrepareResult - Type of data returned by prepare function
544
+ */
545
+ export interface UpdateOperationConfig<
546
+ TModelName extends ModelPropName,
547
+ TFields extends Record<string, AnyFieldDefinition>,
548
+ TPrepareResult extends Record<string, unknown> | undefined = undefined,
549
+ > {
550
+ /**
551
+ * Prisma model name
552
+ */
553
+ model: TModelName;
554
+
555
+ /**
556
+ * Field definitions for the update operation
557
+ */
558
+ fields: TFields;
559
+
560
+ /**
561
+ * Optional authorization check before updating
562
+ */
563
+ authorize?: (
564
+ data: Partial<InferInput<TFields>>,
565
+ ctx: OperationContext<GetPayload<TModelName>, { hasResult: false }>,
566
+ ) => Promise<void>;
567
+
568
+ /**
569
+ * Optional prepare step - runs BEFORE transaction
570
+ * For heavy I/O, validation, data enrichment
571
+ */
572
+ prepareComputedFields?: (
573
+ data: Partial<InferInput<TFields>>,
574
+ ctx: OperationContext<GetPayload<TModelName>, { hasResult: false }>,
575
+ ) => TPrepareResult | Promise<TPrepareResult>;
576
+
577
+ /**
578
+ * Execute the update operation. This function receives validated field data
579
+ * and must return a Prisma update operation. It runs inside the transaction.
580
+ */
581
+ update: <TQueryArgs extends ModelQuery<TModelName>>(input: {
582
+ tx: PrismaTransaction;
583
+ where: WhereUniqueInput<TModelName>;
584
+ data: InferFieldsUpdateOutput<TFields> & TPrepareResult;
585
+ query: { include: NonNullable<TQueryArgs['include']> };
586
+ }) => Promise<
587
+ Result<
588
+ (typeof prisma)[TModelName],
589
+ // We type the query parameter to ensure that the user always includes ...query into the update call
590
+ { include: NonNullable<TQueryArgs['include']> },
591
+ 'update'
592
+ >
593
+ >;
594
+
595
+ /**
596
+ * Optional hooks for the operation
597
+ */
598
+ hooks?: OperationHooks<GetPayload<TModelName>>;
599
+ }
600
+
601
+ /**
602
+ * Input parameters for executing an update operation.
603
+ *
604
+ * @template TModelName - Prisma model name
605
+ * @template TFields - Record of field definitions
606
+ * @template TQueryArgs - Prisma query arguments (select/include)
607
+ */
608
+ export interface UpdateOperationInput<
609
+ TModelName extends ModelPropName,
610
+ TFields extends Record<string, AnyFieldDefinition>,
611
+ TQueryArgs extends ModelQuery<TModelName>,
612
+ > {
613
+ /** Unique identifier to locate the record to update */
614
+ where: WhereUniqueInput<TModelName>;
615
+ /** Partial data containing only the fields to update */
616
+ data: Partial<InferInput<TFields>>;
617
+ /** Optional Prisma query arguments to shape the returned data */
618
+ query?: TQueryArgs;
619
+ /** Service context containing user info, request details, etc. */
620
+ context: ServiceContext;
621
+ /**
622
+ * Skip Zod validation if data has already been validated (avoids double validation).
623
+ * Set to true when validation happened at a higher layer (e.g., GraphQL input type validation).
624
+ */
625
+ skipValidation?: boolean;
626
+ }
627
+
628
+ type UpdateOperationFunction<
629
+ TModelName extends ModelPropName,
630
+ TFields extends Record<string, AnyFieldDefinition>,
631
+ > = (<TQueryArgs extends ModelQuery<TModelName>>(
632
+ input: UpdateOperationInput<TModelName, TFields, TQueryArgs>,
633
+ ) => Promise<GetPayload<TModelName, TQueryArgs>>) & {
634
+ $dataSchema: z.ZodObject<{
635
+ [k in keyof TFields]: z.ZodOptional<TFields[k]['schema']>;
636
+ }>;
637
+ };
638
+ /**
639
+ * Defines a type-safe update operation for a Prisma model.
640
+ *
641
+ * Creates a reusable function for modifying existing records with built-in:
642
+ * - Partial input validation (only specified fields are processed)
643
+ * - Authorization checks with access to existing data
644
+ * - Pre-transaction preparation for heavy I/O
645
+ * - Transaction management
646
+ * - Hook execution at each lifecycle phase
647
+ *
648
+ * @template TModelName - Prisma model name
649
+ * @template TFields - Record of field definitions
650
+ * @template TPrepareResult - Type of prepared data
651
+ * @param config - Operation configuration
652
+ * @returns Async function that executes the update operation
653
+ * @throws {NotFoundError} If the record to update doesn't exist
654
+ *
655
+ * @example
656
+ * ```typescript
657
+ * const updateUser = defineUpdateOperation({
658
+ * model: 'user',
659
+ * fields: {
660
+ * name: scalarField(z.string()),
661
+ * email: scalarField(z.string().email()),
662
+ * },
663
+ * authorize: async (data, ctx) => {
664
+ * const existing = await ctx.loadExisting();
665
+ * // Check if user owns this record
666
+ * },
667
+ * update: ({ tx, where, data, query }) =>
668
+ * tx.user.update({
669
+ * where,
670
+ * data,
671
+ * ...query,
672
+ * }),
673
+ * });
674
+ *
675
+ * // Usage
676
+ * const user = await updateUser({
677
+ * where: { id: userId },
678
+ * data: { name: 'Jane' }, // Only update name
679
+ * context: serviceContext,
680
+ * });
681
+ * ```
682
+ */
683
+ export function defineUpdateOperation<
684
+ TModelName extends ModelPropName,
685
+ TFields extends Record<string, AnyFieldDefinition>,
686
+ TPrepareResult extends Record<string, unknown> | undefined = Record<
687
+ string,
688
+ never
689
+ >,
690
+ >(
691
+ config: UpdateOperationConfig<TModelName, TFields, TPrepareResult>,
692
+ ): UpdateOperationFunction<TModelName, TFields> {
693
+ const dataSchema = generateCreateSchema(config.fields).partial();
694
+
695
+ const updateOperation = async <TQueryArgs extends ModelQuery<TModelName>>({
696
+ where,
697
+ data: inputData,
698
+ query,
699
+ context,
700
+ skipValidation,
701
+ }: UpdateOperationInput<TModelName, TFields, TQueryArgs>): Promise<
702
+ GetPayload<TModelName, TQueryArgs>
703
+ > => {
704
+ // Throw error if query select is provided since we will not necessarily have a full result to return
705
+ if (query?.select) {
706
+ throw new Error(
707
+ 'Query select is not supported for update operations. Use include instead.',
708
+ );
709
+ }
710
+
711
+ // Validate data unless skipValidation is true (e.g., when GraphQL already validated)
712
+ const validatedData = skipValidation
713
+ ? inputData
714
+ : dataSchema.parse(inputData);
715
+
716
+ let existingItem: GetPayload<TModelName> | undefined;
717
+
718
+ const delegate = makeGenericPrismaDelegate(prisma, config.model);
719
+
720
+ const baseOperationContext: OperationContext<
721
+ GetPayload<TModelName>,
722
+ { hasResult: false }
723
+ > = {
724
+ operation: 'update' as const,
725
+ serviceContext: context,
726
+ loadExisting: async () => {
727
+ if (existingItem) return existingItem;
728
+ const result = await delegate.findUnique({
729
+ where,
730
+ });
731
+ if (!result) throw new NotFoundError(`${config.model} not found`);
732
+ existingItem = result;
733
+ return result;
734
+ },
735
+ result: undefined,
736
+ };
737
+ // Authorization
738
+ if (config.authorize) {
739
+ await config.authorize(validatedData, baseOperationContext);
740
+ }
741
+
742
+ // Step 1: Transform fields (outside transaction)
743
+ // Only transform fields provided in input
744
+ const fieldsToTransform = Object.fromEntries(
745
+ Object.entries(config.fields).filter(([key]) => key in validatedData),
746
+ ) as TFields;
747
+
748
+ const [{ data: fieldsData, hooks: fieldsHooks }, preparedData] =
749
+ await Promise.all([
750
+ transformFields(
751
+ fieldsToTransform,
752
+ validatedData as InferInput<TFields>,
753
+ {
754
+ operation: 'update',
755
+ serviceContext: context,
756
+ allowOptionalFields: true,
757
+ loadExisting: baseOperationContext.loadExisting as () => Promise<
758
+ Record<string, unknown>
759
+ >,
760
+ },
761
+ ),
762
+ config.prepareComputedFields
763
+ ? config.prepareComputedFields(validatedData, baseOperationContext)
764
+ : Promise.resolve(undefined as TPrepareResult),
765
+ ]);
766
+
767
+ // Combine config hooks with field hooks
768
+ const allHooks: AnyOperationHooks = {
769
+ beforeExecute: [
770
+ ...(config.hooks?.beforeExecute ?? []),
771
+ ...(fieldsHooks.beforeExecute ?? []),
772
+ ],
773
+ afterExecute: [
774
+ ...(config.hooks?.afterExecute ?? []),
775
+ ...(fieldsHooks.afterExecute ?? []),
776
+ ],
777
+ afterCommit: [
778
+ ...(config.hooks?.afterCommit ?? []),
779
+ ...(fieldsHooks.afterCommit ?? []),
780
+ ],
781
+ };
782
+
783
+ // Execute in transaction
784
+ return prisma
785
+ .$transaction(async (tx) => {
786
+ const txContext: TransactionalOperationContext<
787
+ GetPayload<TModelName>,
788
+ { hasResult: false }
789
+ > = {
790
+ ...baseOperationContext,
791
+ tx,
792
+ };
793
+
794
+ // Run beforeExecute hooks
795
+ await invokeHooks(allHooks.beforeExecute, txContext);
796
+
797
+ // Run all async update data transformations
798
+ const awaitedFieldsData =
799
+ typeof fieldsData === 'function' ? await fieldsData(tx) : fieldsData;
800
+
801
+ const result = await config.update({
802
+ tx,
803
+ where,
804
+ data: { ...awaitedFieldsData.update, ...preparedData },
805
+ query: (query ?? {}) as {
806
+ include: NonNullable<TQueryArgs['include']>;
807
+ },
808
+ });
809
+
810
+ // Run afterExecute hooks
811
+ await invokeHooks(allHooks.afterExecute, {
812
+ ...txContext,
813
+ result,
814
+ });
815
+
816
+ return result;
817
+ })
818
+ .then(async (result) => {
819
+ // Run afterCommit hooks (outside transaction)
820
+ await invokeHooks(allHooks.afterCommit, {
821
+ ...baseOperationContext,
822
+ result,
823
+ });
824
+ return result as GetPayload<TModelName, TQueryArgs>;
825
+ });
826
+ };
827
+ updateOperation.$dataSchema = generateCreateSchema(config.fields).partial();
828
+ return updateOperation;
829
+ }
830
+
831
+ /**
832
+ * Configuration for defining a delete operation.
833
+ *
834
+ * Delete operations remove records from the database with support for:
835
+ * - Authorization checks before deletion
836
+ * - Transaction management
837
+ * - Lifecycle hooks for cleanup operations
838
+ * - Access to the record being deleted
839
+ *
840
+ * @template TModelName - Prisma model name (e.g., 'user', 'post')
841
+ */
842
+ export interface DeleteOperationConfig<TModelName extends ModelPropName> {
843
+ /**
844
+ * Prisma model name
845
+ */
846
+ model: TModelName;
847
+
848
+ /**
849
+ * Optional authorization check before deleting
850
+ */
851
+ authorize?: (
852
+ ctx: OperationContext<
853
+ GetPayload<TModelName> | undefined,
854
+ { hasResult: false }
855
+ >,
856
+ ) => Promise<void>;
857
+
858
+ /**
859
+ * Execute the delete operation. This function receives the where clause
860
+ * and must return a Prisma delete operation. It runs inside the transaction.
861
+ */
862
+ delete: <TQueryArgs extends ModelQuery<TModelName>>(input: {
863
+ tx: PrismaTransaction;
864
+ where: WhereUniqueInput<TModelName>;
865
+ query: { include: NonNullable<TQueryArgs['include']> };
866
+ }) => Promise<
867
+ Result<
868
+ (typeof prisma)[TModelName],
869
+ // We type the query parameter to ensure that the user always includes ...query into the delete call
870
+ { include: NonNullable<TQueryArgs['include']> },
871
+ 'delete'
872
+ >
873
+ >;
874
+
875
+ /**
876
+ * Optional hooks for the operation
877
+ */
878
+ hooks?: OperationHooks<GetPayload<TModelName>>;
879
+ }
880
+
881
+ /**
882
+ * Input parameters for executing a delete operation.
883
+ *
884
+ * @template TModelName - Prisma model name
885
+ * @template TQueryArgs - Prisma query arguments (select/include)
886
+ */
887
+ export interface DeleteOperationInput<
888
+ TModelName extends ModelPropName,
889
+ TQueryArgs extends ModelQuery<TModelName>,
890
+ > {
891
+ /** Unique identifier to locate the record to delete */
892
+ where: WhereUniqueInput<TModelName>;
893
+ /** Optional Prisma query arguments to shape the returned data */
894
+ query?: TQueryArgs;
895
+ /** Service context containing user info, request details, etc. */
896
+ context: ServiceContext;
897
+ }
898
+
899
+ /**
900
+ * Defines a type-safe delete operation for a Prisma model.
901
+ *
902
+ * Creates a reusable function for removing records with built-in:
903
+ * - Authorization checks with access to the record being deleted
904
+ * - Transaction management
905
+ * - Hook execution for cleanup operations (e.g., deleting associated files)
906
+ * - Returns the deleted record
907
+ *
908
+ * @template TModelName - Prisma model name
909
+ * @param config - Operation configuration
910
+ * @returns Async function that executes the delete operation
911
+ * @throws {NotFoundError} If the record to delete doesn't exist
912
+ *
913
+ * @example
914
+ * ```typescript
915
+ * const deleteUser = defineDeleteOperation({
916
+ * model: 'user',
917
+ * authorize: async (ctx) => {
918
+ * const existing = await ctx.loadExisting();
919
+ * // Check if user has permission to delete
920
+ * },
921
+ * delete: ({ tx, where, query }) =>
922
+ * tx.user.delete({
923
+ * where,
924
+ * ...query,
925
+ * }),
926
+ * hooks: {
927
+ * afterCommit: [
928
+ * async (ctx) => {
929
+ * // Clean up user's files, sessions, etc.
930
+ * await cleanupUserResources(ctx.result.id);
931
+ * },
932
+ * ],
933
+ * },
934
+ * });
935
+ *
936
+ * // Usage
937
+ * const deletedUser = await deleteUser({
938
+ * where: { id: userId },
939
+ * context: serviceContext,
940
+ * });
941
+ * ```
942
+ */
943
+ export function defineDeleteOperation<TModelName extends ModelPropName>(
944
+ config: DeleteOperationConfig<TModelName>,
945
+ ): <TQueryArgs extends ModelQuery<TModelName>>(
946
+ input: DeleteOperationInput<TModelName, TQueryArgs>,
947
+ ) => Promise<GetPayload<TModelName, TQueryArgs>> {
948
+ return async <TQueryArgs extends ModelQuery<TModelName>>({
949
+ where,
950
+ query,
951
+ context,
952
+ }: DeleteOperationInput<TModelName, TQueryArgs>) => {
953
+ // Throw error if query select is provided since we will not necessarily have a full result to return
954
+ if (query?.select) {
955
+ throw new Error(
956
+ 'Query select is not supported for delete operations. Use include instead.',
957
+ );
958
+ }
959
+
960
+ const delegate = makeGenericPrismaDelegate(prisma, config.model);
961
+
962
+ let existingItem: GetPayload<TModelName> | undefined;
963
+ const baseOperationContext: OperationContext<
964
+ GetPayload<TModelName>,
965
+ { hasResult: false }
966
+ > = {
967
+ operation: 'delete' as const,
968
+ serviceContext: context,
969
+ loadExisting: async () => {
970
+ if (existingItem) return existingItem;
971
+ const result = await delegate.findUnique({ where });
972
+ if (!result) throw new NotFoundError(`${config.model} not found`);
973
+ existingItem = result;
974
+ return result;
975
+ },
976
+ result: undefined,
977
+ };
978
+
979
+ // Authorization
980
+ if (config.authorize) {
981
+ await config.authorize(baseOperationContext);
982
+ }
983
+
984
+ const allHooks: AnyOperationHooks = {
985
+ beforeExecute: config.hooks?.beforeExecute ?? [],
986
+ afterExecute: config.hooks?.afterExecute ?? [],
987
+ afterCommit: config.hooks?.afterCommit ?? [],
988
+ };
989
+
990
+ // Execute in transaction
991
+ return prisma
992
+ .$transaction(async (tx) => {
993
+ const txContext: TransactionalOperationContext<
994
+ GetPayload<TModelName>,
995
+ { hasResult: false }
996
+ > = {
997
+ ...baseOperationContext,
998
+ tx,
999
+ };
1000
+
1001
+ // Run beforeExecute hooks
1002
+ await invokeHooks(allHooks.beforeExecute, txContext);
1003
+
1004
+ // Execute delete operation
1005
+ const result = await config.delete({
1006
+ tx,
1007
+ where,
1008
+ query: (query ?? {}) as {
1009
+ include: NonNullable<TQueryArgs['include']>;
1010
+ },
1011
+ });
1012
+
1013
+ // Run afterExecute hooks
1014
+ await invokeHooks(allHooks.afterExecute, {
1015
+ ...txContext,
1016
+ result,
1017
+ });
1018
+
1019
+ return result;
1020
+ })
1021
+ .then(async (result) => {
1022
+ // Run afterCommit hooks (outside transaction)
1023
+ await invokeHooks(allHooks.afterCommit, {
1024
+ ...baseOperationContext,
1025
+ result,
1026
+ });
1027
+ return result as GetPayload<TModelName, TQueryArgs>;
1028
+ });
1029
+ };
1030
+ }