Skip to content

Commit abb966c

Browse files
authored
feat(codegen): iOS index directive support (#174)
* feat(modelgen): iOS - generate @key metadata * feat(modelgen): iOS - generate @key metadata, invert params order * feat(modelgen): generateIndexRules feature flag * feat(modelgen): generateIndexRules rebase
1 parent f9c1b1a commit abb966c

File tree

4 files changed

+51
-15
lines changed

4 files changed

+51
-15
lines changed

packages/amplify-codegen-e2e-tests/src/__tests__/feature-flags.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { pathManager } from 'amplify-cli-core';
55
const codegenFeatureFlags = {
66
"handlelistnullabilitytransparently": true,
77
"addtimestampfields": true,
8+
"generateIndexRules": true,
89
"useappsyncmodelgenplugin": true,
910
"usedocsgeneratorplugin": true,
1011
"usetypesgeneratorplugin": true,

packages/amplify-codegen/src/commands/models.js

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@ const platformToLanguageMap = {
1313
javascript: 'javascript',
1414
};
1515

16+
/**
17+
* Returns feature flag value, default to `false`
18+
* @param {string} key feature flag id
19+
* @returns
20+
*/
21+
const readFeatureFlag = (key) => {
22+
let flagValue = false;
23+
try {
24+
flagValue = FeatureFlags.getBoolean(key);
25+
} catch (err) {
26+
flagValue = false;
27+
}
28+
return flagValue;
29+
}
30+
1631
async function generateModels(context) {
1732
// steps:
1833
// 1. Load the schema and validate using transformer
@@ -51,21 +66,11 @@ async function generateModels(context) {
5166
//get modelgen package
5267
const modelgenPackageMigrationflag = 'codegen.useAppSyncModelgenPlugin';
5368
const appSyncDataStoreCodeGen = getModelgenPackage(FeatureFlags.getBoolean(modelgenPackageMigrationflag));
54-
//get timestamp config value
55-
let isTimestampFieldsAdded = false;
56-
try {
57-
isTimestampFieldsAdded = FeatureFlags.getBoolean('codegen.addTimestampFields');
58-
} catch (err) {
59-
isTimestampFieldsAdded = false;
60-
}
6169

62-
//get timestamp config value
63-
let emitAuthProvider = false;
64-
try {
65-
emitAuthProvider = FeatureFlags.getBoolean('codegen.emitAuthProvider');
66-
} catch (err) {
67-
emitAuthProvider = false;
68-
}
70+
const isTimestampFieldsAdded = readFeatureFlag('codegen.addTimestampFields');
71+
72+
const generateIndexRules = readFeatureFlag('codegen.generateIndexRules');
73+
const emitAuthProvider = readFeatureFlag('codegen.emitAuthProvider');
6974

7075
const appsyncLocalConfig = await appSyncDataStoreCodeGen.preset.buildGeneratesSection({
7176
baseOutputDir: outputPath,
@@ -75,6 +80,7 @@ async function generateModels(context) {
7580
directives: directiveDefinitions,
7681
isTimestampFieldsAdded,
7782
emitAuthProvider,
83+
generateIndexRules,
7884
},
7985
});
8086

packages/appsync-modelgen-plugin/src/__tests__/visitors/appsync-swift-visitor.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ const getVisitor = (
1414
generate: CodeGenGenerateEnum = CodeGenGenerateEnum.code,
1515
isTimestampFieldsAdded: boolean = true,
1616
emitAuthProvider: boolean = true,
17+
generateIndexRules: boolean = true,
1718
) => {
1819
const ast = parse(schema);
1920
const builtSchema = buildSchemaWithDirectives(schema);
2021
const visitor = new AppSyncSwiftVisitor(
2122
builtSchema,
22-
{ directives, target: 'swift', scalars: SWIFT_SCALAR_MAP, isTimestampFieldsAdded, emitAuthProvider },
23+
{ directives, target: 'swift', scalars: SWIFT_SCALAR_MAP, isTimestampFieldsAdded, emitAuthProvider, generateIndexRules },
2324
{ selectedType, generate },
2425
);
2526
visit(ast, { leave: visitor });
@@ -339,6 +340,11 @@ describe('AppSyncSwiftVisitor', () => {
339340
340341
model.pluralName = \\"authorBooks\\"
341342
343+
model.attributes(
344+
.index(fields: [\\"author_id\\"], name: \\"byAuthor\\"),
345+
.index(fields: [\\"book_id\\"], name: \\"byBook\\")
346+
)
347+
342348
model.fields(
343349
.id(),
344350
.field(authorBook.author_id, is: .required, ofType: .string),

packages/appsync-modelgen-plugin/src/visitors/appsync-swift-visitor.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,18 @@ export interface RawAppSyncModelSwiftConfig extends RawAppSyncModelConfig {
2424
* @descriptions optional boolean, if true emits the provider value of @auth directives
2525
*/
2626
emitAuthProvider?: boolean;
27+
28+
/**
29+
* @name directives
30+
* @type boolean
31+
* @description optional, defines if custom indexes defined by @key directive should be generated.
32+
*/
33+
generateIndexRules?: boolean;
2734
}
2835

2936
export interface ParsedAppSyncModelSwiftConfig extends ParsedAppSyncModelConfig {
3037
emitAuthProvider?: boolean;
38+
generateIndexRules?: boolean;
3139
}
3240

3341
export class AppSyncSwiftVisitor<
@@ -45,6 +53,7 @@ export class AppSyncSwiftVisitor<
4553
) {
4654
super(schema, rawConfig, additionalConfig, defaultScalars);
4755
this._parsedConfig.emitAuthProvider = rawConfig.emitAuthProvider || false;
56+
this._parsedConfig.generateIndexRules = rawConfig.generateIndexRules || false;
4857
}
4958

5059
generate(): string {
@@ -251,13 +260,15 @@ export class AppSyncSwiftVisitor<
251260
const keysName = lowerCaseFirst(model.name);
252261
const fields = model.fields.map(field => this.generateFieldSchema(field, keysName));
253262
const authRules = this.generateAuthRules(model);
263+
const keyDirectives = this.config.generateIndexRules ? this.generateKeyRules(model) : [];
254264
const closure = [
255265
'{ model in',
256266
`let ${keysName} = ${this.getModelName(model)}.keys`,
257267
'',
258268
...(authRules.length ? [`model.authRules = ${authRules}`, ''] : []),
259269
`model.pluralName = "${this.pluralizeModelName(model)}"`,
260270
'',
271+
...(keyDirectives.length ? ['model.attributes(', indentMultiline(keyDirectives.join(',\n')), ')', ''] : []),
261272
'model.fields(',
262273
indentMultiline(fields.join(',\n')),
263274
')',
@@ -409,6 +420,18 @@ export class AppSyncSwiftVisitor<
409420
return !field.isNullable;
410421
}
411422

423+
protected generateKeyRules(model: CodeGenModel): string[] {
424+
const keyDirectives = model.directives
425+
.filter((directive) => directive.name === 'key')
426+
.map((directive) => {
427+
const name = directive.arguments.name ? `"${directive.arguments.name}"` : 'nil';
428+
const fields: string = directive.arguments.fields.map((field: string) => `"${field}"`).join(', ');
429+
return `.index(fields: [${fields}], name: ${name})`;
430+
});
431+
432+
return keyDirectives
433+
}
434+
412435
protected generateAuthRules(model: CodeGenModel): string {
413436
const authDirectives: AuthDirective[] = (model.directives.filter(d => d.name === 'auth') as any) as AuthDirective[];
414437
const rules: string[] = [];

0 commit comments

Comments
 (0)