@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.
- package/dist/constants/fastify-packages.d.ts +12 -11
- package/dist/constants/fastify-packages.d.ts.map +1 -1
- package/dist/constants/fastify-packages.js +12 -11
- package/dist/constants/fastify-packages.js.map +1 -1
- package/dist/generators/auth/auth-context/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/auth/auth-context/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/auth/auth-context/generated/ts-import-providers.js +1 -1
- package/dist/generators/auth/auth-context/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/auth/auth-roles/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/auth/auth-roles/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/auth/auth-roles/generated/ts-import-providers.js +1 -1
- package/dist/generators/auth/auth-roles/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/auth/index.d.ts +0 -1
- package/dist/generators/auth/index.d.ts.map +1 -1
- package/dist/generators/auth/index.js +0 -1
- package/dist/generators/auth/index.js.map +1 -1
- package/dist/generators/auth/password-hasher-service/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/auth/password-hasher-service/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/auth/password-hasher-service/generated/ts-import-providers.js +1 -1
- package/dist/generators/auth/password-hasher-service/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/auth/user-session-types/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/auth/user-session-types/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/auth/user-session-types/generated/ts-import-providers.js +1 -1
- package/dist/generators/auth/user-session-types/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/bull/bull-mq/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/bull/bull-mq/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/bull/bull-mq/generated/ts-import-providers.js +1 -1
- package/dist/generators/bull/bull-mq/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/core/app-module-setup/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/core/app-module-setup/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/core/app-module-setup/generated/ts-import-providers.js +1 -1
- package/dist/generators/core/app-module-setup/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/core/axios/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/core/axios/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/core/axios/generated/ts-import-providers.js +3 -1
- package/dist/generators/core/axios/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/core/config-service/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/core/config-service/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/core/config-service/generated/ts-import-providers.js +3 -1
- package/dist/generators/core/config-service/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/core/error-handler-service/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/core/error-handler-service/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/core/error-handler-service/generated/ts-import-providers.js +1 -1
- package/dist/generators/core/error-handler-service/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/core/fastify/fastify.generator.js +1 -1
- package/dist/generators/core/fastify/fastify.generator.js.map +1 -1
- package/dist/generators/core/fastify-redis/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/core/fastify-redis/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/core/fastify-redis/generated/ts-import-providers.js +1 -1
- package/dist/generators/core/fastify-redis/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/core/fastify-sentry/fastify-sentry.generator.js +1 -1
- package/dist/generators/core/fastify-sentry/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/core/fastify-sentry/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/core/fastify-sentry/generated/ts-import-providers.js +1 -1
- package/dist/generators/core/fastify-sentry/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/core/logger-service/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/core/logger-service/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/core/logger-service/generated/ts-import-providers.js +3 -1
- package/dist/generators/core/logger-service/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/core/readme/templates/package/README.md +4 -4
- package/dist/generators/core/request-context/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/core/request-context/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/core/request-context/generated/ts-import-providers.js +1 -1
- package/dist/generators/core/request-context/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/core/request-service-context/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/core/request-service-context/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/core/request-service-context/generated/ts-import-providers.js +1 -1
- package/dist/generators/core/request-service-context/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/core/service-context/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/core/service-context/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/core/service-context/generated/ts-import-providers.js +1 -1
- package/dist/generators/core/service-context/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/core/service-file/service-file.generator.d.ts +7 -0
- package/dist/generators/core/service-file/service-file.generator.d.ts.map +1 -1
- package/dist/generators/core/service-file/service-file.generator.js +12 -2
- package/dist/generators/core/service-file/service-file.generator.js.map +1 -1
- package/dist/generators/pothos/pothos/generated/index.d.ts +3 -1
- package/dist/generators/pothos/pothos/generated/index.d.ts.map +1 -1
- package/dist/generators/pothos/pothos/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/pothos/pothos/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/pothos/pothos/generated/ts-import-providers.js +1 -1
- package/dist/generators/pothos/pothos/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/pothos/pothos/generated/typed-templates.d.ts +6 -2
- package/dist/generators/pothos/pothos/generated/typed-templates.d.ts.map +1 -1
- package/dist/generators/pothos/pothos/generated/typed-templates.js +1 -0
- package/dist/generators/pothos/pothos/generated/typed-templates.js.map +1 -1
- package/dist/generators/pothos/pothos/pothos.generator.d.ts +3 -3
- package/dist/generators/pothos/pothos/pothos.generator.d.ts.map +1 -1
- package/dist/generators/pothos/pothos/pothos.generator.js +4 -0
- package/dist/generators/pothos/pothos/pothos.generator.js.map +1 -1
- package/dist/generators/pothos/pothos/templates/src/plugins/graphql/FieldWithInputPayloadPlugin/global-types.ts +3 -5
- package/dist/generators/pothos/pothos/templates/src/plugins/graphql/FieldWithInputPayloadPlugin/schema-builder.ts +9 -4
- package/dist/generators/pothos/pothos/templates/src/plugins/graphql/FieldWithInputPayloadPlugin/types.ts +6 -1
- package/dist/generators/pothos/pothos-auth/pothos-auth.generator.d.ts +1 -1
- package/dist/generators/pothos/pothos-enums-file/pothos-enums-file.generator.d.ts +1 -1
- package/dist/generators/pothos/pothos-prisma/generated/index.d.ts +36 -0
- package/dist/generators/pothos/pothos-prisma/generated/index.d.ts.map +1 -0
- package/dist/generators/pothos/pothos-prisma/generated/index.js +11 -0
- package/dist/generators/pothos/pothos-prisma/generated/index.js.map +1 -0
- package/dist/generators/pothos/pothos-prisma/generated/template-paths.d.ts +12 -0
- package/dist/generators/pothos/pothos-prisma/generated/template-paths.d.ts.map +1 -0
- package/dist/generators/pothos/pothos-prisma/generated/template-paths.js +22 -0
- package/dist/generators/pothos/pothos-prisma/generated/template-paths.js.map +1 -0
- package/dist/generators/pothos/pothos-prisma/generated/template-renderers.d.ts +18 -0
- package/dist/generators/pothos/pothos-prisma/generated/template-renderers.d.ts.map +1 -0
- package/dist/generators/pothos/pothos-prisma/generated/template-renderers.js +34 -0
- package/dist/generators/pothos/pothos-prisma/generated/template-renderers.js.map +1 -0
- package/dist/generators/pothos/pothos-prisma/generated/ts-import-providers.d.ts +30 -0
- package/dist/generators/pothos/pothos-prisma/generated/ts-import-providers.d.ts.map +1 -0
- package/dist/generators/pothos/pothos-prisma/generated/ts-import-providers.js +30 -0
- package/dist/generators/pothos/pothos-prisma/generated/ts-import-providers.js.map +1 -0
- package/dist/generators/pothos/pothos-prisma/generated/typed-templates.d.ts +4 -0
- package/dist/generators/pothos/pothos-prisma/generated/typed-templates.d.ts.map +1 -0
- package/dist/generators/pothos/pothos-prisma/generated/typed-templates.js +14 -0
- package/dist/generators/pothos/pothos-prisma/generated/typed-templates.js.map +1 -0
- package/dist/generators/pothos/pothos-prisma/index.d.ts +2 -0
- package/dist/generators/pothos/pothos-prisma/index.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-prisma/index.js +1 -0
- package/dist/generators/pothos/pothos-prisma/index.js.map +1 -1
- package/dist/generators/pothos/pothos-prisma/pothos-prisma.generator.d.ts +34 -1
- package/dist/generators/pothos/pothos-prisma/pothos-prisma.generator.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-prisma/pothos-prisma.generator.js +20 -6
- package/dist/generators/pothos/pothos-prisma/pothos-prisma.generator.js.map +1 -1
- package/dist/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.d.ts +2 -2
- package/dist/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.js +87 -50
- package/dist/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.js.map +1 -1
- package/dist/generators/pothos/pothos-scalar/generated/index.d.ts +9 -39
- package/dist/generators/pothos/pothos-scalar/generated/index.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-scalar/generated/template-paths.d.ts +2 -0
- package/dist/generators/pothos/pothos-scalar/generated/template-paths.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-scalar/generated/template-paths.js +2 -0
- package/dist/generators/pothos/pothos-scalar/generated/template-paths.js.map +1 -1
- package/dist/generators/pothos/pothos-scalar/generated/template-renderers.d.ts +6 -10
- package/dist/generators/pothos/pothos-scalar/generated/template-renderers.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-scalar/generated/template-renderers.js +21 -6
- package/dist/generators/pothos/pothos-scalar/generated/template-renderers.js.map +1 -1
- package/dist/generators/pothos/pothos-scalar/generated/typed-templates.d.ts +9 -29
- package/dist/generators/pothos/pothos-scalar/generated/typed-templates.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-scalar/generated/typed-templates.js +28 -14
- package/dist/generators/pothos/pothos-scalar/generated/typed-templates.js.map +1 -1
- package/dist/generators/pothos/pothos-scalar/pothos-scalar.generator.d.ts +2 -12
- package/dist/generators/pothos/pothos-scalar/pothos-scalar.generator.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-scalar/pothos-scalar.generator.js +35 -11
- package/dist/generators/pothos/pothos-scalar/pothos-scalar.generator.js.map +1 -1
- package/dist/generators/pothos/pothos-scalar/templates/module/scalars/date-time.ts +21 -28
- package/dist/generators/pothos/pothos-scalar/templates/module/scalars/date.ts +13 -45
- package/dist/generators/pothos/pothos-scalar/templates/module/scalars/json-object.ts +28 -0
- package/dist/generators/pothos/pothos-scalar/templates/module/scalars/json.ts +23 -0
- package/dist/generators/pothos/pothos-scalar/templates/module/scalars/uuid.ts +13 -31
- package/dist/generators/pothos/pothos-sentry/pothos-sentry.generator.d.ts +1 -1
- package/dist/generators/prisma/_providers/index.d.ts +2 -0
- package/dist/generators/prisma/_providers/index.d.ts.map +1 -0
- package/dist/generators/prisma/_providers/index.js +2 -0
- package/dist/generators/prisma/_providers/index.js.map +1 -0
- package/dist/generators/prisma/_providers/prisma-generated-imports.d.ts +15 -0
- package/dist/generators/prisma/_providers/prisma-generated-imports.d.ts.map +1 -0
- package/dist/generators/prisma/_providers/prisma-generated-imports.js +10 -0
- package/dist/generators/prisma/_providers/prisma-generated-imports.js.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.d.ts +124 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.d.ts.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.js +137 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.js.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.d.ts +82 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.d.ts.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.js +215 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.js.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/index.d.ts +3 -0
- package/dist/generators/prisma/_shared/build-data-helpers/index.d.ts.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/index.js +3 -0
- package/dist/generators/prisma/_shared/build-data-helpers/index.js.map +1 -0
- package/dist/generators/prisma/_shared/crud-method/primary-key-input.d.ts +0 -9
- package/dist/generators/prisma/_shared/crud-method/primary-key-input.d.ts.map +1 -1
- package/dist/generators/prisma/_shared/crud-method/primary-key-input.js +0 -32
- package/dist/generators/prisma/_shared/crud-method/primary-key-input.js.map +1 -1
- package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.d.ts +26 -0
- package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.d.ts.map +1 -0
- package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.js +47 -0
- package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.js.map +1 -0
- package/dist/generators/prisma/_shared/field-definition-generators/types.d.ts +8 -0
- package/dist/generators/prisma/_shared/field-definition-generators/types.d.ts.map +1 -0
- package/dist/generators/prisma/_shared/field-definition-generators/types.js +2 -0
- package/dist/generators/prisma/_shared/field-definition-generators/types.js.map +1 -0
- package/dist/generators/prisma/data-utils/data-utils.generator.d.ts +109 -0
- package/dist/generators/prisma/data-utils/data-utils.generator.d.ts.map +1 -0
- package/dist/generators/prisma/data-utils/data-utils.generator.js +32 -0
- package/dist/generators/prisma/data-utils/data-utils.generator.js.map +1 -0
- package/dist/generators/prisma/data-utils/generated/index.d.ts +190 -0
- package/dist/generators/prisma/data-utils/generated/index.d.ts.map +1 -0
- package/dist/generators/prisma/data-utils/generated/index.js +11 -0
- package/dist/generators/prisma/data-utils/generated/index.js.map +1 -0
- package/dist/generators/prisma/data-utils/generated/template-paths.d.ts +17 -0
- package/dist/generators/prisma/data-utils/generated/template-paths.d.ts.map +1 -0
- package/dist/generators/prisma/data-utils/generated/template-paths.js +27 -0
- package/dist/generators/prisma/data-utils/generated/template-paths.js.map +1 -0
- package/dist/generators/prisma/data-utils/generated/template-renderers.d.ts +45 -0
- package/dist/generators/prisma/data-utils/generated/template-renderers.d.ts.map +1 -0
- package/dist/generators/prisma/data-utils/generated/template-renderers.js +47 -0
- package/dist/generators/prisma/data-utils/generated/template-renderers.js.map +1 -0
- package/dist/generators/prisma/data-utils/generated/ts-import-providers.d.ts +183 -0
- package/dist/generators/prisma/data-utils/generated/ts-import-providers.d.ts.map +1 -0
- package/dist/generators/prisma/data-utils/generated/ts-import-providers.js +72 -0
- package/dist/generators/prisma/data-utils/generated/ts-import-providers.js.map +1 -0
- package/dist/generators/prisma/data-utils/generated/typed-templates.d.ts +157 -0
- package/dist/generators/prisma/data-utils/generated/typed-templates.d.ts.map +1 -0
- package/dist/generators/prisma/data-utils/generated/typed-templates.js +125 -0
- package/dist/generators/prisma/data-utils/generated/typed-templates.js.map +1 -0
- package/dist/generators/prisma/data-utils/index.d.ts +4 -0
- package/dist/generators/prisma/data-utils/index.d.ts.map +1 -0
- package/dist/generators/prisma/data-utils/index.js +3 -0
- package/dist/generators/prisma/data-utils/index.js.map +1 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/define-operations.ts +1030 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.ts +782 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-types.ts +164 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-utils.ts +80 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/relation-helpers.ts +196 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts +372 -0
- package/dist/generators/prisma/index.d.ts +7 -6
- package/dist/generators/prisma/index.d.ts.map +1 -1
- package/dist/generators/prisma/index.js +7 -6
- package/dist/generators/prisma/index.js.map +1 -1
- package/dist/generators/prisma/prisma/generated/index.d.ts +19 -1
- package/dist/generators/prisma/prisma/generated/index.d.ts.map +1 -1
- package/dist/generators/prisma/prisma/generated/template-paths.d.ts +1 -0
- package/dist/generators/prisma/prisma/generated/template-paths.d.ts.map +1 -1
- package/dist/generators/prisma/prisma/generated/template-paths.js +1 -0
- package/dist/generators/prisma/prisma/generated/template-paths.js.map +1 -1
- package/dist/generators/prisma/prisma/generated/template-renderers.d.ts +7 -1
- package/dist/generators/prisma/prisma/generated/template-renderers.d.ts.map +1 -1
- package/dist/generators/prisma/prisma/generated/template-renderers.js +14 -1
- package/dist/generators/prisma/prisma/generated/template-renderers.js.map +1 -1
- package/dist/generators/prisma/prisma/generated/ts-import-providers.d.ts +7 -2
- package/dist/generators/prisma/prisma/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/prisma/prisma/generated/ts-import-providers.js +12 -2
- package/dist/generators/prisma/prisma/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/prisma/prisma/generated/typed-templates.d.ts +13 -1
- package/dist/generators/prisma/prisma/generated/typed-templates.d.ts.map +1 -1
- package/dist/generators/prisma/prisma/generated/typed-templates.js +19 -2
- package/dist/generators/prisma/prisma/generated/typed-templates.js.map +1 -1
- package/dist/generators/prisma/prisma/prisma.generator.d.ts +21 -0
- package/dist/generators/prisma/prisma/prisma.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma/prisma.generator.js +42 -8
- package/dist/generators/prisma/prisma/prisma.generator.js.map +1 -1
- package/dist/generators/prisma/prisma/templates/package/prisma.config.mts +7 -2
- package/dist/generators/prisma/prisma/templates/src/services/prisma.ts +5 -2
- package/dist/generators/prisma/prisma-data-create/index.d.ts +2 -0
- package/dist/generators/prisma/prisma-data-create/index.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-data-create/index.js +2 -0
- package/dist/generators/prisma/prisma-data-create/index.js.map +1 -0
- package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.d.ts +73 -0
- package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.js +102 -0
- package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.js.map +1 -0
- package/dist/generators/prisma/prisma-data-delete/index.d.ts +2 -0
- package/dist/generators/prisma/prisma-data-delete/index.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-data-delete/index.js +2 -0
- package/dist/generators/prisma/prisma-data-delete/index.js.map +1 -0
- package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.d.ts +72 -0
- package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.js +82 -0
- package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.js.map +1 -0
- package/dist/generators/prisma/prisma-data-nested-field/index.d.ts +2 -0
- package/dist/generators/prisma/prisma-data-nested-field/index.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-data-nested-field/index.js +2 -0
- package/dist/generators/prisma/prisma-data-nested-field/index.js.map +1 -0
- package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.d.ts +16 -0
- package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.js +179 -0
- package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.js.map +1 -0
- package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.d.ts +95 -0
- package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.js +120 -0
- package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.js.map +1 -0
- package/dist/generators/prisma/prisma-data-service/index.d.ts +2 -0
- package/dist/generators/prisma/prisma-data-service/index.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-data-service/index.js +2 -0
- package/dist/generators/prisma/prisma-data-service/index.js.map +1 -0
- package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.d.ts +117 -0
- package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.js +127 -0
- package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.js.map +1 -0
- package/dist/generators/prisma/prisma-data-update/index.d.ts +2 -0
- package/dist/generators/prisma/prisma-data-update/index.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-data-update/index.js +2 -0
- package/dist/generators/prisma/prisma-data-update/index.js.map +1 -0
- package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.d.ts +73 -0
- package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.js +114 -0
- package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.js.map +1 -0
- package/dist/generators/prisma/prisma-field/prisma-field.generator.d.ts +6 -6
- package/dist/generators/stripe/fastify-stripe/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/stripe/fastify-stripe/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/stripe/fastify-stripe/generated/ts-import-providers.js +1 -1
- package/dist/generators/stripe/fastify-stripe/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/index.d.ts +20 -1
- package/dist/generators/vitest/prisma-vitest/generated/index.d.ts.map +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/template-renderers.d.ts +6 -0
- package/dist/generators/vitest/prisma-vitest/generated/template-renderers.d.ts.map +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/template-renderers.js +7 -1
- package/dist/generators/vitest/prisma-vitest/generated/template-renderers.js.map +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/ts-import-providers.d.ts +1 -2
- package/dist/generators/vitest/prisma-vitest/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/ts-import-providers.js +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/typed-templates.d.ts +14 -1
- package/dist/generators/vitest/prisma-vitest/generated/typed-templates.d.ts.map +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/typed-templates.js +8 -2
- package/dist/generators/vitest/prisma-vitest/generated/typed-templates.js.map +1 -1
- package/dist/generators/vitest/prisma-vitest/prisma-vitest.generator.d.ts +16 -0
- package/dist/generators/vitest/prisma-vitest/prisma-vitest.generator.d.ts.map +1 -1
- package/dist/generators/vitest/prisma-vitest/prisma-vitest.generator.js +5 -10
- package/dist/generators/vitest/prisma-vitest/prisma-vitest.generator.js.map +1 -1
- package/dist/generators/vitest/prisma-vitest/templates/src/tests/helpers/db.test-helper.ts +3 -2
- package/dist/generators/vitest/prisma-vitest/templates/src/tests/helpers/prisma.test-helper.ts +1 -1
- package/dist/types/field-types.d.ts +1 -1
- package/dist/types/field-types.d.ts.map +1 -1
- package/dist/types/field-types.js +2 -0
- package/dist/types/field-types.js.map +1 -1
- package/dist/types/service-dto-kinds.d.ts +59 -0
- package/dist/types/service-dto-kinds.d.ts.map +1 -0
- package/dist/types/service-dto-kinds.js +53 -0
- package/dist/types/service-dto-kinds.js.map +1 -0
- package/dist/types/service-output.d.ts +25 -2
- package/dist/types/service-output.d.ts.map +1 -1
- package/dist/types/service-output.js +22 -2
- package/dist/types/service-output.js.map +1 -1
- package/dist/writers/pothos/input-types.d.ts +1 -1
- package/dist/writers/pothos/input-types.d.ts.map +1 -1
- package/dist/writers/pothos/input-types.js +7 -10
- package/dist/writers/pothos/input-types.js.map +1 -1
- package/dist/writers/pothos/resolvers.d.ts.map +1 -1
- package/dist/writers/pothos/resolvers.js +9 -6
- package/dist/writers/pothos/resolvers.js.map +1 -1
- package/dist/writers/pothos/scalars.d.ts.map +1 -1
- package/dist/writers/pothos/scalars.js +5 -0
- package/dist/writers/pothos/scalars.js.map +1 -1
- package/dist/writers/prisma-schema/fields.d.ts +3 -0
- package/dist/writers/prisma-schema/fields.d.ts.map +1 -1
- package/dist/writers/prisma-schema/fields.js +1 -0
- package/dist/writers/prisma-schema/fields.js.map +1 -1
- package/package.json +8 -6
- package/dist/generators/auth/prisma-password-transformer/index.d.ts +0 -2
- package/dist/generators/auth/prisma-password-transformer/index.d.ts.map +0 -1
- package/dist/generators/auth/prisma-password-transformer/index.js +0 -2
- package/dist/generators/auth/prisma-password-transformer/index.js.map +0 -1
- package/dist/generators/auth/prisma-password-transformer/prisma-password-transformer.generator.d.ts +0 -12
- package/dist/generators/auth/prisma-password-transformer/prisma-password-transformer.generator.d.ts.map +0 -1
- package/dist/generators/auth/prisma-password-transformer/prisma-password-transformer.generator.js +0 -48
- package/dist/generators/auth/prisma-password-transformer/prisma-password-transformer.generator.js.map +0 -1
- package/dist/generators/prisma/_shared/crud-method/data-method.d.ts +0 -31
- package/dist/generators/prisma/_shared/crud-method/data-method.d.ts.map +0 -1
- package/dist/generators/prisma/_shared/crud-method/data-method.js +0 -195
- package/dist/generators/prisma/_shared/crud-method/data-method.js.map +0 -1
- package/dist/generators/prisma/embedded-relation-transformer/embedded-relation-transformer.generator.d.ts +0 -50
- package/dist/generators/prisma/embedded-relation-transformer/embedded-relation-transformer.generator.d.ts.map +0 -1
- package/dist/generators/prisma/embedded-relation-transformer/embedded-relation-transformer.generator.js +0 -371
- package/dist/generators/prisma/embedded-relation-transformer/embedded-relation-transformer.generator.js.map +0 -1
- package/dist/generators/prisma/embedded-relation-transformer/index.d.ts +0 -2
- package/dist/generators/prisma/embedded-relation-transformer/index.d.ts.map +0 -1
- package/dist/generators/prisma/embedded-relation-transformer/index.js +0 -2
- package/dist/generators/prisma/embedded-relation-transformer/index.js.map +0 -1
- package/dist/generators/prisma/prisma-crud-create/index.d.ts +0 -2
- package/dist/generators/prisma/prisma-crud-create/index.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-crud-create/index.js +0 -2
- package/dist/generators/prisma/prisma-crud-create/index.js.map +0 -1
- package/dist/generators/prisma/prisma-crud-create/prisma-crud-create.generator.d.ts +0 -48
- package/dist/generators/prisma/prisma-crud-create/prisma-crud-create.generator.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-crud-create/prisma-crud-create.generator.js +0 -130
- package/dist/generators/prisma/prisma-crud-create/prisma-crud-create.generator.js.map +0 -1
- package/dist/generators/prisma/prisma-crud-delete/index.d.ts +0 -2
- package/dist/generators/prisma/prisma-crud-delete/index.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-crud-delete/index.js +0 -2
- package/dist/generators/prisma/prisma-crud-delete/index.js.map +0 -1
- package/dist/generators/prisma/prisma-crud-delete/prisma-crud-delete.generator.d.ts +0 -38
- package/dist/generators/prisma/prisma-crud-delete/prisma-crud-delete.generator.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-crud-delete/prisma-crud-delete.generator.js +0 -94
- package/dist/generators/prisma/prisma-crud-delete/prisma-crud-delete.generator.js.map +0 -1
- package/dist/generators/prisma/prisma-crud-service/index.d.ts +0 -2
- package/dist/generators/prisma/prisma-crud-service/index.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-crud-service/index.js +0 -2
- package/dist/generators/prisma/prisma-crud-service/index.js.map +0 -1
- package/dist/generators/prisma/prisma-crud-service/prisma-crud-service.generator.d.ts +0 -20
- package/dist/generators/prisma/prisma-crud-service/prisma-crud-service.generator.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-crud-service/prisma-crud-service.generator.js +0 -53
- package/dist/generators/prisma/prisma-crud-service/prisma-crud-service.generator.js.map +0 -1
- package/dist/generators/prisma/prisma-crud-update/index.d.ts +0 -2
- package/dist/generators/prisma/prisma-crud-update/index.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-crud-update/index.js +0 -2
- package/dist/generators/prisma/prisma-crud-update/index.js.map +0 -1
- package/dist/generators/prisma/prisma-crud-update/prisma-crud-update.generator.d.ts +0 -48
- package/dist/generators/prisma/prisma-crud-update/prisma-crud-update.generator.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-crud-update/prisma-crud-update.generator.js +0 -145
- package/dist/generators/prisma/prisma-crud-update/prisma-crud-update.generator.js.map +0 -1
- package/dist/generators/prisma/prisma-utils/generated/index.d.ts +0 -134
- package/dist/generators/prisma/prisma-utils/generated/index.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-utils/generated/index.js +0 -11
- package/dist/generators/prisma/prisma-utils/generated/index.js.map +0 -1
- package/dist/generators/prisma/prisma-utils/generated/template-paths.d.ts +0 -17
- package/dist/generators/prisma/prisma-utils/generated/template-paths.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-utils/generated/template-paths.js +0 -27
- package/dist/generators/prisma/prisma-utils/generated/template-paths.js.map +0 -1
- package/dist/generators/prisma/prisma-utils/generated/template-renderers.d.ts +0 -37
- package/dist/generators/prisma/prisma-utils/generated/template-renderers.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-utils/generated/template-renderers.js +0 -43
- package/dist/generators/prisma/prisma-utils/generated/template-renderers.js.map +0 -1
- package/dist/generators/prisma/prisma-utils/generated/ts-import-providers.d.ts +0 -88
- package/dist/generators/prisma/prisma-utils/generated/ts-import-providers.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-utils/generated/ts-import-providers.js +0 -54
- package/dist/generators/prisma/prisma-utils/generated/ts-import-providers.js.map +0 -1
- package/dist/generators/prisma/prisma-utils/generated/typed-templates.d.ts +0 -125
- package/dist/generators/prisma/prisma-utils/generated/typed-templates.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-utils/generated/typed-templates.js +0 -104
- package/dist/generators/prisma/prisma-utils/generated/typed-templates.js.map +0 -1
- package/dist/generators/prisma/prisma-utils/index.d.ts +0 -4
- package/dist/generators/prisma/prisma-utils/index.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-utils/index.js +0 -3
- package/dist/generators/prisma/prisma-utils/index.js.map +0 -1
- package/dist/generators/prisma/prisma-utils/prisma-utils.generator.d.ts +0 -61
- package/dist/generators/prisma/prisma-utils/prisma-utils.generator.d.ts.map +0 -1
- package/dist/generators/prisma/prisma-utils/prisma-utils.generator.js +0 -43
- package/dist/generators/prisma/prisma-utils/prisma-utils.generator.js.map +0 -1
- package/dist/generators/prisma/prisma-utils/templates/src/utils/crud-service-types.ts +0 -35
- package/dist/generators/prisma/prisma-utils/templates/src/utils/data-pipes.ts +0 -86
- package/dist/generators/prisma/prisma-utils/templates/src/utils/embedded-pipes/embedded-one-to-many.ts +0 -245
- package/dist/generators/prisma/prisma-utils/templates/src/utils/embedded-pipes/embedded-one-to-one.ts +0 -147
- package/dist/generators/prisma/prisma-utils/templates/src/utils/embedded-pipes/embedded-types.ts +0 -6
- package/dist/generators/prisma/prisma-utils/templates/src/utils/prisma-relations.ts +0 -24
- package/dist/providers/prisma/prisma-data-transformable.d.ts +0 -27
- package/dist/providers/prisma/prisma-data-transformable.d.ts.map +0 -1
- package/dist/providers/prisma/prisma-data-transformable.js +0 -2
- package/dist/providers/prisma/prisma-data-transformable.js.map +0 -1
package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/define-operations.ts
ADDED
|
@@ -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
|
+
}
|