@effectify/prisma 0.1.1 → 0.1.2
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/package.json +14 -11
- package/prisma/dev.db +0 -0
- package/prisma/generated/edge.js +7 -7
- package/prisma/generated/effect/index.ts +2 -7
- package/prisma/generated/effect/models/Todo.ts +6 -0
- package/prisma/generated/effect/prisma-repository.ts +18 -18
- package/prisma/generated/effect/schemas/enums.ts +1 -1
- package/prisma/generated/effect/schemas/types.ts +1 -1
- package/prisma/generated/index-browser.js +4 -4
- package/prisma/generated/index.d.ts +25 -9
- package/prisma/generated/index.js +7 -7
- package/prisma/generated/package.json +3 -3
- package/prisma/generated/schema.prisma +1 -1
- package/prisma/schema.prisma +1 -1
- package/src/cli.ts +22 -0
- package/src/commands/init.ts +0 -2
- package/src/commands/prisma.ts +50 -0
- package/src/generators/sql-schema-generator.ts +0 -9
- package/src/services/generator-context.ts +4 -0
- package/src/services/generator-service.ts +178 -0
- package/src/services/render-service.ts +32 -0
- package/src/templates/index-custom-error.eta +190 -0
- package/src/templates/index-default.eta +363 -0
- package/src/templates/model.eta +6 -0
- package/src/templates/prisma-raw-sql.eta +31 -0
- package/src/{effect-prisma.ts → templates/prisma-repository.eta} +18 -890
- package/src/templates/prisma-schema.eta +94 -0
- package/vitest.config.ts +1 -0
- package/src/cli.tsx +0 -23
- package/src/commands/generate-effect.ts +0 -109
- package/src/commands/generate-sql-schema.ts +0 -109
- package/src/generators/prisma-effect-generator.ts +0 -496
|
@@ -1,122 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
/** biome-ignore-all lint/nursery/useMaxParams: TODO: refactor to reduce params */
|
|
3
|
-
/** biome-ignore-all lint/nursery/noShadow: TODO: fix shadowing */
|
|
4
|
-
/** biome-ignore-all lint/complexity/noExcessiveCognitiveComplexity: TODO: reduce complexity */
|
|
5
|
-
import fs from 'node:fs/promises'
|
|
6
|
-
import path from 'node:path'
|
|
7
|
-
import type { DMMF } from '@prisma/client/runtime/client.js'
|
|
8
|
-
import type { GeneratorOptions } from '@prisma/generator'
|
|
9
|
-
import generatorHelper from '@prisma/generator-helper'
|
|
10
|
-
|
|
11
|
-
const { generatorHandler } = generatorHelper
|
|
12
|
-
|
|
13
|
-
const header = '// This file was generated by prisma-effect-generator, do not edit manually.\n'
|
|
14
|
-
|
|
15
|
-
// Utility function to convert PascalCase to camelCase
|
|
16
|
-
|
|
17
|
-
const prismaSchemaContent = `/**
|
|
18
|
-
* @since 1.0.0
|
|
19
|
-
*/
|
|
20
|
-
import * as Cause from 'effect/Cause'
|
|
21
|
-
import * as Effect from 'effect/Effect'
|
|
22
|
-
import type * as Option from 'effect/Option'
|
|
23
|
-
import type { ParseError } from 'effect/ParseResult'
|
|
24
|
-
import * as Schema from 'effect/Schema'
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Run a sql query with a request schema and a result schema.
|
|
28
|
-
*
|
|
29
|
-
* @since 1.0.0
|
|
30
|
-
* @category constructor
|
|
31
|
-
*/
|
|
32
|
-
export const findAll = <IR, II, IA, AR, AI, A, R, E>(options: {
|
|
33
|
-
readonly Request: Schema.Schema<IA, II, IR>
|
|
34
|
-
readonly Result: Schema.Schema<A, AI, AR>
|
|
35
|
-
readonly execute: (request: II) => Effect.Effect<ReadonlyArray<unknown>, E, R>
|
|
36
|
-
}) => {
|
|
37
|
-
const encodeRequest = Schema.encode(options.Request)
|
|
38
|
-
const decode = Schema.decodeUnknown(Schema.Array(options.Result))
|
|
39
|
-
return (request: IA): Effect.Effect<ReadonlyArray<A>, E | ParseError, R | IR | AR> =>
|
|
40
|
-
Effect.flatMap(Effect.flatMap(encodeRequest(request), options.execute), decode)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const void_ = <IR, II, IA, R, E>(options: {
|
|
44
|
-
readonly Request: Schema.Schema<IA, II, IR>
|
|
45
|
-
readonly execute: (request: II) => Effect.Effect<unknown, E, R>
|
|
46
|
-
}) => {
|
|
47
|
-
const encode = Schema.encode(options.Request)
|
|
48
|
-
return (request: IA): Effect.Effect<void, E | ParseError, R | IR> =>
|
|
49
|
-
Effect.asVoid(Effect.flatMap(encode(request), options.execute))
|
|
50
|
-
}
|
|
51
|
-
export {
|
|
52
|
-
/**
|
|
53
|
-
* Run a sql query with a request schema and discard the result.
|
|
54
|
-
*
|
|
55
|
-
* @since 1.0.0
|
|
56
|
-
* @category constructor
|
|
57
|
-
*/
|
|
58
|
-
void_ as void,
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Run a sql query with a request schema and a result schema and return the first result.
|
|
63
|
-
*
|
|
64
|
-
* @since 1.0.0
|
|
65
|
-
* @category constructor
|
|
66
|
-
*/
|
|
67
|
-
export const findOne = <IR, II, IA, AR, AI, A, R, E>(options: {
|
|
68
|
-
readonly Request: Schema.Schema<IA, II, IR>
|
|
69
|
-
readonly Result: Schema.Schema<A, AI, AR>
|
|
70
|
-
readonly execute: (request: II) => Effect.Effect<ReadonlyArray<unknown>, E, R>
|
|
71
|
-
}) => {
|
|
72
|
-
const encodeRequest = Schema.encode(options.Request)
|
|
73
|
-
const decode = Schema.decodeUnknown(options.Result)
|
|
74
|
-
return (request: IA): Effect.Effect<Option.Option<A>, E | ParseError, R | IR | AR> =>
|
|
75
|
-
Effect.flatMap(Effect.flatMap(encodeRequest(request), options.execute), (arr) =>
|
|
76
|
-
Array.isArray(arr) && arr.length > 0 ? Effect.asSome(decode(arr[0])) : Effect.succeedNone,
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Run a sql query with a request schema and a result schema and return the first result.
|
|
82
|
-
*
|
|
83
|
-
* @since 1.0.0
|
|
84
|
-
* @category constructor
|
|
85
|
-
*/
|
|
86
|
-
export const single = <IR, II, IA, AR, AI, A, R, E>(options: {
|
|
87
|
-
readonly Request: Schema.Schema<IA, II, IR>
|
|
88
|
-
readonly Result: Schema.Schema<A, AI, AR>
|
|
89
|
-
readonly execute: (request: II) => Effect.Effect<ReadonlyArray<unknown>, E, R>
|
|
90
|
-
}) => {
|
|
91
|
-
const encodeRequest = Schema.encode(options.Request)
|
|
92
|
-
const decode = Schema.decodeUnknown(options.Result)
|
|
93
|
-
return (request: IA): Effect.Effect<A, E | ParseError | Cause.NoSuchElementException, R | IR | AR> =>
|
|
94
|
-
Effect.flatMap(
|
|
95
|
-
Effect.flatMap(encodeRequest(request), options.execute),
|
|
96
|
-
(arr): Effect.Effect<A, ParseError | Cause.NoSuchElementException, AR> =>
|
|
97
|
-
Array.isArray(arr) && arr.length > 0 ? decode(arr[0]) : Effect.fail(new Cause.NoSuchElementException()),
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export const many = <IR, II, IA, AR, AI, A, R, E>(options: {
|
|
102
|
-
readonly Request: Schema.Schema<IA, II, IR>
|
|
103
|
-
readonly Result: Schema.Schema<A, AI, AR>
|
|
104
|
-
readonly execute: (request: II) => Effect.Effect<Array<unknown>, E, R>
|
|
105
|
-
}) => {
|
|
106
|
-
const encodeRequest = Schema.encode(options.Request)
|
|
107
|
-
const decode = Schema.decodeUnknown(Schema.Array(options.Result))
|
|
108
|
-
return (request: IA): Effect.Effect<Array<A>, E | ParseError, R | IR | AR> =>
|
|
109
|
-
Effect.map(Effect.flatMap(Effect.flatMap(encodeRequest(request), options.execute), decode), (arr) => [...arr])
|
|
110
|
-
}
|
|
111
|
-
`
|
|
112
|
-
|
|
113
|
-
const getPrismaModelContent = (
|
|
114
|
-
clientImportPath: string,
|
|
115
|
-
) => `/** biome-ignore-all lint/suspicious/noExplicitAny: <todo> */
|
|
1
|
+
/** biome-ignore-all lint/suspicious/noExplicitAny: <todo> */
|
|
116
2
|
/** biome-ignore-all lint/style/useDefaultSwitchClause: <todo> */
|
|
117
3
|
|
|
118
4
|
import * as VariantSchema from '@effect/experimental/VariantSchema'
|
|
119
|
-
import { type PrismaClient as BasePrismaClient, Prisma as PrismaNamespace } from '
|
|
5
|
+
import { type PrismaClient as BasePrismaClient, Prisma as PrismaNamespace } from '<%= it.clientImportPath %>'
|
|
120
6
|
import { PrismaClient } from './index.js'
|
|
121
7
|
import * as Data from 'effect/Data'
|
|
122
8
|
import * as Effect from 'effect/Effect'
|
|
@@ -699,7 +585,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
699
585
|
): Effect.Effect<Option.Option<S['Type']>, never, S['Context'] | S['findUnique']['Context']> =>
|
|
700
586
|
findUniqueSchema((args as any).where).pipe(
|
|
701
587
|
Effect.catchTag('ParseError', Effect.die),
|
|
702
|
-
Effect.withSpan(
|
|
588
|
+
Effect.withSpan(`\${options.spanPrefix}.findUnique`, {
|
|
703
589
|
captureStackTrace: false,
|
|
704
590
|
attributes: { ...(args as any).where },
|
|
705
591
|
}),
|
|
@@ -725,7 +611,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
725
611
|
Effect.map((result) => result as S['Type']),
|
|
726
612
|
Effect.catchTag('ParseError', Effect.die),
|
|
727
613
|
Effect.catchTag('NoSuchElementException', Effect.die),
|
|
728
|
-
Effect.withSpan(
|
|
614
|
+
Effect.withSpan(`\${options.spanPrefix}.findUniqueOrThrow`, {
|
|
729
615
|
captureStackTrace: false,
|
|
730
616
|
attributes: { ...(args as any).where },
|
|
731
617
|
}),
|
|
@@ -747,7 +633,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
747
633
|
): Effect.Effect<Option.Option<S['Type']>, never, S['Context'] | S['findFirst']['Context']> =>
|
|
748
634
|
findFirstSchema(args).pipe(
|
|
749
635
|
Effect.catchTag('ParseError', Effect.die),
|
|
750
|
-
Effect.withSpan(
|
|
636
|
+
Effect.withSpan(`\${options.spanPrefix}.findFirst`, {
|
|
751
637
|
captureStackTrace: false,
|
|
752
638
|
attributes: { ...(args as any) },
|
|
753
639
|
}),
|
|
@@ -771,7 +657,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
771
657
|
Effect.map((result) => result as S['Type']),
|
|
772
658
|
Effect.catchTag('ParseError', Effect.die),
|
|
773
659
|
Effect.catchTag('NoSuchElementException', Effect.die),
|
|
774
|
-
Effect.withSpan(
|
|
660
|
+
Effect.withSpan(`\${options.spanPrefix}.findFirstOrThrow`, {
|
|
775
661
|
captureStackTrace: false,
|
|
776
662
|
attributes: { ...(args as any) },
|
|
777
663
|
}),
|
|
@@ -793,7 +679,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
793
679
|
): Effect.Effect<Array<S['Type']>, never, S['Context'] | S['findMany']['Context']> =>
|
|
794
680
|
findManySchema(args).pipe(
|
|
795
681
|
Effect.catchTag('ParseError', Effect.die),
|
|
796
|
-
Effect.withSpan(
|
|
682
|
+
Effect.withSpan(`\${options.spanPrefix}.findMany`, {
|
|
797
683
|
captureStackTrace: false,
|
|
798
684
|
attributes: { ...(args as any) },
|
|
799
685
|
}),
|
|
@@ -815,7 +701,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
815
701
|
createSchema((args as any).data).pipe(
|
|
816
702
|
Effect.catchTag('ParseError', Effect.die),
|
|
817
703
|
Effect.catchTag('NoSuchElementException', Effect.die),
|
|
818
|
-
Effect.withSpan(
|
|
704
|
+
Effect.withSpan(`\${options.spanPrefix}.create`, {
|
|
819
705
|
captureStackTrace: false,
|
|
820
706
|
attributes: { ...(args as any).data },
|
|
821
707
|
}),
|
|
@@ -839,7 +725,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
839
725
|
Effect.map((res) => res as unknown as PrismaNamespace.BatchPayload),
|
|
840
726
|
Effect.catchTag('ParseError', Effect.die),
|
|
841
727
|
Effect.catchTag('NoSuchElementException', Effect.die),
|
|
842
|
-
Effect.withSpan(
|
|
728
|
+
Effect.withSpan(`\${options.spanPrefix}.createMany`, {
|
|
843
729
|
captureStackTrace: false,
|
|
844
730
|
attributes: { ...(args as any).data },
|
|
845
731
|
}),
|
|
@@ -863,7 +749,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
863
749
|
): Effect.Effect<Array<S['Type']>, never, S['Context'] | S['createManyAndReturn']['Context']> =>
|
|
864
750
|
createManyAndReturnSchema((args as any).data).pipe(
|
|
865
751
|
Effect.catchTag('ParseError', Effect.die),
|
|
866
|
-
Effect.withSpan(
|
|
752
|
+
Effect.withSpan(`\${options.spanPrefix}.createManyAndReturn`, {
|
|
867
753
|
captureStackTrace: false,
|
|
868
754
|
attributes: { ...(args as any).data },
|
|
869
755
|
}),
|
|
@@ -885,7 +771,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
885
771
|
countSchema(args).pipe(
|
|
886
772
|
Effect.catchTag('ParseError', Effect.die),
|
|
887
773
|
Effect.catchTag('NoSuchElementException', Effect.die),
|
|
888
|
-
Effect.withSpan(
|
|
774
|
+
Effect.withSpan(`\${options.spanPrefix}.count`, {
|
|
889
775
|
captureStackTrace: false,
|
|
890
776
|
attributes: { ...(args as any) },
|
|
891
777
|
}),
|
|
@@ -907,7 +793,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
907
793
|
updateSchema(args).pipe(
|
|
908
794
|
Effect.catchTag('ParseError', Effect.die),
|
|
909
795
|
Effect.catchTag('NoSuchElementException', Effect.die),
|
|
910
|
-
Effect.withSpan(
|
|
796
|
+
Effect.withSpan(`\${options.spanPrefix}.update`, {
|
|
911
797
|
captureStackTrace: false,
|
|
912
798
|
attributes: { ...(args as any) },
|
|
913
799
|
}),
|
|
@@ -929,7 +815,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
929
815
|
deleteSchema(args).pipe(
|
|
930
816
|
Effect.catchTag('ParseError', Effect.die),
|
|
931
817
|
Effect.catchTag('NoSuchElementException', Effect.die),
|
|
932
|
-
Effect.withSpan(
|
|
818
|
+
Effect.withSpan(`\${options.spanPrefix}.delete`, {
|
|
933
819
|
captureStackTrace: false,
|
|
934
820
|
attributes: { ...(args as any) },
|
|
935
821
|
}),
|
|
@@ -951,7 +837,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
951
837
|
upsertSchema(args).pipe(
|
|
952
838
|
Effect.catchTag('ParseError', Effect.die),
|
|
953
839
|
Effect.catchTag('NoSuchElementException', Effect.die),
|
|
954
|
-
Effect.withSpan(
|
|
840
|
+
Effect.withSpan(`\${options.spanPrefix}.upsert`, {
|
|
955
841
|
captureStackTrace: false,
|
|
956
842
|
attributes: { ...(args as any) },
|
|
957
843
|
}),
|
|
@@ -973,7 +859,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
973
859
|
aggregateSchema(args).pipe(
|
|
974
860
|
Effect.catchTag('ParseError', Effect.die),
|
|
975
861
|
Effect.catchTag('NoSuchElementException', Effect.die),
|
|
976
|
-
Effect.withSpan(
|
|
862
|
+
Effect.withSpan(`\${options.spanPrefix}.aggregate`, {
|
|
977
863
|
captureStackTrace: false,
|
|
978
864
|
attributes: { ...(args as any) },
|
|
979
865
|
}),
|
|
@@ -994,7 +880,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
994
880
|
): Effect.Effect<unknown, never, S['Context']> =>
|
|
995
881
|
groupBySchema(args).pipe(
|
|
996
882
|
Effect.catchTag('ParseError', Effect.die),
|
|
997
|
-
Effect.withSpan(
|
|
883
|
+
Effect.withSpan(`\${options.spanPrefix}.groupBy`, {
|
|
998
884
|
captureStackTrace: false,
|
|
999
885
|
attributes: { ...(args as any) },
|
|
1000
886
|
}),
|
|
@@ -1017,7 +903,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
1017
903
|
Effect.map((res) => res as unknown as PrismaNamespace.BatchPayload),
|
|
1018
904
|
Effect.catchTag('ParseError', Effect.die),
|
|
1019
905
|
Effect.catchTag('NoSuchElementException', Effect.die),
|
|
1020
|
-
Effect.withSpan(
|
|
906
|
+
Effect.withSpan(`\${options.spanPrefix}.updateMany`, {
|
|
1021
907
|
captureStackTrace: false,
|
|
1022
908
|
attributes: { ...(args as any) },
|
|
1023
909
|
}),
|
|
@@ -1040,7 +926,7 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
1040
926
|
Effect.map((res) => res as unknown as PrismaNamespace.BatchPayload),
|
|
1041
927
|
Effect.catchTag('ParseError', Effect.die),
|
|
1042
928
|
Effect.catchTag('NoSuchElementException', Effect.die),
|
|
1043
|
-
Effect.withSpan(
|
|
929
|
+
Effect.withSpan(`\${options.spanPrefix}.deleteMany`, {
|
|
1044
930
|
captureStackTrace: false,
|
|
1045
931
|
attributes: { ...(args as any) },
|
|
1046
932
|
}),
|
|
@@ -1066,761 +952,3 @@ export const make = <S extends Any, M extends keyof BasePrismaClient>(
|
|
|
1066
952
|
} as const
|
|
1067
953
|
|
|
1068
954
|
})
|
|
1069
|
-
`
|
|
1070
|
-
|
|
1071
|
-
generatorHandler({
|
|
1072
|
-
onManifest() {
|
|
1073
|
-
return {
|
|
1074
|
-
defaultOutput: '../generated/effect',
|
|
1075
|
-
prettyName: 'Prisma Effect Generator',
|
|
1076
|
-
// No engines required - we only read the DMMF schema
|
|
1077
|
-
requiresEngines: [],
|
|
1078
|
-
}
|
|
1079
|
-
},
|
|
1080
|
-
|
|
1081
|
-
async onGenerate(options: GeneratorOptions) {
|
|
1082
|
-
const models = options.dmmf.datamodel.models
|
|
1083
|
-
const outputDir = options.generator.output?.value
|
|
1084
|
-
const schemaDir = path.dirname(options.schemaPath)
|
|
1085
|
-
|
|
1086
|
-
const configPath = options.generator.config.clientImportPath
|
|
1087
|
-
const clientImportPath = Array.isArray(configPath) ? configPath[0] : (configPath ?? '@prisma/client')
|
|
1088
|
-
|
|
1089
|
-
const errorConfigRaw = options.generator.config.errorImportPath
|
|
1090
|
-
const errorImportPathRaw = Array.isArray(errorConfigRaw) ? errorConfigRaw[0] : errorConfigRaw
|
|
1091
|
-
|
|
1092
|
-
const importExtConfigRaw = options.generator.config.importFileExtension
|
|
1093
|
-
const importFileExtension = Array.isArray(importExtConfigRaw) ? importExtConfigRaw[0] : (importExtConfigRaw ?? '')
|
|
1094
|
-
|
|
1095
|
-
if (!outputDir) {
|
|
1096
|
-
throw new Error('No output directory specified')
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
const addExtension = (filePath: string): string => {
|
|
1100
|
-
if (!importFileExtension) {
|
|
1101
|
-
return filePath
|
|
1102
|
-
}
|
|
1103
|
-
const ext = path.extname(filePath)
|
|
1104
|
-
if (ext) {
|
|
1105
|
-
return filePath
|
|
1106
|
-
}
|
|
1107
|
-
return `${filePath}.${importFileExtension}`
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
let errorImportPath: string | undefined
|
|
1111
|
-
if (errorImportPathRaw) {
|
|
1112
|
-
const [modulePath, className] = errorImportPathRaw.split('#')
|
|
1113
|
-
if (!(modulePath && className)) {
|
|
1114
|
-
throw new Error(
|
|
1115
|
-
`Invalid errorImportPath format: "${errorImportPathRaw}". Expected "path/to/module#ErrorClassName"`,
|
|
1116
|
-
)
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
if (modulePath.startsWith('.')) {
|
|
1120
|
-
const absoluteErrorPath = path.resolve(schemaDir, modulePath)
|
|
1121
|
-
const relativeToOutput = path.relative(outputDir, absoluteErrorPath)
|
|
1122
|
-
const normalizedPath = relativeToOutput.startsWith('.') ? relativeToOutput : `./${relativeToOutput}`
|
|
1123
|
-
const pathWithExtension = addExtension(normalizedPath)
|
|
1124
|
-
errorImportPath = `${pathWithExtension}#${className}`
|
|
1125
|
-
} else {
|
|
1126
|
-
errorImportPath = errorImportPathRaw
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
|
|
1130
|
-
// Clean output directory
|
|
1131
|
-
// await fs.rm(outputDir, { recursive: true, force: true })
|
|
1132
|
-
await fs.mkdir(outputDir, { recursive: true })
|
|
1133
|
-
|
|
1134
|
-
// Write static files
|
|
1135
|
-
await fs.writeFile(path.join(outputDir, 'prisma-schema.ts'), prismaSchemaContent)
|
|
1136
|
-
await fs.writeFile(path.join(outputDir, 'prisma-repository.ts'), getPrismaModelContent(clientImportPath))
|
|
1137
|
-
|
|
1138
|
-
// Generate unified index file with PrismaService
|
|
1139
|
-
await generateUnifiedService([...models], outputDir, clientImportPath, errorImportPath)
|
|
1140
|
-
|
|
1141
|
-
// Fix imports in schemas/index.ts
|
|
1142
|
-
await fixSchemaImports(outputDir)
|
|
1143
|
-
},
|
|
1144
|
-
})
|
|
1145
|
-
|
|
1146
|
-
async function fixSchemaImports(outputDir: string) {
|
|
1147
|
-
const schemasDir = path.join(outputDir, 'schemas')
|
|
1148
|
-
const indexFile = path.join(schemasDir, 'index.ts')
|
|
1149
|
-
|
|
1150
|
-
try {
|
|
1151
|
-
const content = await fs.readFile(indexFile, 'utf-8')
|
|
1152
|
-
const fixedContent = content
|
|
1153
|
-
.replace(/export \* from '\.\/enums'/g, "export * from './enums.js'")
|
|
1154
|
-
.replace(/export \* from '\.\/types'/g, "export * from './types.js'")
|
|
1155
|
-
|
|
1156
|
-
if (content !== fixedContent) {
|
|
1157
|
-
await fs.writeFile(indexFile, fixedContent)
|
|
1158
|
-
}
|
|
1159
|
-
} catch (_error) {
|
|
1160
|
-
// Ignore if file doesn't exist
|
|
1161
|
-
}
|
|
1162
|
-
}
|
|
1163
|
-
|
|
1164
|
-
type CustomErrorConfig = { path: string; className: string } | null
|
|
1165
|
-
|
|
1166
|
-
function generateRawSqlOperations(customError: CustomErrorConfig) {
|
|
1167
|
-
const errorType = customError ? customError.className : 'PrismaError'
|
|
1168
|
-
|
|
1169
|
-
return `
|
|
1170
|
-
$executeRaw: (args: PrismaNamespace.Sql | [PrismaNamespace.Sql, ...any[]]): Effect.Effect<number, ${errorType}, PrismaClient> =>
|
|
1171
|
-
Effect.flatMap(PrismaClient, ({ tx: client }) =>
|
|
1172
|
-
Effect.tryPromise({
|
|
1173
|
-
try: () => (Array.isArray(args) ? client.$executeRaw(args[0], ...args.slice(1)) : client.$executeRaw(args)),
|
|
1174
|
-
catch: (error) => mapError(error, "$executeRaw", "Prisma")
|
|
1175
|
-
})
|
|
1176
|
-
),
|
|
1177
|
-
|
|
1178
|
-
$executeRawUnsafe: (query: string, ...values: any[]): Effect.Effect<number, ${errorType}, PrismaClient> =>
|
|
1179
|
-
Effect.flatMap(PrismaClient, ({ tx: client }) =>
|
|
1180
|
-
Effect.tryPromise({
|
|
1181
|
-
try: () => client.$executeRawUnsafe(query, ...values),
|
|
1182
|
-
catch: (error) => mapError(error, "$executeRawUnsafe", "Prisma")
|
|
1183
|
-
})
|
|
1184
|
-
),
|
|
1185
|
-
|
|
1186
|
-
$queryRaw: <T = unknown>(args: PrismaNamespace.Sql | [PrismaNamespace.Sql, ...any[]]): Effect.Effect<T, ${errorType}, PrismaClient> =>
|
|
1187
|
-
Effect.flatMap(PrismaClient, ({ tx: client }) =>
|
|
1188
|
-
Effect.tryPromise({
|
|
1189
|
-
try: () => (Array.isArray(args) ? client.$queryRaw(args[0], ...args.slice(1)) : client.$queryRaw(args)) as Promise<T>,
|
|
1190
|
-
catch: (error) => mapError(error, "$queryRaw", "Prisma")
|
|
1191
|
-
})
|
|
1192
|
-
),
|
|
1193
|
-
|
|
1194
|
-
$queryRawUnsafe: <T = unknown>(query: string, ...values: any[]): Effect.Effect<T, ${errorType}, PrismaClient> =>
|
|
1195
|
-
Effect.flatMap(PrismaClient, ({ tx: client }) =>
|
|
1196
|
-
Effect.tryPromise({
|
|
1197
|
-
try: () => client.$queryRawUnsafe(query, ...values) as Promise<T>,
|
|
1198
|
-
catch: (error) => mapError(error, "$queryRawUnsafe", "Prisma")
|
|
1199
|
-
})
|
|
1200
|
-
),`
|
|
1201
|
-
}
|
|
1202
|
-
|
|
1203
|
-
function generateModelClasses(models: DMMF.Model[]) {
|
|
1204
|
-
const modelClasses = models
|
|
1205
|
-
.map((model) => {
|
|
1206
|
-
const modelName = model.name
|
|
1207
|
-
const className = `${modelName}Model`
|
|
1208
|
-
return `export class ${className} extends Model.Class<${className}>("${modelName}")({
|
|
1209
|
-
..._${modelName}.fields
|
|
1210
|
-
}) {}`
|
|
1211
|
-
})
|
|
1212
|
-
.join('\n\n')
|
|
1213
|
-
|
|
1214
|
-
return modelClasses
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
|
-
// Parse error import path like "./errors#PrismaError" into { path, className }
|
|
1218
|
-
function parseErrorImportPath(errorImportPath: string | undefined): { path: string; className: string } | null {
|
|
1219
|
-
if (!errorImportPath) {
|
|
1220
|
-
return null
|
|
1221
|
-
}
|
|
1222
|
-
const [path, className] = errorImportPath.split('#')
|
|
1223
|
-
if (!(path && className)) {
|
|
1224
|
-
throw new Error(`Invalid errorImportPath format: "${errorImportPath}". Expected "path/to/module#ErrorClassName"`)
|
|
1225
|
-
}
|
|
1226
|
-
return { path, className }
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
async function generateUnifiedService(
|
|
1230
|
-
models: DMMF.Model[],
|
|
1231
|
-
outputDir: string,
|
|
1232
|
-
clientImportPath: string,
|
|
1233
|
-
errorImportPath: string | undefined,
|
|
1234
|
-
) {
|
|
1235
|
-
const customError = parseErrorImportPath(errorImportPath)
|
|
1236
|
-
const rawSqlOperations = generateRawSqlOperations(customError)
|
|
1237
|
-
const modelClasses = generateModelClasses(models)
|
|
1238
|
-
|
|
1239
|
-
// Generate different content based on whether custom error is configured
|
|
1240
|
-
const serviceContent = customError
|
|
1241
|
-
? generateCustomErrorService(customError, clientImportPath, rawSqlOperations, modelClasses, models)
|
|
1242
|
-
: generateDefaultErrorService(clientImportPath, rawSqlOperations, modelClasses, models)
|
|
1243
|
-
|
|
1244
|
-
await fs.writeFile(path.join(outputDir, 'index.ts'), serviceContent)
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
/**
|
|
1248
|
-
* Generate service with custom user-provided error class.
|
|
1249
|
-
*/
|
|
1250
|
-
function generateCustomErrorService(
|
|
1251
|
-
customError: { path: string; className: string },
|
|
1252
|
-
clientImportPath: string,
|
|
1253
|
-
rawSqlOperations: string,
|
|
1254
|
-
modelClasses: string,
|
|
1255
|
-
models: DMMF.Model[],
|
|
1256
|
-
): string {
|
|
1257
|
-
const schemaImports = models.map((m) => `_${m.name}`).join(', ')
|
|
1258
|
-
|
|
1259
|
-
return `${header}
|
|
1260
|
-
import { Context, Effect, Exit, Layer } from "effect"
|
|
1261
|
-
import { Service } from "effect/Effect"
|
|
1262
|
-
import { Prisma as PrismaNamespace, PrismaClient as BasePrismaClient } from "${clientImportPath}"
|
|
1263
|
-
import { ${customError.className}, mapPrismaError } from "${customError.path}"
|
|
1264
|
-
import * as Model from "./prisma-repository.js"
|
|
1265
|
-
import { ${schemaImports} } from "./schemas/index.js"
|
|
1266
|
-
|
|
1267
|
-
// Symbol used to identify intentional rollbacks vs actual errors
|
|
1268
|
-
const ROLLBACK = Symbol.for("prisma.effect.rollback")
|
|
1269
|
-
|
|
1270
|
-
// Type for the flat transaction client with commit/rollback control
|
|
1271
|
-
type FlatTransactionClient = PrismaNamespace.TransactionClient & {
|
|
1272
|
-
$commit: () => Promise<void>
|
|
1273
|
-
$rollback: () => Promise<void>
|
|
1274
|
-
}
|
|
1275
|
-
|
|
1276
|
-
/** Transaction options for $transaction and $isolatedTransaction */
|
|
1277
|
-
type TransactionOptions = {
|
|
1278
|
-
maxWait?: number
|
|
1279
|
-
timeout?: number
|
|
1280
|
-
isolationLevel?: PrismaNamespace.TransactionIsolationLevel
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
|
-
/**
|
|
1284
|
-
* Context tag for the Prisma client instance.
|
|
1285
|
-
* Holds the transaction client (tx) and root client.
|
|
1286
|
-
*/
|
|
1287
|
-
export class PrismaClient extends Context.Tag("PrismaClient")<
|
|
1288
|
-
PrismaClient,
|
|
1289
|
-
{
|
|
1290
|
-
tx: BasePrismaClient | PrismaNamespace.TransactionClient
|
|
1291
|
-
client: BasePrismaClient
|
|
1292
|
-
}
|
|
1293
|
-
>() {
|
|
1294
|
-
static layer = (
|
|
1295
|
-
...args: ConstructorParameters<typeof BasePrismaClient>
|
|
1296
|
-
) => Layer.scoped(
|
|
1297
|
-
PrismaClient,
|
|
1298
|
-
Effect.gen(function* () {
|
|
1299
|
-
const prisma = new BasePrismaClient(...args)
|
|
1300
|
-
yield* Effect.addFinalizer(() => Effect.promise(() => prisma.$disconnect()))
|
|
1301
|
-
return { tx: prisma, client: prisma }
|
|
1302
|
-
})
|
|
1303
|
-
)
|
|
1304
|
-
|
|
1305
|
-
static layerEffect = <R, E>(
|
|
1306
|
-
optionsEffect: Effect.Effect<ConstructorParameters<typeof BasePrismaClient>[0], E, R>
|
|
1307
|
-
) => Layer.scoped(
|
|
1308
|
-
PrismaClient,
|
|
1309
|
-
Effect.gen(function* () {
|
|
1310
|
-
const options = yield* optionsEffect
|
|
1311
|
-
const prisma = new BasePrismaClient(options)
|
|
1312
|
-
yield* Effect.addFinalizer(() => Effect.promise(() => prisma.$disconnect()))
|
|
1313
|
-
return { tx: prisma, client: prisma }
|
|
1314
|
-
})
|
|
1315
|
-
)
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
// Re-export the custom error type for convenience
|
|
1319
|
-
export { ${customError.className} }
|
|
1320
|
-
|
|
1321
|
-
// Use the user-provided error mapper
|
|
1322
|
-
const mapError = mapPrismaError
|
|
1323
|
-
|
|
1324
|
-
/**
|
|
1325
|
-
* Internal helper to begin a callback-free interactive transaction.
|
|
1326
|
-
*/
|
|
1327
|
-
const $begin = (
|
|
1328
|
-
client: BasePrismaClient,
|
|
1329
|
-
options?: {
|
|
1330
|
-
maxWait?: number
|
|
1331
|
-
timeout?: number
|
|
1332
|
-
isolationLevel?: PrismaNamespace.TransactionIsolationLevel
|
|
1333
|
-
}
|
|
1334
|
-
): Effect.Effect<FlatTransactionClient, ${customError.className}> =>
|
|
1335
|
-
Effect.async<FlatTransactionClient, ${customError.className}>((resume) => {
|
|
1336
|
-
let setTxClient: (txClient: PrismaNamespace.TransactionClient) => void
|
|
1337
|
-
let commit: () => void
|
|
1338
|
-
let rollback: () => void
|
|
1339
|
-
|
|
1340
|
-
const txClientPromise = new Promise<PrismaNamespace.TransactionClient>((res) => {
|
|
1341
|
-
setTxClient = res
|
|
1342
|
-
})
|
|
1343
|
-
|
|
1344
|
-
const txPromise = new Promise<void>((_res, _rej) => {
|
|
1345
|
-
commit = () => _res(undefined)
|
|
1346
|
-
rollback = () => _rej(ROLLBACK)
|
|
1347
|
-
})
|
|
1348
|
-
|
|
1349
|
-
const tx = client.$transaction((txClient) => {
|
|
1350
|
-
setTxClient(txClient)
|
|
1351
|
-
return txPromise
|
|
1352
|
-
}, options).catch((e) => {
|
|
1353
|
-
if (e === ROLLBACK) return
|
|
1354
|
-
throw e
|
|
1355
|
-
})
|
|
1356
|
-
|
|
1357
|
-
txClientPromise.then((innerTx) => {
|
|
1358
|
-
const proxy = new Proxy(innerTx, {
|
|
1359
|
-
get(target, prop) {
|
|
1360
|
-
if (prop === "$commit") return () => { commit(); return tx }
|
|
1361
|
-
if (prop === "$rollback") return () => { rollback(); return tx }
|
|
1362
|
-
return target[prop as keyof typeof target]
|
|
1363
|
-
},
|
|
1364
|
-
}) as FlatTransactionClient
|
|
1365
|
-
resume(Effect.succeed(proxy))
|
|
1366
|
-
}).catch((error) => {
|
|
1367
|
-
resume(Effect.fail(mapError(error, "$transaction", "Prisma")))
|
|
1368
|
-
})
|
|
1369
|
-
})
|
|
1370
|
-
|
|
1371
|
-
/**
|
|
1372
|
-
* The main Prisma service with all database operations.
|
|
1373
|
-
* Provides type-safe, effectful access to your Prisma models.
|
|
1374
|
-
*/
|
|
1375
|
-
export class Prisma extends Service<Prisma>()("Prisma", {
|
|
1376
|
-
effect: Effect.gen(function* () {
|
|
1377
|
-
return {
|
|
1378
|
-
$transaction: <R, E, A>(
|
|
1379
|
-
effect: Effect.Effect<A, E, R>,
|
|
1380
|
-
options?: TransactionOptions
|
|
1381
|
-
) =>
|
|
1382
|
-
Effect.flatMap(
|
|
1383
|
-
PrismaClient,
|
|
1384
|
-
({ client, tx }): Effect.Effect<A, E | ${customError.className}, R> => {
|
|
1385
|
-
const isRootClient = "$transaction" in tx
|
|
1386
|
-
if (!isRootClient) {
|
|
1387
|
-
return effect
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
return Effect.acquireUseRelease(
|
|
1391
|
-
$begin(client, options),
|
|
1392
|
-
(txClient) =>
|
|
1393
|
-
effect.pipe(
|
|
1394
|
-
Effect.provideService(PrismaClient, { tx: txClient, client })
|
|
1395
|
-
),
|
|
1396
|
-
(txClient, exit) =>
|
|
1397
|
-
Exit.isSuccess(exit)
|
|
1398
|
-
? Effect.promise(() => txClient.$commit())
|
|
1399
|
-
: Effect.promise(() => txClient.$rollback())
|
|
1400
|
-
)
|
|
1401
|
-
}
|
|
1402
|
-
),
|
|
1403
|
-
|
|
1404
|
-
$isolatedTransaction: <R, E, A>(
|
|
1405
|
-
effect: Effect.Effect<A, E, R>,
|
|
1406
|
-
options?: TransactionOptions
|
|
1407
|
-
) =>
|
|
1408
|
-
Effect.flatMap(
|
|
1409
|
-
PrismaClient,
|
|
1410
|
-
({ client }): Effect.Effect<A, E | ${customError.className}, R> => {
|
|
1411
|
-
return Effect.acquireUseRelease(
|
|
1412
|
-
$begin(client, options),
|
|
1413
|
-
(txClient) =>
|
|
1414
|
-
effect.pipe(
|
|
1415
|
-
Effect.provideService(PrismaClient, { tx: txClient, client })
|
|
1416
|
-
),
|
|
1417
|
-
(txClient, exit) =>
|
|
1418
|
-
Exit.isSuccess(exit)
|
|
1419
|
-
? Effect.promise(() => txClient.$commit())
|
|
1420
|
-
: Effect.promise(() => txClient.$rollback())
|
|
1421
|
-
)
|
|
1422
|
-
}
|
|
1423
|
-
),
|
|
1424
|
-
${rawSqlOperations}
|
|
1425
|
-
}
|
|
1426
|
-
})
|
|
1427
|
-
}) {
|
|
1428
|
-
static layer = (
|
|
1429
|
-
...args: ConstructorParameters<typeof BasePrismaClient>
|
|
1430
|
-
) => Layer.merge(PrismaClient.layer(...args), Prisma.Default)
|
|
1431
|
-
|
|
1432
|
-
static layerEffect = <R, E>(
|
|
1433
|
-
optionsEffect: Effect.Effect<ConstructorParameters<typeof BasePrismaClient>[0], E, R>
|
|
1434
|
-
) => Layer.merge(PrismaClient.layerEffect(optionsEffect), Prisma.Default)
|
|
1435
|
-
|
|
1436
|
-
}
|
|
1437
|
-
|
|
1438
|
-
// ============================================================================
|
|
1439
|
-
// Deprecated aliases for backward compatibility
|
|
1440
|
-
// ============================================================================
|
|
1441
|
-
|
|
1442
|
-
export const PrismaClientService = PrismaClient
|
|
1443
|
-
export const PrismaService = Prisma
|
|
1444
|
-
export const makePrismaLayer = PrismaClient.layer
|
|
1445
|
-
export const makePrismaLayerEffect = PrismaClient.layerEffect
|
|
1446
|
-
|
|
1447
|
-
${modelClasses}
|
|
1448
|
-
`
|
|
1449
|
-
}
|
|
1450
|
-
|
|
1451
|
-
/**
|
|
1452
|
-
* Generate service with default tagged error classes.
|
|
1453
|
-
*/
|
|
1454
|
-
function generateDefaultErrorService(
|
|
1455
|
-
clientImportPath: string,
|
|
1456
|
-
rawSqlOperations: string,
|
|
1457
|
-
modelClasses: string,
|
|
1458
|
-
models: DMMF.Model[],
|
|
1459
|
-
): string {
|
|
1460
|
-
const schemaImports = models.map((m) => `_${m.name}`).join(', ')
|
|
1461
|
-
|
|
1462
|
-
return `${header}
|
|
1463
|
-
import { Context, Data, Effect, Exit, Layer } from "effect"
|
|
1464
|
-
import { Service } from "effect/Effect"
|
|
1465
|
-
import { Prisma as PrismaNamespace, PrismaClient as BasePrismaClient } from "${clientImportPath}"
|
|
1466
|
-
import * as Model from "./prisma-repository.js"
|
|
1467
|
-
import { ${schemaImports} } from "./schemas/index.js"
|
|
1468
|
-
|
|
1469
|
-
// Symbol used to identify intentional rollbacks vs actual errors
|
|
1470
|
-
const ROLLBACK = Symbol.for("prisma.effect.rollback")
|
|
1471
|
-
|
|
1472
|
-
// Type for the flat transaction client with commit/rollback control
|
|
1473
|
-
type FlatTransactionClient = PrismaNamespace.TransactionClient & {
|
|
1474
|
-
$commit: () => Promise<void>
|
|
1475
|
-
$rollback: () => Promise<void>
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1478
|
-
/** Transaction options for $transaction and $isolatedTransaction */
|
|
1479
|
-
type TransactionOptions = {
|
|
1480
|
-
maxWait?: number
|
|
1481
|
-
timeout?: number
|
|
1482
|
-
isolationLevel?: PrismaNamespace.TransactionIsolationLevel
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
/**
|
|
1486
|
-
* Context tag for the Prisma client instance.
|
|
1487
|
-
* Holds the transaction client (tx) and root client.
|
|
1488
|
-
*/
|
|
1489
|
-
export class PrismaClient extends Context.Tag("PrismaClient")<
|
|
1490
|
-
PrismaClient,
|
|
1491
|
-
{
|
|
1492
|
-
tx: BasePrismaClient | PrismaNamespace.TransactionClient
|
|
1493
|
-
client: BasePrismaClient
|
|
1494
|
-
}
|
|
1495
|
-
>() {
|
|
1496
|
-
static layer = (
|
|
1497
|
-
...args: ConstructorParameters<typeof BasePrismaClient>
|
|
1498
|
-
) => Layer.scoped(
|
|
1499
|
-
PrismaClient,
|
|
1500
|
-
Effect.gen(function* () {
|
|
1501
|
-
const prisma = new BasePrismaClient(...args)
|
|
1502
|
-
yield* Effect.addFinalizer(() => Effect.promise(() => prisma.$disconnect()))
|
|
1503
|
-
return { tx: prisma, client: prisma }
|
|
1504
|
-
})
|
|
1505
|
-
)
|
|
1506
|
-
|
|
1507
|
-
static layerEffect = <R, E>(
|
|
1508
|
-
optionsEffect: Effect.Effect<ConstructorParameters<typeof BasePrismaClient>[0], E, R>
|
|
1509
|
-
) => Layer.scoped(
|
|
1510
|
-
PrismaClient,
|
|
1511
|
-
Effect.gen(function* () {
|
|
1512
|
-
const options = yield* optionsEffect
|
|
1513
|
-
const prisma = new BasePrismaClient(options)
|
|
1514
|
-
yield* Effect.addFinalizer(() => Effect.promise(() => prisma.$disconnect()))
|
|
1515
|
-
return { tx: prisma, client: prisma }
|
|
1516
|
-
})
|
|
1517
|
-
)
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
export class PrismaUniqueConstraintError extends Data.TaggedError("PrismaUniqueConstraintError")<{
|
|
1521
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1522
|
-
operation: string
|
|
1523
|
-
model: string
|
|
1524
|
-
}> {}
|
|
1525
|
-
|
|
1526
|
-
export class PrismaForeignKeyConstraintError extends Data.TaggedError("PrismaForeignKeyConstraintError")<{
|
|
1527
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1528
|
-
operation: string
|
|
1529
|
-
model: string
|
|
1530
|
-
}> {}
|
|
1531
|
-
|
|
1532
|
-
export class PrismaRecordNotFoundError extends Data.TaggedError("PrismaRecordNotFoundError")<{
|
|
1533
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1534
|
-
operation: string
|
|
1535
|
-
model: string
|
|
1536
|
-
}> {}
|
|
1537
|
-
|
|
1538
|
-
export class PrismaRelationViolationError extends Data.TaggedError("PrismaRelationViolationError")<{
|
|
1539
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1540
|
-
operation: string
|
|
1541
|
-
model: string
|
|
1542
|
-
}> {}
|
|
1543
|
-
|
|
1544
|
-
export class PrismaRelatedRecordNotFoundError extends Data.TaggedError("PrismaRelatedRecordNotFoundError")<{
|
|
1545
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1546
|
-
operation: string
|
|
1547
|
-
model: string
|
|
1548
|
-
}> {}
|
|
1549
|
-
|
|
1550
|
-
export class PrismaTransactionConflictError extends Data.TaggedError("PrismaTransactionConflictError")<{
|
|
1551
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1552
|
-
operation: string
|
|
1553
|
-
model: string
|
|
1554
|
-
}> {}
|
|
1555
|
-
|
|
1556
|
-
export class PrismaValueTooLongError extends Data.TaggedError("PrismaValueTooLongError")<{
|
|
1557
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1558
|
-
operation: string
|
|
1559
|
-
model: string
|
|
1560
|
-
}> {}
|
|
1561
|
-
|
|
1562
|
-
export class PrismaValueOutOfRangeError extends Data.TaggedError("PrismaValueOutOfRangeError")<{
|
|
1563
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1564
|
-
operation: string
|
|
1565
|
-
model: string
|
|
1566
|
-
}> {}
|
|
1567
|
-
|
|
1568
|
-
export class PrismaDbConstraintError extends Data.TaggedError("PrismaDbConstraintError")<{
|
|
1569
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1570
|
-
operation: string
|
|
1571
|
-
model: string
|
|
1572
|
-
}> {}
|
|
1573
|
-
|
|
1574
|
-
export class PrismaConnectionError extends Data.TaggedError("PrismaConnectionError")<{
|
|
1575
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1576
|
-
operation: string
|
|
1577
|
-
model: string
|
|
1578
|
-
}> {}
|
|
1579
|
-
|
|
1580
|
-
export class PrismaMissingRequiredValueError extends Data.TaggedError("PrismaMissingRequiredValueError")<{
|
|
1581
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1582
|
-
operation: string
|
|
1583
|
-
model: string
|
|
1584
|
-
}> {}
|
|
1585
|
-
|
|
1586
|
-
export class PrismaInputValidationError extends Data.TaggedError("PrismaInputValidationError")<{
|
|
1587
|
-
cause: PrismaNamespace.PrismaClientKnownRequestError
|
|
1588
|
-
operation: string
|
|
1589
|
-
model: string
|
|
1590
|
-
}> {}
|
|
1591
|
-
|
|
1592
|
-
export type PrismaCreateError =
|
|
1593
|
-
| PrismaValueTooLongError
|
|
1594
|
-
| PrismaUniqueConstraintError
|
|
1595
|
-
| PrismaForeignKeyConstraintError
|
|
1596
|
-
| PrismaDbConstraintError
|
|
1597
|
-
| PrismaInputValidationError
|
|
1598
|
-
| PrismaMissingRequiredValueError
|
|
1599
|
-
| PrismaRelatedRecordNotFoundError
|
|
1600
|
-
| PrismaValueOutOfRangeError
|
|
1601
|
-
| PrismaConnectionError
|
|
1602
|
-
| PrismaTransactionConflictError
|
|
1603
|
-
|
|
1604
|
-
export type PrismaUpdateError =
|
|
1605
|
-
| PrismaValueTooLongError
|
|
1606
|
-
| PrismaUniqueConstraintError
|
|
1607
|
-
| PrismaForeignKeyConstraintError
|
|
1608
|
-
| PrismaDbConstraintError
|
|
1609
|
-
| PrismaInputValidationError
|
|
1610
|
-
| PrismaMissingRequiredValueError
|
|
1611
|
-
| PrismaRelationViolationError
|
|
1612
|
-
| PrismaRelatedRecordNotFoundError
|
|
1613
|
-
| PrismaValueOutOfRangeError
|
|
1614
|
-
| PrismaConnectionError
|
|
1615
|
-
| PrismaRecordNotFoundError
|
|
1616
|
-
| PrismaTransactionConflictError
|
|
1617
|
-
|
|
1618
|
-
export type PrismaDeleteError =
|
|
1619
|
-
| PrismaForeignKeyConstraintError
|
|
1620
|
-
| PrismaRelationViolationError
|
|
1621
|
-
| PrismaConnectionError
|
|
1622
|
-
| PrismaRecordNotFoundError
|
|
1623
|
-
| PrismaTransactionConflictError
|
|
1624
|
-
|
|
1625
|
-
export type PrismaFindOrThrowError =
|
|
1626
|
-
| PrismaConnectionError
|
|
1627
|
-
| PrismaRecordNotFoundError
|
|
1628
|
-
|
|
1629
|
-
export type PrismaFindError =
|
|
1630
|
-
| PrismaConnectionError
|
|
1631
|
-
|
|
1632
|
-
export type PrismaDeleteManyError =
|
|
1633
|
-
| PrismaForeignKeyConstraintError
|
|
1634
|
-
| PrismaRelationViolationError
|
|
1635
|
-
| PrismaConnectionError
|
|
1636
|
-
| PrismaTransactionConflictError
|
|
1637
|
-
|
|
1638
|
-
export type PrismaUpdateManyError =
|
|
1639
|
-
| PrismaValueTooLongError
|
|
1640
|
-
| PrismaUniqueConstraintError
|
|
1641
|
-
| PrismaForeignKeyConstraintError
|
|
1642
|
-
| PrismaDbConstraintError
|
|
1643
|
-
| PrismaInputValidationError
|
|
1644
|
-
| PrismaMissingRequiredValueError
|
|
1645
|
-
| PrismaValueOutOfRangeError
|
|
1646
|
-
| PrismaConnectionError
|
|
1647
|
-
| PrismaTransactionConflictError
|
|
1648
|
-
|
|
1649
|
-
export type PrismaError =
|
|
1650
|
-
| PrismaValueTooLongError
|
|
1651
|
-
| PrismaUniqueConstraintError
|
|
1652
|
-
| PrismaForeignKeyConstraintError
|
|
1653
|
-
| PrismaDbConstraintError
|
|
1654
|
-
| PrismaInputValidationError
|
|
1655
|
-
| PrismaMissingRequiredValueError
|
|
1656
|
-
| PrismaRelationViolationError
|
|
1657
|
-
| PrismaRelatedRecordNotFoundError
|
|
1658
|
-
| PrismaValueOutOfRangeError
|
|
1659
|
-
| PrismaConnectionError
|
|
1660
|
-
| PrismaRecordNotFoundError
|
|
1661
|
-
| PrismaTransactionConflictError
|
|
1662
|
-
|
|
1663
|
-
// Generic mapper for raw operations and fallback
|
|
1664
|
-
const mapError = (error: unknown, operation: string, model: string): PrismaError => {
|
|
1665
|
-
if (error instanceof PrismaNamespace.PrismaClientKnownRequestError) {
|
|
1666
|
-
switch (error.code) {
|
|
1667
|
-
case "P2000":
|
|
1668
|
-
return new PrismaValueTooLongError({ cause: error, operation, model });
|
|
1669
|
-
case "P2002":
|
|
1670
|
-
return new PrismaUniqueConstraintError({ cause: error, operation, model });
|
|
1671
|
-
case "P2003":
|
|
1672
|
-
return new PrismaForeignKeyConstraintError({ cause: error, operation, model });
|
|
1673
|
-
case "P2004":
|
|
1674
|
-
return new PrismaDbConstraintError({ cause: error, operation, model });
|
|
1675
|
-
case "P2005":
|
|
1676
|
-
case "P2006":
|
|
1677
|
-
case "P2019":
|
|
1678
|
-
return new PrismaInputValidationError({ cause: error, operation, model });
|
|
1679
|
-
case "P2011":
|
|
1680
|
-
case "P2012":
|
|
1681
|
-
return new PrismaMissingRequiredValueError({ cause: error, operation, model });
|
|
1682
|
-
case "P2014":
|
|
1683
|
-
return new PrismaRelationViolationError({ cause: error, operation, model });
|
|
1684
|
-
case "P2015":
|
|
1685
|
-
case "P2018":
|
|
1686
|
-
return new PrismaRelatedRecordNotFoundError({ cause: error, operation, model });
|
|
1687
|
-
case "P2020":
|
|
1688
|
-
return new PrismaValueOutOfRangeError({ cause: error, operation, model });
|
|
1689
|
-
case "P2024":
|
|
1690
|
-
return new PrismaConnectionError({ cause: error, operation, model });
|
|
1691
|
-
case "P2025":
|
|
1692
|
-
return new PrismaRecordNotFoundError({ cause: error, operation, model });
|
|
1693
|
-
case "P2034":
|
|
1694
|
-
return new PrismaTransactionConflictError({ cause: error, operation, model });
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
// Unknown errors are not handled and will be treated as defects
|
|
1698
|
-
throw error;
|
|
1699
|
-
}
|
|
1700
|
-
|
|
1701
|
-
/**
|
|
1702
|
-
* Internal helper to begin a callback-free interactive transaction.
|
|
1703
|
-
*/
|
|
1704
|
-
const $begin = (
|
|
1705
|
-
client: BasePrismaClient,
|
|
1706
|
-
options?: {
|
|
1707
|
-
maxWait?: number
|
|
1708
|
-
timeout?: number
|
|
1709
|
-
isolationLevel?: PrismaNamespace.TransactionIsolationLevel
|
|
1710
|
-
}
|
|
1711
|
-
): Effect.Effect<FlatTransactionClient, PrismaError> =>
|
|
1712
|
-
Effect.async<FlatTransactionClient, PrismaError>((resume) => {
|
|
1713
|
-
let setTxClient: (txClient: PrismaNamespace.TransactionClient) => void
|
|
1714
|
-
let commit: () => void
|
|
1715
|
-
let rollback: () => void
|
|
1716
|
-
|
|
1717
|
-
const txClientPromise = new Promise<PrismaNamespace.TransactionClient>((res) => {
|
|
1718
|
-
setTxClient = res
|
|
1719
|
-
})
|
|
1720
|
-
|
|
1721
|
-
const txPromise = new Promise<void>((_res, _rej) => {
|
|
1722
|
-
commit = () => _res(undefined)
|
|
1723
|
-
rollback = () => _rej(ROLLBACK)
|
|
1724
|
-
})
|
|
1725
|
-
|
|
1726
|
-
const tx = client.$transaction((txClient) => {
|
|
1727
|
-
setTxClient(txClient)
|
|
1728
|
-
return txPromise
|
|
1729
|
-
}, options).catch((e) => {
|
|
1730
|
-
if (e === ROLLBACK) return
|
|
1731
|
-
throw e
|
|
1732
|
-
})
|
|
1733
|
-
|
|
1734
|
-
txClientPromise.then((innerTx) => {
|
|
1735
|
-
const proxy = new Proxy(innerTx, {
|
|
1736
|
-
get(target, prop) {
|
|
1737
|
-
if (prop === "$commit") return () => { commit(); return tx }
|
|
1738
|
-
if (prop === "$rollback") return () => { rollback(); return tx }
|
|
1739
|
-
return target[prop as keyof typeof target]
|
|
1740
|
-
},
|
|
1741
|
-
}) as FlatTransactionClient
|
|
1742
|
-
resume(Effect.succeed(proxy))
|
|
1743
|
-
}).catch((error) => {
|
|
1744
|
-
resume(Effect.fail(mapError(error, "$transaction", "Prisma")))
|
|
1745
|
-
})
|
|
1746
|
-
})
|
|
1747
|
-
|
|
1748
|
-
/**
|
|
1749
|
-
* The main Prisma service with all database operations.
|
|
1750
|
-
* Provides type-safe, effectful access to your Prisma models.
|
|
1751
|
-
*/
|
|
1752
|
-
export class Prisma extends Service<Prisma>()("Prisma", {
|
|
1753
|
-
effect: Effect.gen(function* () {
|
|
1754
|
-
return {
|
|
1755
|
-
$transaction: <R, E, A>(
|
|
1756
|
-
effect: Effect.Effect<A, E, R>,
|
|
1757
|
-
options?: TransactionOptions
|
|
1758
|
-
) =>
|
|
1759
|
-
Effect.flatMap(
|
|
1760
|
-
PrismaClient,
|
|
1761
|
-
({ client, tx }): Effect.Effect<A, E | PrismaError, R> => {
|
|
1762
|
-
const isRootClient = "$transaction" in tx
|
|
1763
|
-
if (!isRootClient) {
|
|
1764
|
-
return effect
|
|
1765
|
-
}
|
|
1766
|
-
|
|
1767
|
-
return Effect.acquireUseRelease(
|
|
1768
|
-
$begin(client, options),
|
|
1769
|
-
(txClient) =>
|
|
1770
|
-
effect.pipe(
|
|
1771
|
-
Effect.provideService(PrismaClient, { tx: txClient, client })
|
|
1772
|
-
),
|
|
1773
|
-
(txClient, exit) =>
|
|
1774
|
-
Exit.isSuccess(exit)
|
|
1775
|
-
? Effect.promise(() => txClient.$commit())
|
|
1776
|
-
: Effect.promise(() => txClient.$rollback())
|
|
1777
|
-
)
|
|
1778
|
-
}
|
|
1779
|
-
),
|
|
1780
|
-
|
|
1781
|
-
$isolatedTransaction: <R, E, A>(
|
|
1782
|
-
effect: Effect.Effect<A, E, R>,
|
|
1783
|
-
options?: TransactionOptions
|
|
1784
|
-
) =>
|
|
1785
|
-
Effect.flatMap(
|
|
1786
|
-
PrismaClient,
|
|
1787
|
-
({ client }): Effect.Effect<A, E | PrismaError, R> => {
|
|
1788
|
-
return Effect.acquireUseRelease(
|
|
1789
|
-
$begin(client, options),
|
|
1790
|
-
(txClient) =>
|
|
1791
|
-
effect.pipe(
|
|
1792
|
-
Effect.provideService(PrismaClient, { tx: txClient, client })
|
|
1793
|
-
),
|
|
1794
|
-
(txClient, exit) =>
|
|
1795
|
-
Exit.isSuccess(exit)
|
|
1796
|
-
? Effect.promise(() => txClient.$commit())
|
|
1797
|
-
: Effect.promise(() => txClient.$rollback())
|
|
1798
|
-
)
|
|
1799
|
-
}
|
|
1800
|
-
),
|
|
1801
|
-
${rawSqlOperations}
|
|
1802
|
-
}
|
|
1803
|
-
})
|
|
1804
|
-
}) {
|
|
1805
|
-
static layer = (
|
|
1806
|
-
...args: ConstructorParameters<typeof BasePrismaClient>
|
|
1807
|
-
) => Layer.merge(PrismaClient.layer(...args), Prisma.Default)
|
|
1808
|
-
|
|
1809
|
-
static layerEffect = <R, E>(
|
|
1810
|
-
optionsEffect: Effect.Effect<ConstructorParameters<typeof BasePrismaClient>[0], E, R>
|
|
1811
|
-
) => Layer.merge(PrismaClient.layerEffect(optionsEffect), Prisma.Default)
|
|
1812
|
-
|
|
1813
|
-
}
|
|
1814
|
-
|
|
1815
|
-
// ============================================================================
|
|
1816
|
-
// Deprecated aliases for backward compatibility
|
|
1817
|
-
// ============================================================================
|
|
1818
|
-
|
|
1819
|
-
export const PrismaClientService = PrismaClient
|
|
1820
|
-
export const PrismaService = Prisma
|
|
1821
|
-
export const makePrismaLayer = PrismaClient.layer
|
|
1822
|
-
export const makePrismaLayerEffect = PrismaClient.layerEffect
|
|
1823
|
-
|
|
1824
|
-
${modelClasses}
|
|
1825
|
-
`
|
|
1826
|
-
}
|