Skip to content

Commit 60dd629

Browse files
authored
fix(amplify-codegen): support multiple indexes on the same field in introspection schema (#879)
1 parent 8801359 commit 60dd629

File tree

3 files changed

+94
-13
lines changed

3 files changed

+94
-13
lines changed

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

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,78 @@ describe('processIndex', () => {
6868
]);
6969
});
7070

71+
it('support multiple @index directives on a field', () => {
72+
const model: CodeGenModel = {
73+
directives: [
74+
{
75+
name: 'model',
76+
arguments: {},
77+
},
78+
],
79+
name: 'testModel',
80+
type: 'model',
81+
fields: [
82+
{
83+
type: 'field',
84+
isList: false,
85+
isNullable: true,
86+
name: 'connectionField',
87+
directives: [
88+
{
89+
name: 'index',
90+
arguments: {
91+
name: 'byItemAndSortField',
92+
sortKeyFields: ['sortField'],
93+
},
94+
},
95+
{
96+
name: 'index',
97+
arguments: {
98+
name: 'byItemAndAnotherSortField',
99+
sortKeyFields: ['anotherSortField'],
100+
},
101+
},
102+
{
103+
name: 'index',
104+
arguments: {
105+
name: 'byItemAndSomeOtherSortField',
106+
sortKeyFields: ['someOtherSortField'],
107+
},
108+
},
109+
],
110+
},
111+
],
112+
};
113+
processIndex(model);
114+
expect(model.directives).toEqual([
115+
{
116+
name: 'model',
117+
arguments: {},
118+
},
119+
{
120+
name: 'key',
121+
arguments: {
122+
name: 'byItemAndSortField',
123+
fields: ['connectionField', 'sortField'],
124+
},
125+
},
126+
{
127+
name: 'key',
128+
arguments: {
129+
name: 'byItemAndAnotherSortField',
130+
fields: ['connectionField', 'anotherSortField'],
131+
},
132+
},
133+
{
134+
name: 'key',
135+
arguments: {
136+
name: 'byItemAndSomeOtherSortField',
137+
fields: ['connectionField', 'someOtherSortField'],
138+
},
139+
},
140+
]);
141+
});
142+
71143
it('adds simple @index directives as model key attributes', () => {
72144
const model: CodeGenModel = {
73145
directives: [

packages/appsync-modelgen-plugin/src/utils/fieldUtils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export function removeFieldFromModel(model: CodeGenModel, fieldName: string): vo
1515
export const getDirective = (fieldOrModel: CodeGenField | CodeGenModel) => (directiveName: string): CodeGenDirective | undefined =>
1616
fieldOrModel.directives.find(d => d.name === directiveName);
1717

18+
export const getDirectives = (fieldOrModel: CodeGenField | CodeGenModel) => (directiveName: string): CodeGenDirective[] | undefined =>
19+
fieldOrModel.directives.filter(d => d.name === directiveName);
20+
1821
// Function matching to GraphQL transformer so that the auto-generated field
1922
export function toCamelCase(words: string[]): string {
2023
const formatted = words.map((w, i) => (i === 0 ? w.charAt(0).toLowerCase() + w.slice(1) : w.charAt(0).toUpperCase() + w.slice(1)));

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

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CodeGenDirective, CodeGenModel } from '../visitors/appsync-visitor';
2-
import { getDirective } from './fieldUtils';
2+
import { getDirectives } from './fieldUtils';
33
import pluralize from 'pluralize';
44
import { toLower, toUpper } from './stringUtils';
55

@@ -9,21 +9,27 @@ import { toLower, toUpper } from './stringUtils';
99
*/
1010
export const processIndex = (model: CodeGenModel) => {
1111
const indexMap = model.fields.reduce((acc, field) => {
12-
const indexDirective = getDirective(field)('index');
13-
if (!indexDirective) {
12+
const indexDirectives = getDirectives(field)('index');
13+
if (!indexDirectives) {
1414
return acc;
1515
}
16-
return { ...acc, [field.name]: indexDirective };
17-
}, {} as Record<string, CodeGenDirective>);
16+
return { ...acc, [field.name]: indexDirectives };
17+
}, {} as Record<string, CodeGenDirective[]>);
18+
19+
const keyList: CodeGenDirective[] = [];
20+
Object.entries(indexMap).forEach(([fieldName, directives]) => {
21+
directives.forEach(directive => {
22+
keyList.push({
23+
name: 'key',
24+
arguments: {
25+
name: directive.arguments.name ?? generateDefaultIndexName(model.name, [fieldName].concat((directive.arguments.sortKeyFields as string[]) ?? [])),
26+
queryField: directive.arguments.queryField,
27+
fields: [fieldName].concat((directive.arguments.sortKeyFields as string[]) ?? []),
28+
},
29+
});
30+
});
31+
});
1832

19-
const keyList: CodeGenDirective[] = Object.entries(indexMap).map(([fieldName, directive]) => ({
20-
name: 'key',
21-
arguments: {
22-
name: directive.arguments.name ?? generateDefaultIndexName(model.name, [fieldName].concat((directive.arguments.sortKeyFields as string[]) ?? [])),
23-
queryField: directive.arguments.queryField,
24-
fields: [fieldName].concat((directive.arguments.sortKeyFields as string[]) ?? []),
25-
},
26-
}));
2733
const existingIndexNames = model.directives
2834
.filter(directive => directive.name === 'key' && !!directive.arguments.name)
2935
.map(directive => directive.arguments.name);

0 commit comments

Comments
 (0)