UNPKG

@aws-amplify/graphql-model-transformer

Version:
245 lines 15.6 kB
"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