@aws-amplify/graphql-model-transformer
Version:
Amplify graphql @model transformer
245 lines • 15.6 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DynamoModelResourceGenerator = void 0;
const cdk = __importStar(require("aws-cdk-lib"));
const graphql_transformer_common_1 = require("graphql-transformer-common");
const graphql_transformer_core_1 = require("@aws-amplify/graphql-transformer-core");
const aws_dynamodb_1 = require("aws-cdk-lib/aws-dynamodb");
const iam = __importStar(require("aws-cdk-lib/aws-iam"));
const resolvers_1 = require("../resolvers");
const model_resource_generator_1 = require("./model-resource-generator");
class DynamoModelResourceGenerator extends model_resource_generator_1.ModelResourceGenerator {
constructor() {
super(...arguments);
this.generatorType = 'DynamoModelResourceGenerator';
this.createIAMRole = (context, def, scope, tableName) => {
const roleName = context.resourceHelper.generateIAMRoleName(graphql_transformer_common_1.ModelResourceIDs.ModelTableIAMRoleID(def.name.value));
const amplifyDataStoreTableName = context.resourceHelper.generateTableName(graphql_transformer_common_1.SyncResourceIDs.syncTableName);
const role = new iam.Role(scope, graphql_transformer_common_1.ModelResourceIDs.ModelTableIAMRoleID(def.name.value), {
roleName,
assumedBy: new iam.ServicePrincipal('appsync.amazonaws.com'),
inlinePolicies: {
DynamoDBAccess: new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
'dynamodb:BatchGetItem',
'dynamodb:BatchWriteItem',
'dynamodb:PutItem',
'dynamodb:DeleteItem',
'dynamodb:GetItem',
'dynamodb:Scan',
'dynamodb:Query',
'dynamodb:UpdateItem',
'dynamodb:ConditionCheckItem',
'dynamodb:DescribeTable',
'dynamodb:GetRecords',
'dynamodb:GetShardIterator',
],
resources: [
cdk.Fn.sub('arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}', {
tablename: tableName,
}),
cdk.Fn.sub('arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}/*', {
tablename: tableName,
}),
...(context.isProjectUsingDataStore()
? [
cdk.Fn.sub('arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}', {
tablename: amplifyDataStoreTableName,
}),
cdk.Fn.sub('arn:${AWS::Partition}:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${tablename}/*', {
tablename: amplifyDataStoreTableName,
}),
]
: []),
],
}),
],
}),
},
});
(0, graphql_transformer_core_1.setResourceName)(role, { name: graphql_transformer_common_1.ModelResourceIDs.ModelTableIAMRoleID(def.name.value), setOnDefaultChild: true });
const syncConfig = graphql_transformer_core_1.SyncUtils.getSyncConfig(context, def.name.value);
if (syncConfig && graphql_transformer_core_1.SyncUtils.isLambdaSyncConfig(syncConfig)) {
role.attachInlinePolicy(graphql_transformer_core_1.SyncUtils.createSyncLambdaIAMPolicy(context, scope, syncConfig.LambdaConflictHandler.name, syncConfig.LambdaConflictHandler.region));
}
return role.withoutPolicyUpdates();
};
}
generateResources(ctx) {
if (!this.isEnabled()) {
return;
}
if (this.isProvisioned()) {
const rootStack = cdk.Stack.of(ctx.stackManager.scope);
this.createDynamoDBParameters(rootStack, false);
}
this.models.forEach((model) => {
const tableBaseName = ctx.resourceHelper.getModelNameMapping(model.name.value);
const tableLogicalName = graphql_transformer_common_1.ModelResourceIDs.ModelTableResourceID(tableBaseName);
const scope = ctx.stackManager.getScopeFor(tableLogicalName, tableBaseName);
this.createModelTable(scope, model, ctx);
});
this.generateResolvers(ctx);
}
getVTLGenerator() {
return new resolvers_1.DynamoDBModelVTLGenerator();
}
createModelTable(scope, def, context) {
const modelName = def.name.value;
const tableLogicalName = graphql_transformer_common_1.ModelResourceIDs.ModelTableResourceID(modelName);
const tableName = context.resourceHelper.generateTableName(modelName);
const { readIops, writeIops, billingMode, pointInTimeRecovery, enableSSE } = this.createDynamoDBParameters(scope, true);
new cdk.CfnCondition(scope, graphql_transformer_common_1.ResourceConstants.CONDITIONS.HasEnvironmentParameter, {
expression: cdk.Fn.conditionNot(cdk.Fn.conditionEquals(context.synthParameters.amplifyEnvironmentName, graphql_transformer_common_1.ResourceConstants.NONE)),
});
const useSSE = new cdk.CfnCondition(scope, graphql_transformer_common_1.ResourceConstants.CONDITIONS.ShouldUseServerSideEncryption, {
expression: cdk.Fn.conditionEquals(enableSSE, 'true'),
});
const usePayPerRequestBilling = new cdk.CfnCondition(scope, graphql_transformer_common_1.ResourceConstants.CONDITIONS.ShouldUsePayPerRequestBilling, {
expression: cdk.Fn.conditionEquals(billingMode, 'PAY_PER_REQUEST'),
});
const usePointInTimeRecovery = new cdk.CfnCondition(scope, graphql_transformer_common_1.ResourceConstants.CONDITIONS.ShouldUsePointInTimeRecovery, {
expression: cdk.Fn.conditionEquals(pointInTimeRecovery, 'true'),
});
const removalPolicy = this.options.EnableDeletionProtection ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY;
const table = new aws_dynamodb_1.Table(scope, tableLogicalName, {
tableName,
partitionKey: {
name: 'id',
type: aws_dynamodb_1.AttributeType.STRING,
},
stream: aws_dynamodb_1.StreamViewType.NEW_AND_OLD_IMAGES,
encryption: aws_dynamodb_1.TableEncryption.DEFAULT,
removalPolicy,
...(context.isProjectUsingDataStore() ? { timeToLiveAttribute: '_ttl' } : undefined),
});
const cfnTable = table.node.defaultChild;
(0, graphql_transformer_core_1.setResourceName)(table, { name: modelName, setOnDefaultChild: true });
cfnTable.provisionedThroughput = cdk.Fn.conditionIf(usePayPerRequestBilling.logicalId, cdk.Fn.ref('AWS::NoValue'), {
ReadCapacityUnits: readIops,
WriteCapacityUnits: writeIops,
});
cfnTable.pointInTimeRecoverySpecification = cdk.Fn.conditionIf(usePointInTimeRecovery.logicalId, { PointInTimeRecoveryEnabled: true }, cdk.Fn.ref('AWS::NoValue'));
cfnTable.billingMode = cdk.Fn.conditionIf(usePayPerRequestBilling.logicalId, 'PAY_PER_REQUEST', cdk.Fn.ref('AWS::NoValue')).toString();
cfnTable.sseSpecification = {
sseEnabled: cdk.Fn.conditionIf(useSSE.logicalId, true, false),
};
if (context.transformParameters.enableTransformerCfnOutputs) {
if (table.tableStreamArn) {
const streamArnOutputId = `GetAtt${graphql_transformer_common_1.ModelResourceIDs.ModelTableStreamArn(def.name.value)}`;
new cdk.CfnOutput(cdk.Stack.of(scope), streamArnOutputId, {
value: table.tableStreamArn,
description: 'Your DynamoDB table StreamArn.',
exportName: cdk.Fn.join(':', [context.api.apiId, 'GetAtt', tableLogicalName, 'StreamArn']),
});
}
const tableNameOutputId = `GetAtt${tableLogicalName}Name`;
new cdk.CfnOutput(cdk.Stack.of(scope), tableNameOutputId, {
value: table.tableName,
description: 'Your DynamoDB table name.',
exportName: cdk.Fn.join(':', [context.api.apiId, 'GetAtt', tableLogicalName, 'Name']),
});
}
const role = this.createIAMRole(context, def, scope, tableName);
const tableDataSourceLogicalName = `${def.name.value}Table`;
this.createModelTableDataSource(def, context, table, scope, role, tableDataSourceLogicalName);
}
createModelTableDataSource(def, context, table, scope, role, dataSourceLogicalName) {
const datasourceRoleLogicalID = graphql_transformer_common_1.ModelResourceIDs.ModelTableDataSourceID(def.name.value);
const dataSource = context.api.host.addDynamoDbDataSource(datasourceRoleLogicalID, table, { name: dataSourceLogicalName, serviceRole: role }, scope);
const cfnDataSource = dataSource.node.defaultChild;
cfnDataSource.addDependency(role.node.defaultChild);
if (context.isProjectUsingDataStore()) {
const datasourceDynamoDb = cfnDataSource.dynamoDbConfig;
datasourceDynamoDb.deltaSyncConfig = {
deltaSyncTableName: context.resourceHelper.generateTableName(graphql_transformer_common_1.SyncResourceIDs.syncTableName),
deltaSyncTableTtl: '30',
baseTableTtl: '43200',
};
datasourceDynamoDb.versioned = true;
}
if (context.transformParameters.enableTransformerCfnOutputs) {
const datasourceOutputId = `GetAtt${datasourceRoleLogicalID}Name`;
new cdk.CfnOutput(cdk.Stack.of(scope), datasourceOutputId, {
value: dataSource.ds.attrName,
description: 'Your model DataSource name.',
exportName: cdk.Fn.join(':', [context.api.apiId, 'GetAtt', datasourceRoleLogicalID, 'Name']),
});
}
context.dataSources.add(def, dataSource);
this.datasourceMap[def.name.value] = dataSource;
}
createDynamoDBParameters(scope, isNestedStack) {
var _a, _b, _c, _d, _e;
const readIops = (_a = scope.node.tryFindChild(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBModelTableReadIOPS)) !== null && _a !== void 0 ? _a : new cdk.CfnParameter(scope, graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBModelTableReadIOPS, {
description: 'The number of read IOPS the table should support.',
type: 'Number',
default: 5,
});
const writeIops = (_b = scope.node.tryFindChild(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBModelTableWriteIOPS)) !== null && _b !== void 0 ? _b : new cdk.CfnParameter(scope, graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBModelTableWriteIOPS, {
description: 'The number of write IOPS the table should support.',
type: 'Number',
default: 5,
});
const billingMode = (_c = scope.node.tryFindChild(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBBillingMode)) !== null && _c !== void 0 ? _c : new cdk.CfnParameter(scope, graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBBillingMode, {
description: 'Configure @model types to create DynamoDB tables with PAY_PER_REQUEST or PROVISIONED billing modes.',
type: 'String',
default: 'PAY_PER_REQUEST',
allowedValues: ['PAY_PER_REQUEST', 'PROVISIONED'],
});
const pointInTimeRecovery = (_d = scope.node.tryFindChild(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBEnablePointInTimeRecovery)) !== null && _d !== void 0 ? _d : new cdk.CfnParameter(scope, graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBEnablePointInTimeRecovery, {
description: 'Whether to enable Point in Time Recovery on the table.',
type: 'String',
default: 'false',
allowedValues: ['true', 'false'],
});
const enableSSE = (_e = scope.node.tryFindChild(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBEnableServerSideEncryption)) !== null && _e !== void 0 ? _e : new cdk.CfnParameter(scope, graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBEnableServerSideEncryption, {
description: 'Enable server side encryption powered by KMS.',
type: 'String',
default: 'true',
allowedValues: ['true', 'false'],
});
if (isNestedStack) {
scope.setParameter(readIops.node.id, cdk.Fn.ref(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBModelTableReadIOPS));
scope.setParameter(writeIops.node.id, cdk.Fn.ref(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBModelTableWriteIOPS));
scope.setParameter(billingMode.node.id, cdk.Fn.ref(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBBillingMode));
scope.setParameter(pointInTimeRecovery.node.id, cdk.Fn.ref(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBEnablePointInTimeRecovery));
scope.setParameter(enableSSE.node.id, cdk.Fn.ref(graphql_transformer_common_1.ResourceConstants.PARAMETERS.DynamoDBEnableServerSideEncryption));
}
return {
readIops,
writeIops,
billingMode,
pointInTimeRecovery,
enableSSE,
};
}
}
exports.DynamoModelResourceGenerator = DynamoModelResourceGenerator;
//# sourceMappingURL=dynamo-model-resource-generator.js.map