Skip to content

Commit a9470bd

Browse files
authored
Merge pull request #584 from sundersc/generate-default-index-name
fix(codegen): generate default name for index directive
2 parents 066615e + d58aba7 commit a9470bd

File tree

3 files changed

+149
-1
lines changed

3 files changed

+149
-1
lines changed

packages/appsync-modelgen-plugin/src/__tests__/utils/process-index.test.ts

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,134 @@ describe('processIndex', () => {
132132
]);
133133
});
134134

135+
it('should generate a default name to @index directive', () => {
136+
const model: CodeGenModel = {
137+
directives: [
138+
{
139+
name: 'model',
140+
arguments: {},
141+
},
142+
],
143+
name: 'testModel',
144+
type: 'model',
145+
fields: [
146+
{
147+
type: 'field',
148+
isList: false,
149+
isNullable: true,
150+
name: 'connectionField',
151+
directives: [
152+
{
153+
name: 'index',
154+
arguments: {},
155+
},
156+
],
157+
},
158+
{
159+
type: 'field',
160+
isList: false,
161+
isNullable: true,
162+
name: 'anotherConnection',
163+
directives: [
164+
{
165+
name: 'index',
166+
arguments: {},
167+
},
168+
],
169+
},
170+
],
171+
};
172+
processIndex(model);
173+
expect(model.directives).toEqual([
174+
{
175+
name: 'model',
176+
arguments: {},
177+
},
178+
{
179+
name: 'key',
180+
arguments: {
181+
name: 'testModelsByConnectionField',
182+
fields: ['connectionField'],
183+
queryField: undefined,
184+
},
185+
},
186+
{
187+
name: 'key',
188+
arguments: {
189+
name: 'testModelsByAnotherConnection',
190+
fields: ['anotherConnection'],
191+
queryField: undefined,
192+
},
193+
},
194+
]);
195+
});
196+
197+
it('should generate a default name to @index directive with sortkeys', () => {
198+
const model: CodeGenModel = {
199+
directives: [
200+
{
201+
name: 'model',
202+
arguments: {},
203+
},
204+
],
205+
name: 'testModel',
206+
type: 'model',
207+
fields: [
208+
{
209+
type: 'field',
210+
isList: false,
211+
isNullable: true,
212+
name: 'connectionField',
213+
directives: [
214+
{
215+
name: 'index',
216+
arguments: {
217+
sortKeyFields: ['sortField'],
218+
},
219+
},
220+
],
221+
},
222+
{
223+
type: 'field',
224+
isList: false,
225+
isNullable: true,
226+
name: 'anotherConnection',
227+
directives: [
228+
{
229+
name: 'index',
230+
arguments: {
231+
sortKeyFields: ['sortField1', 'sortField2'],
232+
},
233+
},
234+
],
235+
},
236+
],
237+
};
238+
processIndex(model);
239+
expect(model.directives).toEqual([
240+
{
241+
name: 'model',
242+
arguments: {},
243+
},
244+
{
245+
name: 'key',
246+
arguments: {
247+
name: 'testModelsByConnectionFieldAndSortField',
248+
fields: ['connectionField', 'sortField'],
249+
queryField: undefined,
250+
},
251+
},
252+
{
253+
name: 'key',
254+
arguments: {
255+
name: 'testModelsByAnotherConnectionAndSortField1AndSortField2',
256+
fields: ['anotherConnection', 'sortField1', 'sortField2'],
257+
queryField: undefined,
258+
},
259+
},
260+
]);
261+
});
262+
135263
it('does nothing if no @index directives in model', () => {
136264
const model: CodeGenModel = {
137265
directives: [

packages/appsync-modelgen-plugin/src/utils/process-index.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { CodeGenDirective, CodeGenModel } from '../visitors/appsync-visitor';
22
import { getDirective } from './fieldUtils';
3+
import pluralize from 'pluralize';
4+
import { toLower, toUpper } from './stringUtils';
35

46
/**
57
* Maps @index directives back to how they would be represented with the old @key directive
@@ -17,7 +19,7 @@ export const processIndex = (model: CodeGenModel) => {
1719
const keyList: CodeGenDirective[] = Object.entries(indexMap).map(([fieldName, directive]) => ({
1820
name: 'key',
1921
arguments: {
20-
name: directive.arguments.name,
22+
name: directive.arguments.name ?? generateDefaultIndexName(model.name, [fieldName].concat((directive.arguments.sortKeyFields as string[]) ?? [])),
2123
queryField: directive.arguments.queryField,
2224
fields: [fieldName].concat((directive.arguments.sortKeyFields as string[]) ?? []),
2325
},
@@ -28,3 +30,14 @@ export const processIndex = (model: CodeGenModel) => {
2830
const deDupedKeyList = keyList.filter(key => !existingIndexNames.includes(key.arguments.name));
2931
model.directives.push(...deDupedKeyList);
3032
};
33+
34+
/*
35+
* Accepts a model and field name, and potentially empty list of sortKeyFields to generate a unique index name.
36+
* e.g. modelName = Employee, fieldName = manager, sortKeyFields = [level]
37+
* will generate a name like employeesByManagerAndLevel.
38+
* (This naming logic is used to generate a default index name for @index directives that don't have a name argument).
39+
* Refer https://github.com/aws-amplify/amplify-category-api/blob/main/packages/amplify-graphql-index-transformer/src/utils.ts
40+
*/
41+
export const generateDefaultIndexName = (modelName: string, fieldNames: string[]): string => {
42+
return `${toLower(pluralize(modelName))}By${fieldNames.map(toUpper).join('And')}`;
43+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function toUpper(word: string): string {
2+
return word.charAt(0).toUpperCase() + word.slice(1);
3+
}
4+
5+
export function toLower(word: string): string {
6+
return word.charAt(0).toLowerCase() + word.slice(1);
7+
}

0 commit comments

Comments
 (0)