Skip to content

Commit ad4bf57

Browse files
author
Justin Shih
committed
chore(amplify-util-uibuilder): remove codegen-ui usage
1 parent 8b5d433 commit ad4bf57

13 files changed

+4820
-127
lines changed

packages/amplify-util-uibuilder/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
"@aws-amplify/amplify-category-api": "^5.6.2",
1818
"@aws-amplify/amplify-cli-core": "4.2.5",
1919
"@aws-amplify/amplify-prompts": "2.8.2",
20-
"@aws-amplify/codegen-ui": "2.14.2",
21-
"@aws-amplify/codegen-ui-react": "2.14.2",
20+
"@aws-amplify/datastore": "^4.7.5",
2221
"amplify-codegen": "^4.4.0",
2322
"aws-sdk": "^2.1426.0",
2423
"fs-extra": "^8.1.0",
@@ -32,6 +31,7 @@
3231
"@types/jest": "^29.5.1",
3332
"@types/semver": "^7.1.0",
3433
"@types/tiny-async-pool": "^2.0.0",
34+
"semver": "^7.5.4",
3535
"ts-jest": "^29.1.0"
3636
},
3737
"jest": {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import semver from 'semver';
2+
import { ReactRequiredDependencyProvider } from '../commands/utils/codegen-ui-dependency-provider';
3+
4+
describe('ReactStudioDependencyProvider', () => {
5+
const requiredDependencies = new ReactRequiredDependencyProvider().getRequiredDependencies(false);
6+
const requiredDependenciesWithStorageManager = new ReactRequiredDependencyProvider().getRequiredDependencies(true);
7+
8+
describe('getRequiredDependencies', () => {
9+
it('has required dependencies', () => {
10+
expect(requiredDependencies.length).toBeGreaterThan(0);
11+
});
12+
13+
it('includes ui-react', () => {
14+
expect(requiredDependencies.filter((dep) => dep.dependencyName === '@aws-amplify/ui-react')).toBeTruthy();
15+
});
16+
17+
it('includes all valid semver values', () => {
18+
requiredDependencies.forEach((dep) => {
19+
expect(semver.valid(dep.supportedSemVerPattern)).toBeDefined();
20+
});
21+
});
22+
23+
it('includes reasons on all dependencies', () => {
24+
requiredDependencies.forEach((dep) => {
25+
expect(dep.reason.length).toBeGreaterThan(0);
26+
});
27+
});
28+
29+
it('does not include ui-react-storage if user does not use StorageManager', () => {
30+
expect(requiredDependencies.filter((dep) => dep.dependencyName !== '@aws-amplify/ui-react-storage')).toBeTruthy();
31+
});
32+
33+
it('includes ui-react-storage if user is using StorageManager', () => {
34+
expect(requiredDependenciesWithStorageManager.filter((dep) => dep.dependencyName === '@aws-amplify/ui-react-storage')).toBeTruthy();
35+
});
36+
});
37+
});
Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
import { getGenericFromDataStore } from '../commands/utils/codegen-ui';
2+
import { HasManyRelationshipType } from '../commands/utils/data-types';
3+
import {
4+
schemaWithEnums,
5+
schemaWithNonModels,
6+
schemaWithRelationships,
7+
schemaWithRelationshipsV2,
8+
schemaWithAssumptions,
9+
schemaWithCPK,
10+
schemaWithCompositeKeys,
11+
schemaWithHasManyBelongsTo,
12+
schemaWithoutJoinTables,
13+
introspectionSchemaWithCompositeKeys,
14+
schemaWithBiDirectionalHasManyWithDefinedField,
15+
} from './mock-schemas';
16+
17+
describe('getGenericFromDataStore', () => {
18+
it('should map fields', () => {
19+
const genericSchema = getGenericFromDataStore(schemaWithRelationships);
20+
expect(genericSchema.models.Child.fields).toStrictEqual({
21+
id: {
22+
dataType: 'ID',
23+
required: true,
24+
readOnly: false,
25+
isArray: false,
26+
},
27+
name: {
28+
dataType: 'String',
29+
required: false,
30+
readOnly: false,
31+
isArray: false,
32+
},
33+
createdAt: {
34+
dataType: 'AWSDateTime',
35+
required: false,
36+
readOnly: true,
37+
isArray: false,
38+
},
39+
updatedAt: {
40+
dataType: 'AWSDateTime',
41+
required: false,
42+
readOnly: true,
43+
isArray: false,
44+
},
45+
});
46+
});
47+
48+
it('should map relationships', () => {
49+
const genericSchema = getGenericFromDataStore(schemaWithRelationships);
50+
51+
expect(genericSchema.models.PrimaryCareGiver.fields.Child.relationship).toStrictEqual({
52+
type: 'HAS_ONE',
53+
relatedModelName: 'Child',
54+
associatedFields: ['primaryCareGiverChildId'],
55+
});
56+
57+
expect(genericSchema.models.PrimaryCareGiver.fields.primaryCareGiverChildId.relationship).toStrictEqual({
58+
type: 'HAS_ONE',
59+
relatedModelName: 'Child',
60+
});
61+
62+
expect(genericSchema.models.Student.fields.Teachers.relationship).toStrictEqual<HasManyRelationshipType>({
63+
type: 'HAS_MANY',
64+
relatedModelName: 'Teacher',
65+
relatedModelFields: ['student'],
66+
belongsToFieldOnRelatedModel: 'student',
67+
canUnlinkAssociatedModel: false,
68+
relatedJoinFieldName: 'teacher',
69+
relatedJoinTableName: 'StudentTeacher',
70+
});
71+
72+
expect(genericSchema.models.Teacher.fields.students.relationship).toStrictEqual<HasManyRelationshipType>({
73+
type: 'HAS_MANY',
74+
relatedModelName: 'Student',
75+
belongsToFieldOnRelatedModel: 'teacher',
76+
relatedModelFields: ['teacher'],
77+
canUnlinkAssociatedModel: false,
78+
relatedJoinFieldName: 'student',
79+
relatedJoinTableName: 'StudentTeacher',
80+
});
81+
82+
expect(genericSchema.models.Lock.fields.Key.relationship).toStrictEqual({
83+
type: 'HAS_ONE',
84+
relatedModelName: 'Key',
85+
associatedFields: ['lockKeyId'],
86+
});
87+
88+
expect(genericSchema.models.Lock.fields.lockKeyId.relationship).toStrictEqual({
89+
type: 'HAS_ONE',
90+
relatedModelName: 'Key',
91+
});
92+
93+
expect(genericSchema.models.Key.fields.Lock.relationship).toStrictEqual({
94+
type: 'BELONGS_TO',
95+
relatedModelName: 'Lock',
96+
associatedFields: ['keyLockId'],
97+
});
98+
99+
expect(genericSchema.models.Owner.fields.Dog.relationship).toStrictEqual<HasManyRelationshipType>({
100+
type: 'HAS_MANY',
101+
relatedModelName: 'Dog',
102+
relatedModelFields: ['ownerID'],
103+
canUnlinkAssociatedModel: true,
104+
relatedJoinFieldName: undefined,
105+
relatedJoinTableName: undefined,
106+
});
107+
108+
expect(genericSchema.models.Dog.fields.ownerID.relationship).toStrictEqual({
109+
type: 'HAS_ONE',
110+
relatedModelName: 'Owner',
111+
isHasManyIndex: true,
112+
});
113+
});
114+
115+
it('should map v2 relationships', () => {
116+
const genericSchema = getGenericFromDataStore(schemaWithRelationshipsV2);
117+
118+
expect(genericSchema.models.PrimaryCareGiver.fields.Child.relationship).toStrictEqual({
119+
type: 'HAS_ONE',
120+
relatedModelName: 'Child',
121+
associatedFields: ['primaryCareGiverChildId'],
122+
});
123+
124+
expect(genericSchema.models.PrimaryCareGiver.fields.primaryCareGiverChildId.relationship).toStrictEqual({
125+
type: 'HAS_ONE',
126+
relatedModelName: 'Child',
127+
});
128+
129+
expect(genericSchema.models.Student.fields.Teachers.relationship).toStrictEqual<HasManyRelationshipType>({
130+
type: 'HAS_MANY',
131+
relatedModelName: 'Teacher',
132+
relatedModelFields: ['student'],
133+
belongsToFieldOnRelatedModel: 'student',
134+
canUnlinkAssociatedModel: false,
135+
relatedJoinFieldName: 'teacher',
136+
relatedJoinTableName: 'StudentTeacher',
137+
});
138+
139+
expect(genericSchema.models.Teacher.fields.students.relationship).toStrictEqual<HasManyRelationshipType>({
140+
type: 'HAS_MANY',
141+
relatedModelName: 'Student',
142+
belongsToFieldOnRelatedModel: 'teacher',
143+
relatedModelFields: ['teacher'],
144+
canUnlinkAssociatedModel: false,
145+
relatedJoinFieldName: 'student',
146+
relatedJoinTableName: 'StudentTeacher',
147+
});
148+
149+
expect(genericSchema.models.Lock.fields.Key.relationship).toStrictEqual({
150+
type: 'HAS_ONE',
151+
relatedModelName: 'Key',
152+
associatedFields: ['lockKeyId'],
153+
});
154+
155+
expect(genericSchema.models.Lock.fields.lockKeyId.relationship).toStrictEqual({
156+
type: 'HAS_ONE',
157+
relatedModelName: 'Key',
158+
});
159+
160+
expect(genericSchema.models.Key.fields.Lock.relationship).toStrictEqual({
161+
type: 'BELONGS_TO',
162+
relatedModelName: 'Lock',
163+
associatedFields: ['keyLockId'],
164+
});
165+
166+
expect(genericSchema.models.Owner.fields.Dog.relationship).toStrictEqual<HasManyRelationshipType>({
167+
type: 'HAS_MANY',
168+
relatedModelName: 'Dog',
169+
relatedModelFields: ['ownerID'],
170+
canUnlinkAssociatedModel: true,
171+
relatedJoinFieldName: undefined,
172+
relatedJoinTableName: undefined,
173+
});
174+
175+
expect(genericSchema.models.Dog.fields.ownerID.relationship).toStrictEqual({
176+
type: 'HAS_ONE',
177+
relatedModelName: 'Owner',
178+
isHasManyIndex: true,
179+
});
180+
});
181+
182+
it('should map enums', () => {
183+
const genericSchema = getGenericFromDataStore(schemaWithEnums);
184+
185+
expect(genericSchema.enums).toStrictEqual(schemaWithEnums.enums);
186+
});
187+
188+
it('should map nonModels', () => {
189+
const genericSchema = getGenericFromDataStore(schemaWithNonModels);
190+
expect(genericSchema.nonModels).toStrictEqual({
191+
Reactions: {
192+
fields: {
193+
ball: { dataType: 'String', required: false, readOnly: false, isArray: false },
194+
fireworks: { dataType: 'String', required: false, readOnly: false, isArray: false },
195+
},
196+
},
197+
Misc: { fields: { quotes: { dataType: 'String', required: false, readOnly: false, isArray: true } } },
198+
});
199+
});
200+
201+
it('should handle schema with assumed associated fields and models', () => {
202+
const genericSchema = getGenericFromDataStore(schemaWithAssumptions);
203+
const userFields = genericSchema.models.User.fields;
204+
205+
expect(userFields.friends.relationship).toStrictEqual<HasManyRelationshipType>({
206+
type: 'HAS_MANY',
207+
relatedModelName: 'Friend',
208+
relatedModelFields: ['friendId'],
209+
canUnlinkAssociatedModel: true,
210+
relatedJoinFieldName: undefined,
211+
relatedJoinTableName: undefined,
212+
});
213+
214+
expect(userFields.posts.relationship).toStrictEqual<HasManyRelationshipType>({
215+
type: 'HAS_MANY',
216+
relatedModelName: 'Post',
217+
relatedModelFields: ['userPostsId'],
218+
canUnlinkAssociatedModel: true,
219+
relatedJoinFieldName: undefined,
220+
relatedJoinTableName: undefined,
221+
});
222+
});
223+
224+
it('should correctly identify join tables', () => {
225+
const genericSchemaWithJoinTable = getGenericFromDataStore(schemaWithRelationships);
226+
const joinTables1 = Object.entries(genericSchemaWithJoinTable.models)
227+
.filter(([, model]) => model.isJoinTable)
228+
.map(([name]) => name);
229+
expect(joinTables1).toStrictEqual(['StudentTeacher']);
230+
231+
const genericSchemaWithoutJoinTable = getGenericFromDataStore(schemaWithoutJoinTables);
232+
const joinTables2 = Object.entries(genericSchemaWithoutJoinTable.models)
233+
.filter(([, model]) => model.isJoinTable)
234+
.map(([name]) => name);
235+
expect(joinTables2).toHaveLength(0);
236+
});
237+
238+
it('should correctly identify primary keys', () => {
239+
const genericSchema = getGenericFromDataStore(schemaWithCPK);
240+
const { models } = genericSchema;
241+
expect(models.CPKStudent.primaryKeys).toStrictEqual(['specialStudentId']);
242+
expect(models.CPKTeacher.primaryKeys).toStrictEqual(['specialTeacherId']);
243+
});
244+
245+
it('should correctly map model with composite keys', () => {
246+
const genericSchema = getGenericFromDataStore(schemaWithCompositeKeys);
247+
const { CompositeDog } = genericSchema.models;
248+
expect(CompositeDog.primaryKeys).toStrictEqual(['name', 'description']);
249+
expect(CompositeDog.fields.CompositeBowl.relationship).toStrictEqual({
250+
type: 'HAS_ONE',
251+
relatedModelName: 'CompositeBowl',
252+
associatedFields: ['compositeDogCompositeBowlShape', 'compositeDogCompositeBowlSize'],
253+
});
254+
expect(CompositeDog.fields.CompositeOwner.relationship).toStrictEqual({
255+
type: 'BELONGS_TO',
256+
relatedModelName: 'CompositeOwner',
257+
associatedFields: ['compositeDogCompositeOwnerLastName', 'compositeDogCompositeOwnerFirstName'],
258+
});
259+
});
260+
261+
it('should correctly map schema with hasMany-belongsTo', () => {
262+
const genericSchema = getGenericFromDataStore(schemaWithHasManyBelongsTo);
263+
const { User, Org, Post, Comment } = genericSchema.models;
264+
265+
expect(User.fields.comments.relationship).toStrictEqual({
266+
type: 'HAS_MANY',
267+
canUnlinkAssociatedModel: true,
268+
relatedModelName: 'Comment',
269+
relatedModelFields: ['userCommentsId'],
270+
belongsToFieldOnRelatedModel: 'User',
271+
relatedJoinFieldName: undefined,
272+
relatedJoinTableName: undefined,
273+
});
274+
275+
expect(Post.fields.comments.relationship).toStrictEqual({
276+
type: 'HAS_MANY',
277+
canUnlinkAssociatedModel: true,
278+
relatedModelName: 'Comment',
279+
relatedModelFields: ['postCommentsId'],
280+
belongsToFieldOnRelatedModel: 'post',
281+
relatedJoinFieldName: undefined,
282+
relatedJoinTableName: undefined,
283+
});
284+
285+
expect(Org.fields.comments.relationship).toStrictEqual({
286+
type: 'HAS_MANY',
287+
canUnlinkAssociatedModel: false,
288+
relatedModelName: 'Comment',
289+
relatedModelFields: ['orgCommentsId'],
290+
belongsToFieldOnRelatedModel: 'Org',
291+
relatedJoinFieldName: undefined,
292+
relatedJoinTableName: undefined,
293+
});
294+
295+
expect(Comment.fields.postID.relationship).toStrictEqual({
296+
type: 'BELONGS_TO',
297+
relatedModelName: 'Post',
298+
});
299+
300+
expect(Comment.fields.userCommentsId.relationship).toStrictEqual({
301+
type: 'BELONGS_TO',
302+
relatedModelName: 'User',
303+
isHasManyIndex: true,
304+
});
305+
306+
expect(Comment.fields.orgCommentsId.relationship).toStrictEqual({
307+
type: 'BELONGS_TO',
308+
relatedModelName: 'Org',
309+
isHasManyIndex: true,
310+
});
311+
312+
expect(Comment.fields.postCommentsId.relationship).toStrictEqual({
313+
type: 'HAS_ONE',
314+
relatedModelName: 'Post',
315+
isHasManyIndex: true,
316+
});
317+
});
318+
319+
it('should produce the same generic schema from MIPR and introspection schema', () => {
320+
expect(getGenericFromDataStore(introspectionSchemaWithCompositeKeys).models).toStrictEqual(
321+
getGenericFromDataStore(schemaWithCompositeKeys).models,
322+
);
323+
});
324+
325+
it('should handle bidirectional hasMany with defined field', () => {
326+
const { Car, Dealership } = getGenericFromDataStore(schemaWithBiDirectionalHasManyWithDefinedField).models;
327+
expect(Car.fields.dealership.relationship).toStrictEqual({
328+
type: 'BELONGS_TO',
329+
relatedModelName: 'Dealership',
330+
associatedFields: ['dealershipId'],
331+
});
332+
333+
expect(Dealership.fields.cars.relationship).toStrictEqual({
334+
type: 'HAS_MANY',
335+
canUnlinkAssociatedModel: true,
336+
relatedModelName: 'Car',
337+
relatedModelFields: [],
338+
belongsToFieldOnRelatedModel: 'dealership',
339+
relatedJoinFieldName: undefined,
340+
relatedJoinTableName: undefined,
341+
});
342+
});
343+
});

0 commit comments

Comments
 (0)