import type { Brand } from './util'; import type { InternalField, BaseModelField } from './ModelField'; import type { RefType } from './RefType'; import type { EnumType } from './EnumType'; /** * Custom Types * * can be defined in-line to strongly type object types * */ // `.default()` is not allowed on a Custom Type field export type CustomTypeAllowedModifiers = 'authorization' | 'array' | 'required'; type CustomTypeFields = Record< string, | BaseModelField | RefType | EnumType | CustomType >; type InternalModelFields = Record; type CustomTypeData = { fields: CustomTypeFields; type: 'customType'; }; type InternalCustomTypeData = CustomTypeData & { fields: InternalModelFields; }; export type CustomTypeParamShape = { fields: CustomTypeFields; }; /** * Custom type container * * @param T - The shape of the custom type container */ export type CustomType = T & Brand<'customType'>; /** * Internal representation of CustomType that exposes the `data` property. * Used at buildtime. */ export type InternalCustomType = CustomType & { data: InternalCustomTypeData; }; function _customType(fields: T['fields']) { const data: CustomTypeData = { fields, type: 'customType', }; return { data } as InternalCustomType as CustomType; } /** * Define a custom type. This type represents an inline, typed JSON object. * @see {@link https://docs.amplify.aws/react/build-a-backend/data/data-modeling/add-fields/#specify-a-custom-field-type} * @param fields the fields to be added to the custom type * @returns a custom type * @example * a.schema({ * Post: a.model({ * location: a.customType({ * lat: a.float(), * long: a.float(), * }), * content: a.string(), * }), * }); * @example * a.schema({ * Location: a.customType({ * lat: a.float(), * long: a.float(), * }), * * Post: a.model({ * location: a.ref('Location'), * content: a.string(), * }), * * User: a.model({ * lastKnownLocation: a.ref('Location'), * }), * }); */ export function customType( fields: T, ): CustomType<{ fields: T }> { return _customType(fields); }