Skip to content

Commit

Permalink
fix: use frontendToTargetMap, and fix outpuDirParam bug
Browse files Browse the repository at this point in the history
  • Loading branch information
alharris-at committed Sep 12, 2023
1 parent aa9145e commit 5a0cb15
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 79 deletions.
130 changes: 52 additions & 78 deletions packages/amplify-codegen/src/commands/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,13 @@ const { validateAmplifyFlutterMinSupportedVersion } = require('../utils/validate
const defaultDirectiveDefinitions = require('../utils/defaultDirectiveDefinitions');
const getModelSchemaPathParam = require('../utils/getModelSchemaPathParam');

/**
* Returns feature flag value, default to `false`
* @param {!string} key feature flag id
* @returns {string} the feature flag value
*/
const readFeatureFlag = (key) => {
try {
return FeatureFlags.getBoolean(key);
} catch (_) {
return false;
}
};

/**
* Returns feature flag value, default to `1`
* @param {!string} key feature flag id
* @returns {number} the feature flag value
*/
const readNumericFeatureFlag = (key) => {
try {
return FeatureFlags.getNumber(key);
} catch (_) {
return 1;
}
const frontendToTargetMap = {
android: 'java',
ios: 'swift',
flutter: 'dart',
javascript: 'javascript',
typescript: 'typescript',
introspection: 'introspection',
};

// type GenerateModelsOptions = {
Expand Down Expand Up @@ -127,7 +110,7 @@ const getOutputPath = (context, overrideOutputDir, projectRoot) => {
* @param {!boolean} isIntrospection whether or not this is a request for an introspection model.
* @returns {!import('@aws-amplify/appsync-modelgen-plugin').Target} the Modelgen target as a string
*/
const getTarget = (context, isIntrospection) => {
const getFrontend = (context, isIntrospection) => {
if (isIntrospection) {
return 'introspection';
}
Expand All @@ -146,21 +129,27 @@ const getTarget = (context, isIntrospection) => {
* @param {!string} flagName the feature flag name
* @returns {boolean | null} the feature flag value if found, and can be coerced to a boolean, else null
*/
const getOptionBasedFeatureFlag = (context, flagName) => {
const getBooleanFeatureFlag = (context, flagName) => {
// Attempt to read from cli input options as overrides first.~
const featureFlagParamName = `feature-flag:${flagName}`;
const paramNames = context.parameters?.options ? new Set(Object.keys(context.parameters?.options)) : new Set();
if (!paramNames.has(featureFlagParamName)) {
return null;
if (paramNames.has(featureFlagParamName)) {
const optionValue = context.parameters?.options?.[featureFlagParamName];
if (optionValue === 'true' || optionValue === 'True' || optionValue === true) {
return true;
}
if (optionValue === 'false' || optionValue === 'False' || optionValue === false) {
return false;
}
throw new Error(`Feature flag value for parameter ${featureFlagParamName} could not be marshalled to boolean type, found ${optionValue}`);
}

const optionValue = context.parameters?.options?.[featureFlagParamName];
if (optionValue === 'true' || optionValue === 'True' || optionValue === true) {
return true;
}
if (optionValue === 'false' || optionValue === 'False' || optionValue === false) {
// Read from feature flag file, fall back to false if nothing is found, and no default exists in-system.
try {
return FeatureFlags.getBoolean(flagName);
} catch (_) {
return false;
}
return null;
};

/**
Expand All @@ -169,45 +158,32 @@ const getOptionBasedFeatureFlag = (context, flagName) => {
* @param {!string} flagName the feature flag name
* @returns {number | null} the feature flag value if found, and can be coerced to an int, else null
*/
const getOptionBasedNumericFeatureFlag = (context, flagName) => {
const getNumericFeatureFlag = (context, flagName) => {
// Attempt to read from cli input options as overrides first.
const featureFlagParamName = `feature-flag:${flagName}`;
const paramNames = context.parameters?.options ? new Set(Object.keys(context.parameters?.options)) : new Set();
if (!paramNames.has(featureFlagParamName)) {
return null;
if (paramNames.has(featureFlagParamName)) {
const optionValue = context.parameters?.options?.[featureFlagParamName];
return Number.parseInt(optionValue, 10);
}

const optionValue = context.parameters?.options?.[featureFlagParamName];
return Number.parseInt(optionValue, 10);
};

/**
* Retrieve the feature flags either using sane defaults, or an amplify feature flags file.
* @param {*} context the amplify runtime context
* @returns {({ generateIndexRules: boolean, emitAuthProvider: boolean, useExperimentalPipelinedTransformer: boolean, transformerVersion: number, respectPrimaryKeyAttributesOnConnectionField: boolean, generateModelsForLazyLoadAndCustomSelectionSet: boolean, improvePluralization: boolean, addTimestampFields: boolean, handleListNullabilityTransparently: boolean })} the feature flags to provide to the generator
*/
const getFeatureFlags = (context) => {
return {
generateIndexRules: getOptionBasedFeatureFlag(context, 'codegen.generateIndexRules') ?? readFeatureFlag('codegen.generateIndexRules'),
emitAuthProvider: getOptionBasedFeatureFlag(context, 'codegen.emitAuthProvider') ?? readFeatureFlag('codegen.emitAuthProvider'),
useExperimentalPipelinedTransformer: getOptionBasedFeatureFlag(context, 'graphQLTransformer.useExperimentalPipelinedTransformer') ?? readFeatureFlag('graphQLTransformer.useExperimentalPipelinedTransformer'),
transformerVersion: getOptionBasedNumericFeatureFlag(context, 'graphQLTransformer.transformerVersion') ?? readNumericFeatureFlag('graphQLTransformer.transformerVersion'),
respectPrimaryKeyAttributesOnConnectionField: getOptionBasedFeatureFlag(context, 'graphQLTransformer.respectPrimaryKeyAttributesOnConnectionField') ?? readFeatureFlag('graphQLTransformer.respectPrimaryKeyAttributesOnConnectionField'),
generateModelsForLazyLoadAndCustomSelectionSet: getOptionBasedFeatureFlag(context, 'codegen.generateModelsForLazyLoadAndCustomSelectionSet') ?? readFeatureFlag('codegen.generateModelsForLazyLoadAndCustomSelectionSet'),
improvePluralization: getOptionBasedFeatureFlag(context, 'graphQLTransformer.improvePluralization') ?? readFeatureFlag('graphQLTransformer.improvePluralization'),
addTimestampFields: getOptionBasedFeatureFlag(context, 'codegen.addTimestampFields') ?? readFeatureFlag('codegen.addTimestampFields'),
handleListNullabilityTransparently: getOptionBasedFeatureFlag(context, 'codegen.handleListNullabilityTransparently') ?? readFeatureFlag('codegen.handleListNullabilityTransparently'),
};
// Read from feature flag file, fall back to '1' if nothing is found, and no default exists in-system.
try {
return FeatureFlags.getNumber(flagName);
} catch (_) {
return 1;
}
};

/**
* Run validations over the project state, return the errors of an array of strings.
* @param {!string} projectRoot the project root path for validating local state
* @param {!import('@aws-amplify/appsync-modelgen-plugin').Target} target the runtime target we are running modelgen for.
* @param {!string} frontend the frontend being targeted for this project.
* @returns {Array<string>} the list of validation failures detected
*/
const validateProjectState = (projectRoot, target) => {
const validateProjectState = (projectRoot, frontend) => {
const validationFailures = [];
if (target === 'flutter' && !validateAmplifyFlutterMinSupportedVersion(projectRoot)) {
if (frontend === 'flutter' && !validateAmplifyFlutterMinSupportedVersion(projectRoot)) {
validationFailures.push(`🚫 Models are not generated!
Amplify Flutter versions prior to 0.6.0 are no longer supported by codegen. Please upgrade to use codegen.`);
}
Expand All @@ -228,30 +204,28 @@ async function generateModels(context, generateOptions = null) {

await validateSchema(context);
const schema = loadSchema(modelSchemaPath);
const target = getTarget(context, isIntrospection);
const frontend = getFrontend(context, isIntrospection);

const validationFailures = validateProjectState(projectRoot, target);
const validationFailures = validateProjectState(projectRoot, frontend);
if (validationFailures.length > 0) {
validationFailures.forEach((validationFailure) => context.print.error(validationFailure));
return;
}

const {
generateIndexRules,
emitAuthProvider,
useExperimentalPipelinedTransformer,
transformerVersion,
respectPrimaryKeyAttributesOnConnectionField,
generateModelsForLazyLoadAndCustomSelectionSet,
improvePluralization,
addTimestampFields,
handleListNullabilityTransparently,
} = getFeatureFlags(context);
const generateIndexRules = getBooleanFeatureFlag(context, 'codegen.generateIndexRules');
const emitAuthProvider = getBooleanFeatureFlag(context, 'codegen.emitAuthProvider');
const useExperimentalPipelinedTransformer = getBooleanFeatureFlag(context, 'graphQLTransformer.useExperimentalPipelinedTransformer');
const transformerVersion = getNumericFeatureFlag(context, 'graphQLTransformer.transformerVersion');
const respectPrimaryKeyAttributesOnConnectionField = getBooleanFeatureFlag(context, 'graphQLTransformer.respectPrimaryKeyAttributesOnConnectionField');
const generateModelsForLazyLoadAndCustomSelectionSet = getBooleanFeatureFlag(context, 'codegen.generateModelsForLazyLoadAndCustomSelectionSet');
const improvePluralization = getBooleanFeatureFlag(context, 'graphQLTransformer.improvePluralization');
const addTimestampFields = getBooleanFeatureFlag(context, 'codegen.addTimestampFields');
const handleListNullabilityTransparently = getBooleanFeatureFlag(context, 'codegen.handleListNullabilityTransparently');

const generatedCode = await generateModelsHelper({
schema,
directives,
target,
target: frontendToTargetMap[frontend],
generateIndexRules,
emitAuthProvider,
useExperimentalPipelinedTransformer,
Expand All @@ -274,7 +248,7 @@ async function generateModels(context, generateOptions = null) {

try {
// TODO: move to @aws-amplify/graphql-generator
generateEslintIgnore(context, target);
generateEslintIgnore(context, frontend);
} catch (e) {}

context.print.info(`Successfully generated models. Generated models can be found in ${outputPath}`);
Expand Down Expand Up @@ -342,8 +316,8 @@ function getModelOutputPath(context) {
}
}

const generateEslintIgnore = (context, target) => {
if (target !== 'javascript') {
const generateEslintIgnore = (context, frontend) => {
if (frontend !== 'javascript') {
return;
}

Expand Down
1 change: 0 additions & 1 deletion packages/amplify-codegen/src/utils/getOutputDirParam.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ function getOutputDirParam(context, isRequired) {
}
let projectRoot;
try {
context.amplify.getProjectMeta();
projectRoot = context.amplify.getEnvInfo().projectPath;
} catch (e) {
projectRoot = process.cwd();
Expand Down

0 comments on commit 5a0cb15

Please sign in to comment.