import { BaseModelField } from '../../ModelField'; import { ModelRelationshipField, ModelRelationshipFieldParamShape } from '../../ModelRelationshipField'; import { EnumType } from '../../EnumType'; import { CustomType } from '../../CustomType'; import { RefType, RefTypeParamShape } from '../../RefType'; import { ResolveRef } from './ResolveRef'; import { LazyLoader } from '../../runtime'; import type { ModelTypeParamShape } from '../../ModelType'; type ExtendsNever = [T] extends [never] ? true : false; /** * Takes a `ReturnType` and turns it into a client-consumable type. Fields * definitions (e.g., `a.string()`) are turned into the client facing types (e.g., `string`), * `a.ref()` fields will be resolved, and relationships (e.g., `a.belongsTo()`) will be * turned into `LazyLoader` fields (e.g., `post.comments({...})`). * * The first type parameter (`Bag`) should always just be the top-level `ClientSchema` that * references and related model definitions can be resolved against. */ export type ResolveFields, T> = ShallowPretty<{ [K in keyof T as IsRequired extends true ? K : never]: ResolveIndividualField; } & { [K in keyof T as IsRequired extends true ? never : K]+?: ResolveIndividualField; }>; export type FlatResolveFields, T, FlatModelName extends keyof Bag & string = never> = ShallowPretty<{ [K in keyof T]: ResolveIndividualField; }>; type ShallowPretty = { [K in keyof T]: T[K]; }; export type ResolveIndividualField, T, FlatModelName extends keyof Bag & string = never> = T extends BaseModelField ? FieldShape : T extends RefType ? ResolveRef : T extends ModelRelationshipField ? ResolveRelationship : T extends CustomType ? ResolveFields | null : T extends EnumType ? values[number] | null : never; /** * This mapped type eliminates redundant recursive types when * generating the ['__meta']['flatModel'] type that serves as the * basis for custom selection set path type generation * * It drops belongsTo relational fields that match the source model * * For example, assuming the typical Post->Comment bi-directional hasMany relationship, * The generated structure will be * { * id: string; * title: string; * createdAt: string; * updatedAt: string; * comments: { * id: string; * createdAt: string; * updatedAt: string; * content: string; * postId: string; * ~~post~~ is dropped because data would be the same as top level object * }[] * } * */ type ShortCircuitBiDirectionalRelationship, ParentModelName extends string, Raw extends ModelTypeParamShape['fields']> = { [Field in keyof Model as Field extends keyof Raw ? Raw[Field] extends ModelRelationshipField ? RelationshipShape['relationshipType'] extends 'belongsTo' ? RelationshipShape['relatedModel'] extends ParentModelName ? never : Field : Field : Field : Field]: Model[Field]; }; type ResolveRelationship, RelationshipShape extends ModelRelationshipFieldParamShape, ParentModelName extends keyof Bag & string = never> = ExtendsNever extends true ? DependentLazyLoaderOpIsAvailable extends true ? LazyLoader : never : RelationshipShape['array'] extends true ? Array> : ShortCircuitBiDirectionalRelationship; type DependentLazyLoaderOpIsAvailable, RelationshipShape extends ModelRelationshipFieldParamShape> = RelationshipShape['relationshipType'] extends 'hasOne' | 'hasMany' ? 'list' extends keyof Bag[RelationshipShape['relatedModel']]['__meta']['disabledOperations'] ? false : true : 'get' extends keyof Bag[RelationshipShape['relatedModel']]['__meta']['disabledOperations'] ? false : true; type IsRequired = T extends BaseModelField ? null extends FieldShape ? false : true : T extends RefType ? IsRefRequired : T extends ModelRelationshipField ? true : T extends CustomType | EnumType ? false : never; type IsRefRequired = T['array'] extends true ? T['arrayRequired'] : T['valueRequired']; export {};