From bd65d825989000fbe78d06081abadf43e4a5d78f Mon Sep 17 00:00:00 2001 From: Hein Jeong Date: Tue, 13 Dec 2022 20:22:05 +0000 Subject: [PATCH] feat: support hasMany and manyToMany between models with composite keys --- ...studio-ui-codegen-react-forms.test.ts.snap | 118 ++++--- .../__tests__/__utils__/mock-data-schemas.ts | 4 +- .../studio-ui-codegen-react-forms.test.ts | 14 +- .../lib/amplify-ui-renderers/form.ts | 9 +- .../forms/form-renderer-helper/cta-props.ts | 11 +- .../map-from-fieldConfigs.ts | 9 +- .../form-renderer-helper/model-values.ts | 1 - .../form-renderer-helper/relationship.ts | 314 ++++++++++-------- .../lib/forms/react-form-renderer.ts | 15 +- .../lib/react-studio-template-renderer.ts | 5 +- .../__tests__/generic-from-datastore.test.ts | 16 +- .../codegen-ui/lib/generic-from-datastore.ts | 65 ++-- packages/codegen-ui/lib/types/data.ts | 2 +- .../lib/utils/component-metadata.ts | 4 +- .../lib/utils/dataschema-metadata.ts | 30 -- packages/codegen-ui/lib/utils/index.ts | 1 - 16 files changed, 337 insertions(+), 281 deletions(-) delete mode 100644 packages/codegen-ui/lib/utils/dataschema-metadata.ts diff --git a/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap b/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap index 724ba6b2e..4c5700acb 100644 --- a/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap +++ b/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap @@ -2699,17 +2699,19 @@ export default function UpdateCompositeDogForm(props) { const compositeToysToUnLink = []; const compositeToysSet = new Set(); const linkedCompositeToysSet = new Set(); - CompositeToys.forEach((r) => compositeToysSet.add(r.kind)); + CompositeToys.forEach((r) => + compositeToysSet.add(getIDValue.CompositeToys?.(r)) + ); linkedCompositeToys.forEach((r) => - linkedCompositeToysSet.add(r.kind) + linkedCompositeToysSet.add(getIDValue.CompositeToys?.(r)) ); linkedCompositeToys.forEach((r) => { - if (!compositeToysSet.has(r.id)) { + if (!compositeToysSet.has(getIDValue.CompositeToys?.(r))) { compositeToysToUnLink.push(r); } }); CompositeToys.forEach((r) => { - if (!linkedCompositeToysSet.has(r.id)) { + if (!linkedCompositeToysSet.has(getIDValue.CompositeToys?.(r))) { compositeToysToLink.push(r); } }); @@ -2718,6 +2720,7 @@ export default function UpdateCompositeDogForm(props) { DataStore.save( CompositeToy.copyOf(original, (updated) => { updated.compositeDogCompositeToysName = null; + updated.compositeDogCompositeToysDescription = null; }) ) ); @@ -2728,6 +2731,8 @@ export default function UpdateCompositeDogForm(props) { CompositeToy.copyOf(original, (updated) => { updated.compositeDogCompositeToysName = compositeDogRecord.name; + updated.compositeDogCompositeToysDescription = + compositeDogRecord.description; }) ) ); @@ -2737,14 +2742,16 @@ export default function UpdateCompositeDogForm(props) { const compositeVetsMap = new Map(); const linkedCompositeVetsMap = new Map(); CompositeVets.forEach((r) => { - const count = compositeVetsMap.get(r.specialty); + const count = compositeVetsMap.get(getIDValue.CompositeVets?.(r)); const newCount = count ? count + 1 : 1; - compositeVetsMap.set(r.specialty, newCount); + compositeVetsMap.set(getIDValue.CompositeVets?.(r), newCount); }); linkedCompositeVets.forEach((r) => { - const count = linkedCompositeVetsMap.get(r.specialty); + const count = linkedCompositeVetsMap.get( + getIDValue.CompositeVets?.(r) + ); const newCount = count ? count + 1 : 1; - linkedCompositeVetsMap.set(r.specialty, newCount); + linkedCompositeVetsMap.set(getIDValue.CompositeVets?.(r), newCount); }); linkedCompositeVetsMap.forEach((count, id) => { const newCount = compositeVetsMap.get(id); @@ -2772,10 +2779,17 @@ export default function UpdateCompositeDogForm(props) { const compositeDogCompositeVetRecords = await DataStore.query( CompositeDogCompositeVet, (r) => - r.and((r) => [ - r.compositeVetID.eq(id), - r.compositeDogID.eq(compositeDogRecord.name), - ]) + r.and((r) => { + const recordKeys = JSON.parse(id); + return [ + r.compositeVetSpecialty.eq(recordKeys.specialty), + r.compositeVetcity.eq(recordKeys.city), + r.compositeDogName.eq(compositeDogRecord.name), + r.compositeDogdescription.eq( + compositeDogRecord.description + ), + ]; + }) ); for (let i = 0; i < count; i++) { promises.push( @@ -2788,8 +2802,12 @@ export default function UpdateCompositeDogForm(props) { promises.push( DataStore.save( new CompositeDogCompositeVet({ - compositeDogID: compositeDogRecord.name, - compositeVetID: id, + compositeDog: compositeDogRecord, + compositeVet: compositeVetRecords.find((r) => + Object.entries(JSON.parse(id)).every( + ([key, value]) => r[key] === value + ) + ), }) ) ); @@ -2826,7 +2844,7 @@ export default function UpdateCompositeDogForm(props) { { let { value } = e.target; @@ -2855,7 +2873,7 @@ export default function UpdateCompositeDogForm(props) { { let { value } = e.target; @@ -3655,14 +3673,14 @@ export default function UpdateCPKTeacherForm(props) { const cPKClassesMap = new Map(); const linkedCPKClassesMap = new Map(); CPKClasses.forEach((r) => { - const count = cPKClassesMap.get(r.specialClassId); + const count = cPKClassesMap.get(getIDValue.CPKClasses?.(r)); const newCount = count ? count + 1 : 1; - cPKClassesMap.set(r.specialClassId, newCount); + cPKClassesMap.set(getIDValue.CPKClasses?.(r), newCount); }); linkedCPKClasses.forEach((r) => { - const count = linkedCPKClassesMap.get(r.specialClassId); + const count = linkedCPKClassesMap.get(getIDValue.CPKClasses?.(r)); const newCount = count ? count + 1 : 1; - linkedCPKClassesMap.set(r.specialClassId, newCount); + linkedCPKClassesMap.set(getIDValue.CPKClasses?.(r), newCount); }); linkedCPKClassesMap.forEach((count, id) => { const newCount = cPKClassesMap.get(id); @@ -3690,10 +3708,13 @@ export default function UpdateCPKTeacherForm(props) { const cPKTeacherCPKClassRecords = await DataStore.query( CPKTeacherCPKClass, (r) => - r.and((r) => [ - r.cpkClassID.eq(id), - r.cpkTeacherID.eq(cPKTeacherRecord.specialTeacherId), - ]) + r.and((r) => { + const recordKeys = JSON.parse(id); + return [ + r.cpkClassID.eq(recordKeys.specialClassId), + r.cpkTeacherID.eq(cPKTeacherRecord.specialTeacherId), + ]; + }) ); for (let i = 0; i < count; i++) { promises.push(DataStore.delete(cPKTeacherCPKClassRecords[i])); @@ -3704,8 +3725,12 @@ export default function UpdateCPKTeacherForm(props) { promises.push( DataStore.save( new CPKTeacherCPKClass({ - cpkTeacherID: cPKTeacherRecord.specialTeacherId, - cpkClassID: id, + cpkTeacher: cPKTeacherRecord, + cpkClass: cPKClassRecords.find((r) => + Object.entries(JSON.parse(id)).every( + ([key, value]) => r[key] === value + ) + ), }) ) ); @@ -3715,17 +3740,19 @@ export default function UpdateCPKTeacherForm(props) { const cPKProjectsToUnLink = []; const cPKProjectsSet = new Set(); const linkedCPKProjectsSet = new Set(); - CPKProjects.forEach((r) => cPKProjectsSet.add(r.specialProjectId)); + CPKProjects.forEach((r) => + cPKProjectsSet.add(getIDValue.CPKProjects?.(r)) + ); linkedCPKProjects.forEach((r) => - linkedCPKProjectsSet.add(r.specialProjectId) + linkedCPKProjectsSet.add(getIDValue.CPKProjects?.(r)) ); linkedCPKProjects.forEach((r) => { - if (!cPKProjectsSet.has(r.id)) { + if (!cPKProjectsSet.has(getIDValue.CPKProjects?.(r))) { cPKProjectsToUnLink.push(r); } }); CPKProjects.forEach((r) => { - if (!linkedCPKProjectsSet.has(r.id)) { + if (!linkedCPKProjectsSet.has(getIDValue.CPKProjects?.(r))) { cPKProjectsToLink.push(r); } }); @@ -9743,15 +9770,17 @@ export default function SchoolUpdateForm(props) { const studentsToUnLink = []; const studentsSet = new Set(); const linkedStudentsSet = new Set(); - Students.forEach((r) => studentsSet.add(r.id)); - linkedStudents.forEach((r) => linkedStudentsSet.add(r.id)); + Students.forEach((r) => studentsSet.add(getIDValue.Students?.(r))); + linkedStudents.forEach((r) => + linkedStudentsSet.add(getIDValue.Students?.(r)) + ); linkedStudents.forEach((r) => { - if (!studentsSet.has(r.id)) { + if (!studentsSet.has(getIDValue.Students?.(r))) { studentsToUnLink.push(r); } }); Students.forEach((r) => { - if (!linkedStudentsSet.has(r.id)) { + if (!linkedStudentsSet.has(getIDValue.Students?.(r))) { studentsToLink.push(r); } }); @@ -10772,14 +10801,14 @@ export default function TagUpdateForm(props) { const postsMap = new Map(); const linkedPostsMap = new Map(); Posts.forEach((r) => { - const count = postsMap.get(r.id); + const count = postsMap.get(getIDValue.Posts?.(r)); const newCount = count ? count + 1 : 1; - postsMap.set(r.id, newCount); + postsMap.set(getIDValue.Posts?.(r), newCount); }); linkedPosts.forEach((r) => { - const count = linkedPostsMap.get(r.id); + const count = linkedPostsMap.get(getIDValue.Posts?.(r)); const newCount = count ? count + 1 : 1; - linkedPostsMap.set(r.id, newCount); + linkedPostsMap.set(getIDValue.Posts?.(r), newCount); }); linkedPostsMap.forEach((count, id) => { const newCount = postsMap.get(id); @@ -10805,7 +10834,10 @@ export default function TagUpdateForm(props) { }); postsToUnLinkMap.forEach(async (count, id) => { const tagPostRecords = await DataStore.query(TagPost, (r) => - r.and((r) => [r.postID.eq(id), r.tagID.eq(tagRecord.id)]) + r.and((r) => { + const recordKeys = JSON.parse(id); + return [r.postID.eq(recordKeys.id), r.tagID.eq(tagRecord.id)]; + }) ); for (let i = 0; i < count; i++) { promises.push(DataStore.delete(tagPostRecords[i])); @@ -10816,8 +10848,12 @@ export default function TagUpdateForm(props) { promises.push( DataStore.save( new TagPost({ - tagID: tagRecord.id, - postID: id, + tag: tagRecord, + post: postRecords.find((r) => + Object.entries(JSON.parse(id)).every( + ([key, value]) => r[key] === value + ) + ), }) ) ); diff --git a/packages/codegen-ui-react/lib/__tests__/__utils__/mock-data-schemas.ts b/packages/codegen-ui-react/lib/__tests__/__utils__/mock-data-schemas.ts index 11e8b1e00..8d90b6b6a 100644 --- a/packages/codegen-ui-react/lib/__tests__/__utils__/mock-data-schemas.ts +++ b/packages/codegen-ui-react/lib/__tests__/__utils__/mock-data-schemas.ts @@ -19,6 +19,7 @@ export const authorHasManySchema: GenericDataSchema = { dataSourceType: 'DataStore', models: { Book: { + primaryKeys: ['id'], fields: { id: { dataType: 'ID', @@ -69,6 +70,7 @@ export const authorHasManySchema: GenericDataSchema = { }, }, Author: { + primaryKeys: ['id'], fields: { id: { dataType: 'ID', @@ -104,7 +106,7 @@ export const authorHasManySchema: GenericDataSchema = { relationship: { type: 'HAS_MANY', relatedModelName: 'Book', - relatedModelField: 'authorID', + relatedModelFields: ['authorID'], }, }, createdAt: { diff --git a/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts b/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts index 6b4a6c5ed..f0d9130a5 100644 --- a/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts +++ b/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts @@ -389,16 +389,16 @@ describe('amplify form renderer tests', () => { expect(componentText).toContain('JSON.stringify({ specialStudentId: r?.specialStudentId })'); // manyToMany - expect(componentText).toContain('const count = cPKClassesMap.get(r.specialClassId)'); - expect(componentText).toContain('cPKClassesMap.set(r.specialClassId, newCount)'); - expect(componentText).toContain('const count = linkedCPKClassesMap.get(r.specialClassId)'); - expect(componentText).toContain('linkedCPKClassesMap.set(r.specialClassId, newCount)'); + expect(componentText).toContain('const count = cPKClassesMap.get(getIDValue.CPKClasses?.(r))'); + expect(componentText).toContain('cPKClassesMap.set(getIDValue.CPKClasses?.(r), newCount)'); + expect(componentText).toContain('const count = linkedCPKClassesMap.get(getIDValue.CPKClasses?.(r))'); + expect(componentText).toContain('linkedCPKClassesMap.set(getIDValue.CPKClasses?.(r), newCount)'); expect(componentText).toContain('r.cpkTeacherID.eq(cPKTeacherRecord.specialTeacherId)'); - expect(componentText).toContain('cpkTeacherID: cPKTeacherRecord.specialTeacherId'); + expect(componentText).toContain('cpkTeacher: cPKTeacherRecord'); // hasMany - expect(componentText).toContain('CPKProjects.forEach((r) => cPKProjectsSet.add(r.specialProjectId))'); - expect(componentText).toContain('linkedCPKProjectsSet.add(r.specialProjectId)'); + expect(componentText).toContain('cPKProjectsSet.add(getIDValue.CPKProjects?.(r)'); + expect(componentText).toContain('linkedCPKProjectsSet.add(getIDValue.CPKProjects?.(r))'); expect(componentText).toContain('updated.cPKTeacherID = cPKTeacherRecord.specialTeacherId'); expect(componentText).toMatchSnapshot(); diff --git a/packages/codegen-ui-react/lib/amplify-ui-renderers/form.ts b/packages/codegen-ui-react/lib/amplify-ui-renderers/form.ts index aea88cfbe..1bb9ea9f6 100644 --- a/packages/codegen-ui-react/lib/amplify-ui-renderers/form.ts +++ b/packages/codegen-ui-react/lib/amplify-ui-renderers/form.ts @@ -112,10 +112,9 @@ export default class FormRenderer extends ReactComponentRenderer, - thisModelPrimaryKey: string, + dataSchema: GenericDataSchema, ) => { + const thisModelPrimaryKeys = dataSchema.models[modelName].primaryKeys; let isHasManyFieldConfigExisting = false; const hasManyDataStoreStatements: (VariableStatement | ExpressionStatement)[] = []; @@ -118,12 +119,14 @@ export const buildDataStoreExpression = ( if (fieldConfigMetaData.relationship?.type === 'HAS_MANY') { isHasManyFieldConfigExisting = true; if (isManyToManyRelationship(fieldConfigMetaData)) { + const joinTable = dataSchema.models[fieldConfigMetaData.relationship.relatedJoinTableName]; hasManyDataStoreStatements.push( ...buildManyToManyRelationshipDataStoreStatements( dataStoreActionType, importedModelName, fieldConfig, - thisModelPrimaryKey, + thisModelPrimaryKeys, + joinTable, ), ); } else { @@ -132,7 +135,7 @@ export const buildDataStoreExpression = ( dataStoreActionType, importedModelName, fieldConfig, - thisModelPrimaryKey, + thisModelPrimaryKeys, ), ); } diff --git a/packages/codegen-ui-react/lib/forms/form-renderer-helper/map-from-fieldConfigs.ts b/packages/codegen-ui-react/lib/forms/form-renderer-helper/map-from-fieldConfigs.ts index b051a6fd9..3cd9ffc74 100644 --- a/packages/codegen-ui-react/lib/forms/form-renderer-helper/map-from-fieldConfigs.ts +++ b/packages/codegen-ui-react/lib/forms/form-renderer-helper/map-from-fieldConfigs.ts @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { FieldConfigMetadata } from '@aws-amplify/codegen-ui'; +import { FieldConfigMetadata, HasManyRelationshipType } from '@aws-amplify/codegen-ui'; import { PropertyAssignment } from 'typescript'; import { buildDisplayValueFunction, @@ -91,5 +91,8 @@ export function mapFromFieldConfigs(fieldConfigs: Record - fieldConfigMetaData.relationship?.type === 'HAS_MANY' && fieldConfigMetaData.relationship.relatedJoinTableName; +export const isManyToManyRelationship = ( + fieldConfigMetaData: FieldConfigMetadata, +): fieldConfigMetaData is FieldConfigMetadata & { + relationship: HasManyRelationshipType & { relatedJoinTableName: string }; +} => !!(fieldConfigMetaData.relationship?.type === 'HAS_MANY' && fieldConfigMetaData.relationship.relatedJoinTableName); diff --git a/packages/codegen-ui-react/lib/forms/form-renderer-helper/model-values.ts b/packages/codegen-ui-react/lib/forms/form-renderer-helper/model-values.ts index e34cf3aad..13681c39b 100644 --- a/packages/codegen-ui-react/lib/forms/form-renderer-helper/model-values.ts +++ b/packages/codegen-ui-react/lib/forms/form-renderer-helper/model-values.ts @@ -228,7 +228,6 @@ export function extractModelAndKeys(valueMappings?: StudioFormValueMappings): { } }); } - console.log('KEYSSS', keys); return { model, keys }; } diff --git a/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts b/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts index a5ecfaeed..b332e5414 100644 --- a/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts +++ b/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts @@ -13,19 +13,21 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { factory, IfStatement, NodeFlags, SyntaxKind } from 'typescript'; +import { CallExpression, factory, IfStatement, NodeFlags, SyntaxKind } from 'typescript'; import { FieldConfigMetadata, GenericDataRelationshipType, HasManyRelationshipType, InternalError, + GenericDataModel, + GenericDataField, } from '@aws-amplify/codegen-ui'; import { getRecordsName, getLinkedDataName, getSetNameIdentifier, buildAccessChain } from './form-state'; import { buildBaseCollectionVariableStatement } from '../../react-studio-template-renderer-helper'; import { ImportCollection, ImportSource } from '../../imports'; import { lowerCaseFirst } from '../../helpers'; import { isManyToManyRelationship } from './map-from-fieldConfigs'; -import { extractModelAndKeys } from './model-values'; +import { extractModelAndKeys, getIDValueCallChain, getMatchEveryModelFieldCallExpression } from './model-values'; import { isModelDataType } from './render-checkers'; export const buildRelationshipQuery = ( @@ -49,29 +51,142 @@ export const buildRelationshipQuery = ( ); }; +const getJoinTableQueryArrowFunction = ({ + thisModelPrimaryKeys, + relatedModelPrimaryKeys, + joinTableThisModelFields, + joinTableRelatedModelFields, + thisModelRecord, +}: { + thisModelPrimaryKeys: string[]; + relatedModelPrimaryKeys: string[]; + joinTableThisModelFields: string[]; + joinTableRelatedModelFields: string[]; + thisModelRecord: string; +}) => { + const getQueryCallExpression = (queriedKey: string, recordName: string, recordKey: string) => + factory.createCallExpression( + factory.createPropertyAccessExpression( + factory.createPropertyAccessExpression(factory.createIdentifier('r'), factory.createIdentifier(queriedKey)), + factory.createIdentifier('eq'), + ), + undefined, + [ + factory.createPropertyAccessExpression( + factory.createIdentifier(recordName), + factory.createIdentifier(recordKey), + ), + ], + ); + + const recordKeysString = 'recordKeys'; + + const queryCallExpressions: CallExpression[] = []; + + joinTableRelatedModelFields.forEach((field, index) => { + const recordKey = relatedModelPrimaryKeys[index]; + if (!recordKey) { + throw new InternalError(`Cannot find corresponding key for ${field}`); + } + queryCallExpressions.push(getQueryCallExpression(field, recordKeysString, recordKey)); + }); + + joinTableThisModelFields.forEach((field, index) => { + const recordKey = thisModelPrimaryKeys[index]; + if (!recordKey) { + throw new InternalError(`Cannot find corresponding key for ${field}`); + } + queryCallExpressions.push(getQueryCallExpression(field, thisModelRecord, recordKey)); + }); + + return factory.createArrowFunction( + undefined, + undefined, + [ + factory.createParameterDeclaration( + undefined, + undefined, + undefined, + factory.createIdentifier('r'), + undefined, + undefined, + undefined, + ), + ], + undefined, + factory.createToken(SyntaxKind.EqualsGreaterThanToken), + factory.createBlock( + [ + factory.createVariableStatement( + undefined, + factory.createVariableDeclarationList( + [ + factory.createVariableDeclaration( + factory.createIdentifier(recordKeysString), + undefined, + undefined, + factory.createCallExpression( + factory.createPropertyAccessExpression( + factory.createIdentifier('JSON'), + factory.createIdentifier('parse'), + ), + undefined, + [factory.createIdentifier('id')], + ), + ), + ], + NodeFlags.Const, + ), + ), + factory.createReturnStatement(factory.createArrayLiteralExpression(queryCallExpressions, true)), + ], + true, + ), + ); +}; + +function extractAssociatedFields(field: GenericDataField): string[] | undefined { + const { relationship } = field; + if (relationship && 'associatedFields' in relationship && relationship.associatedFields) { + return relationship.associatedFields; + } + return undefined; +} + export const buildManyToManyRelationshipDataStoreStatements = ( dataStoreActionType: 'update' | 'create', modelName: string, hasManyFieldConfig: [string, FieldConfigMetadata], - thisModelPrimaryKey: string, + thisModelPrimaryKeys: string[], + joinTable: GenericDataModel, ) => { let [fieldName] = hasManyFieldConfig; const [, fieldConfigMetaData] = hasManyFieldConfig; fieldName = fieldConfigMetaData.sanitizedFieldName || fieldName; - const { relatedModelField, relatedJoinFieldName, relatedJoinTableName, relatedModelName } = + const { relatedModelFields, relatedJoinFieldName, relatedJoinTableName, relatedModelName } = fieldConfigMetaData.relationship as HasManyRelationshipType; + const joinTableThisModelName = relatedModelFields[0]; + const joinTableRelatedModelName = relatedJoinFieldName; + if (!joinTableRelatedModelName) { + throw new InternalError(`Cannot find corresponding field in join table for ${fieldName}`); + } + const joinTableThisModelFields = extractAssociatedFields(joinTable.fields[joinTableThisModelName]); + const joinTableRelatedModelFields = extractAssociatedFields(joinTable.fields[joinTableRelatedModelName]); + + if (!joinTableThisModelFields || !joinTableRelatedModelFields) { + throw new InternalError(`Cannot find associated fields to build ${fieldName}`); + } if (dataStoreActionType === 'update') { + const idValueCallChain = getIDValueCallChain({ fieldName, recordString: 'r' }); const linkedDataName = getLinkedDataName(fieldName); const dataToLinkMap = `${lowerCaseFirst(fieldName)}ToLinkMap`; const dataToUnlinkMap = `${lowerCaseFirst(fieldName)}ToUnLinkMap`; const updatedMap = `${lowerCaseFirst(fieldName)}Map`; const originalMap = `${linkedDataName}Map`; - const { keys } = extractModelAndKeys(fieldConfigMetaData.valueMappings); - if (!keys) { + const { keys: relatedModelPrimaryKeys } = extractModelAndKeys(fieldConfigMetaData.valueMappings); + if (!relatedModelPrimaryKeys) { throw new InternalError(`Could not identify primary key(s) for ${relatedModelName}`); } - // TODO: update for composite - const relatedModelPrimaryKey = keys[0]; return [ factory.createVariableStatement( @@ -159,7 +274,7 @@ export const buildManyToManyRelationshipDataStoreStatements = ( [ factory.createVariableStatement( undefined, - // const count = cPKClassesMap.get(r.specialClassId); + // const count = cPKClassesMap.get(getIDValue.CPKClasses?.(r)); factory.createVariableDeclarationList( [ factory.createVariableDeclaration( @@ -172,12 +287,7 @@ export const buildManyToManyRelationshipDataStoreStatements = ( factory.createIdentifier('get'), ), undefined, - [ - factory.createPropertyAccessExpression( - factory.createIdentifier('r'), - factory.createIdentifier(relatedModelPrimaryKey), - ), - ], + [idValueCallChain], ), ), ], @@ -208,7 +318,7 @@ export const buildManyToManyRelationshipDataStoreStatements = ( NodeFlags.Const, ), ), - // cPKClassesMap.set(r.specialClassId, newCount); + // cPKClassesMap.set(getIDValue.CPKClasses?.(r), newCount); factory.createExpressionStatement( factory.createCallExpression( factory.createPropertyAccessExpression( @@ -216,13 +326,7 @@ export const buildManyToManyRelationshipDataStoreStatements = ( factory.createIdentifier('set'), ), undefined, - [ - factory.createPropertyAccessExpression( - factory.createIdentifier('r'), - factory.createIdentifier(relatedModelPrimaryKey), - ), - factory.createIdentifier('newCount'), - ], + [idValueCallChain, factory.createIdentifier('newCount')], ), ), ], @@ -262,7 +366,7 @@ export const buildManyToManyRelationshipDataStoreStatements = ( undefined, factory.createVariableDeclarationList( [ - // const count = linkedCPKClassesMap.get(r.specialClassId); + // const count = linkedCPKClassesMap.get(getIDValue.CPKClasses?.(r)); factory.createVariableDeclaration( factory.createIdentifier('count'), undefined, @@ -273,12 +377,7 @@ export const buildManyToManyRelationshipDataStoreStatements = ( factory.createIdentifier('get'), ), undefined, - [ - factory.createPropertyAccessExpression( - factory.createIdentifier('r'), - factory.createIdentifier(relatedModelPrimaryKey), - ), - ], + [idValueCallChain], ), ), ], @@ -310,20 +409,14 @@ export const buildManyToManyRelationshipDataStoreStatements = ( ), ), factory.createExpressionStatement( - // linkedCPKClassesMap.set(r.specialClassId, newCount); + // linkedCPKClassesMap.set(getIDValue.CPKClasses?.(r), newCount); factory.createCallExpression( factory.createPropertyAccessExpression( factory.createIdentifier(originalMap), factory.createIdentifier('set'), ), undefined, - [ - factory.createPropertyAccessExpression( - factory.createIdentifier('r'), - factory.createIdentifier(relatedModelPrimaryKey), - ), - factory.createIdentifier('newCount'), - ], + [idValueCallChain, factory.createIdentifier('newCount')], ), ), ], @@ -662,56 +755,13 @@ export const buildManyToManyRelationshipDataStoreStatements = ( ), undefined, [ - factory.createArrowFunction( - undefined, - undefined, - [ - factory.createParameterDeclaration( - undefined, - undefined, - undefined, - factory.createIdentifier('r'), - undefined, - undefined, - undefined, - ), - ], - undefined, - factory.createToken(SyntaxKind.EqualsGreaterThanToken), - factory.createArrayLiteralExpression( - [ - factory.createCallExpression( - factory.createPropertyAccessExpression( - factory.createPropertyAccessExpression( - factory.createIdentifier('r'), - factory.createIdentifier(`${relatedJoinFieldName}ID`), - ), - factory.createIdentifier('eq'), - ), - undefined, - [factory.createIdentifier('id')], - ), - // r.cpkTeacherID.eq(cPKTeacherRecord.specialTeacherId), - factory.createCallExpression( - factory.createPropertyAccessExpression( - factory.createPropertyAccessExpression( - factory.createIdentifier('r'), - factory.createIdentifier(`${relatedModelField}ID`), - ), - factory.createIdentifier('eq'), - ), - undefined, - [ - factory.createPropertyAccessExpression( - factory.createIdentifier(`${lowerCaseFirst(modelName)}Record`), - factory.createIdentifier(thisModelPrimaryKey), - ), - ], - ), - ], - false, - ), - ), + getJoinTableQueryArrowFunction({ + thisModelPrimaryKeys, + relatedModelPrimaryKeys, + joinTableThisModelFields, + joinTableRelatedModelFields, + thisModelRecord: `${lowerCaseFirst(modelName)}Record`, + }), ], ), ), @@ -856,17 +906,20 @@ export const buildManyToManyRelationshipDataStoreStatements = ( [ factory.createObjectLiteralExpression( [ - // cpkTeacherID: cPKTeacherRecord.specialTeacherId, + // cpkTeacher: cPKTeacherRecord, factory.createPropertyAssignment( - factory.createIdentifier(`${relatedModelField}ID`), - factory.createPropertyAccessExpression( - factory.createIdentifier(`${lowerCaseFirst(modelName)}Record`), - factory.createIdentifier(thisModelPrimaryKey), - ), + factory.createIdentifier(joinTableThisModelName), + factory.createIdentifier(`${lowerCaseFirst(modelName)}Record`), ), + // compositeVet: compositeVetRecords.find( + // (r) => Object.entries(JSON.parse(id)).every(([key, value]) => + // r[key] === value)) factory.createPropertyAssignment( - factory.createIdentifier(`${relatedJoinFieldName}ID`), - factory.createIdentifier('id'), + factory.createIdentifier(joinTableRelatedModelName), + getMatchEveryModelFieldCallExpression({ + recordsArrayName: getRecordsName(relatedModelName), + JSONName: 'id', + }), ), ], true, @@ -954,7 +1007,8 @@ export const buildManyToManyRelationshipDataStoreStatements = ( factory.createObjectLiteralExpression( [ factory.createShorthandPropertyAssignment( - factory.createIdentifier(relatedModelField), + // TODO: update w/ create form support for composite keys + factory.createIdentifier(relatedModelFields[0]), undefined, ), factory.createShorthandPropertyAssignment( @@ -1154,12 +1208,12 @@ export const buildHasManyRelationshipDataStoreStatements = ( dataStoreActionType: 'update' | 'create', modelName: string, hasManyFieldConfig: [string, FieldConfigMetadata], - thisModelPrimaryKey: string, + thisModelPrimaryKeys: string[], ) => { let [fieldName] = hasManyFieldConfig; const [, fieldConfigMetaData] = hasManyFieldConfig; fieldName = fieldConfigMetaData.sanitizedFieldName || fieldName; - const { relatedModelName, relatedModelField } = fieldConfigMetaData.relationship as HasManyRelationshipType; + const { relatedModelName, relatedModelFields } = fieldConfigMetaData.relationship as HasManyRelationshipType; const linkedDataName = getLinkedDataName(fieldName); const dataToLink = `${lowerCaseFirst(fieldName)}ToLink`; const dataToUnLink = `${lowerCaseFirst(fieldName)}ToUnLink`; @@ -1169,9 +1223,9 @@ export const buildHasManyRelationshipDataStoreStatements = ( if (!keys) { throw new InternalError(`Could not identify primary key(s) for ${relatedModelName}`); } - // TODO: update for composite keys - const relatedModelPrimaryKey = keys[0]; if (dataStoreActionType === 'update') { + const idValueCallChain = getIDValueCallChain({ fieldName, recordString: 'r' }); + return [ factory.createVariableStatement( undefined, @@ -1231,7 +1285,7 @@ export const buildHasManyRelationshipDataStoreStatements = ( ), factory.createExpressionStatement( factory.createCallExpression( - // CPKProjects.forEach((r) => cPKProjectsSet.add(r.specialProjectId)); + // CPKProjects.forEach((r) => cPKProjectsSet.add(getIDValue.CPKProjects?.(r))); factory.createPropertyAccessExpression( factory.createIdentifier(fieldName), factory.createIdentifier('forEach'), @@ -1260,18 +1314,13 @@ export const buildHasManyRelationshipDataStoreStatements = ( factory.createIdentifier('add'), ), undefined, - [ - factory.createPropertyAccessExpression( - factory.createIdentifier('r'), - factory.createIdentifier(relatedModelPrimaryKey), - ), - ], + [idValueCallChain], ), ), ], ), ), - // linkedCPKProjects.forEach((r) => linkedCPKProjectsSet.add(r.specialProjectId)); + // linkedCPKProjects.forEach((r) => linkedCPKProjectsSet.add(getIDValue.CPKProjects?.(r))); factory.createExpressionStatement( factory.createCallExpression( factory.createPropertyAccessExpression( @@ -1302,12 +1351,7 @@ export const buildHasManyRelationshipDataStoreStatements = ( factory.createIdentifier('add'), ), undefined, - [ - factory.createPropertyAccessExpression( - factory.createIdentifier('r'), - factory.createIdentifier(relatedModelPrimaryKey), - ), - ], + [idValueCallChain], ), ), ], @@ -1348,12 +1392,7 @@ export const buildHasManyRelationshipDataStoreStatements = ( factory.createIdentifier('has'), ), undefined, - [ - factory.createPropertyAccessExpression( - factory.createIdentifier('r'), - factory.createIdentifier('id'), - ), - ], + [idValueCallChain], ), ), factory.createBlock( @@ -1415,12 +1454,7 @@ export const buildHasManyRelationshipDataStoreStatements = ( factory.createIdentifier('has'), ), undefined, - [ - factory.createPropertyAccessExpression( - factory.createIdentifier('r'), - factory.createIdentifier('id'), - ), - ], + [idValueCallChain], ), ), factory.createBlock( @@ -1513,7 +1547,7 @@ export const buildHasManyRelationshipDataStoreStatements = ( undefined, factory.createToken(SyntaxKind.EqualsGreaterThanToken), factory.createBlock( - [ + relatedModelFields.map((relatedModelField) => factory.createExpressionStatement( factory.createBinaryExpression( factory.createPropertyAccessExpression( @@ -1524,7 +1558,7 @@ export const buildHasManyRelationshipDataStoreStatements = ( factory.createNull(), ), ), - ], + ), true, ), ), @@ -1608,9 +1642,16 @@ export const buildHasManyRelationshipDataStoreStatements = ( undefined, factory.createToken(SyntaxKind.EqualsGreaterThanToken), factory.createBlock( - [ - // updated.cPKTeacherID = cPKTeacherRecord.specialTeacherId; - factory.createExpressionStatement( + // updated.cPKTeacherID = cPKTeacherRecord.specialTeacherId; + relatedModelFields.map((relatedModelField, index) => { + const correspondingPrimaryKey = thisModelPrimaryKeys[index]; + if (!correspondingPrimaryKey) { + throw new InternalError( + `Corresponding primary key not found for ${relatedModelField}`, + ); + } + + return factory.createExpressionStatement( factory.createBinaryExpression( factory.createPropertyAccessExpression( factory.createIdentifier('updated'), @@ -1619,11 +1660,11 @@ export const buildHasManyRelationshipDataStoreStatements = ( factory.createToken(SyntaxKind.EqualsToken), factory.createPropertyAccessExpression( factory.createIdentifier(`${lowerCaseFirst(modelName)}Record`), - factory.createIdentifier(thisModelPrimaryKey), + factory.createIdentifier(correspondingPrimaryKey), ), ), - ), - ], + ); + }), true, ), ), @@ -1729,7 +1770,8 @@ export const buildHasManyRelationshipDataStoreStatements = ( factory.createBinaryExpression( factory.createPropertyAccessExpression( factory.createIdentifier('updated'), - factory.createIdentifier(relatedModelField), + // TODO: update w/ create form support for composite keys + factory.createIdentifier(relatedModelFields[0]), ), factory.createToken(SyntaxKind.EqualsToken), factory.createPropertyAccessExpression( diff --git a/packages/codegen-ui-react/lib/forms/react-form-renderer.ts b/packages/codegen-ui-react/lib/forms/react-form-renderer.ts index a20ae5938..fc9ad8a47 100644 --- a/packages/codegen-ui-react/lib/forms/react-form-renderer.ts +++ b/packages/codegen-ui-react/lib/forms/react-form-renderer.ts @@ -29,7 +29,6 @@ import { StudioNode, StudioTemplateRenderer, validateFormSchema, - getDataSchemaMetaData, } from '@aws-amplify/codegen-ui'; import { EOL } from 'os'; import { @@ -131,7 +130,7 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer< protected shouldRenderArrayField = false; - protected primaryKey: string | undefined; + protected primaryKeys: string[] | undefined; constructor(component: StudioForm, dataSchema: GenericDataSchema | undefined, renderConfig: ReactRenderConfig) { super(component, new ReactOutputManager(), renderConfig); @@ -151,11 +150,11 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer< this.componentMetadata.formMetadata = mapFormMetadata(this.component, this.formDefinition); this.importCollection = new ImportCollection(this.componentMetadata); if (dataSchema) { - const dataSchemaMetadata = getDataSchemaMetaData({ dataSchema }); + const dataSchemaMetadata = dataSchema; this.componentMetadata.dataSchemaMetadata = dataSchemaMetadata; const { dataSourceType, dataTypeName } = this.component.dataType; if (dataSourceType === 'DataStore') { - this.primaryKey = dataSchemaMetadata.models[dataTypeName].primaryKey; + this.primaryKeys = dataSchemaMetadata.models[dataTypeName].primaryKeys; } } } @@ -347,7 +346,7 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer< factory.createTypeReferenceNode(factory.createIdentifier('React.PropsWithChildren'), [ factory.createIntersectionTypeNode([ escapeHatchTypeNode, - buildFormPropNode(this.component, modelName, this.primaryKey), + buildFormPropNode(this.component, modelName, this.primaryKeys?.[0]), factory.createTypeReferenceNode( factory.createQualifiedName(factory.createIdentifier('React'), factory.createIdentifier('CSSProperties')), undefined, @@ -393,7 +392,7 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer< const elements: BindingElement[] = [ // add in hooks for before/complete with ds and basic onSubmit with props - ...buildMutationBindings(this.component, this.primaryKey), + ...buildMutationBindings(this.component, this.primaryKeys?.[0]), // onValidate prop factory.createBindingElement(undefined, undefined, factory.createIdentifier('onValidate'), undefined), // onChange prop @@ -490,8 +489,8 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer< }); // primaryKey should exist if DataStore update form. This condition is just for ts - if (this.primaryKey) { - const destructuredPrimaryKey = getPropName(this.primaryKey); + if (this.primaryKeys) { + const destructuredPrimaryKey = getPropName(this.primaryKeys[0]); statements.push( addUseEffectWrapper( buildUpdateDatastoreQuery( diff --git a/packages/codegen-ui-react/lib/react-studio-template-renderer.ts b/packages/codegen-ui-react/lib/react-studio-template-renderer.ts index bad6ae385..36f68b99c 100644 --- a/packages/codegen-ui-react/lib/react-studio-template-renderer.ts +++ b/packages/codegen-ui-react/lib/react-studio-template-renderer.ts @@ -1138,7 +1138,7 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer const propAssigments: PropertyAssignment[] = []; Object.entries(this.dataSchema.models[model].fields).forEach(([key, field]) => { if (field.relationship?.type === 'HAS_MANY') { - const { relatedModelName, relatedModelField } = field.relationship; + const { relatedModelName, relatedModelFields } = field.relationship; const modelName = this.importCollection.addImport(ImportSource.LOCAL_MODELS, relatedModelName); const itemsName = getActionIdentifier(relatedModelName, 'Items'); statements.push( @@ -1147,7 +1147,8 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer this.buildUseDataStoreBindingCall('collection', modelName), ), ); - propAssigments.push(buildPropAssignmentWithFilter(key, itemsName, relatedModelField)); + // TODO: support composite keys in collections + propAssigments.push(buildPropAssignmentWithFilter(key, itemsName, relatedModelFields[0])); } }); statements.push( diff --git a/packages/codegen-ui/lib/__tests__/generic-from-datastore.test.ts b/packages/codegen-ui/lib/__tests__/generic-from-datastore.test.ts index 7124ded5c..fa5df955e 100644 --- a/packages/codegen-ui/lib/__tests__/generic-from-datastore.test.ts +++ b/packages/codegen-ui/lib/__tests__/generic-from-datastore.test.ts @@ -73,7 +73,7 @@ describe('getGenericFromDataStore', () => { expect(genericSchema.models.Student.fields.Teachers.relationship).toStrictEqual({ type: 'HAS_MANY', relatedModelName: 'Teacher', - relatedModelField: 'student', + relatedModelFields: ['student'], relatedJoinFieldName: 'teacher', relatedJoinTableName: 'StudentTeacher', }); @@ -81,7 +81,7 @@ describe('getGenericFromDataStore', () => { expect(genericSchema.models.Teacher.fields.students.relationship).toStrictEqual({ type: 'HAS_MANY', relatedModelName: 'Student', - relatedModelField: 'teacher', + relatedModelFields: ['teacher'], relatedJoinFieldName: 'student', relatedJoinTableName: 'StudentTeacher', }); @@ -106,7 +106,7 @@ describe('getGenericFromDataStore', () => { expect(genericSchema.models.Owner.fields.Dog.relationship).toStrictEqual({ type: 'HAS_MANY', relatedModelName: 'Dog', - relatedModelField: 'ownerID', + relatedModelFields: ['ownerID'], relatedJoinFieldName: undefined, relatedJoinTableName: undefined, }); @@ -134,7 +134,7 @@ describe('getGenericFromDataStore', () => { expect(genericSchema.models.Student.fields.Teachers.relationship).toStrictEqual({ type: 'HAS_MANY', relatedModelName: 'Teacher', - relatedModelField: 'student', + relatedModelFields: ['student'], relatedJoinFieldName: 'teacher', relatedJoinTableName: 'StudentTeacher', }); @@ -142,7 +142,7 @@ describe('getGenericFromDataStore', () => { expect(genericSchema.models.Teacher.fields.students.relationship).toStrictEqual({ type: 'HAS_MANY', relatedModelName: 'Student', - relatedModelField: 'teacher', + relatedModelFields: ['teacher'], relatedJoinFieldName: 'student', relatedJoinTableName: 'StudentTeacher', }); @@ -167,7 +167,7 @@ describe('getGenericFromDataStore', () => { expect(genericSchema.models.Owner.fields.Dog.relationship).toStrictEqual({ type: 'HAS_MANY', relatedModelName: 'Dog', - relatedModelField: 'ownerID', + relatedModelFields: ['ownerID'], relatedJoinFieldName: undefined, relatedJoinTableName: undefined, }); @@ -204,7 +204,7 @@ describe('getGenericFromDataStore', () => { expect(userFields.friends.relationship).toStrictEqual({ type: 'HAS_MANY', relatedModelName: 'Friend', - relatedModelField: 'friendId', + relatedModelFields: ['friendId'], relatedJoinFieldName: undefined, relatedJoinTableName: undefined, }); @@ -212,7 +212,7 @@ describe('getGenericFromDataStore', () => { expect(userFields.posts.relationship).toStrictEqual({ type: 'HAS_MANY', relatedModelName: 'Post', - relatedModelField: 'userPostsId', + relatedModelFields: ['userPostsId'], relatedJoinFieldName: undefined, relatedJoinTableName: undefined, }); diff --git a/packages/codegen-ui/lib/generic-from-datastore.ts b/packages/codegen-ui/lib/generic-from-datastore.ts index 59f7bb702..439ee904e 100644 --- a/packages/codegen-ui/lib/generic-from-datastore.ts +++ b/packages/codegen-ui/lib/generic-from-datastore.ts @@ -97,41 +97,44 @@ export function getGenericFromDataStore(dataStoreSchema: DataStoreSchema): Gener if (relationshipType === 'HAS_MANY' && 'associatedWith' in field.association) { const associatedModel = dataStoreSchema.models[relatedModelName]; - const associatedFieldName = Array.isArray(field.association?.associatedWith) - ? field.association.associatedWith[0] - : field.association.associatedWith; - const associatedField = associatedModel?.fields[associatedFieldName]; - // if the associated model is a join table, update relatedModelName to the actual related model - if ( - associatedField && - typeof associatedField.type === 'object' && - 'model' in associatedField.type && - associatedField.type.model === model.name - ) { - joinTableNames.push(associatedModel.name); - - const relatedJoinField = Object.values(associatedModel.fields).find( - (joinField) => - joinField.name !== associatedFieldName && - typeof joinField.type === 'object' && - 'model' in joinField.type, - ); - if (relatedJoinField && typeof relatedJoinField.type === 'object' && 'model' in relatedJoinField.type) { - relatedModelName = relatedJoinField.type.model; - relatedJoinFieldName = relatedJoinField.name; - relatedJoinTableName = field.type.model; + const associatedFieldNames = Array.isArray(field.association?.associatedWith) + ? field.association.associatedWith + : [field.association.associatedWith]; + + associatedFieldNames.forEach((associatedFieldName) => { + const associatedField = associatedModel?.fields[associatedFieldName]; + // if the associated model is a join table, update relatedModelName to the actual related model + if ( + associatedField && + typeof associatedField.type === 'object' && + 'model' in associatedField.type && + associatedField.type.model === model.name + ) { + joinTableNames.push(associatedModel.name); + + const relatedJoinField = Object.values(associatedModel.fields).find( + (joinField) => + joinField.name !== associatedFieldName && + typeof joinField.type === 'object' && + 'model' in joinField.type, + ); + if (relatedJoinField && typeof relatedJoinField.type === 'object' && 'model' in relatedJoinField.type) { + relatedJoinTableName = relatedModelName; + relatedModelName = relatedJoinField.type.model; + relatedJoinFieldName = relatedJoinField.name; + } + // if the associated model is not a join table, note implicit relationship for associated field + } else { + addRelationship(fieldsWithImplicitRelationships, relatedModelName, associatedFieldName, { + type: 'HAS_ONE', + relatedModelName: model.name, + }); } - // if the associated model is not a join table, note implicit relationship for associated field - } else { - addRelationship(fieldsWithImplicitRelationships, relatedModelName, associatedFieldName, { - type: 'HAS_ONE', - relatedModelName: model.name, - }); - } + }); modelRelationship = { type: relationshipType, relatedModelName, - relatedModelField: associatedFieldName, + relatedModelFields: associatedFieldNames, relatedJoinFieldName, relatedJoinTableName, }; diff --git a/packages/codegen-ui/lib/types/data.ts b/packages/codegen-ui/lib/types/data.ts index d04d391d1..5b2502edc 100644 --- a/packages/codegen-ui/lib/types/data.ts +++ b/packages/codegen-ui/lib/types/data.ts @@ -36,7 +36,7 @@ export type CommonRelationshipType = { export type HasManyRelationshipType = { type: 'HAS_MANY'; - relatedModelField: string; + relatedModelFields: string[]; relatedJoinFieldName?: string; relatedJoinTableName?: string; } & CommonRelationshipType; diff --git a/packages/codegen-ui/lib/utils/component-metadata.ts b/packages/codegen-ui/lib/utils/component-metadata.ts index 992f534e0..7939aa083 100644 --- a/packages/codegen-ui/lib/utils/component-metadata.ts +++ b/packages/codegen-ui/lib/utils/component-metadata.ts @@ -22,8 +22,8 @@ import { StudioComponentPropertyBinding, StateReference, FormMetadata, + GenericDataSchema, } from '../types'; -import { DataSchemaMetaData } from './dataschema-metadata'; import { StateReferenceMetadata, computeStateReferenceMetadata } from './state-reference-metadata'; export type ComponentMetadata = { @@ -32,7 +32,7 @@ export type ComponentMetadata = { stateReferences: StateReferenceMetadata[]; componentNameToTypeMap: Record; formMetadata?: FormMetadata; - dataSchemaMetadata?: DataSchemaMetaData; + dataSchemaMetadata?: GenericDataSchema; }; /** diff --git a/packages/codegen-ui/lib/utils/dataschema-metadata.ts b/packages/codegen-ui/lib/utils/dataschema-metadata.ts deleted file mode 100644 index b6d11b0de..000000000 --- a/packages/codegen-ui/lib/utils/dataschema-metadata.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"). - You may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ -import { GenericDataSchema } from '../types/data'; - -export type DataSchemaMetaData = { - models: { [modelName: string]: { primaryKey: string } }; -}; - -export function getDataSchemaMetaData({ dataSchema }: { dataSchema: GenericDataSchema }): DataSchemaMetaData { - const metaData: DataSchemaMetaData = { models: {} }; - - Object.entries(dataSchema.models).forEach(([modelName, modelConfig]) => { - metaData.models[modelName] = { primaryKey: modelConfig.primaryKeys[0] }; - }); - - return metaData; -} diff --git a/packages/codegen-ui/lib/utils/index.ts b/packages/codegen-ui/lib/utils/index.ts index 9b0a32460..b44a1209a 100644 --- a/packages/codegen-ui/lib/utils/index.ts +++ b/packages/codegen-ui/lib/utils/index.ts @@ -22,4 +22,3 @@ export * from './form-to-component'; export * from './breakpoint-utils'; export * from './form-utils'; export * from './reserved-words'; -export * from './dataschema-metadata';