import { GenericModelSchema } from './ModelSchema'; import { brand, Brand, IndexLimitUnion } from './util'; const _COMBINED_SCHEMA_LIMIT = 50; export type CombinedSchemaIndexesUnion = IndexLimitUnion< typeof _COMBINED_SCHEMA_LIMIT >[number]; const CombinedSchemaBrandName = 'CombinedSchema'; export const combinedSchemaBrand = brand(CombinedSchemaBrandName); export type CombinedSchemaBrand = Brand; /** * CombinedModel schema definition interface * * @param Schemas - The schemas to combine into a single API */ export type CombinedModelSchema[]> = CombinedSchemaBrand & { schemas: [...Schemas] }; /** * The interface for merging up to 50 schemas into a single API. * @param schemas The schemas to combine into a single API * @returns An API and data model definition to be deployed with Amplify (Gen 2) experience (`processSchema(...)`) * or with the Amplify Data CDK construct (`@aws-amplify/data-construct`) */ export function combine[]>( schemas: [...Schema], ): CombinedModelSchema { return internalCombine(schemas); } function internalCombine< Schema extends GenericModelSchema[], SchemasTuple extends [...Schema], >(schemas: SchemasTuple): CombinedModelSchema { validateDuplicateTypeNames(schemas); const combined = { ...combinedSchemaBrand, schemas: schemas, }; for (const schema of combined.schemas) { schema.context = combined; } return combined; } function validateDuplicateTypeNames[]>( schemas: [...Schema], ) { const allSchemaKeys = schemas.flatMap((s) => Object.keys(s.data.types)); const keySet = new Set(); const duplicateKeySet = new Set(); allSchemaKeys.forEach((key) => { if (keySet.has(key)) { duplicateKeySet.add(key); } else { keySet.add(key); } }); if (duplicateKeySet.size > 0) { throw new Error( `The schemas you are attempting to combine have a name collision. Please remove or rename ${Array.from(duplicateKeySet).join(', ')}.`, ); } }