@baseplate-dev/fastify-generators 0.5.3 → 0.6.1
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 +70 -0
- package/dist/constants/fastify-packages.d.ts +14 -14
- package/dist/constants/fastify-packages.js +14 -14
- package/dist/constants/fastify-packages.js.map +1 -1
- package/dist/generators/auth/auth-context/templates/module/types/auth-context.types.ts +1 -0
- package/dist/generators/auth/auth-context/templates/module/utils/auth-context.utils.ts +3 -1
- package/dist/generators/core/fastify/fastify.generator.d.ts.map +1 -1
- package/dist/generators/core/fastify/fastify.generator.js +3 -1
- package/dist/generators/core/fastify/fastify.generator.js.map +1 -1
- package/dist/generators/pothos/index.d.ts +1 -0
- package/dist/generators/pothos/index.d.ts.map +1 -1
- package/dist/generators/pothos/index.js +1 -0
- package/dist/generators/pothos/index.js.map +1 -1
- package/dist/generators/pothos/pothos-auth/pothos-auth.generator.d.ts +5 -0
- package/dist/generators/pothos/pothos-auth/pothos-auth.generator.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-auth/pothos-auth.generator.js +8 -0
- package/dist/generators/pothos/pothos-auth/pothos-auth.generator.js.map +1 -1
- package/dist/generators/pothos/pothos-prisma-count-query/index.d.ts +2 -0
- package/dist/generators/pothos/pothos-prisma-count-query/index.d.ts.map +1 -0
- package/dist/generators/pothos/pothos-prisma-count-query/index.js +2 -0
- package/dist/generators/pothos/pothos-prisma-count-query/index.js.map +1 -0
- package/dist/generators/pothos/pothos-prisma-count-query/pothos-prisma-count-query.generator.d.ts +16 -0
- package/dist/generators/pothos/pothos-prisma-count-query/pothos-prisma-count-query.generator.d.ts.map +1 -0
- package/dist/generators/pothos/pothos-prisma-count-query/pothos-prisma-count-query.generator.js +104 -0
- package/dist/generators/pothos/pothos-prisma-count-query/pothos-prisma-count-query.generator.js.map +1 -0
- 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 +2 -5
- package/dist/generators/pothos/pothos-prisma-crud-mutation/pothos-prisma-crud-mutation.generator.js.map +1 -1
- package/dist/generators/pothos/pothos-prisma-find-query/pothos-prisma-find-query.generator.d.ts +4 -0
- package/dist/generators/pothos/pothos-prisma-find-query/pothos-prisma-find-query.generator.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-prisma-find-query/pothos-prisma-find-query.generator.js +52 -10
- package/dist/generators/pothos/pothos-prisma-find-query/pothos-prisma-find-query.generator.js.map +1 -1
- package/dist/generators/pothos/pothos-prisma-list-query/pothos-prisma-list-query.generator.d.ts +4 -0
- package/dist/generators/pothos/pothos-prisma-list-query/pothos-prisma-list-query.generator.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-prisma-list-query/pothos-prisma-list-query.generator.js +39 -3
- package/dist/generators/pothos/pothos-prisma-list-query/pothos-prisma-list-query.generator.js.map +1 -1
- package/dist/generators/pothos/pothos-prisma-object/pothos-prisma-object.generator.d.ts +7 -1
- package/dist/generators/pothos/pothos-prisma-object/pothos-prisma-object.generator.d.ts.map +1 -1
- package/dist/generators/pothos/pothos-prisma-object/pothos-prisma-object.generator.js +73 -13
- package/dist/generators/pothos/pothos-prisma-object/pothos-prisma-object.generator.js.map +1 -1
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorize-fragment.d.ts +20 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorize-fragment.d.ts.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorize-fragment.js +28 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-authorize-fragment.js.map +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.d.ts +48 -55
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.d.ts.map +1 -1
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.js +130 -67
- package/dist/generators/prisma/_shared/build-data-helpers/generate-operation-callbacks.js.map +1 -1
- package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.d.ts +2 -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 +3 -3
- package/dist/generators/prisma/_shared/build-data-helpers/generate-relation-build-data.js.map +1 -1
- package/dist/generators/prisma/_shared/build-data-helpers/index.d.ts +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/index.d.ts.map +1 -1
- package/dist/generators/prisma/_shared/build-data-helpers/index.js +1 -0
- package/dist/generators/prisma/_shared/build-data-helpers/index.js.map +1 -1
- package/dist/generators/prisma/data-utils/data-utils.generator.d.ts +25 -6
- package/dist/generators/prisma/data-utils/data-utils.generator.d.ts.map +1 -1
- package/dist/generators/prisma/data-utils/generated/index.d.ts +78 -23
- package/dist/generators/prisma/data-utils/generated/index.d.ts.map +1 -1
- package/dist/generators/prisma/data-utils/generated/template-paths.d.ts +3 -1
- package/dist/generators/prisma/data-utils/generated/template-paths.d.ts.map +1 -1
- package/dist/generators/prisma/data-utils/generated/template-paths.js +3 -1
- package/dist/generators/prisma/data-utils/generated/template-paths.js.map +1 -1
- package/dist/generators/prisma/data-utils/generated/ts-import-providers.d.ts +75 -18
- 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 +26 -8
- 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 +106 -34
- package/dist/generators/prisma/data-utils/generated/typed-templates.d.ts.map +1 -1
- package/dist/generators/prisma/data-utils/generated/typed-templates.js +61 -14
- package/dist/generators/prisma/data-utils/generated/typed-templates.js.map +1 -1
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/commit-operations.ts +366 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/compose-operations.ts +131 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.ts +26 -30
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/field-utils.ts +201 -0
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-types.ts +24 -20
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/prisma-utils.ts +14 -6
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/relation-helpers.ts +21 -26
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/types.ts +374 -25
- package/dist/generators/prisma/index.d.ts +2 -0
- package/dist/generators/prisma/index.d.ts.map +1 -1
- package/dist/generators/prisma/index.js +2 -0
- package/dist/generators/prisma/index.js.map +1 -1
- package/dist/generators/prisma/prisma-authorizer-utils/generated/index.d.ts +50 -12
- 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 +25 -6
- 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 +50 -12
- 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 +25 -6
- package/dist/generators/prisma/prisma-authorizer-utils/prisma-authorizer-utils.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-data-create/prisma-data-create.generator.d.ts +26 -6
- 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 +53 -25
- 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 +31 -6
- 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 +52 -15
- package/dist/generators/prisma/prisma-data-delete/prisma-data-delete.generator.js.map +1 -1
- package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.d.ts +25 -6
- package/dist/generators/prisma/prisma-data-nested-field/prisma-data-nested-field.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.d.ts +25 -6
- package/dist/generators/prisma/prisma-data-service/prisma-data-service.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.d.ts +31 -6
- 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 +65 -23
- package/dist/generators/prisma/prisma-data-update/prisma-data-update.generator.js.map +1 -1
- package/dist/generators/prisma/prisma-model-authorizer/prisma-model-authorizer.generator.d.ts +2 -0
- package/dist/generators/prisma/prisma-model-authorizer/prisma-model-authorizer.generator.d.ts.map +1 -1
- package/dist/generators/prisma/prisma-model-authorizer/prisma-model-authorizer.generator.js +86 -53
- package/dist/generators/prisma/prisma-model-authorizer/prisma-model-authorizer.generator.js.map +1 -1
- package/dist/generators/prisma/prisma-model-query-filter/index.d.ts +2 -0
- package/dist/generators/prisma/prisma-model-query-filter/index.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-model-query-filter/index.js +2 -0
- package/dist/generators/prisma/prisma-model-query-filter/index.js.map +1 -0
- package/dist/generators/prisma/prisma-model-query-filter/prisma-model-query-filter.generator.d.ts +60 -0
- package/dist/generators/prisma/prisma-model-query-filter/prisma-model-query-filter.generator.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-model-query-filter/prisma-model-query-filter.generator.js +124 -0
- package/dist/generators/prisma/prisma-model-query-filter/prisma-model-query-filter.generator.js.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/index.d.ts +364 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/index.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/index.js +13 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/index.js.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/template-paths.d.ts +13 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/template-paths.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/template-paths.js +25 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/template-paths.js.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/template-renderers.d.ts +131 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/template-renderers.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/template-renderers.js +49 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/template-renderers.js.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/ts-import-providers.d.ts +66 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/ts-import-providers.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/ts-import-providers.js +40 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/ts-import-providers.js.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/typed-templates.d.ts +411 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/typed-templates.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/typed-templates.js +46 -0
- package/dist/generators/prisma/prisma-query-filter-utils/generated/typed-templates.js.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/index.d.ts +4 -0
- package/dist/generators/prisma/prisma-query-filter-utils/index.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/index.js +3 -0
- package/dist/generators/prisma/prisma-query-filter-utils/index.js.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/prisma-query-filter-utils.generator.d.ts +156 -0
- package/dist/generators/prisma/prisma-query-filter-utils/prisma-query-filter-utils.generator.d.ts.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/prisma-query-filter-utils.generator.js +32 -0
- package/dist/generators/prisma/prisma-query-filter-utils/prisma-query-filter-utils.generator.js.map +1 -0
- package/dist/generators/prisma/prisma-query-filter-utils/templates/src/utils/query-filters.ts +209 -0
- package/dist/generators/prisma/prisma-query-filter-utils/templates/src/utils/query-helpers.ts +70 -0
- package/dist/generators/vitest/prisma-vitest/generated/index.d.ts +0 -6
- package/dist/generators/vitest/prisma-vitest/generated/index.d.ts.map +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/template-renderers.d.ts.map +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/template-renderers.js +0 -1
- package/dist/generators/vitest/prisma-vitest/generated/template-renderers.js.map +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/typed-templates.d.ts +0 -6
- package/dist/generators/vitest/prisma-vitest/generated/typed-templates.d.ts.map +1 -1
- package/dist/generators/vitest/prisma-vitest/generated/typed-templates.js +1 -4
- package/dist/generators/vitest/prisma-vitest/generated/typed-templates.js.map +1 -1
- package/dist/generators/vitest/prisma-vitest/templates/src/tests/helpers/prisma.test-helper.ts +2 -10
- package/dist/types/service-dto-kinds.d.ts +0 -6
- package/dist/types/service-dto-kinds.d.ts.map +1 -1
- package/dist/types/service-dto-kinds.js +0 -6
- package/dist/types/service-dto-kinds.js.map +1 -1
- package/dist/writers/pothos/helpers.d.ts +1 -0
- package/dist/writers/pothos/helpers.d.ts.map +1 -1
- package/dist/writers/pothos/helpers.js +1 -0
- package/dist/writers/pothos/helpers.js.map +1 -1
- package/dist/writers/pothos/scalar-fields.d.ts +3 -1
- package/dist/writers/pothos/scalar-fields.d.ts.map +1 -1
- package/dist/writers/pothos/scalar-fields.js +1 -0
- package/dist/writers/pothos/scalar-fields.js.map +1 -1
- package/dist/writers/prisma-schema/fields.d.ts +1 -1
- package/dist/writers/prisma-schema/fields.js +2 -2
- package/dist/writers/prisma-schema/fields.js.map +1 -1
- package/package.json +8 -8
- package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/define-operations.ts +0 -1134
package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/commit-operations.ts
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
GetPayload,
|
|
5
|
+
ModelInclude,
|
|
6
|
+
ModelPropName,
|
|
7
|
+
WhereUniqueInput,
|
|
8
|
+
} from '$prismaTypes';
|
|
9
|
+
import type {
|
|
10
|
+
AnyFieldDefinition,
|
|
11
|
+
AnyOperationHooks,
|
|
12
|
+
CommitCreateConfig,
|
|
13
|
+
CommitDeleteConfig,
|
|
14
|
+
CommitUpdateConfig,
|
|
15
|
+
CreatePlan,
|
|
16
|
+
OperationContext,
|
|
17
|
+
TransactionalOperationContext,
|
|
18
|
+
UpdatePlan,
|
|
19
|
+
} from '$types';
|
|
20
|
+
|
|
21
|
+
import { invokeHooks } from '$fieldUtils';
|
|
22
|
+
import { makeGenericPrismaDelegate } from '$prismaUtils';
|
|
23
|
+
import { checkInstanceAuthorization } from '%authorizerUtilsImports';
|
|
24
|
+
import { NotFoundError } from '%errorHandlerServiceImports';
|
|
25
|
+
import { prisma } from '%prismaImports';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Validate that query does not use `select` — only `include` is supported.
|
|
29
|
+
* Prisma `select` changes the return shape, which is incompatible with our
|
|
30
|
+
* typed return values and re-fetch logic.
|
|
31
|
+
*/
|
|
32
|
+
function validateQuery(query: unknown, operation: string): void {
|
|
33
|
+
if (query && typeof query === 'object') {
|
|
34
|
+
const unsupportedKeys = Object.entries(query)
|
|
35
|
+
.filter(([key, value]) => key !== 'include' && value !== undefined)
|
|
36
|
+
.map(([key]) => key);
|
|
37
|
+
if (unsupportedKeys.length > 0) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`Unsupported query keys for ${operation} operations: ${unsupportedKeys.join(', ')}. Only 'include' is supported.`,
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Checks if any hooks are present that could modify data after the initial operation.
|
|
47
|
+
* Used to determine if a re-fetch is needed after operation completes.
|
|
48
|
+
*/
|
|
49
|
+
function hasPostExecuteHooks(hooks: AnyOperationHooks): boolean {
|
|
50
|
+
return (
|
|
51
|
+
(hooks.afterExecute?.length ?? 0) > 0 ||
|
|
52
|
+
(hooks.afterCommit?.length ?? 0) > 0
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Re-fetch a record after hooks have run, ensuring included relations are fresh.
|
|
58
|
+
*
|
|
59
|
+
* Uses the caller's `refetchWithQuery` if provided, otherwise falls back to
|
|
60
|
+
* `makeGenericPrismaDelegate` with `{ id: result.id }`. Throws an explicit
|
|
61
|
+
* error if the result has no `id` field and no custom refetch was provided.
|
|
62
|
+
*/
|
|
63
|
+
async function refetchResult<
|
|
64
|
+
TModelName extends ModelPropName,
|
|
65
|
+
TIncludeArgs extends ModelInclude<TModelName>,
|
|
66
|
+
>(
|
|
67
|
+
model: TModelName,
|
|
68
|
+
result: GetPayload<TModelName>,
|
|
69
|
+
query: TIncludeArgs,
|
|
70
|
+
refetchWithQuery?: (
|
|
71
|
+
result: GetPayload<TModelName>,
|
|
72
|
+
query: TIncludeArgs,
|
|
73
|
+
) => Promise<GetPayload<TModelName, TIncludeArgs>>,
|
|
74
|
+
): Promise<GetPayload<TModelName, TIncludeArgs>> {
|
|
75
|
+
if (refetchWithQuery) {
|
|
76
|
+
return refetchWithQuery(result, query);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const resultRecord = result as Record<string, unknown>;
|
|
80
|
+
if (!('id' in resultRecord) || !resultRecord.id) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Cannot refetch ${model}: result has no 'id' field. Provide a custom refetchWithQuery.`,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const delegate = makeGenericPrismaDelegate(prisma, model);
|
|
87
|
+
const freshResult = await delegate.findUnique({
|
|
88
|
+
where: { id: resultRecord.id } as WhereUniqueInput<TModelName>,
|
|
89
|
+
include: query.include as NonNullable<ModelInclude<TModelName>['include']>,
|
|
90
|
+
});
|
|
91
|
+
if (!freshResult) {
|
|
92
|
+
throw new NotFoundError(`${model} not found after operation`);
|
|
93
|
+
}
|
|
94
|
+
return freshResult as GetPayload<TModelName, TIncludeArgs>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Commit a create operation plan.
|
|
99
|
+
*
|
|
100
|
+
* Opens a Prisma transaction and executes the full lifecycle:
|
|
101
|
+
* 1. Validate query (no `select`)
|
|
102
|
+
* 2. Run beforeExecute hooks (inside transaction)
|
|
103
|
+
* 3. Call the execute callback with plan data
|
|
104
|
+
* 4. Run afterExecute hooks (inside transaction, with result)
|
|
105
|
+
* 5. Run afterCommit hooks (outside transaction, with result)
|
|
106
|
+
* 6. Re-fetch if hooks modified related records and query includes relations
|
|
107
|
+
*/
|
|
108
|
+
export async function commitCreate<
|
|
109
|
+
TModelName extends ModelPropName,
|
|
110
|
+
TFields extends Record<string, AnyFieldDefinition>,
|
|
111
|
+
TIncludeArgs extends ModelInclude<TModelName> = ModelInclude<TModelName>,
|
|
112
|
+
>(
|
|
113
|
+
plan: CreatePlan<TModelName, TFields>,
|
|
114
|
+
config: CommitCreateConfig<TModelName, TFields, TIncludeArgs>,
|
|
115
|
+
): Promise<GetPayload<TModelName, TIncludeArgs>> {
|
|
116
|
+
validateQuery(config.query, 'create');
|
|
117
|
+
|
|
118
|
+
const { execute } = config;
|
|
119
|
+
const needsRefetch = hasPostExecuteHooks(plan.hooks);
|
|
120
|
+
|
|
121
|
+
const baseOperationContext: OperationContext<
|
|
122
|
+
GetPayload<TModelName>,
|
|
123
|
+
{ hasResult: false }
|
|
124
|
+
> = {
|
|
125
|
+
operation: 'create',
|
|
126
|
+
serviceContext: plan.serviceContext,
|
|
127
|
+
loadExisting: () => Promise.resolve(undefined),
|
|
128
|
+
result: undefined,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const transactionResult = await prisma.$transaction(async (tx) => {
|
|
132
|
+
const txContext: TransactionalOperationContext<
|
|
133
|
+
GetPayload<TModelName>,
|
|
134
|
+
{ hasResult: false }
|
|
135
|
+
> = {
|
|
136
|
+
...baseOperationContext,
|
|
137
|
+
tx,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Run beforeExecute hooks
|
|
141
|
+
await invokeHooks(plan.hooks.beforeExecute, txContext);
|
|
142
|
+
|
|
143
|
+
// If re-fetching, don't include relations in initial create
|
|
144
|
+
const createQuery =
|
|
145
|
+
needsRefetch || !config.query
|
|
146
|
+
? ({} as ModelInclude<TModelName>)
|
|
147
|
+
: (config.query as ModelInclude<TModelName>);
|
|
148
|
+
|
|
149
|
+
const result = await execute({
|
|
150
|
+
tx,
|
|
151
|
+
data: plan.data,
|
|
152
|
+
query: createQuery,
|
|
153
|
+
serviceContext: plan.serviceContext,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Run afterExecute hooks
|
|
157
|
+
await invokeHooks(plan.hooks.afterExecute, {
|
|
158
|
+
...txContext,
|
|
159
|
+
result,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
return result;
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Run afterCommit hooks (outside transaction)
|
|
166
|
+
await invokeHooks(plan.hooks.afterCommit, {
|
|
167
|
+
...baseOperationContext,
|
|
168
|
+
result: transactionResult,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Re-fetch if hooks modified related records and query includes relations
|
|
172
|
+
if (needsRefetch && config.query?.include) {
|
|
173
|
+
return refetchResult(
|
|
174
|
+
plan.model,
|
|
175
|
+
transactionResult as GetPayload<TModelName>,
|
|
176
|
+
config.query,
|
|
177
|
+
config.refetchWithQuery,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return transactionResult as GetPayload<TModelName, TIncludeArgs>;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Commit an update operation plan.
|
|
186
|
+
*
|
|
187
|
+
* Opens a Prisma transaction and executes the full lifecycle:
|
|
188
|
+
* 1. Validate query (no `select`)
|
|
189
|
+
* 2. Run beforeExecute hooks (inside transaction)
|
|
190
|
+
* 3. Call the execute callback with plan data
|
|
191
|
+
* 4. Run afterExecute hooks (inside transaction, with result)
|
|
192
|
+
* 5. Run afterCommit hooks (outside transaction, with result)
|
|
193
|
+
* 6. Re-fetch if hooks modified related records and query includes relations
|
|
194
|
+
*/
|
|
195
|
+
export async function commitUpdate<
|
|
196
|
+
TModelName extends ModelPropName,
|
|
197
|
+
TFields extends Record<string, AnyFieldDefinition>,
|
|
198
|
+
TIncludeArgs extends ModelInclude<TModelName> = ModelInclude<TModelName>,
|
|
199
|
+
>(
|
|
200
|
+
plan: UpdatePlan<TModelName, TFields>,
|
|
201
|
+
config: CommitUpdateConfig<TModelName, TFields, TIncludeArgs>,
|
|
202
|
+
): Promise<GetPayload<TModelName, TIncludeArgs>> {
|
|
203
|
+
validateQuery(config.query, 'update');
|
|
204
|
+
|
|
205
|
+
const { execute } = config;
|
|
206
|
+
const needsRefetch = hasPostExecuteHooks(plan.hooks);
|
|
207
|
+
|
|
208
|
+
const baseOperationContext: OperationContext<
|
|
209
|
+
GetPayload<TModelName>,
|
|
210
|
+
{ hasResult: false }
|
|
211
|
+
> = {
|
|
212
|
+
operation: 'update',
|
|
213
|
+
serviceContext: plan.serviceContext,
|
|
214
|
+
loadExisting: plan.loadExisting as () => Promise<
|
|
215
|
+
GetPayload<TModelName> | undefined
|
|
216
|
+
>,
|
|
217
|
+
result: undefined,
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const transactionResult = await prisma.$transaction(async (tx) => {
|
|
221
|
+
const txContext: TransactionalOperationContext<
|
|
222
|
+
GetPayload<TModelName>,
|
|
223
|
+
{ hasResult: false }
|
|
224
|
+
> = {
|
|
225
|
+
...baseOperationContext,
|
|
226
|
+
tx,
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// Run beforeExecute hooks
|
|
230
|
+
await invokeHooks(plan.hooks.beforeExecute, txContext);
|
|
231
|
+
|
|
232
|
+
// If re-fetching, don't include relations in initial update
|
|
233
|
+
const updateQuery =
|
|
234
|
+
needsRefetch || !config.query
|
|
235
|
+
? ({} as ModelInclude<TModelName>)
|
|
236
|
+
: (config.query as ModelInclude<TModelName>);
|
|
237
|
+
|
|
238
|
+
const result = await execute({
|
|
239
|
+
tx,
|
|
240
|
+
data: plan.data,
|
|
241
|
+
query: updateQuery,
|
|
242
|
+
serviceContext: plan.serviceContext,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Run afterExecute hooks
|
|
246
|
+
await invokeHooks(plan.hooks.afterExecute, {
|
|
247
|
+
...txContext,
|
|
248
|
+
result,
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
return result;
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Run afterCommit hooks (outside transaction)
|
|
255
|
+
await invokeHooks(plan.hooks.afterCommit, {
|
|
256
|
+
...baseOperationContext,
|
|
257
|
+
result: transactionResult,
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Re-fetch if hooks modified related records and query includes relations
|
|
261
|
+
if (needsRefetch && config.query?.include) {
|
|
262
|
+
return refetchResult(
|
|
263
|
+
plan.model,
|
|
264
|
+
transactionResult as GetPayload<TModelName>,
|
|
265
|
+
config.query,
|
|
266
|
+
config.refetchWithQuery,
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return transactionResult as GetPayload<TModelName, TIncludeArgs>;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Execute a delete operation.
|
|
275
|
+
*
|
|
276
|
+
* No compose step is needed since there are no fields to process.
|
|
277
|
+
* Handles authorization, hooks, transaction, and execution directly.
|
|
278
|
+
*
|
|
279
|
+
* 1. Validate query (no `select`)
|
|
280
|
+
* 2. Run authorization checks (if configured)
|
|
281
|
+
* 3. Open transaction
|
|
282
|
+
* 4. Run beforeExecute hooks (inside transaction)
|
|
283
|
+
* 5. Call the execute callback
|
|
284
|
+
* 6. Run afterExecute hooks (inside transaction, with result)
|
|
285
|
+
* 7. Run afterCommit hooks (outside transaction, with result)
|
|
286
|
+
*/
|
|
287
|
+
export async function commitDelete<
|
|
288
|
+
TModelName extends ModelPropName,
|
|
289
|
+
TIncludeArgs extends ModelInclude<TModelName> = ModelInclude<TModelName>,
|
|
290
|
+
>(
|
|
291
|
+
config: CommitDeleteConfig<TModelName, TIncludeArgs>,
|
|
292
|
+
): Promise<GetPayload<TModelName, TIncludeArgs>> {
|
|
293
|
+
validateQuery(config.query, 'delete');
|
|
294
|
+
|
|
295
|
+
const { context, execute, loadExisting: rawLoadExisting } = config;
|
|
296
|
+
|
|
297
|
+
// Memoize loadExisting if provided
|
|
298
|
+
let cached: GetPayload<TModelName> | undefined;
|
|
299
|
+
const loadExisting: () => Promise<GetPayload<TModelName> | undefined> =
|
|
300
|
+
rawLoadExisting
|
|
301
|
+
? async () => {
|
|
302
|
+
cached ??= await rawLoadExisting();
|
|
303
|
+
return cached;
|
|
304
|
+
}
|
|
305
|
+
: () => Promise.resolve(undefined);
|
|
306
|
+
|
|
307
|
+
// Authorization
|
|
308
|
+
if (config.authorize && config.authorize.length > 0) {
|
|
309
|
+
await checkInstanceAuthorization(
|
|
310
|
+
context,
|
|
311
|
+
loadExisting as () => Promise<GetPayload<TModelName>>,
|
|
312
|
+
config.authorize,
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const hooks: Required<AnyOperationHooks> = {
|
|
317
|
+
beforeExecute: [...(config.hooks?.beforeExecute ?? [])],
|
|
318
|
+
afterExecute: [...(config.hooks?.afterExecute ?? [])],
|
|
319
|
+
afterCommit: [...(config.hooks?.afterCommit ?? [])],
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const baseOperationContext: OperationContext<
|
|
323
|
+
GetPayload<TModelName>,
|
|
324
|
+
{ hasResult: false }
|
|
325
|
+
> = {
|
|
326
|
+
operation: 'delete',
|
|
327
|
+
serviceContext: context,
|
|
328
|
+
loadExisting,
|
|
329
|
+
result: undefined,
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const transactionResult = await prisma.$transaction(async (tx) => {
|
|
333
|
+
const txContext: TransactionalOperationContext<
|
|
334
|
+
GetPayload<TModelName>,
|
|
335
|
+
{ hasResult: false }
|
|
336
|
+
> = {
|
|
337
|
+
...baseOperationContext,
|
|
338
|
+
tx,
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// Run beforeExecute hooks
|
|
342
|
+
await invokeHooks(hooks.beforeExecute, txContext);
|
|
343
|
+
|
|
344
|
+
const result = await execute({
|
|
345
|
+
tx,
|
|
346
|
+
query: (config.query ?? {}) as ModelInclude<TModelName>,
|
|
347
|
+
serviceContext: context,
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
// Run afterExecute hooks
|
|
351
|
+
await invokeHooks(hooks.afterExecute, {
|
|
352
|
+
...txContext,
|
|
353
|
+
result,
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
return result;
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
// Run afterCommit hooks (outside transaction)
|
|
360
|
+
await invokeHooks(hooks.afterCommit, {
|
|
361
|
+
...baseOperationContext,
|
|
362
|
+
result: transactionResult,
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
return transactionResult as GetPayload<TModelName, TIncludeArgs>;
|
|
366
|
+
}
|
package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/compose-operations.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
|
|
3
|
+
import type { GetPayload, ModelPropName } from '$prismaTypes';
|
|
4
|
+
import type {
|
|
5
|
+
AnyFieldDefinition,
|
|
6
|
+
AnyOperationHooks,
|
|
7
|
+
ComposeCreateConfig,
|
|
8
|
+
ComposeUpdateConfig,
|
|
9
|
+
InferInput,
|
|
10
|
+
} from '$types';
|
|
11
|
+
|
|
12
|
+
import { transformFields } from '$fieldUtils';
|
|
13
|
+
import { CreatePlan, UpdatePlan } from '$types';
|
|
14
|
+
import {
|
|
15
|
+
checkGlobalAuthorization,
|
|
16
|
+
checkInstanceAuthorization,
|
|
17
|
+
} from '%authorizerUtilsImports';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Compose a create operation plan.
|
|
21
|
+
*
|
|
22
|
+
* Processes field definitions via `transformFields`, collecting data transformations
|
|
23
|
+
* and hooks. Returns an immutable plan that can be transformed via `mapData` and
|
|
24
|
+
* `addHook` before committing.
|
|
25
|
+
*
|
|
26
|
+
* This is the pre-commit phase — field processing like `fileField` may do DB reads
|
|
27
|
+
* for validation, so this is not a pure function.
|
|
28
|
+
*/
|
|
29
|
+
export async function composeCreate<
|
|
30
|
+
TModelName extends ModelPropName,
|
|
31
|
+
TFields extends Record<string, AnyFieldDefinition>,
|
|
32
|
+
>(
|
|
33
|
+
config: ComposeCreateConfig<TModelName, TFields>,
|
|
34
|
+
): Promise<CreatePlan<TModelName, TFields>> {
|
|
35
|
+
const { fields, input, context, authorize } = config;
|
|
36
|
+
|
|
37
|
+
// Authorization — fail fast before field processing
|
|
38
|
+
if (authorize && authorize.length > 0) {
|
|
39
|
+
checkGlobalAuthorization(context, authorize);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const { data: fieldsData, hooks: fieldsHooks } = await transformFields(
|
|
43
|
+
fields,
|
|
44
|
+
input,
|
|
45
|
+
{
|
|
46
|
+
operation: 'create',
|
|
47
|
+
serviceContext: context,
|
|
48
|
+
allowOptionalFields: false,
|
|
49
|
+
loadExisting: () => Promise.resolve(undefined),
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const hooks: Required<AnyOperationHooks> = {
|
|
54
|
+
beforeExecute: [...(fieldsHooks.beforeExecute ?? [])],
|
|
55
|
+
afterExecute: [...(fieldsHooks.afterExecute ?? [])],
|
|
56
|
+
afterCommit: [...(fieldsHooks.afterCommit ?? [])],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return new CreatePlan({
|
|
60
|
+
model: config.model,
|
|
61
|
+
data: fieldsData.create,
|
|
62
|
+
hooks,
|
|
63
|
+
serviceContext: context,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Compose an update operation plan.
|
|
69
|
+
*
|
|
70
|
+
* Processes field definitions via `transformFields`, collecting data transformations
|
|
71
|
+
* and hooks. The caller provides a `loadExisting` function that controls how the
|
|
72
|
+
* existing item is fetched (e.g., with extra includes for authorization or diffing).
|
|
73
|
+
*
|
|
74
|
+
* Returns an immutable plan that can be transformed via `mapData` and `addHook`.
|
|
75
|
+
*/
|
|
76
|
+
export async function composeUpdate<
|
|
77
|
+
TModelName extends ModelPropName,
|
|
78
|
+
TFields extends Record<string, AnyFieldDefinition>,
|
|
79
|
+
>(
|
|
80
|
+
config: ComposeUpdateConfig<TModelName, TFields>,
|
|
81
|
+
): Promise<UpdatePlan<TModelName, TFields>> {
|
|
82
|
+
const {
|
|
83
|
+
fields,
|
|
84
|
+
input,
|
|
85
|
+
context,
|
|
86
|
+
loadExisting: rawLoadExisting,
|
|
87
|
+
authorize,
|
|
88
|
+
} = config;
|
|
89
|
+
|
|
90
|
+
// Memoize loadExisting so multiple callers (authorization, field processing, developer inspection) share one fetch
|
|
91
|
+
let cached: GetPayload<TModelName> | undefined;
|
|
92
|
+
const loadExisting = async (): Promise<GetPayload<TModelName>> => {
|
|
93
|
+
cached ??= await rawLoadExisting();
|
|
94
|
+
return cached;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Authorization — fail fast before field processing
|
|
98
|
+
if (authorize && authorize.length > 0) {
|
|
99
|
+
await checkInstanceAuthorization(context, loadExisting, authorize);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Only transform fields present in input
|
|
103
|
+
const fieldsToTransform = Object.fromEntries(
|
|
104
|
+
Object.entries(fields).filter(([key]) => key in (input as object)),
|
|
105
|
+
) as TFields;
|
|
106
|
+
|
|
107
|
+
const { data: fieldsData, hooks: fieldsHooks } = await transformFields(
|
|
108
|
+
fieldsToTransform,
|
|
109
|
+
input as InferInput<TFields>,
|
|
110
|
+
{
|
|
111
|
+
operation: 'update',
|
|
112
|
+
serviceContext: context,
|
|
113
|
+
allowOptionalFields: true,
|
|
114
|
+
loadExisting: loadExisting as () => Promise<Record<string, unknown>>,
|
|
115
|
+
},
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const hooks: Required<AnyOperationHooks> = {
|
|
119
|
+
beforeExecute: [...(fieldsHooks.beforeExecute ?? [])],
|
|
120
|
+
afterExecute: [...(fieldsHooks.afterExecute ?? [])],
|
|
121
|
+
afterCommit: [...(fieldsHooks.afterCommit ?? [])],
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return new UpdatePlan({
|
|
125
|
+
model: config.model,
|
|
126
|
+
data: fieldsData.update,
|
|
127
|
+
hooks,
|
|
128
|
+
serviceContext: context,
|
|
129
|
+
loadExisting,
|
|
130
|
+
});
|
|
131
|
+
}
|
package/dist/generators/prisma/data-utils/templates/src/utils/data-operations/field-definitions.ts
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
generateCreateSchema,
|
|
26
26
|
invokeHooks,
|
|
27
27
|
transformFields,
|
|
28
|
-
} from '$
|
|
28
|
+
} from '$fieldUtils';
|
|
29
29
|
import { makeGenericPrismaDelegate } from '$prismaUtils';
|
|
30
30
|
import { prisma } from '%prismaImports';
|
|
31
31
|
|
|
@@ -37,7 +37,7 @@ import { prisma } from '%prismaImports';
|
|
|
37
37
|
*
|
|
38
38
|
* @template TSchema - The Zod schema type for validation
|
|
39
39
|
* @param schema - Zod schema for validation
|
|
40
|
-
* @returns
|
|
40
|
+
* @returns Scalar field definition that maps validated input directly to Prisma create/update data
|
|
41
41
|
*
|
|
42
42
|
* @example
|
|
43
43
|
* ```typescript
|
|
@@ -213,15 +213,13 @@ export interface NestedOneToOneFieldConfig<
|
|
|
213
213
|
* avatar: fileField(avatarFileCategory),
|
|
214
214
|
* },
|
|
215
215
|
* getWhereUnique: (parent) => ({ userId: parent.id }),
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
* avatar: data.update.avatar ? { connect: { id: data.update.avatar } } : undefined,
|
|
224
|
-
* },
|
|
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,
|
|
225
223
|
* }),
|
|
226
224
|
* }),
|
|
227
225
|
* };
|
|
@@ -315,8 +313,6 @@ export function nestedOneToOneField<
|
|
|
315
313
|
],
|
|
316
314
|
afterExecute: [
|
|
317
315
|
async (ctx) => {
|
|
318
|
-
const awaitedData =
|
|
319
|
-
typeof data === 'function' ? await data(ctx.tx) : data;
|
|
320
316
|
const whereUnique = config.getWhereUnique(
|
|
321
317
|
ctx.result as GetPayload<TParentModelName>,
|
|
322
318
|
);
|
|
@@ -331,7 +327,7 @@ export function nestedOneToOneField<
|
|
|
331
327
|
const [builtCreate, builtUpdate] = await Promise.all([
|
|
332
328
|
config.buildCreateData(
|
|
333
329
|
{
|
|
334
|
-
...
|
|
330
|
+
...data.create,
|
|
335
331
|
...({
|
|
336
332
|
[config.relationName]: { connect: parentWhereUnique },
|
|
337
333
|
} as Record<
|
|
@@ -343,7 +339,7 @@ export function nestedOneToOneField<
|
|
|
343
339
|
sharedCtx,
|
|
344
340
|
),
|
|
345
341
|
config.buildUpdateData(
|
|
346
|
-
|
|
342
|
+
data.update,
|
|
347
343
|
ctx.result as GetPayload<TParentModelName>,
|
|
348
344
|
sharedCtx,
|
|
349
345
|
),
|
|
@@ -433,7 +429,8 @@ export interface NestedOneToManyFieldConfig<
|
|
|
433
429
|
|
|
434
430
|
/**
|
|
435
431
|
* Transform validated create field data into final Prisma structure for a single item.
|
|
436
|
-
* The
|
|
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.
|
|
437
434
|
*/
|
|
438
435
|
buildCreateData: (
|
|
439
436
|
data: InferFieldsCreateOutput<TFields> &
|
|
@@ -502,6 +499,9 @@ function expandWhereUnique<TModelName extends ModelPropName>(
|
|
|
502
499
|
* - **Delete**: Existing items not present in the input array are removed
|
|
503
500
|
* - **No Change**: Passing `undefined` leaves the collection unchanged
|
|
504
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
505
|
* All operations are performed atomically within the parent operation's transaction,
|
|
506
506
|
* ensuring data consistency even if the operation fails.
|
|
507
507
|
*
|
|
@@ -510,7 +510,7 @@ function expandWhereUnique<TModelName extends ModelPropName>(
|
|
|
510
510
|
* @template TRelationName - Relation field name on child model
|
|
511
511
|
* @template TFields - Field definitions for each child item
|
|
512
512
|
* @param config - Configuration object for the one-to-many relationship
|
|
513
|
-
* @returns Field definition for use
|
|
513
|
+
* @returns Field definition for use with `composeCreate`/`composeUpdate` and `commitCreate`/`commitUpdate`
|
|
514
514
|
*
|
|
515
515
|
* @example
|
|
516
516
|
* ```typescript
|
|
@@ -524,10 +524,8 @@ function expandWhereUnique<TModelName extends ModelPropName>(
|
|
|
524
524
|
* caption: scalarField(z.string()),
|
|
525
525
|
* },
|
|
526
526
|
* getWhereUnique: (input) => input.id ? { id: input.id } : undefined,
|
|
527
|
-
*
|
|
528
|
-
*
|
|
529
|
-
* update: { caption: data.caption },
|
|
530
|
-
* }),
|
|
527
|
+
* buildCreateData: (data) => ({ caption: data.caption }),
|
|
528
|
+
* buildUpdateData: (data) => ({ caption: data.caption }),
|
|
531
529
|
* }),
|
|
532
530
|
* };
|
|
533
531
|
*
|
|
@@ -628,7 +626,7 @@ export function nestedOneToManyField<
|
|
|
628
626
|
const processedItems = await Promise.all(
|
|
629
627
|
value.map(async (itemInput, idx) => {
|
|
630
628
|
const whereUnique =
|
|
631
|
-
existingModel &&
|
|
629
|
+
existingModel && getWhereUnique(itemInput, existingModel);
|
|
632
630
|
|
|
633
631
|
const { data, hooks } = await transformFields(
|
|
634
632
|
config.fields,
|
|
@@ -697,11 +695,6 @@ export function nestedOneToManyField<
|
|
|
697
695
|
// Upsert items
|
|
698
696
|
await Promise.all(
|
|
699
697
|
processedItems.map(async (item, idx) => {
|
|
700
|
-
const awaitedData =
|
|
701
|
-
typeof item.data === 'function'
|
|
702
|
-
? await item.data(ctx.tx)
|
|
703
|
-
: item.data;
|
|
704
|
-
|
|
705
698
|
const parentWhereUnique = config.parentModel.getWhereUnique(
|
|
706
699
|
ctx.result,
|
|
707
700
|
);
|
|
@@ -718,7 +711,7 @@ export function nestedOneToManyField<
|
|
|
718
711
|
const [builtCreate, builtUpdate] = await Promise.all([
|
|
719
712
|
config.buildCreateData(
|
|
720
713
|
{
|
|
721
|
-
...
|
|
714
|
+
...item.data.create,
|
|
722
715
|
...({
|
|
723
716
|
[config.relationName]: { connect: parentWhereUnique },
|
|
724
717
|
} as Record<
|
|
@@ -729,12 +722,15 @@ export function nestedOneToManyField<
|
|
|
729
722
|
ctx.result,
|
|
730
723
|
sharedCtx,
|
|
731
724
|
),
|
|
732
|
-
config.buildUpdateData(
|
|
725
|
+
config.buildUpdateData(item.data.update, ctx.result, sharedCtx),
|
|
733
726
|
]);
|
|
734
727
|
|
|
735
728
|
results[idx] = item.whereUnique
|
|
736
729
|
? await prismaDelegate.upsert({
|
|
737
|
-
where:
|
|
730
|
+
where: {
|
|
731
|
+
...item.whereUnique,
|
|
732
|
+
...whereFromOriginalModel,
|
|
733
|
+
} as WhereUniqueInput<TModelName>,
|
|
738
734
|
create: builtCreate,
|
|
739
735
|
update: builtUpdate,
|
|
740
736
|
})
|