Skip to content

Commit

Permalink
feat: use default directive definitions if outside amplify project
Browse files Browse the repository at this point in the history
  • Loading branch information
dpilch committed Sep 8, 2023
1 parent dbe12ab commit e7ba7f8
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 115 deletions.
12 changes: 9 additions & 3 deletions packages/amplify-codegen/src/commands/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const glob = require('glob-all');
const { FeatureFlags, pathManager } = require('@aws-amplify/amplify-cli-core');
const { generateModels: generateModelsHelper } = require('@aws-amplify/graphql-generator');
const { validateAmplifyFlutterMinSupportedVersion } = require('../utils/validateAmplifyFlutterMinSupportedVersion');
const defaultDirectiveDefinitions = require('../utils/defaultDirectiveDefinitions');

const platformToLanguageMap = {
android: 'java',
Expand Down Expand Up @@ -85,9 +86,14 @@ async function generateModels(context, generateOptions = null) {
const backendPath = await context.amplify.pathManager.getBackendDirPath();
const apiResourcePath = path.join(backendPath, 'api', apiResource.resourceName);

const directiveDefinitions = await context.amplify.executeProviderUtils(context, 'awscloudformation', 'getTransformerDirectives', {
resourceDir: apiResourcePath,
});
let directiveDefinitions;
try {
directiveDefinitions = await context.amplify.executeProviderUtils(context, 'awscloudformation', 'getTransformerDirectives', {
resourceDir: apiResourcePath,
});
} catch {
directiveDefinitions = defaultDirectiveDefinitions;
}

const schemaContent = loadSchema(apiResourcePath);
const baseOutputDir = overrideOutputDir || path.join(projectRoot, getModelOutputPath(context));
Expand Down
113 changes: 113 additions & 0 deletions packages/amplify-codegen/src/utils/defaultDirectiveDefinitions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
const defaultDirectiveDefinitions = `
directive @aws_subscribe(mutations: [String!]!) on FIELD_DEFINITION
directive @aws_auth(cognito_groups: [String!]!) on FIELD_DEFINITION
directive @aws_api_key on FIELD_DEFINITION | OBJECT
directive @aws_iam on FIELD_DEFINITION | OBJECT
directive @aws_oidc on FIELD_DEFINITION | OBJECT
directive @aws_cognito_user_pools(cognito_groups: [String!]) on FIELD_DEFINITION | OBJECT
directive @aws_lambda on FIELD_DEFINITION | OBJECT
directive @deprecated(reason: String) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION | ENUM | ENUM_VALUE
directive @model(queries: ModelQueryMap, mutations: ModelMutationMap, subscriptions: ModelSubscriptionMap, timestamps: TimestampConfiguration) on OBJECT
input ModelMutationMap {
create: String
update: String
delete: String
}
input ModelQueryMap {
get: String
list: String
}
input ModelSubscriptionMap {
onCreate: [String]
onUpdate: [String]
onDelete: [String]
level: ModelSubscriptionLevel
}
enum ModelSubscriptionLevel {
off
public
on
}
input TimestampConfiguration {
createdAt: String
updatedAt: String
}
directive @function(name: String!, region: String, accountId: String) repeatable on FIELD_DEFINITION
directive @http(method: HttpMethod = GET, url: String!, headers: [HttpHeader] = []) on FIELD_DEFINITION
enum HttpMethod {
GET
POST
PUT
DELETE
PATCH
}
input HttpHeader {
key: String
value: String
}
directive @predictions(actions: [PredictionsActions!]!) on FIELD_DEFINITION
enum PredictionsActions {
identifyText
identifyLabels
convertTextToSpeech
translateText
}
directive @primaryKey(sortKeyFields: [String]) on FIELD_DEFINITION
directive @index(name: String, sortKeyFields: [String], queryField: String) repeatable on FIELD_DEFINITION
directive @hasMany(indexName: String, fields: [String!], limit: Int = 100) on FIELD_DEFINITION
directive @hasOne(fields: [String!]) on FIELD_DEFINITION
directive @manyToMany(relationName: String!, limit: Int = 100) on FIELD_DEFINITION
directive @belongsTo(fields: [String!]) on FIELD_DEFINITION
directive @default(value: String!) on FIELD_DEFINITION
directive @auth(rules: [AuthRule!]!) on OBJECT | FIELD_DEFINITION
input AuthRule {
allow: AuthStrategy!
provider: AuthProvider
identityClaim: String
groupClaim: String
ownerField: String
groupsField: String
groups: [String]
operations: [ModelOperation]
}
enum AuthStrategy {
owner
groups
private
public
custom
}
enum AuthProvider {
apiKey
iam
oidc
userPools
function
}
enum ModelOperation {
create
update
delete
read
list
get
sync
listen
search
}
directive @mapsTo(name: String!) on OBJECT
directive @searchable(queries: SearchableQueryMap) on OBJECT
input SearchableQueryMap {
search: String
}
`;

module.exports = defaultDirectiveDefinitions;
2 changes: 2 additions & 0 deletions packages/amplify-codegen/src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const getSDLSchemaLocation = require('./getSDLSchemaLocation');
const switchToSDLSchema = require('./switchToSDLSchema');
const ensureIntrospectionSchema = require('./ensureIntrospectionSchema');
const { readSchemaFromFile } = require('./readSchemaFromFile');
const defaultDirectiveDefinitions = require('./defaultDirectiveDefinitions');
module.exports = {
getAppSyncAPIDetails,
getFrontEndHandler,
Expand All @@ -33,4 +34,5 @@ module.exports = {
switchToSDLSchema,
ensureIntrospectionSchema,
readSchemaFromFile,
defaultDirectiveDefinitions,
};
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,12 @@ Array [
"schema.js",
]
`;

exports[`command-models-generates models in expected output path should use default directive definitions if getTransformerDirectives fails 1`] = `
Array [
"index.d.ts",
"index.js",
"schema.d.ts",
"schema.js",
]
`;
138 changes: 26 additions & 112 deletions packages/amplify-codegen/tests/commands/models.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const {
validateAmplifyFlutterMinSupportedVersion,
MINIMUM_SUPPORTED_VERSION_CONSTRAINT,
} = require('../../src/utils/validateAmplifyFlutterMinSupportedVersion');
const defaultDirectiveDefinitions = require('../../src/utils/defaultDirectiveDefinitions');
const mockFs = require('mock-fs');
const fs = require('fs');
const path = require('path');
Expand Down Expand Up @@ -143,6 +144,30 @@ describe('command-models-generates models in expected output path', () => {
}
}

it('should use default directive definitions if getTransformerDirectives fails', async () => {
MOCK_CONTEXT.amplify.executeProviderUtils.mockRejectedValue('no amplify project');
const frontend = 'javascript';
// mock the input and output file structure
const schemaFilePath = path.join(MOCK_BACKEND_DIRECTORY, 'api', MOCK_PROJECT_NAME);
const outputDirectory = path.join(MOCK_PROJECT_ROOT, OUTPUT_PATHS[frontend]);
const mockedFiles = {};
const nodeModules = path.resolve(path.join(__dirname, '../../../../node_modules'));
mockedFiles[schemaFilePath] = {
'schema.graphql': ' type SimpleModel @model { id: ID! status: String } ',
};
mockedFiles[outputDirectory] = {};
mockFs(mockedFiles);
MOCK_CONTEXT.amplify.getProjectConfig.mockReturnValue({ frontend: frontend });

// assert empty folder before generation
expect(fs.readdirSync(outputDirectory).length).toEqual(0);

await generateModels(MOCK_CONTEXT);

// assert model files are generated in expected output directory
expect(fs.readdirSync(outputDirectory)).toMatchSnapshot();
});

afterEach(mockFs.restore);
});

Expand All @@ -158,117 +183,6 @@ function addMocksToContext() {
},
],
});
MOCK_CONTEXT.amplify.executeProviderUtils.mockReturnValue(directives);
MOCK_CONTEXT.amplify.executeProviderUtils.mockReturnValue(defaultDirectiveDefinitions);
MOCK_CONTEXT.amplify.pathManager.getBackendDirPath.mockReturnValue(MOCK_BACKEND_DIRECTORY);
}

const directives = `
directive @aws_subscribe(mutations: [String!]!) on FIELD_DEFINITION
directive @aws_auth(cognito_groups: [String!]!) on FIELD_DEFINITION
directive @aws_api_key on FIELD_DEFINITION | OBJECT
directive @aws_iam on FIELD_DEFINITION | OBJECT
directive @aws_oidc on FIELD_DEFINITION | OBJECT
directive @aws_cognito_user_pools(cognito_groups: [String!]) on FIELD_DEFINITION | OBJECT
directive @aws_lambda on FIELD_DEFINITION | OBJECT
directive @deprecated(reason: String) on FIELD_DEFINITION | INPUT_FIELD_DEFINITION | ENUM | ENUM_VALUE
directive @model(queries: ModelQueryMap, mutations: ModelMutationMap, subscriptions: ModelSubscriptionMap, timestamps: TimestampConfiguration) on OBJECT
input ModelMutationMap {
create: String
update: String
delete: String
}
input ModelQueryMap {
get: String
list: String
}
input ModelSubscriptionMap {
onCreate: [String]
onUpdate: [String]
onDelete: [String]
level: ModelSubscriptionLevel
}
enum ModelSubscriptionLevel {
off
public
on
}
input TimestampConfiguration {
createdAt: String
updatedAt: String
}
directive @function(name: String!, region: String, accountId: String) repeatable on FIELD_DEFINITION
directive @http(method: HttpMethod = GET, url: String!, headers: [HttpHeader] = []) on FIELD_DEFINITION
enum HttpMethod {
GET
POST
PUT
DELETE
PATCH
}
input HttpHeader {
key: String
value: String
}
directive @predictions(actions: [PredictionsActions!]!) on FIELD_DEFINITION
enum PredictionsActions {
identifyText
identifyLabels
convertTextToSpeech
translateText
}
directive @primaryKey(sortKeyFields: [String]) on FIELD_DEFINITION
directive @index(name: String, sortKeyFields: [String], queryField: String) repeatable on FIELD_DEFINITION
directive @hasMany(indexName: String, fields: [String!], limit: Int = 100) on FIELD_DEFINITION
directive @hasOne(fields: [String!]) on FIELD_DEFINITION
directive @manyToMany(relationName: String!, limit: Int = 100) on FIELD_DEFINITION
directive @belongsTo(fields: [String!]) on FIELD_DEFINITION
directive @default(value: String!) on FIELD_DEFINITION
directive @auth(rules: [AuthRule!]!) on OBJECT | FIELD_DEFINITION
input AuthRule {
allow: AuthStrategy!
provider: AuthProvider
identityClaim: String
groupClaim: String
ownerField: String
groupsField: String
groups: [String]
operations: [ModelOperation]
}
enum AuthStrategy {
owner
groups
private
public
custom
}
enum AuthProvider {
apiKey
iam
oidc
userPools
function
}
enum ModelOperation {
create
update
delete
read
list
get
sync
listen
search
}
directive @mapsTo(name: String!) on OBJECT
directive @searchable(queries: SearchableQueryMap) on OBJECT
input SearchableQueryMap {
search: String
}`;

0 comments on commit e7ba7f8

Please sign in to comment.