Skip to content

Commit 5772cde

Browse files
authored
Dart codegen optimizations (#576)
* chore(dart-visitor): remove outdated enableDartNullSafety feature flag * chore(dart-visitor): remove outdated enableDartZeroThreeFeatures feature flag * chore(dart-visitor): remove outdated dartUpdateAmplifyCoreDependency feature flag * fix(dart-visitor): use import prefix for amplify_core package - To avoid name collision with developer schema * chore(dart-visitor): remove usage of flutter/foundation package * chore(dart-visitor): add Amplify Flutter 0.6.0 min version check * feat(dart-visitor): generate copyWithModelFieldValues method * fix(dart-visitor): make connection has many field nullable * chore(dart-visitor): remove outdated dart-style usage
1 parent 3c1f15d commit 5772cde

17 files changed

+5469
-5123
lines changed

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

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ const { FeatureFlags, pathManager } = require('@aws-amplify/amplify-cli-core');
66
const gqlCodeGen = require('@graphql-codegen/core');
77
const appSyncDataStoreCodeGen = require('@aws-amplify/appsync-modelgen-plugin');
88
const { version: packageVersion } = require('../../package.json');
9-
const { validateDartSDK } = require('../utils/validateDartSDK');
10-
const { validateAmplifyFlutterCapableZeroThreeFeatures } = require('../utils/validateAmplifyFlutterCapableZeroThreeFeatures');
11-
const { validateAmplifyFlutterCoreLibraryDependency } = require('../utils/validateAmplifyFlutterCoreLibraryDependency');
9+
const { validateAmplifyFlutterMinSupportedVersion } = require('../utils/validateAmplifyFlutterMinSupportedVersion');
1210

1311
const platformToLanguageMap = {
1412
android: 'java',
@@ -98,6 +96,12 @@ async function generateModels(context, generateOptions = null) {
9896
const schema = parse(schemaContent);
9997
const projectConfig = context.amplify.getProjectConfig();
10098

99+
if (!isIntrospection && projectConfig.frontend === 'flutter' && !validateAmplifyFlutterMinSupportedVersion(projectRoot)) {
100+
context.print.error(`🚫 Models are not generated!
101+
Amplify Flutter versions prior to 0.6.0 are no longer supported by codegen. Please upgrade to use codegen.`);
102+
return;
103+
}
104+
101105
const generateIndexRules = readFeatureFlag('codegen.generateIndexRules');
102106
const emitAuthProvider = readFeatureFlag('codegen.emitAuthProvider');
103107
const usePipelinedTransformer = readFeatureFlag('graphQLTransformer.useExperimentalPipelinedTransformer');
@@ -106,29 +110,6 @@ async function generateModels(context, generateOptions = null) {
106110
const generateModelsForLazyLoadAndCustomSelectionSet = readFeatureFlag('codegen.generateModelsForLazyLoadAndCustomSelectionSet');
107111

108112
let isTimestampFieldsAdded = readFeatureFlag('codegen.addTimestampFields');
109-
let enableDartNullSafety = readFeatureFlag('codegen.enableDartNullSafety');
110-
let enableDartZeroThreeFeatures = false;
111-
let dartUpdateAmplifyCoreDependency = false;
112-
113-
if (projectConfig.frontend === 'flutter') {
114-
const isMinimumDartVersionSatisfied = validateDartSDK(context, projectRoot);
115-
context.print.warning(`Detected feature flag: “enableDartNullSafety : ${enableDartNullSafety}”`);
116-
if (isMinimumDartVersionSatisfied && enableDartNullSafety) {
117-
context.print.warning(
118-
'Generating Dart Models with null safety. To opt out of null safe models, turn off the “enableDartNullSafety” feature flag. Learn more: https://docs.amplify.aws/lib/project-setup/null-safety/q/platform/flutter',
119-
);
120-
} else {
121-
enableDartNullSafety = false;
122-
context.print.warning(
123-
'Generating Dart Models without null safety. To generate null safe data models, turn on the “enableDartNullSafety” feature flag and set your Dart SDK version to “>= 2.12.0”. Learn more: https://docs.amplify.aws/lib/project-setup/null-safety/q/platform/flutter',
124-
);
125-
}
126-
// override isTimestampFieldsAdded to true when using amplify-flutter > 0.3.0 || > 0.3.0-rc.2
127-
isTimestampFieldsAdded = validateAmplifyFlutterCapableZeroThreeFeatures(projectRoot);
128-
enableDartZeroThreeFeatures = validateAmplifyFlutterCapableZeroThreeFeatures(projectRoot);
129-
// This feature is supported only for users using amplify-flutter > 0.4.0 || > 0.4.0-rc.1
130-
dartUpdateAmplifyCoreDependency = validateAmplifyFlutterCoreLibraryDependency(projectRoot);
131-
}
132113

133114
const handleListNullabilityTransparently = readFeatureFlag('codegen.handleListNullabilityTransparently');
134115
const appsyncLocalConfig = await appSyncDataStoreCodeGen.preset.buildGeneratesSection({
@@ -140,12 +121,9 @@ async function generateModels(context, generateOptions = null) {
140121
isTimestampFieldsAdded,
141122
emitAuthProvider,
142123
generateIndexRules,
143-
enableDartNullSafety,
144124
handleListNullabilityTransparently,
145125
usePipelinedTransformer,
146-
enableDartZeroThreeFeatures,
147126
transformerVersion,
148-
dartUpdateAmplifyCoreDependency,
149127
respectPrimaryKeyAttributesOnConnectionField,
150128
generateModelsForLazyLoadAndCustomSelectionSet,
151129
codegenVersion: packageVersion,

packages/amplify-codegen/src/utils/validateAmplifyFlutterCapableZeroThreeFeatures.js

Lines changed: 0 additions & 9 deletions
This file was deleted.

packages/amplify-codegen/src/utils/validateAmplifyFlutterCoreLibraryDependency.js

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const { validateAmplifyFlutterVersion } = require('./validateAmplifyFlutterVersion');
2+
3+
const MINIMUM_SUPPORTED_VERSION_CONSTRAINT = '>=0.6.0';
4+
5+
function validateAmplifyFlutterMinSupportedVersion(projectRoot) {
6+
return validateAmplifyFlutterVersion(projectRoot, MINIMUM_SUPPORTED_VERSION_CONSTRAINT);
7+
}
8+
9+
module.exports = { validateAmplifyFlutterMinSupportedVersion, MINIMUM_SUPPORTED_VERSION_CONSTRAINT };

packages/amplify-codegen/src/utils/validateAmplifyFlutterVersion.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ function validateAmplifyFlutterVersion(projectRoot, versionConstraint) {
2121
console.log(e.message);
2222
}
2323

24-
console.log('An error occurred while parsing ' + PUBSPEC_LOCK_FILE_NAME + '.');
24+
console.log(
25+
`An error occurred while parsing ${PUBSPEC_LOCK_FILE_NAME}. If you haven't, run \`flutter pub get\` to ensure generating the ${PUBSPEC_LOCK_FILE_NAME} file.`,
26+
);
2527
return false;
2628
}
2729
}

packages/amplify-codegen/tests/commands/models.test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,27 @@
11
const generateModels = require('../../src/commands/models');
2+
const {
3+
validateAmplifyFlutterMinSupportedVersion,
4+
MINIMUM_SUPPORTED_VERSION_CONSTRAINT,
5+
} = require('../../src/utils/validateAmplifyFlutterMinSupportedVersion');
26
const mockFs = require('mock-fs');
37
const graphqlCodegen = require('@graphql-codegen/core');
48
const fs = require('fs');
59
const path = require('path');
610

711
jest.mock('@graphql-codegen/core');
12+
jest.mock('../../src/utils/validateAmplifyFlutterMinSupportedVersion', () => {
13+
const originalModule = jest.requireActual('../../src/utils/validateAmplifyFlutterMinSupportedVersion');
14+
15+
return {
16+
...originalModule,
17+
validateAmplifyFlutterMinSupportedVersion: jest.fn(),
18+
};
19+
});
820
const MOCK_CONTEXT = {
921
print: {
1022
info: jest.fn(),
1123
warning: jest.fn(),
24+
error: jest.fn(),
1225
},
1326
amplify: {
1427
getProjectMeta: jest.fn(),
@@ -37,6 +50,7 @@ describe('command-models-generates models in expected output path', () => {
3750
jest.resetAllMocks();
3851
addMocksToContext();
3952
graphqlCodegen.codegen.mockReturnValue(MOCK_GENERATED_CODE);
53+
validateAmplifyFlutterMinSupportedVersion.mockReturnValue(true);
4054
});
4155

4256
for (const frontend in OUTPUT_PATHS) {
@@ -87,6 +101,30 @@ describe('command-models-generates models in expected output path', () => {
87101
// assert model files are generated in expected output directory
88102
expect(fs.readdirSync(outputDirectory).length).toBeGreaterThan(0);
89103
});
104+
105+
if (frontend === 'flutter') {
106+
it(`${frontend}: Should print error when Amplify Flutter version < ${MINIMUM_SUPPORTED_VERSION_CONSTRAINT} and not generate any models`, async () => {
107+
validateAmplifyFlutterMinSupportedVersion.mockReturnValue(false);
108+
// mock the input and output file structure
109+
const schemaFilePath = path.join(MOCK_BACKEND_DIRECTORY, 'api', MOCK_PROJECT_NAME);
110+
const outputDirectory = path.join(MOCK_PROJECT_ROOT, OUTPUT_PATHS[frontend]);
111+
const mockedFiles = {};
112+
mockedFiles[schemaFilePath] = {
113+
'schema.graphql': ' type SimpleModel { id: ID! status: String } ',
114+
};
115+
mockedFiles[outputDirectory] = {};
116+
mockFs(mockedFiles);
117+
MOCK_CONTEXT.amplify.getProjectConfig.mockReturnValue({ frontend: frontend });
118+
119+
// assert empty folder before generation
120+
expect(fs.readdirSync(outputDirectory).length).toEqual(0);
121+
122+
await generateModels(MOCK_CONTEXT);
123+
124+
expect(MOCK_CONTEXT.print.error).toBeCalled();
125+
expect(graphqlCodegen.codegen).not.toBeCalled();
126+
});
127+
}
90128
}
91129

92130
afterEach(mockFs.restore);

packages/amplify-codegen/tests/utils/validateAmplifyFlutterCapableForNonModel.test.js renamed to packages/amplify-codegen/tests/utils/validateAmplifyFlutterMinSupportedVersion.test.js

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,46 @@
11
const {
2-
validateAmplifyFlutterCapableZeroThreeFeatures
3-
} = require('../../src/utils/validateAmplifyFlutterCapableZeroThreeFeatures');
2+
validateAmplifyFlutterMinSupportedVersion,
3+
MINIMUM_SUPPORTED_VERSION_CONSTRAINT,
4+
} = require('../../src/utils/validateAmplifyFlutterMinSupportedVersion');
45
const { PUBSPEC_LOCK_FILE_NAME } = require('../../src/utils/validateAmplifyFlutterVersion');
56
const mockFs = require('mock-fs');
67
const { join } = require('path');
78
const yaml = require('js-yaml');
89

910
const MOCK_PROJECT_ROOT = 'project';
1011
const MOCK_PUBSPEC_FILE_PATH = join(MOCK_PROJECT_ROOT, PUBSPEC_LOCK_FILE_NAME);
11-
const MINIMUM_VERSION_CONSTRAINT = '>= 0.3.0 || >= 0.3.0-rc.2';
12-
global.console = {log: jest.fn()}
12+
global.console = { log: jest.fn() };
1313
const mockErrorPrinter = console.log;
1414

1515
describe('Validate amplify flutter version tests', () => {
1616
afterEach(() => {
1717
mockFs.restore();
1818
});
1919

20-
describe(`should return true if the resolved version meets the version constrain: ${MINIMUM_VERSION_CONSTRAINT}`, () => {
21-
['0.3.0', '0.3.1', '1.0.0', '0.3.0-rc.2', '0.4.0', '0.4.0-rc.2'].forEach(version => {
20+
describe('MINIMUM_SUPPORTED_VERSION_CONSTRAINT', () => {
21+
it('should be `>=0.6.0` as of today', () => {
22+
expect(MINIMUM_SUPPORTED_VERSION_CONSTRAINT === '>=0.6.0').toBe(true);
23+
});
24+
});
25+
26+
describe(`should return true if the resolved version meets the version constrain: ${MINIMUM_SUPPORTED_VERSION_CONSTRAINT}`, () => {
27+
['0.6.0', '0.6.12', '1.0.0', '1.0.1', '1.1.0', '2.0.0'].forEach(version => {
2228
test(`when the resolved version is ${version}`, () => {
2329
const lockFile = {
24-
packages: {
25-
amplify_flutter: {
26-
version,
30+
packages: {
31+
amplify_flutter: {
32+
version,
33+
},
2734
},
28-
},
29-
};
30-
mockFs({ [MOCK_PUBSPEC_FILE_PATH]: yaml.dump(lockFile) });
31-
expect(validateAmplifyFlutterCapableZeroThreeFeatures(MOCK_PROJECT_ROOT)).toBe(true);
32-
})
35+
};
36+
mockFs({ [MOCK_PUBSPEC_FILE_PATH]: yaml.dump(lockFile) });
37+
expect(validateAmplifyFlutterMinSupportedVersion(MOCK_PROJECT_ROOT)).toBe(true);
38+
});
3339
});
3440
});
3541

36-
describe(`should return false if the resolved version does NOT meet the version constrain: ${MINIMUM_VERSION_CONSTRAINT}`, () => {
37-
['0.2.0', '0.2.9', '0.3.0-rc.1'].forEach(version => {
42+
describe(`should return false if the resolved version does NOT meet the version constrain: ${MINIMUM_SUPPORTED_VERSION_CONSTRAINT}`, () => {
43+
['0.2.0', '0.3.9', '0.5.0'].forEach(version => {
3844
test(`when the resolved version is ${version}`, () => {
3945
const lockFile = {
4046
packages: {
@@ -44,15 +50,15 @@ describe('Validate amplify flutter version tests', () => {
4450
},
4551
};
4652
mockFs({ [MOCK_PUBSPEC_FILE_PATH]: yaml.dump(lockFile) });
47-
expect(validateAmplifyFlutterCapableZeroThreeFeatures(MOCK_PROJECT_ROOT)).toBe(false);
53+
expect(validateAmplifyFlutterMinSupportedVersion(MOCK_PROJECT_ROOT)).toBe(false);
4854
});
4955
});
5056
});
5157

5258
it('should return false if the sdk version cannot be found', () => {
5359
const lockFile = {};
5460
mockFs({ [MOCK_PUBSPEC_FILE_PATH]: yaml.dump(lockFile) });
55-
expect(validateAmplifyFlutterCapableZeroThreeFeatures(MOCK_PROJECT_ROOT)).toBe(false);
61+
expect(validateAmplifyFlutterMinSupportedVersion(MOCK_PROJECT_ROOT)).toBe(false);
5662
});
5763

5864
describe('when yaml file cannot be correctly loaded', () => {
@@ -61,20 +67,20 @@ describe('Validate amplify flutter version tests', () => {
6167
mockErrorPrinter.mockClear();
6268
loadSpy = jest.spyOn(yaml, 'load');
6369
loadSpy.mockImplementation(() => {
64-
throw Error("Cannot read yaml file.");
70+
throw Error('Cannot read yaml file.');
6571
});
6672
});
6773

6874
afterAll(() => {
6975
loadSpy.mockClear();
7076
mockErrorPrinter.mockClear();
71-
})
77+
});
7278

7379
it('should print error when error is thrown while loading yaml file', () => {
7480
const lockFile = {};
7581
mockFs({ [MOCK_PUBSPEC_FILE_PATH]: yaml.dump(lockFile) });
7682

77-
expect(validateAmplifyFlutterCapableZeroThreeFeatures(MOCK_PROJECT_ROOT)).toBe(false);
83+
expect(validateAmplifyFlutterMinSupportedVersion(MOCK_PROJECT_ROOT)).toBe(false);
7884
expect(mockErrorPrinter).toHaveBeenCalledTimes(3);
7985
});
8086
});

packages/appsync-modelgen-plugin/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
"@types/pluralize": "0.0.29",
3434
"chalk": "^3.0.0",
3535
"change-case": "^4.1.1",
36-
"dart-style": "1.3.2-dev",
3736
"lower-case-first": "^2.0.1",
3837
"pluralize": "^8.0.0",
3938
"strip-indent": "^3.0.0",

0 commit comments

Comments
 (0)