@baseplate-dev/fastify-generators 0.6.3 → 0.6.5
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/CHANGELOG.md +30 -0
- package/dist/constants/fastify-packages.d.ts +3 -3
- package/dist/constants/fastify-packages.js +3 -3
- package/dist/generators/auth/auth-roles/auth-roles.generator.d.ts +1 -0
- package/dist/generators/auth/auth-roles/auth-roles.generator.d.ts.map +1 -1
- package/dist/generators/auth/auth-roles/auth-roles.generator.js +5 -1
- package/dist/generators/auth/auth-roles/auth-roles.generator.js.map +1 -1
- package/dist/generators/auth/auth-roles/templates/module/constants/auth-roles.constants.ts +4 -3
- package/dist/generators/pothos/pothos-prisma-enum/pothos-prisma-enum.generator.d.ts +1 -0
- package/dist/generators/pothos/pothos-prisma-enum/pothos-prisma-enum.generator.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-prisma-enum/pothos-prisma-enum.generator.js +11 -2
- package/dist/generators/pothos/pothos-prisma-enum/pothos-prisma-enum.generator.js.map +1 -1
- package/dist/generators/prisma/_shared/build-data-helpers/build-schema-fragments.d.ts +47 -0
- package/dist/generators/prisma/_shared/build-data-helpers/build-schema-fragments.d.ts.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/build-schema-fragments.js +56 -0
- package/dist/generators/prisma/_shared/build-data-helpers/build-schema-fragments.js.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/build-transform-operation-parts.d.ts +71 -0
- package/dist/generators/prisma/_shared/build-data-helpers/build-transform-operation-parts.d.ts.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/build-transform-operation-parts.js +153 -0
- package/dist/generators/prisma/_shared/build-data-helpers/build-transform-operation-parts.js.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorization-statements.d.ts +46 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorization-statements.d.ts.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorization-statements.js +44 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorization-statements.js.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.d.ts +6 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.d.ts.map +1 -1
- package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.js +13 -1
- package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.js.map +1 -1
- package/dist/generators/prisma/_shared/build-data-helpers/generate-where-type.d.ts +24 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-where-type.d.ts.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-where-type.js +49 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-where-type.js.map +1 -0
- package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.d.ts +1 -4
- package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.d.ts.map +1 -1
- package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.js +10 -2
- package/dist/generators/prisma/_shared/field-definition-generators/generate-scalar-input-field.js.map +1 -1
- package/dist/generators/prisma/_shared/field-definition-generators/types.d.ts +47 -1
- package/dist/generators/prisma/_shared/field-definition-generators/types.d.ts.map +1 -1
- package/dist/generators/prisma/data-utils/data-utils.generator.d.ts +17 -74
- package/dist/generators/prisma/data-utils/data-utils.generator.d.ts.map +1 -1
- package/dist/generators/prisma/data-utils/generated/index.d.ts +50 -145
- package/dist/generators/prisma/data-utils/generated/index.d.ts.map +1 -1
- package/dist/generators/prisma/data-utils/generated/template-paths.d.ts +5 -6
- package/dist/generators/prisma/data-utils/generated/template-paths.d.ts.map +1 -1
- package/dist/generators/prisma/data-utils/generated/template-paths.js +5 -6
- package/dist/generators/prisma/data-utils/generated/template-paths.js.map +1 -1
- package/dist/generators/prisma/data-utils/generated/template-renderers.d.ts +0 -21
- package/dist/generators/prisma/data-utils/generated/template-renderers.d.ts.map +1 -1
- package/dist/generators/prisma/data-utils/generated/template-renderers.js +1 -7
- package/dist/generators/prisma/data-utils/generated/template-renderers.js.map +1 -1
- package/dist/generators/prisma/data-utils/generated/ts-import-providers.d.ts +51 -159
- package/dist/generators/prisma/data-utils/generated/ts-import-providers.d.ts.map +1 -1
- package/dist/generators/prisma/data-utils/generated/ts-import-providers.js +32 -64
- package/dist/generators/prisma/data-utils/generated/ts-import-providers.js.map +1 -1
- package/dist/generators/prisma/data-utils/generated/typed-templates.d.ts +66 -142
- package/dist/generators/prisma/data-utils/generated/typed-templates.d.ts.map +1 -1
- package/dist/generators/prisma/data-utils/generated/typed-templates.js +47 -98
- package/dist/generators/prisma/data-utils/generated/typed-templates.js.map +1 -1
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/define-transformer.ts +130 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/execute-transform-plan.ts +108 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/nested-transformers.ts +364 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/prepare-transformers.ts +73 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-types.ts +6 -83
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/transformer-types.ts +118 -0
- package/dist/generators/prisma/prisma-authorizer-utils/generated/index.d.ts +34 -106
- package/dist/generators/prisma/prisma-authorizer-utils/generated/index.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-authorizer-utils/generated/template-renderers.d.ts +17 -53
- package/dist/generators/prisma/prisma-authorizer-utils/generated/template-renderers.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-authorizer-utils/generated/typed-templates.d.ts +34 -106
- package/dist/generators/prisma/prisma-authorizer-utils/generated/typed-templates.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-authorizer-utils/prisma-authorizer-utils.generator.d.ts +17 -53
- package/dist/generators/prisma/prisma-authorizer-utils/prisma-authorizer-utils.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-authorizer-utils/templates/src/utils/authorizers.ts +11 -11
- package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.d.ts +39 -49
- package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.js +82 -45
- package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.js.map +1 -1
- package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.d.ts +39 -52
- package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.js +48 -32
- package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.js.map +1 -1
- package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.d.ts +16 -2
- package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.js +282 -138
- package/dist/generators/prisma/prisma-data-nested-field/nested-field-writer.js.map +1 -1
- package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.d.ts +19 -55
- package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.js +18 -4
- package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.js.map +1 -1
- package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.d.ts +37 -92
- package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.js +86 -29
- package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.js.map +1 -1
- package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.d.ts +40 -52
- package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.js +102 -49
- package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.js.map +1 -1
- package/dist/generators/prisma/prisma-query-filter-utils/generated/index.d.ts +51 -159
- package/dist/generators/prisma/prisma-query-filter-utils/generated/index.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-query-filter-utils/generated/template-renderers.d.ts +17 -53
- package/dist/generators/prisma/prisma-query-filter-utils/generated/template-renderers.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-query-filter-utils/generated/typed-templates.d.ts +68 -212
- package/dist/generators/prisma/prisma-query-filter-utils/generated/typed-templates.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-query-filter-utils/prisma-query-filter-utils.generator.d.ts +17 -53
- package/dist/generators/prisma/prisma-query-filter-utils/prisma-query-filter-utils.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-relation-field/prisma-relation-field.generator.js +1 -1
- package/dist/generators/prisma/prisma-relation-field/prisma-relation-field.generator.js.map +1 -1
- package/dist/writers/prisma-schema/fields.d.ts +5 -1
- package/dist/writers/prisma-schema/fields.d.ts.map +1 -1
- package/dist/writers/prisma-schema/fields.js +8 -2
- package/dist/writers/prisma-schema/fields.js.map +1 -1
- package/package.json +8 -8
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorize-fragment.d.ts +0 -20
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorize-fragment.d.ts.map +0 -1
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorize-fragment.js +0 -28
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorize-fragment.js.map +0 -1
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.d.ts +0 -130
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.d.ts.map +0 -1
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.js +0 -221
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.js.map +0 -1
- package/dist/generators/prisma/_shared/build-data-helpers/index.d.ts +0 -4
- package/dist/generators/prisma/_shared/build-data-helpers/index.d.ts.map +0 -1
- package/dist/generators/prisma/_shared/build-data-helpers/index.js +0 -4
- package/dist/generators/prisma/_shared/build-data-helpers/index.js.map +0 -1
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/commit-operations.ts +0 -366
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/compose-operations.ts +0 -131
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.ts +0 -777
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/field-utils.ts +0 -201
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-utils.ts +0 -90
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts +0 -721
package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.ts
DELETED
|
@@ -1,777 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
CreateInput,
|
|
5
|
-
GetPayload,
|
|
6
|
-
ModelPropName,
|
|
7
|
-
UpdateInput,
|
|
8
|
-
WhereInput,
|
|
9
|
-
WhereUniqueInput,
|
|
10
|
-
} from '$prismaTypes';
|
|
11
|
-
import type {
|
|
12
|
-
AnyFieldDefinition,
|
|
13
|
-
FieldDefinition,
|
|
14
|
-
InferFieldsCreateOutput,
|
|
15
|
-
InferFieldsUpdateOutput,
|
|
16
|
-
InferInput,
|
|
17
|
-
InferInputSchema,
|
|
18
|
-
OperationContext,
|
|
19
|
-
TransactionalOperationContext,
|
|
20
|
-
} from '$types';
|
|
21
|
-
import type { Payload } from '@prisma/client/runtime/client';
|
|
22
|
-
import type { z } from 'zod';
|
|
23
|
-
|
|
24
|
-
import {
|
|
25
|
-
generateCreateSchema,
|
|
26
|
-
invokeHooks,
|
|
27
|
-
transformFields,
|
|
28
|
-
} from '$fieldUtils';
|
|
29
|
-
import { makeGenericPrismaDelegate } from '$prismaUtils';
|
|
30
|
-
import { prisma } from '%prismaImports';
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Create a simple scalar field with validation
|
|
34
|
-
*
|
|
35
|
-
* This helper creates a field definition that validates input using a Zod schema.
|
|
36
|
-
* The validated value is used directly for both create and update operations.
|
|
37
|
-
*
|
|
38
|
-
* @template TSchema - The Zod schema type for validation
|
|
39
|
-
* @param schema - Zod schema for validation
|
|
40
|
-
* @returns Scalar field definition that maps validated input directly to Prisma create/update data
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```typescript
|
|
44
|
-
* const fields = {
|
|
45
|
-
* title: scalarField(z.string()),
|
|
46
|
-
* email: scalarField(z.string().email()),
|
|
47
|
-
* age: scalarField(z.number().int().positive()),
|
|
48
|
-
* };
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
export function scalarField<TSchema extends z.ZodType>(
|
|
52
|
-
schema: TSchema,
|
|
53
|
-
): FieldDefinition<TSchema, z.output<TSchema>, z.output<TSchema>> {
|
|
54
|
-
return {
|
|
55
|
-
schema,
|
|
56
|
-
processInput: (value) => ({
|
|
57
|
-
data: { create: value, update: value },
|
|
58
|
-
}),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* =========================================
|
|
64
|
-
* Nested Field Handlers
|
|
65
|
-
* =========================================
|
|
66
|
-
*/
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Configuration for a parent model in nested field definitions.
|
|
70
|
-
*
|
|
71
|
-
* Used to establish the relationship between a parent and child model
|
|
72
|
-
* in nested one-to-one and one-to-many field handlers.
|
|
73
|
-
*
|
|
74
|
-
* @template TModelName - Prisma model name
|
|
75
|
-
*/
|
|
76
|
-
export interface ParentModelConfig<TModelName extends ModelPropName> {
|
|
77
|
-
/** Prisma model name of the parent */
|
|
78
|
-
model: TModelName;
|
|
79
|
-
/** Function to extract unique identifier from parent model instance */
|
|
80
|
-
getWhereUnique: (
|
|
81
|
-
parentModel: GetPayload<TModelName>,
|
|
82
|
-
) => WhereUniqueInput<TModelName>;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Creates a parent model configuration for use in nested field definitions.
|
|
87
|
-
*
|
|
88
|
-
* @template TModelName - Prisma model name
|
|
89
|
-
* @param model - Prisma model name
|
|
90
|
-
* @param getWhereUnique - Function to extract unique identifier from parent model
|
|
91
|
-
* @returns Parent model configuration object
|
|
92
|
-
*
|
|
93
|
-
* @example
|
|
94
|
-
* ```typescript
|
|
95
|
-
* const parentModel = createParentModelConfig('user', (user) => ({
|
|
96
|
-
* id: user.id,
|
|
97
|
-
* }));
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
|
-
export function createParentModelConfig<TModelName extends ModelPropName>(
|
|
101
|
-
model: TModelName,
|
|
102
|
-
getWhereUnique: (
|
|
103
|
-
parentModel: GetPayload<TModelName>,
|
|
104
|
-
) => WhereUniqueInput<TModelName>,
|
|
105
|
-
): ParentModelConfig<TModelName> {
|
|
106
|
-
return {
|
|
107
|
-
model,
|
|
108
|
-
getWhereUnique,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
type RelationName<TModelName extends ModelPropName> = keyof Payload<
|
|
113
|
-
(typeof prisma)[TModelName]
|
|
114
|
-
>['objects'];
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Configuration for defining a nested one-to-one relationship field.
|
|
118
|
-
*
|
|
119
|
-
* One-to-one fields represent a single related entity that can be created,
|
|
120
|
-
* updated, or deleted along with the parent entity. The field handler manages
|
|
121
|
-
* the lifecycle of the nested entity automatically.
|
|
122
|
-
*
|
|
123
|
-
* @template TParentModelName - Parent model name
|
|
124
|
-
* @template TModelName - Child model name
|
|
125
|
-
* @template TRelationName - Relation field name on the child model
|
|
126
|
-
* @template TFields - Field definitions for the nested entity
|
|
127
|
-
*/
|
|
128
|
-
export interface NestedOneToOneFieldConfig<
|
|
129
|
-
TParentModelName extends ModelPropName,
|
|
130
|
-
TModelName extends ModelPropName,
|
|
131
|
-
TRelationName extends RelationName<TModelName>,
|
|
132
|
-
TFields extends Record<string, AnyFieldDefinition>,
|
|
133
|
-
> {
|
|
134
|
-
/**
|
|
135
|
-
* Prisma model name of parent model
|
|
136
|
-
*/
|
|
137
|
-
parentModel: ParentModelConfig<TParentModelName>;
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Prisma model name of the child model
|
|
141
|
-
*/
|
|
142
|
-
model: TModelName;
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Relation name of the parent model from the child model
|
|
146
|
-
*/
|
|
147
|
-
relationName: TRelationName;
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Field definitions for the nested entity
|
|
151
|
-
*/
|
|
152
|
-
fields: TFields;
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Extract where unique from parent model
|
|
156
|
-
*/
|
|
157
|
-
getWhereUnique: (
|
|
158
|
-
parentModel: GetPayload<TParentModelName>,
|
|
159
|
-
) => WhereUniqueInput<TModelName>;
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Transform validated create field data into final Prisma structure
|
|
163
|
-
*/
|
|
164
|
-
buildCreateData: (
|
|
165
|
-
data: InferFieldsCreateOutput<TFields> &
|
|
166
|
-
Record<TRelationName, { connect: WhereUniqueInput<TParentModelName> }>,
|
|
167
|
-
parentModel: GetPayload<TParentModelName>,
|
|
168
|
-
ctx: TransactionalOperationContext<
|
|
169
|
-
GetPayload<TModelName>,
|
|
170
|
-
{ hasResult: false }
|
|
171
|
-
>,
|
|
172
|
-
) => CreateInput<TModelName> | Promise<CreateInput<TModelName>>;
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Transform validated update field data into final Prisma structure
|
|
176
|
-
*/
|
|
177
|
-
buildUpdateData: (
|
|
178
|
-
data: InferFieldsUpdateOutput<TFields>,
|
|
179
|
-
parentModel: GetPayload<TParentModelName>,
|
|
180
|
-
ctx: TransactionalOperationContext<
|
|
181
|
-
GetPayload<TModelName>,
|
|
182
|
-
{ hasResult: false }
|
|
183
|
-
>,
|
|
184
|
-
) => UpdateInput<TModelName> | Promise<UpdateInput<TModelName>>;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Create a nested one-to-one relationship field handler
|
|
189
|
-
*
|
|
190
|
-
* This helper creates a field definition for managing one-to-one nested relationships.
|
|
191
|
-
* It handles nested field validation, transformation, and supports both create and update operations.
|
|
192
|
-
*
|
|
193
|
-
* The nested entity is created/updated via afterExecute hooks, allowing it to reference
|
|
194
|
-
* the parent entity after it has been created.
|
|
195
|
-
*
|
|
196
|
-
* Behavior:
|
|
197
|
-
* - **Provided value**: Upserts the nested entity (creates if new, updates if exists)
|
|
198
|
-
* - **null**: Deletes the nested entity (update only)
|
|
199
|
-
* - **undefined**: No change to nested entity
|
|
200
|
-
*
|
|
201
|
-
* @param config - Configuration object
|
|
202
|
-
* @returns Field definition
|
|
203
|
-
*
|
|
204
|
-
* @example
|
|
205
|
-
* ```typescript
|
|
206
|
-
* const fields = {
|
|
207
|
-
* userProfile: nestedOneToOneField({
|
|
208
|
-
* parentModel: createParentModelConfig('user', (user) => ({ id: user.id })),
|
|
209
|
-
* model: 'userProfile',
|
|
210
|
-
* relationName: 'user',
|
|
211
|
-
* fields: {
|
|
212
|
-
* bio: scalarField(z.string()),
|
|
213
|
-
* avatar: fileField(avatarFileCategory),
|
|
214
|
-
* },
|
|
215
|
-
* getWhereUnique: (parent) => ({ userId: parent.id }),
|
|
216
|
-
* buildCreateData: (data) => ({
|
|
217
|
-
* bio: data.bio,
|
|
218
|
-
* avatar: data.avatar ? { connect: { id: data.avatar } } : undefined,
|
|
219
|
-
* }),
|
|
220
|
-
* buildUpdateData: (data) => ({
|
|
221
|
-
* bio: data.bio,
|
|
222
|
-
* avatar: data.avatar ? { connect: { id: data.avatar } } : undefined,
|
|
223
|
-
* }),
|
|
224
|
-
* }),
|
|
225
|
-
* };
|
|
226
|
-
* ```
|
|
227
|
-
*/
|
|
228
|
-
export function nestedOneToOneField<
|
|
229
|
-
TParentModelName extends ModelPropName,
|
|
230
|
-
TModelName extends ModelPropName,
|
|
231
|
-
TRelationName extends RelationName<TModelName>,
|
|
232
|
-
TFields extends Record<string, AnyFieldDefinition>,
|
|
233
|
-
>(
|
|
234
|
-
config: NestedOneToOneFieldConfig<
|
|
235
|
-
TParentModelName,
|
|
236
|
-
TModelName,
|
|
237
|
-
TRelationName,
|
|
238
|
-
TFields
|
|
239
|
-
>,
|
|
240
|
-
): FieldDefinition<
|
|
241
|
-
z.ZodOptional<z.ZodNullable<InferInputSchema<TFields>>>,
|
|
242
|
-
undefined,
|
|
243
|
-
undefined
|
|
244
|
-
> {
|
|
245
|
-
return {
|
|
246
|
-
schema: generateCreateSchema(config.fields).nullish(),
|
|
247
|
-
processInput: async (value, processCtx) => {
|
|
248
|
-
// Handle null - delete the relation if it exists
|
|
249
|
-
if (value === null) {
|
|
250
|
-
return {
|
|
251
|
-
data: {
|
|
252
|
-
create: undefined,
|
|
253
|
-
update: undefined,
|
|
254
|
-
},
|
|
255
|
-
hooks: {
|
|
256
|
-
afterExecute: [
|
|
257
|
-
async (ctx) => {
|
|
258
|
-
const whereUnique = config.getWhereUnique(
|
|
259
|
-
ctx.result as GetPayload<TParentModelName>,
|
|
260
|
-
);
|
|
261
|
-
const prismaDelegate = makeGenericPrismaDelegate(
|
|
262
|
-
ctx.tx,
|
|
263
|
-
config.model,
|
|
264
|
-
);
|
|
265
|
-
// Use deleteMany which is idempotent - won't error if no record exists
|
|
266
|
-
await prismaDelegate.deleteMany({
|
|
267
|
-
where: expandWhereUnique(whereUnique),
|
|
268
|
-
});
|
|
269
|
-
},
|
|
270
|
-
],
|
|
271
|
-
},
|
|
272
|
-
};
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// Handle undefined - no change
|
|
276
|
-
if (value === undefined) {
|
|
277
|
-
return { data: { create: undefined, update: undefined } };
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
let cachedExisting: GetPayload<TModelName> | undefined;
|
|
281
|
-
async function loadExisting(): Promise<
|
|
282
|
-
GetPayload<TModelName> | undefined
|
|
283
|
-
> {
|
|
284
|
-
if (cachedExisting) return cachedExisting;
|
|
285
|
-
const existingParent = await processCtx.loadExisting();
|
|
286
|
-
if (!existingParent) return undefined;
|
|
287
|
-
const whereUnique = config.getWhereUnique(
|
|
288
|
-
existingParent as GetPayload<TParentModelName>,
|
|
289
|
-
);
|
|
290
|
-
const prismaDelegate = makeGenericPrismaDelegate(prisma, config.model);
|
|
291
|
-
cachedExisting =
|
|
292
|
-
((await prismaDelegate.findUnique({
|
|
293
|
-
where: whereUnique,
|
|
294
|
-
})) as GetPayload<TModelName> | null) ?? undefined;
|
|
295
|
-
return cachedExisting;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// Process nested fields
|
|
299
|
-
const { data, hooks } = await transformFields(config.fields, value, {
|
|
300
|
-
serviceContext: processCtx.serviceContext,
|
|
301
|
-
operation: 'upsert',
|
|
302
|
-
allowOptionalFields: false,
|
|
303
|
-
loadExisting: loadExisting as () => Promise<object | undefined>,
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
let newModelResult: GetPayload<TModelName> | undefined;
|
|
307
|
-
|
|
308
|
-
return {
|
|
309
|
-
data: {},
|
|
310
|
-
hooks: {
|
|
311
|
-
beforeExecute: [
|
|
312
|
-
(ctx) => invokeHooks(hooks.beforeExecute, { ...ctx, loadExisting }),
|
|
313
|
-
],
|
|
314
|
-
afterExecute: [
|
|
315
|
-
async (ctx) => {
|
|
316
|
-
const whereUnique = config.getWhereUnique(
|
|
317
|
-
ctx.result as GetPayload<TParentModelName>,
|
|
318
|
-
);
|
|
319
|
-
const parentWhereUnique = config.parentModel.getWhereUnique(
|
|
320
|
-
ctx.result as GetPayload<TParentModelName>,
|
|
321
|
-
);
|
|
322
|
-
const sharedCtx = {
|
|
323
|
-
...ctx,
|
|
324
|
-
operation: 'upsert' as const,
|
|
325
|
-
loadExisting,
|
|
326
|
-
};
|
|
327
|
-
const [builtCreate, builtUpdate] = await Promise.all([
|
|
328
|
-
config.buildCreateData(
|
|
329
|
-
{
|
|
330
|
-
...data.create,
|
|
331
|
-
...({
|
|
332
|
-
[config.relationName]: { connect: parentWhereUnique },
|
|
333
|
-
} as Record<
|
|
334
|
-
TRelationName,
|
|
335
|
-
{ connect: WhereUniqueInput<TParentModelName> }
|
|
336
|
-
>),
|
|
337
|
-
},
|
|
338
|
-
ctx.result as GetPayload<TParentModelName>,
|
|
339
|
-
sharedCtx,
|
|
340
|
-
),
|
|
341
|
-
config.buildUpdateData(
|
|
342
|
-
data.update,
|
|
343
|
-
ctx.result as GetPayload<TParentModelName>,
|
|
344
|
-
sharedCtx,
|
|
345
|
-
),
|
|
346
|
-
]);
|
|
347
|
-
const prismaDelegate = makeGenericPrismaDelegate(
|
|
348
|
-
ctx.tx,
|
|
349
|
-
config.model,
|
|
350
|
-
);
|
|
351
|
-
|
|
352
|
-
newModelResult = await prismaDelegate.upsert({
|
|
353
|
-
where: whereUnique,
|
|
354
|
-
create: builtCreate,
|
|
355
|
-
update: builtUpdate,
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
await invokeHooks(hooks.afterExecute, {
|
|
359
|
-
...ctx,
|
|
360
|
-
loadExisting,
|
|
361
|
-
result: newModelResult,
|
|
362
|
-
});
|
|
363
|
-
},
|
|
364
|
-
],
|
|
365
|
-
afterCommit: [
|
|
366
|
-
async (ctx) => {
|
|
367
|
-
await invokeHooks(hooks.afterCommit, {
|
|
368
|
-
...ctx,
|
|
369
|
-
loadExisting,
|
|
370
|
-
result: newModelResult,
|
|
371
|
-
});
|
|
372
|
-
},
|
|
373
|
-
],
|
|
374
|
-
},
|
|
375
|
-
};
|
|
376
|
-
},
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Configuration for defining a nested one-to-many relationship field.
|
|
382
|
-
*
|
|
383
|
-
* One-to-many fields represent a collection of related entities that are synchronized
|
|
384
|
-
* with the input array. The handler automatically:
|
|
385
|
-
* - Creates new items without unique identifiers
|
|
386
|
-
* - Updates existing items with unique identifiers
|
|
387
|
-
* - Deletes items not present in the input array
|
|
388
|
-
*
|
|
389
|
-
* @template TParentModelName - Parent model name
|
|
390
|
-
* @template TModelName - Child model name
|
|
391
|
-
* @template TRelationName - Relation field name on the child model
|
|
392
|
-
* @template TFields - Field definitions for each item in the collection
|
|
393
|
-
*/
|
|
394
|
-
export interface NestedOneToManyFieldConfig<
|
|
395
|
-
TParentModelName extends ModelPropName,
|
|
396
|
-
TModelName extends ModelPropName,
|
|
397
|
-
TRelationName extends RelationName<TModelName>,
|
|
398
|
-
TFields extends Record<string, AnyFieldDefinition>,
|
|
399
|
-
> {
|
|
400
|
-
/**
|
|
401
|
-
* Prisma model name of parent model
|
|
402
|
-
*/
|
|
403
|
-
parentModel: ParentModelConfig<TParentModelName>;
|
|
404
|
-
|
|
405
|
-
/**
|
|
406
|
-
* Prisma model name of the child model
|
|
407
|
-
*/
|
|
408
|
-
model: TModelName;
|
|
409
|
-
|
|
410
|
-
/**
|
|
411
|
-
* Relation name of the parent model from the child model
|
|
412
|
-
*/
|
|
413
|
-
relationName: TRelationName;
|
|
414
|
-
|
|
415
|
-
/**
|
|
416
|
-
* Field definitions for the nested entity
|
|
417
|
-
*/
|
|
418
|
-
fields: TFields;
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* Function to extract a unique where clause from the input data for a child item and
|
|
422
|
-
* the parent model.
|
|
423
|
-
* If it returns undefined, the item is considered a new item to be created.
|
|
424
|
-
*/
|
|
425
|
-
getWhereUnique: (
|
|
426
|
-
input: InferInput<TFields>,
|
|
427
|
-
originalModel: GetPayload<TParentModelName>,
|
|
428
|
-
) => WhereUniqueInput<TModelName> | undefined;
|
|
429
|
-
|
|
430
|
-
/**
|
|
431
|
-
* Transform validated create field data into final Prisma structure for a single item.
|
|
432
|
-
* The parent relation connect is included in the data parameter. You can pass it
|
|
433
|
-
* through directly (e.g., `(data) => data`) or restructure as needed.
|
|
434
|
-
*/
|
|
435
|
-
buildCreateData: (
|
|
436
|
-
data: InferFieldsCreateOutput<TFields> &
|
|
437
|
-
Record<TRelationName, { connect: WhereUniqueInput<TParentModelName> }>,
|
|
438
|
-
parentModel: GetPayload<TParentModelName>,
|
|
439
|
-
ctx: TransactionalOperationContext<
|
|
440
|
-
GetPayload<TModelName> | undefined,
|
|
441
|
-
{ hasResult: false }
|
|
442
|
-
>,
|
|
443
|
-
) => CreateInput<TModelName> | Promise<CreateInput<TModelName>>;
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
* Transform validated update field data into final Prisma structure for a single item.
|
|
447
|
-
*/
|
|
448
|
-
buildUpdateData: (
|
|
449
|
-
data: InferFieldsUpdateOutput<TFields>,
|
|
450
|
-
parentModel: GetPayload<TParentModelName>,
|
|
451
|
-
ctx: TransactionalOperationContext<
|
|
452
|
-
GetPayload<TModelName> | undefined,
|
|
453
|
-
{ hasResult: false }
|
|
454
|
-
>,
|
|
455
|
-
) => UpdateInput<TModelName> | Promise<UpdateInput<TModelName>>;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
/**
|
|
459
|
-
* Converts a Prisma `WhereUniqueInput` into a plain `WhereInput`.
|
|
460
|
-
*
|
|
461
|
-
* Compound unique constraints arrive as synthetic keys (e.g., `userId_role: { userId, role }`),
|
|
462
|
-
* while generic `where` filters need the flattened field structure. This normalization allows
|
|
463
|
-
* composing unique constraints with parent-level filters when constructing delete conditions
|
|
464
|
-
* in one-to-many relationships.
|
|
465
|
-
*
|
|
466
|
-
* @template TModelName - Prisma model name
|
|
467
|
-
* @param whereUnique - Unique filter returned by `getWhereUnique`, or undefined for new items
|
|
468
|
-
* @returns Normalized where filter or undefined if no usable fields exist
|
|
469
|
-
*
|
|
470
|
-
* @internal This function is used internally by nestedOneToManyField
|
|
471
|
-
*/
|
|
472
|
-
function expandWhereUnique<TModelName extends ModelPropName>(
|
|
473
|
-
whereUnique: WhereUniqueInput<TModelName> | undefined,
|
|
474
|
-
): WhereInput<TModelName> | undefined {
|
|
475
|
-
if (!whereUnique) return undefined;
|
|
476
|
-
|
|
477
|
-
const entries = Object.entries(whereUnique as Record<string, unknown>).filter(
|
|
478
|
-
([, value]) => value !== undefined && value !== null,
|
|
479
|
-
);
|
|
480
|
-
|
|
481
|
-
if (entries.length === 0) return undefined;
|
|
482
|
-
|
|
483
|
-
const [[key, value]] = entries;
|
|
484
|
-
|
|
485
|
-
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
486
|
-
return value as WhereInput<TModelName>;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
return { [key]: value as unknown } as WhereInput<TModelName>;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
/**
|
|
493
|
-
* Creates a nested one-to-many relationship field handler.
|
|
494
|
-
*
|
|
495
|
-
* This helper manages collections of child entities by synchronizing them with the input array.
|
|
496
|
-
* The synchronization logic:
|
|
497
|
-
* - **Update**: Items with unique identifiers (from `getWhereUnique`) are updated
|
|
498
|
-
* - **Create**: Items without unique identifiers are created as new records
|
|
499
|
-
* - **Delete**: Existing items not present in the input array are removed
|
|
500
|
-
* - **No Change**: Passing `undefined` leaves the collection unchanged
|
|
501
|
-
*
|
|
502
|
-
* **Important:** When a value is provided (not `undefined`), the input array is treated
|
|
503
|
-
* as the complete collection. Existing items not present in the array will be deleted.
|
|
504
|
-
*
|
|
505
|
-
* All operations are performed atomically within the parent operation's transaction,
|
|
506
|
-
* ensuring data consistency even if the operation fails.
|
|
507
|
-
*
|
|
508
|
-
* @template TParentModelName - Parent model name
|
|
509
|
-
* @template TModelName - Child model name
|
|
510
|
-
* @template TRelationName - Relation field name on child model
|
|
511
|
-
* @template TFields - Field definitions for each child item
|
|
512
|
-
* @param config - Configuration object for the one-to-many relationship
|
|
513
|
-
* @returns Field definition for use with `composeCreate`/`composeUpdate` and `commitCreate`/`commitUpdate`
|
|
514
|
-
*
|
|
515
|
-
* @example
|
|
516
|
-
* ```typescript
|
|
517
|
-
* const fields = {
|
|
518
|
-
* images: nestedOneToManyField({
|
|
519
|
-
* parentModel: createParentModelConfig('user', (user) => ({ id: user.id })),
|
|
520
|
-
* model: 'userImage',
|
|
521
|
-
* relationName: 'user',
|
|
522
|
-
* fields: {
|
|
523
|
-
* id: scalarField(z.string()),
|
|
524
|
-
* caption: scalarField(z.string()),
|
|
525
|
-
* },
|
|
526
|
-
* getWhereUnique: (input) => input.id ? { id: input.id } : undefined,
|
|
527
|
-
* buildCreateData: (data) => ({ caption: data.caption }),
|
|
528
|
-
* buildUpdateData: (data) => ({ caption: data.caption }),
|
|
529
|
-
* }),
|
|
530
|
-
* };
|
|
531
|
-
*
|
|
532
|
-
* // Create user with images
|
|
533
|
-
* await createUser({
|
|
534
|
-
* data: {
|
|
535
|
-
* name: 'John',
|
|
536
|
-
* images: [
|
|
537
|
-
* { caption: 'First image' },
|
|
538
|
-
* { caption: 'Second image' },
|
|
539
|
-
* ],
|
|
540
|
-
* },
|
|
541
|
-
* context: ctx,
|
|
542
|
-
* });
|
|
543
|
-
*
|
|
544
|
-
* // Update user images (creates new, updates existing, deletes removed)
|
|
545
|
-
* await updateUser({
|
|
546
|
-
* where: { id: userId },
|
|
547
|
-
* data: {
|
|
548
|
-
* images: [
|
|
549
|
-
* { id: 'img-1', caption: 'Updated caption' }, // Updates existing
|
|
550
|
-
* { caption: 'New image' }, // Creates new
|
|
551
|
-
* // img-2 not in array, will be deleted
|
|
552
|
-
* ],
|
|
553
|
-
* },
|
|
554
|
-
* context: ctx,
|
|
555
|
-
* });
|
|
556
|
-
* ```
|
|
557
|
-
*/
|
|
558
|
-
export function nestedOneToManyField<
|
|
559
|
-
TParentModelName extends ModelPropName,
|
|
560
|
-
TModelName extends ModelPropName,
|
|
561
|
-
TRelationName extends RelationName<TModelName>,
|
|
562
|
-
TFields extends Record<string, AnyFieldDefinition>,
|
|
563
|
-
>(
|
|
564
|
-
config: NestedOneToManyFieldConfig<
|
|
565
|
-
TParentModelName,
|
|
566
|
-
TModelName,
|
|
567
|
-
TRelationName,
|
|
568
|
-
TFields
|
|
569
|
-
>,
|
|
570
|
-
): FieldDefinition<
|
|
571
|
-
z.ZodOptional<z.ZodArray<InferInputSchema<TFields>>>,
|
|
572
|
-
undefined,
|
|
573
|
-
undefined | { deleteMany: Record<never, never> }
|
|
574
|
-
> {
|
|
575
|
-
const getWhereUnique = (
|
|
576
|
-
input: InferInput<TFields>,
|
|
577
|
-
originalModel: GetPayload<TParentModelName>,
|
|
578
|
-
): WhereUniqueInput<TModelName> | undefined => {
|
|
579
|
-
const whereUnique = config.getWhereUnique(input, originalModel);
|
|
580
|
-
if (whereUnique && Object.values(whereUnique).includes(undefined)) {
|
|
581
|
-
throw new Error(
|
|
582
|
-
'getWhereUnique cannot return any undefined values in the object',
|
|
583
|
-
);
|
|
584
|
-
}
|
|
585
|
-
return whereUnique;
|
|
586
|
-
};
|
|
587
|
-
|
|
588
|
-
return {
|
|
589
|
-
schema: generateCreateSchema(config.fields).array().optional(),
|
|
590
|
-
processInput: async (value, processCtx) => {
|
|
591
|
-
const { serviceContext, loadExisting } = processCtx;
|
|
592
|
-
|
|
593
|
-
if (value === undefined) {
|
|
594
|
-
return { data: { create: undefined, update: undefined } };
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
const existingModel = (await loadExisting()) as
|
|
598
|
-
| GetPayload<TParentModelName>
|
|
599
|
-
| undefined;
|
|
600
|
-
|
|
601
|
-
// Filter objects that relate to parent model only
|
|
602
|
-
const whereFromOriginalModel = existingModel && {
|
|
603
|
-
[config.relationName]: expandWhereUnique(
|
|
604
|
-
config.parentModel.getWhereUnique(existingModel),
|
|
605
|
-
),
|
|
606
|
-
};
|
|
607
|
-
// Handle list of items
|
|
608
|
-
const delegate = makeGenericPrismaDelegate(prisma, config.model);
|
|
609
|
-
|
|
610
|
-
const cachedLoadExisting = value.map((itemInput) => {
|
|
611
|
-
let cachedExisting: GetPayload<TModelName> | undefined;
|
|
612
|
-
const whereUnique =
|
|
613
|
-
existingModel && getWhereUnique(itemInput, existingModel);
|
|
614
|
-
|
|
615
|
-
return async (): Promise<GetPayload<TModelName> | undefined> => {
|
|
616
|
-
if (cachedExisting) return cachedExisting;
|
|
617
|
-
if (!whereUnique) return undefined;
|
|
618
|
-
cachedExisting =
|
|
619
|
-
((await delegate.findUnique({
|
|
620
|
-
where: { ...whereUnique, ...whereFromOriginalModel },
|
|
621
|
-
})) as GetPayload<TModelName> | null) ?? undefined;
|
|
622
|
-
return cachedExisting;
|
|
623
|
-
};
|
|
624
|
-
});
|
|
625
|
-
|
|
626
|
-
const processedItems = await Promise.all(
|
|
627
|
-
value.map(async (itemInput, idx) => {
|
|
628
|
-
const whereUnique =
|
|
629
|
-
existingModel && getWhereUnique(itemInput, existingModel);
|
|
630
|
-
|
|
631
|
-
const { data, hooks } = await transformFields(
|
|
632
|
-
config.fields,
|
|
633
|
-
itemInput,
|
|
634
|
-
{
|
|
635
|
-
serviceContext,
|
|
636
|
-
operation: 'upsert',
|
|
637
|
-
allowOptionalFields: false,
|
|
638
|
-
loadExisting: cachedLoadExisting[idx] as () => Promise<
|
|
639
|
-
object | undefined
|
|
640
|
-
>,
|
|
641
|
-
},
|
|
642
|
-
);
|
|
643
|
-
|
|
644
|
-
return { whereUnique, data, hooks };
|
|
645
|
-
}),
|
|
646
|
-
);
|
|
647
|
-
|
|
648
|
-
const beforeExecuteHook = async (
|
|
649
|
-
ctx: TransactionalOperationContext<
|
|
650
|
-
GetPayload<TParentModelName>,
|
|
651
|
-
{ hasResult: false }
|
|
652
|
-
>,
|
|
653
|
-
): Promise<void> => {
|
|
654
|
-
await Promise.all(
|
|
655
|
-
processedItems.map((item, idx) =>
|
|
656
|
-
invokeHooks(item.hooks.beforeExecute, {
|
|
657
|
-
...ctx,
|
|
658
|
-
loadExisting: cachedLoadExisting[idx],
|
|
659
|
-
}),
|
|
660
|
-
),
|
|
661
|
-
);
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
const results: (GetPayload<TModelName> | undefined)[] = Array.from(
|
|
665
|
-
{ length: value.length },
|
|
666
|
-
() => undefined,
|
|
667
|
-
);
|
|
668
|
-
const afterExecuteHook = async (
|
|
669
|
-
ctx: TransactionalOperationContext<
|
|
670
|
-
GetPayload<TParentModelName>,
|
|
671
|
-
{ hasResult: true }
|
|
672
|
-
>,
|
|
673
|
-
): Promise<void> => {
|
|
674
|
-
const prismaDelegate = makeGenericPrismaDelegate(ctx.tx, config.model);
|
|
675
|
-
|
|
676
|
-
// Delete items not in the input
|
|
677
|
-
if (whereFromOriginalModel) {
|
|
678
|
-
const keepFilters = processedItems
|
|
679
|
-
.map((item) => expandWhereUnique(item.whereUnique))
|
|
680
|
-
.filter(
|
|
681
|
-
(where): where is WhereInput<TModelName> => where !== undefined,
|
|
682
|
-
)
|
|
683
|
-
.map((where) => ({ NOT: where }));
|
|
684
|
-
|
|
685
|
-
const deleteWhere =
|
|
686
|
-
keepFilters.length === 0
|
|
687
|
-
? whereFromOriginalModel
|
|
688
|
-
: ({
|
|
689
|
-
AND: [whereFromOriginalModel, ...keepFilters],
|
|
690
|
-
} as WhereInput<TModelName>);
|
|
691
|
-
|
|
692
|
-
await prismaDelegate.deleteMany({ where: deleteWhere });
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
// Upsert items
|
|
696
|
-
await Promise.all(
|
|
697
|
-
processedItems.map(async (item, idx) => {
|
|
698
|
-
const parentWhereUnique = config.parentModel.getWhereUnique(
|
|
699
|
-
ctx.result,
|
|
700
|
-
);
|
|
701
|
-
|
|
702
|
-
const sharedCtx: TransactionalOperationContext<
|
|
703
|
-
GetPayload<TModelName> | undefined,
|
|
704
|
-
{ hasResult: false }
|
|
705
|
-
> = {
|
|
706
|
-
...ctx,
|
|
707
|
-
operation: item.whereUnique ? 'update' : 'create',
|
|
708
|
-
loadExisting: cachedLoadExisting[idx],
|
|
709
|
-
result: undefined,
|
|
710
|
-
};
|
|
711
|
-
const [builtCreate, builtUpdate] = await Promise.all([
|
|
712
|
-
config.buildCreateData(
|
|
713
|
-
{
|
|
714
|
-
...item.data.create,
|
|
715
|
-
...({
|
|
716
|
-
[config.relationName]: { connect: parentWhereUnique },
|
|
717
|
-
} as Record<
|
|
718
|
-
TRelationName,
|
|
719
|
-
{ connect: WhereUniqueInput<TParentModelName> }
|
|
720
|
-
>),
|
|
721
|
-
},
|
|
722
|
-
ctx.result,
|
|
723
|
-
sharedCtx,
|
|
724
|
-
),
|
|
725
|
-
config.buildUpdateData(item.data.update, ctx.result, sharedCtx),
|
|
726
|
-
]);
|
|
727
|
-
|
|
728
|
-
results[idx] = item.whereUnique
|
|
729
|
-
? await prismaDelegate.upsert({
|
|
730
|
-
where: {
|
|
731
|
-
...item.whereUnique,
|
|
732
|
-
...whereFromOriginalModel,
|
|
733
|
-
} as WhereUniqueInput<TModelName>,
|
|
734
|
-
create: builtCreate,
|
|
735
|
-
update: builtUpdate,
|
|
736
|
-
})
|
|
737
|
-
: await prismaDelegate.create({
|
|
738
|
-
data: builtCreate,
|
|
739
|
-
});
|
|
740
|
-
|
|
741
|
-
await invokeHooks(item.hooks.afterExecute, {
|
|
742
|
-
...ctx,
|
|
743
|
-
result: results[idx],
|
|
744
|
-
loadExisting: cachedLoadExisting[idx],
|
|
745
|
-
});
|
|
746
|
-
}),
|
|
747
|
-
);
|
|
748
|
-
};
|
|
749
|
-
|
|
750
|
-
const afterCommitHook = async (
|
|
751
|
-
ctx: OperationContext<
|
|
752
|
-
GetPayload<TParentModelName>,
|
|
753
|
-
{ hasResult: true }
|
|
754
|
-
>,
|
|
755
|
-
): Promise<void> => {
|
|
756
|
-
await Promise.all(
|
|
757
|
-
processedItems.map((item, idx) =>
|
|
758
|
-
invokeHooks(item.hooks.afterCommit, {
|
|
759
|
-
...ctx,
|
|
760
|
-
result: results[idx],
|
|
761
|
-
loadExisting: cachedLoadExisting[idx],
|
|
762
|
-
}),
|
|
763
|
-
),
|
|
764
|
-
);
|
|
765
|
-
};
|
|
766
|
-
|
|
767
|
-
return {
|
|
768
|
-
data: {},
|
|
769
|
-
hooks: {
|
|
770
|
-
beforeExecute: [beforeExecuteHook],
|
|
771
|
-
afterExecute: [afterExecuteHook],
|
|
772
|
-
afterCommit: [afterCommitHook],
|
|
773
|
-
},
|
|
774
|
-
};
|
|
775
|
-
},
|
|
776
|
-
};
|
|
777
|
-
}
|