import { DMMF } from '@prisma/client/runtime' import { getPhotonDmmf } from './utils' import { DmmfDocument } from './DmmfDocument' import { DmmfTypes } from './DmmfTypes' export const getTransformedDmmf = ( photonClientPackagePath: string, ): DmmfDocument => new DmmfDocument(transform(getPhotonDmmf(photonClientPackagePath))) export function transform(document: DMMF.Document): DmmfTypes.Document { return { datamodel: transformDatamodel(document.datamodel), mappings: document.mappings as DmmfTypes.Mapping[], schema: transformSchema(document.schema), } } function transformDatamodel(datamodel: DMMF.Datamodel): DmmfTypes.Datamodel { return { enums: datamodel.enums, models: datamodel.models.map(model => ({ ...model, fields: model.fields.map(field => ({ ...field, kind: field.kind === 'object' ? 'relation' : field.kind, })), })), } } function transformSchema(schema: DMMF.Schema): DmmfTypes.Schema { return { enums: schema.enums, inputTypes: schema.inputTypes.map(transformInputType), outputTypes: schema.outputTypes.map(o => ({ ...o, fields: o.fields.map(f => ({ ...f, args: f.args.map(transformArg), outputType: { ...f.outputType, type: getReturnTypeName(f.outputType.type), }, })), })), } } /** * Conversion from a Photon arg type to a GraphQL arg type using * heuristics. A conversion is needed becuase GraphQL does not * support union types on args, but Photon does. */ function transformArg(arg: DMMF.SchemaArg): DmmfTypes.SchemaArg { // FIXME: *Enum*Filter are currently empty let inputType = arg.inputType.some(a => a.kind === 'enum') ? arg.inputType[0] : arg.inputType.find(a => a.kind === 'object')! if (!inputType) { inputType = arg.inputType[0] } return { name: arg.name, inputType: { ...inputType, type: getReturnTypeName(inputType.type), }, collapsedTo: undefined, computedFields: {}, } } function transformInputType(inputType: DMMF.InputType): DmmfTypes.InputType { return { ...inputType, fields: inputType.fields.map(transformArg), } } /** * Make the "return type" property type always be a string. In Photon * it is allowed to be a nested structured object but we want only the * reference-by-name form. * */ // // TODO _why_ is the dmmf like this? // // FIXME `any` type becuase this is used by both outputType and inputType // and there is currently no generic capturing both ideas. // function getReturnTypeName(type: any) { if (typeof type === 'string') { return type } return type.name }