| 1 | import { |
| 2 | defineContract as nativeDefineContract, |
| 3 | field as nativeField, |
| 4 | model as nativeModel, |
| 5 | } from "@prisma/orm-postgres/contract-builder"; |
| 6 | import type { |
| 7 | Contract, |
| 8 | NamespaceId, |
| 9 | } from "@prisma/orm-postgres/contract/types"; |
| 10 | import type { |
| 11 | ContractWithTypeMaps, |
| 12 | ExtractTypeMapsFromContract, |
| 13 | SqlStorage, |
| 14 | TypeMapsPhantomKey, |
| 15 | } from "@prisma/orm-postgres/family-contract/types"; |
| 16 | import type { FieldHelpers, Helpers, ModelHelper } from "./AuthoringTypes.ts"; |
| 17 | import type { PostgresAggregateTypes } from "./PostgresAggregateTypes.ts"; |
| 18 | import type { CodecTypes } from "@prisma/orm-postgres/target/codec-types"; |
| 19 | import type { QueryOperationTypes } from "@prisma/orm-postgres/adapter/operation-types"; |
| 20 | |
| 21 | // Native authoring stays behind an opt-in module to preserve the optional peer. |
| 22 | export * from "@prisma/orm-postgres/contract-builder"; |
| 23 | export type { DescriptorCodecInput } from "@prisma/orm-postgres/relational-core/ast"; |
| 24 | export const field = nativeField as FieldHelpers<typeof nativeField>; |
| 25 | export const model = nativeModel as ModelHelper; |
| 26 | |
| 27 | type NativeFactory = Parameters<typeof nativeDefineContract>[1]; |
| 28 | type Authored = ReturnType<NativeFactory>; |
| 29 | type Types = NonNullable<Authored["types"]>; |
| 30 | type Models = NonNullable<Authored["models"]>; |
| 31 | type Enums = NonNullable<Authored["enums"]>; |
| 32 | type Extensions = Parameters<typeof nativeDefineContract>[0]["extensions"]; |
| 33 | type Empty = Record<never, never>; |
| 34 | type IdentityNaming = { |
| 35 | readonly naming?: { |
| 36 | readonly tables?: "identity"; |
| 37 | readonly columns?: "identity"; |
| 38 | }; |
| 39 | }; |
| 40 | type ContractShape = Pick<Contract<SqlStorage>, "domain"> & { |
| 41 | readonly storage: Pick<SqlStorage, "namespaces">; |
| 42 | }; |
| 43 | type Known<T> = { |
| 44 | [ |
| 45 | K in keyof T as string extends K ? never : number extends K ? never : K |
| 46 | ]: T[K]; |
| 47 | }; |
| 48 | type State<F> = F extends { readonly __state: infer S } ? S : never; |
| 49 | type Fields<M> = M extends { readonly stageOne: { readonly fields: infer F } } |
| 50 | ? F |
| 51 | : never; |
| 52 | type Relations<M> = M extends { |
| 53 | readonly stageOne: { readonly relations: infer R }; |
| 54 | } |
| 55 | ? R |
| 56 | : never; |
| 57 | type Namespace<M> = M extends { |
| 58 | readonly stageOne: { readonly namespace?: infer N extends string }; |
| 59 | } |
| 60 | ? N extends "unbound" |
| 61 | ? "__unbound__" |
| 62 | : N |
| 63 | : "public"; |
| 64 | type Namespaces<Ms extends Models> = Namespace<Ms[keyof Ms]>; |
| 65 | type ModelRef<R> = R extends { readonly modelName: infer M extends string } |
| 66 | ? M |
| 67 | : R extends { readonly resolve: () => infer M extends string } |
| 68 | ? M |
| 69 | : never; |
| 70 | type Tuple<T> = T extends readonly string[] |
| 71 | ? T |
| 72 | : T extends string |
| 73 | ? readonly [T] |
| 74 | : readonly []; |
| 75 | type InlineIds<M> = { |
| 76 | [K in keyof Fields<M>]: State<Fields<M>[K]> extends { readonly id: object } |
| 77 | ? K |
| 78 | : never; |
| 79 | }[keyof Fields<M>] & |
| 80 | string; |
| 81 | type PrimaryFields<M> = M extends { |
| 82 | readonly __attributes: { |
| 83 | readonly id: { readonly fields: infer F extends readonly string[] }; |
| 84 | }; |
| 85 | } |
| 86 | ? F |
| 87 | : readonly [InlineIds<M>]; |
| 88 | type NullableFields<M> = { |
| 89 | [K in keyof Fields<M>]: State<Fields<M>[K]> extends { |
| 90 | readonly nullable: true; |
| 91 | } |
| 92 | ? K |
| 93 | : never; |
| 94 | }[keyof Fields<M>]; |
| 95 | type IsNullable<M, F> = |
| 96 | Extract<Tuple<F>[number], NullableFields<M>> extends never ? false : true; |
| 97 | type NativeModels<C extends ContractShape> = |
| 98 | C["domain"]["namespaces"][string]["models"]; |
| 99 | type Table< |
| 100 | C extends ContractShape, |
| 101 | M extends keyof NativeModels<C>, |
| 102 | > = NativeModels<C>[M]["storage"]["table"] & string; |
| 103 | type Column< |
| 104 | C extends ContractShape, |
| 105 | M extends keyof NativeModels<C>, |
| 106 | F, |
| 107 | > = F extends keyof NativeModels<C>[M]["storage"]["fields"] |
| 108 | ? NativeModels<C>[M]["storage"]["fields"][F] extends { |
| 109 | readonly column: infer Col extends string; |
| 110 | } |
| 111 | ? Col |
| 112 | : never |
| 113 | : never; |
| 114 | type Columns< |
| 115 | C extends ContractShape, |
| 116 | M extends keyof NativeModels<C>, |
| 117 | Fs extends readonly string[], |
| 118 | > = { readonly [K in keyof Fs]: Column<C, M, Fs[K]> }; |
| 119 | |
| 120 | type RelationType< |
| 121 | C extends ContractShape, |
| 122 | Ms extends Models, |
| 123 | M extends keyof Ms, |
| 124 | R, |
| 125 | > = R extends { readonly kind: infer Kind; readonly toModel: infer To } |
| 126 | ? ModelRef<To> extends keyof Ms |
| 127 | ? { |
| 128 | readonly to: { |
| 129 | readonly namespace: Namespace<Ms[ModelRef<To>]> & NamespaceId; |
| 130 | readonly model: ModelRef<To>; |
| 131 | }; |
| 132 | } & (R extends { |
| 133 | readonly kind: "belongsTo"; |
| 134 | readonly from: infer From; |
| 135 | readonly to: infer Target; |
| 136 | } |
| 137 | ? { |
| 138 | readonly cardinality: "N:1"; |
| 139 | readonly nullable: IsNullable<Ms[M], From>; |
| 140 | readonly on: { |
| 141 | readonly localFields: Tuple<From>; |
| 142 | readonly targetFields: Tuple<Target>; |
| 143 | }; |
| 144 | } |
| 145 | : R extends { |
| 146 | readonly kind: "hasMany" | "hasOne"; |
| 147 | readonly by: infer By; |
| 148 | } |
| 149 | ? { |
| 150 | readonly cardinality: Kind extends "hasOne" ? "1:1" : "1:N"; |
| 151 | readonly nullable: true; |
| 152 | readonly on: { |
| 153 | readonly localFields: PrimaryFields<Ms[M]>; |
| 154 | readonly targetFields: Tuple<By>; |
| 155 | }; |
| 156 | } |
| 157 | : R extends { |
| 158 | readonly kind: "manyToMany"; |
| 159 | readonly through: infer Through; |
| 160 | readonly from: infer From; |
| 161 | readonly to: infer Target; |
| 162 | } |
| 163 | ? ModelRef<Through> extends keyof Ms & keyof NativeModels<C> |
| 164 | ? { |
| 165 | readonly cardinality: "N:M"; |
| 166 | readonly on: { |
| 167 | readonly localFields: PrimaryFields<Ms[M]>; |
| 168 | readonly targetFields: PrimaryFields<Ms[ModelRef<To>]>; |
| 169 | }; |
| 170 | readonly through: { |
| 171 | readonly namespaceId: Namespace<Ms[ModelRef<Through>]>; |
| 172 | readonly table: Table<C, ModelRef<Through>>; |
| 173 | readonly parentColumns: Columns< |
| 174 | C, |
| 175 | ModelRef<Through>, |
| 176 | Tuple<From> |
| 177 | >; |
| 178 | readonly childColumns: Columns< |
| 179 | C, |
| 180 | ModelRef<Through>, |
| 181 | Tuple<Target> |
| 182 | >; |
| 183 | readonly targetColumns: Columns< |
| 184 | C, |
| 185 | ModelRef<To> & keyof NativeModels<C>, |
| 186 | PrimaryFields<Ms[ModelRef<To>]> |
| 187 | >; |
| 188 | }; |
| 189 | } |
| 190 | : never |
| 191 | : never) |
| 192 | : never |
| 193 | : never; |
| 194 | |
| 195 | type Unmany<T> = T extends readonly (infer A)[] ? A : T; |
| 196 | type FixFields<C extends ContractShape, Ms extends Models, Map> = Map extends { |
| 197 | readonly public: infer ModelsMap; |
| 198 | } |
| 199 | ? { |
| 200 | readonly [Ns in Namespaces<Ms>]: { |
| 201 | readonly [ |
| 202 | M in keyof ModelsMap & keyof Ms as Namespace<Ms[M]> extends Ns |
| 203 | ? M |
| 204 | : never |
| 205 | ]: { |
| 206 | readonly [F in keyof ModelsMap[M]]: F extends keyof Fields<Ms[M]> |
| 207 | ? true extends State<Fields<Ms[M]>[F]>["many"] |
| 208 | ? ModelsMap[M][F] |
| 209 | : M extends keyof NativeModels<C> |
| 210 | ? Column<C, M, F> extends keyof NativeColumns<C, M> |
| 211 | ? NativeColumns<C, M>[Column<C, M, F>] extends { |
| 212 | readonly many: true; |
| 213 | } |
| 214 | ? Unmany<ModelsMap[M][F]> |
| 215 | : ModelsMap[M][F] |
| 216 | : ModelsMap[M][F] |
| 217 | : ModelsMap[M][F] |
| 218 | : ModelsMap[M][F]; |
| 219 | }; |
| 220 | }; |
| 221 | } |
| 222 | : never; |
| 223 | type StorageFields<C extends ContractShape, Ms extends Models, Map> = { |
| 224 | readonly [Ns in keyof Map]: { |
| 225 | readonly [ |
| 226 | M in keyof Map[Ns] & keyof Ms & keyof NativeModels<C> as Table<C, M> |
| 227 | ]: { |
| 228 | readonly [F in keyof Map[Ns][M] as Column<C, M, F>]: Map[Ns][M][F]; |
| 229 | }; |
| 230 | }; |
| 231 | }; |
| 232 | export interface AuthoringTypeMaps< |
| 233 | Inputs, |
| 234 | Outputs, |
| 235 | StorageInputs, |
| 236 | StorageOutputs, |
| 237 | AdditionalCodecs, |
| 238 | > { |
| 239 | readonly codecTypes: CodecTypes & AdditionalCodecs; |
| 240 | readonly fieldInputTypes: Inputs; |
| 241 | readonly fieldOutputTypes: Outputs; |
| 242 | readonly storageColumnInputTypes: StorageInputs; |
| 243 | readonly storageColumnTypes: StorageOutputs; |
| 244 | readonly queryOperationTypes: QueryOperationTypes<CodecTypes>; |
| 245 | readonly aggregateTypes: PostgresAggregateTypes; |
| 246 | } |
| 247 | type FixedMaps< |
| 248 | C extends ContractShape, |
| 249 | Ms extends Models, |
| 250 | Maps = ExtractTypeMapsFromContract<C>, |
| 251 | > = Maps extends { |
| 252 | readonly codecTypes: infer Codecs; |
| 253 | readonly fieldInputTypes: infer Inputs; |
| 254 | readonly fieldOutputTypes: infer Outputs; |
| 255 | } |
| 256 | ? AuthoringTypeMaps< |
| 257 | Materialize<FixFields<C, Ms, Inputs>>, |
| 258 | Materialize<FixFields<C, Ms, Outputs>>, |
| 259 | Materialize<StorageFields<C, Ms, FixFields<C, Ms, Inputs>>>, |
| 260 | Materialize<StorageFields<C, Ms, FixFields<C, Ms, Outputs>>>, |
| 261 | Omit<Known<Codecs>, keyof CodecTypes> |
| 262 | > |
| 263 | : never; |
| 264 | type FixedModels< |
| 265 | C extends ContractShape, |
| 266 | Ms extends Models, |
| 267 | Ns extends string, |
| 268 | > = { |
| 269 | readonly [ |
| 270 | M in keyof Ms & keyof NativeModels<C> as Namespace<Ms[M]> extends Ns |
| 271 | ? M |
| 272 | : never |
| 273 | ]: Omit<NativeModels<C>[M], "relations" | "storage"> & { |
| 274 | readonly storage: NativeModels<C>[M]["storage"] & { |
| 275 | readonly namespaceId: Namespace<Ms[M]>; |
| 276 | }; |
| 277 | readonly relations: { |
| 278 | readonly [R in keyof Relations<Ms[M]>]: RelationType< |
| 279 | C, |
| 280 | Ms, |
| 281 | M, |
| 282 | State<Relations<Ms[M]>[R]> |
| 283 | >; |
| 284 | }; |
| 285 | }; |
| 286 | }; |
| 287 | type InlineUniques< |
| 288 | C extends ContractShape, |
| 289 | Ms extends Models, |
| 290 | M extends keyof Ms & keyof NativeModels<C>, |
| 291 | > = { |
| 292 | [F in keyof Fields<Ms[M]> & string]: State<Fields<Ms[M]>[F]> extends { |
| 293 | readonly unique: object; |
| 294 | } |
| 295 | ? { readonly columns: readonly [Column<C, M, F>] } |
| 296 | : never; |
| 297 | }[keyof Fields<Ms[M]> & string]; |
| 298 | type AttributeUniques< |
| 299 | C extends ContractShape, |
| 300 | Ms extends Models, |
| 301 | M extends keyof Ms & keyof NativeModels<C>, |
| 302 | > = Ms[M] extends { |
| 303 | readonly __attributes: { readonly uniques: readonly (infer U)[] }; |
| 304 | } |
| 305 | ? U extends { readonly fields: infer Fs extends readonly string[] } |
| 306 | ? { readonly columns: Columns<C, M, Fs> } |
| 307 | : never |
| 308 | : never; |
| 309 | type NativeTables<C extends ContractShape> = |
| 310 | C["storage"]["namespaces"]["public"]["entries"]["table"]; |
| 311 | type NativeColumns<C extends ContractShape, M extends keyof NativeModels<C>> = |
| 312 | Table<C, M> extends keyof NativeTables<C> |
| 313 | ? NativeTables<C>[Table<C, M>] extends { readonly columns: infer Cols } |
| 314 | ? Cols |
| 315 | : never |
| 316 | : never; |
| 317 | type FixColumn<Col, S> = Omit<Col, "many" | "default"> & |
| 318 | (S extends { readonly many?: infer Many } |
| 319 | ? true extends Many |
| 320 | ? { readonly many: true } |
| 321 | : Empty |
| 322 | : Empty) & |
| 323 | (S extends { readonly default: infer D } ? { readonly default: D } : Empty); |
| 324 | type FixedTable< |
| 325 | C extends ContractShape, |
| 326 | Ms extends Models, |
| 327 | M extends keyof Ms & keyof NativeModels<C>, |
| 328 | > = |
| 329 | Table<C, M> extends keyof NativeTables<C> |
| 330 | ? Omit<NativeTables<C>[Table<C, M>], "columns" | "uniques"> & { |
| 331 | readonly columns: { |
| 332 | readonly [F in keyof Fields<Ms[M]> as Column<C, M, F>]: Column< |
| 333 | C, |
| 334 | M, |
| 335 | F |
| 336 | > extends keyof NativeColumns<C, M> |
| 337 | ? FixColumn< |
| 338 | NativeColumns<C, M>[Column<C, M, F>], |
| 339 | State<Fields<Ms[M]>[F]> |
| 340 | > |
| 341 | : never; |
| 342 | }; |
| 343 | readonly uniques: readonly ( |
| 344 | | InlineUniques<C, Ms, M> |
| 345 | | AttributeUniques<C, Ms, M> |
| 346 | )[]; |
| 347 | } |
| 348 | : never; |
| 349 | type FixStorage<C extends ContractShape, Ms extends Models> = Omit< |
| 350 | C["storage"], |
| 351 | "namespaces" |
| 352 | > & { |
| 353 | readonly namespaces: { |
| 354 | readonly [Ns in Namespaces<Ms> | "public"]: { |
| 355 | readonly id: Ns; |
| 356 | readonly kind: string; |
| 357 | readonly entries: { |
| 358 | readonly table: { |
| 359 | readonly [ |
| 360 | M in keyof Ms & keyof NativeModels<C> as Namespace<Ms[M]> extends Ns |
| 361 | ? Table<C, M> |
| 362 | : never |
| 363 | ]: FixedTable<C, Ms, M>; |
| 364 | }; |
| 365 | }; |
| 366 | }; |
| 367 | }; |
| 368 | }; |
| 369 | |
| 370 | type PostgresCapabilities = { |
| 371 | readonly postgres: { |
| 372 | readonly distinctOn: true; |
| 373 | readonly jsonAgg: true; |
| 374 | readonly lateral: true; |
| 375 | readonly limit: true; |
| 376 | readonly orderBy: true; |
| 377 | readonly returning: true; |
| 378 | }; |
| 379 | readonly sql: { |
| 380 | readonly checkConstraint: true; |
| 381 | readonly defaultInInsert: true; |
| 382 | readonly enums: true; |
| 383 | readonly lateral: true; |
| 384 | readonly returning: true; |
| 385 | readonly scalarList: true; |
| 386 | }; |
| 387 | }; |
| 388 | type ExecutionDefaults<C extends ContractShape, Ms extends Models> = { |
| 389 | [M in keyof Ms & keyof NativeModels<C>]: { |
| 390 | [F in keyof Fields<Ms[M]>]: State<Fields<Ms[M]>[F]> extends { |
| 391 | readonly executionDefaults: infer D; |
| 392 | } |
| 393 | ? D & { |
| 394 | readonly ref: { |
| 395 | readonly namespace: Namespace<Ms[M]>; |
| 396 | readonly table: Table<C, M>; |
| 397 | readonly column: Column<C, M, F>; |
| 398 | }; |
| 399 | } |
| 400 | : never; |
| 401 | }[keyof Fields<Ms[M]>]; |
| 402 | }[keyof Ms & keyof NativeModels<C>]; |
| 403 | type Depths = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8]; |
| 404 | type Materialize<T, Depth extends number = 9> = Depth extends 0 |
| 405 | ? T |
| 406 | : T extends |
| 407 | | string |
| 408 | | number |
| 409 | | bigint |
| 410 | | boolean |
| 411 | | symbol |
| 412 | | null |
| 413 | | undefined |
| 414 | | Date |
| 415 | | Uint8Array |
| 416 | | ((...args: never[]) => unknown) |
| 417 | ? T |
| 418 | : T extends object |
| 419 | ? { |
| 420 | [K in keyof T]: K extends TypeMapsPhantomKey |
| 421 | ? T[K] |
| 422 | : Materialize<T[K], Depths[Depth]>; |
| 423 | } |
| 424 | : T; |
| 425 | /** Native runtime contract with rc.11's erased authoring metadata restored. */ |
| 426 | export type AuthoredContract< |
| 427 | C extends ContractShape, |
| 428 | Ms extends Models, |
| 429 | > = ContractWithTypeMaps< |
| 430 | Omit< |
| 431 | C, |
| 432 | "domain" | "storage" | "capabilities" | "execution" | TypeMapsPhantomKey |
| 433 | > & { |
| 434 | readonly domain: Omit<C["domain"], "namespaces"> & { |
| 435 | readonly namespaces: { |
| 436 | readonly [Ns in Namespaces<Ms>]: { |
| 437 | readonly models: FixedModels<C, Ms, Ns>; |
| 438 | }; |
| 439 | }; |
| 440 | }; |
| 441 | readonly storage: FixStorage<C, Ms>; |
| 442 | readonly capabilities: PostgresCapabilities; |
| 443 | } & ([ExecutionDefaults<C, Ms>] extends [never] |
| 444 | ? Empty |
| 445 | : { |
| 446 | readonly execution: { |
| 447 | readonly executionHash: NonNullable< |
| 448 | Contract["execution"] |
| 449 | >["executionHash"]; |
| 450 | readonly mutations: { |
| 451 | readonly defaults: readonly ExecutionDefaults<C, Ms>[]; |
| 452 | }; |
| 453 | }; |
| 454 | }), |
| 455 | FixedMaps<C, Ms> |
| 456 | >; |
| 457 | interface DefineContract { |
| 458 | < |
| 459 | const T extends Types = Empty, |
| 460 | const M extends Models = Empty, |
| 461 | const E extends Extensions = undefined, |
| 462 | const EN extends Enums = Empty, |
| 463 | >( |
| 464 | definition: Omit< |
| 465 | Parameters<typeof nativeDefineContract<T, M, E, EN, Empty>>[0], |
| 466 | "types" | "models" | "naming" |
| 467 | > & |
| 468 | IdentityNaming & { readonly types?: T; readonly models?: M }, |
| 469 | ): Materialize< |
| 470 | AuthoredContract< |
| 471 | ReturnType< |
| 472 | typeof nativeDefineContract< |
| 473 | T, |
| 474 | M, |
| 475 | E extends undefined ? Empty : E, |
| 476 | EN, |
| 477 | Empty |
| 478 | > |
| 479 | >, |
| 480 | M |
| 481 | > |
| 482 | >; |
| 483 | < |
| 484 | const T extends Types = Empty, |
| 485 | const M extends Models = Empty, |
| 486 | const E extends Extensions = undefined, |
| 487 | const SE extends Enums = Empty, |
| 488 | const FE extends Enums = Empty, |
| 489 | >( |
| 490 | scaffold: Omit< |
| 491 | Parameters<typeof nativeDefineContract<T, M, E, SE, FE>>[0], |
| 492 | "naming" |
| 493 | > & |
| 494 | IdentityNaming, |
| 495 | factory: ( |
| 496 | helpers: Helpers< |
| 497 | Parameters< |
| 498 | Parameters<typeof nativeDefineContract<T, M, NoInfer<E>, SE, FE>>[1] |
| 499 | >[0] |
| 500 | >, |
| 501 | ) => { readonly types?: T; readonly models?: M; readonly enums?: FE }, |
| 502 | ): Materialize< |
| 503 | AuthoredContract< |
| 504 | ReturnType< |
| 505 | typeof nativeDefineContract< |
| 506 | T, |
| 507 | M, |
| 508 | E extends undefined ? Empty : E, |
| 509 | SE, |
| 510 | FE |
| 511 | > |
| 512 | >, |
| 513 | M |
| 514 | > |
| 515 | >; |
| 516 | } |
| 517 | /** |
| 518 | * Preserve native Prisma authoring types without generated application imports. |
| 519 | * This is Prisma's own function; only its TypeScript declaration is adapted. |
| 520 | * Upstream: https://github.com/prisma/orm/issues/30341. |
| 521 | */ |
| 522 | export const defineContract = nativeDefineContract as unknown as DefineContract; |