UNPKG

@aws-amplify/graphql-model-transformer

Version:
416 lines 28 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ModelResourceGenerator = void 0; const graphql_transformer_interfaces_1 = require("@aws-amplify/graphql-transformer-interfaces"); const graphql_transformer_core_1 = require("@aws-amplify/graphql-transformer-core"); const graphql_transformer_common_1 = require("graphql-transformer-common"); const resolvers_1 = require("../resolvers"); const directive_1 = require("../directive"); class ModelResourceGenerator { constructor(options = {}) { this.datasourceMap = {}; this.resolverMap = {}; this.generatorType = 'ModelResourceGenerator'; this.enabled = false; this.provisioned = false; this.unprovisioned = false; this.models = new Array(); this.modelDirectiveMap = new Map(); this.generateGetResolver = (ctx, type, typeName, fieldName, resolverLogicalId) => { const isSyncEnabled = ctx.isProjectUsingDataStore(); const dataSource = this.datasourceMap[type.name.value]; const resolverKey = `Get${(0, resolvers_1.generateResolverKey)(typeName, fieldName)}`; const vtlGenerator = this.getVTLGenerator(); const modelIndexFields = type .fields.filter((field) => { var _a; return (_a = field.directives) === null || _a === void 0 ? void 0 : _a.some((it) => it.name.value === 'index'); }) .map((it) => it.name.value); const requestConfig = { operation: 'GET', operationName: fieldName, modelName: type.name.value, }; const responseConfig = { ...requestConfig, isSyncEnabled, modelName: type.name.value, modelIndexFields, }; if (!this.resolverMap[resolverKey]) { this.resolverMap[resolverKey] = ctx.resolvers.generateQueryResolver(typeName, fieldName, resolverLogicalId, dataSource, graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateGetRequestTemplate(requestConfig, ctx), `${typeName}.${fieldName}.req.vtl`), graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateGetResponseTemplate(responseConfig), `${typeName}.${fieldName}.res.vtl`)); } return this.resolverMap[resolverKey]; }; this.generateListResolver = (ctx, type, typeName, fieldName, resolverLogicalId) => { const isSyncEnabled = ctx.isProjectUsingDataStore(); const dataSource = this.datasourceMap[type.name.value]; const resolverKey = `List${(0, resolvers_1.generateResolverKey)(typeName, fieldName)}`; const vtlGenerator = this.getVTLGenerator(); const requestConfig = { operation: 'LIST', operationName: fieldName, modelName: type.name.value, }; const responseConfig = { ...requestConfig, isSyncEnabled, mutation: false, }; if (!this.resolverMap[resolverKey]) { this.resolverMap[resolverKey] = ctx.resolvers.generateQueryResolver(typeName, fieldName, resolverLogicalId, dataSource, graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateListRequestTemplate(requestConfig, ctx), `${typeName}.${fieldName}.req.vtl`), graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateDefaultResponseMappingTemplate(responseConfig), `${typeName}.${fieldName}.res.vtl`)); } return this.resolverMap[resolverKey]; }; this.generateCreateResolver = (ctx, type, typeName, fieldName, resolverLogicalId) => { const isSyncEnabled = ctx.isProjectUsingDataStore(); const dataSource = this.datasourceMap[type.name.value]; const resolverKey = `Create${(0, resolvers_1.generateResolverKey)(typeName, fieldName)}`; const vtlGenerator = this.getVTLGenerator(); const modelIndexFields = type .fields.filter((field) => { var _a; return (_a = field.directives) === null || _a === void 0 ? void 0 : _a.some((it) => it.name.value === 'index'); }) .map((it) => it.name.value); const requestConfig = { operation: 'CREATE', operationName: fieldName, modelIndexFields, modelName: type.name.value, }; const responseConfig = { operation: 'CREATE', operationName: fieldName, isSyncEnabled, mutation: true, modelName: type.name.value, }; if (!this.resolverMap[resolverKey]) { const resolver = ctx.resolvers.generateMutationResolver(typeName, fieldName, resolverLogicalId, dataSource, graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateCreateRequestTemplate(requestConfig, ctx), `${typeName}.${fieldName}.req.vtl`), graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateDefaultResponseMappingTemplate(responseConfig), `${typeName}.${fieldName}.res.vtl`)); this.resolverMap[resolverKey] = resolver; const initSlotConfig = { operation: 'CREATE', operationName: fieldName, modelConfig: this.modelDirectiveMap.get(type.name.value), }; const outputType = ctx.output.getObject(type.name.value); const initializeIdField = !!(outputType === null || outputType === void 0 ? void 0 : outputType.fields.find((field) => field.name.value === 'id' && ((field.type.kind === 'NonNullType' && field.type.type.kind === 'NamedType' && (field.type.type.name.value === 'ID' || field.type.type.name.value === 'String')) || (field.type.kind === 'NamedType' && (field.type.name.value === 'ID' || field.type.name.value === 'String'))))); resolver.addVtlFunctionToSlot('init', graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateCreateInitSlotTemplate(initSlotConfig, initializeIdField), `${typeName}.${fieldName}.{slotName}.{slotIndex}.req.vtl`)); } return this.resolverMap[resolverKey]; }; this.generateUpdateResolver = (ctx, type, modelConfig, typeName, fieldName, resolverLogicalId) => { const isSyncEnabled = ctx.isProjectUsingDataStore(); const dataSource = this.datasourceMap[type.name.value]; const resolverKey = `Update${(0, resolvers_1.generateResolverKey)(typeName, fieldName)}`; const vtlGenerator = this.getVTLGenerator(); const modelIndexFields = type .fields.filter((field) => { var _a; return (_a = field.directives) === null || _a === void 0 ? void 0 : _a.some((it) => it.name.value === 'index'); }) .map((it) => it.name.value); const requestConfig = { operation: 'UPDATE', operationName: fieldName, isSyncEnabled, modelName: type.name.value, modelIndexFields, }; const responseConfig = { operation: 'UPDATE', operationName: fieldName, isSyncEnabled, mutation: true, modelName: type.name.value, }; if (!this.resolverMap[resolverKey]) { const resolver = ctx.resolvers.generateMutationResolver(typeName, fieldName, resolverLogicalId, dataSource, graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateUpdateRequestTemplate(requestConfig, ctx), `${typeName}.${fieldName}.req.vtl`), graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateDefaultResponseMappingTemplate(responseConfig), `${typeName}.${fieldName}.res.vtl`)); const updateInitConfig = { modelConfig, operation: 'UPDATE', operationName: fieldName, }; resolver.addVtlFunctionToSlot('init', graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateUpdateInitSlotTemplate(updateInitConfig), `${typeName}.${fieldName}.{slotName}.{slotIndex}.req.vtl`)); this.resolverMap[resolverKey] = resolver; } return this.resolverMap[resolverKey]; }; this.generateDeleteResolver = (ctx, type, typeName, fieldName, resolverLogicalId) => { const isSyncEnabled = ctx.isProjectUsingDataStore(); const dataSource = this.datasourceMap[type.name.value]; const resolverKey = `delete${(0, resolvers_1.generateResolverKey)(typeName, fieldName)}`; const vtlGenerator = this.getVTLGenerator(); const modelIndexFields = type .fields.filter((field) => { var _a; return (_a = field.directives) === null || _a === void 0 ? void 0 : _a.some((it) => it.name.value === 'index'); }) .map((it) => it.name.value); const requestConfig = { operation: 'DELETE', operationName: fieldName, isSyncEnabled, modelName: type.name.value, modelIndexFields, }; const responseConfig = { operation: 'DELETE', operationName: fieldName, isSyncEnabled, mutation: true, modelName: type.name.value, }; if (!this.resolverMap[resolverKey]) { this.resolverMap[resolverKey] = ctx.resolvers.generateMutationResolver(typeName, fieldName, resolverLogicalId, dataSource, graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateDeleteRequestTemplate(requestConfig, ctx), `${typeName}.${fieldName}.req.vtl`), graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateDefaultResponseMappingTemplate(responseConfig), `${typeName}.${fieldName}.res.vtl`)); } return this.resolverMap[resolverKey]; }; this.generateOnCreateResolver = (ctx, typeName, fieldName, resolverLogicalId) => { const resolverKey = `OnCreate${(0, resolvers_1.generateResolverKey)(typeName, fieldName)}`; const vtlGenerator = this.getVTLGenerator(); if (!this.resolverMap[resolverKey]) { this.resolverMap[resolverKey] = ctx.resolvers.generateSubscriptionResolver(typeName, fieldName, resolverLogicalId, graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateSubscriptionRequestTemplate(), `${typeName}.${fieldName}.req.vtl`), graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateSubscriptionResponseTemplate(), `${typeName}.${fieldName}.res.vtl`)); } return this.resolverMap[resolverKey]; }; this.generateOnUpdateResolver = (ctx, typeName, fieldName, resolverLogicalId) => { const resolverKey = `OnUpdate${(0, resolvers_1.generateResolverKey)(typeName, fieldName)}`; const vtlGenerator = this.getVTLGenerator(); if (!this.resolverMap[resolverKey]) { this.resolverMap[resolverKey] = ctx.resolvers.generateSubscriptionResolver(typeName, fieldName, resolverLogicalId, graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateSubscriptionRequestTemplate(), `${typeName}.${fieldName}.req.vtl`), graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateSubscriptionResponseTemplate(), `${typeName}.${fieldName}.res.vtl`)); } return this.resolverMap[resolverKey]; }; this.generateOnDeleteResolver = (ctx, typeName, fieldName, resolverLogicalId) => { const resolverKey = `OnDelete${(0, resolvers_1.generateResolverKey)(typeName, fieldName)}`; const vtlGenerator = this.getVTLGenerator(); if (!this.resolverMap[resolverKey]) { this.resolverMap[resolverKey] = ctx.resolvers.generateSubscriptionResolver(typeName, fieldName, resolverLogicalId, graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateSubscriptionRequestTemplate(), `${typeName}.${fieldName}.req.vtl`), graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateSubscriptionResponseTemplate(), `${typeName}.${fieldName}.res.vtl`)); } return this.resolverMap[resolverKey]; }; this.generateSyncResolver = (ctx, type, typeName, fieldName, resolverLogicalId) => { const isSyncEnabled = ctx.isProjectUsingDataStore(); const dataSource = this.datasourceMap[type.name.value]; const resolverKey = `Sync${(0, resolvers_1.generateResolverKey)(typeName, fieldName)}`; const vtlGenerator = this.getVTLGenerator(); const requestConfig = { operation: 'SYNC', operationName: fieldName, modelName: type.name.value, }; const responseConfig = { ...requestConfig, isSyncEnabled, mutation: false, modelName: type.name.value, }; if (!this.resolverMap[resolverKey]) { this.resolverMap[resolverKey] = ctx.resolvers.generateQueryResolver(typeName, fieldName, resolverLogicalId, dataSource, graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateSyncRequestTemplate(requestConfig), `${typeName}.${fieldName}.req.vtl`), graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString(vtlGenerator.generateDefaultResponseMappingTemplate(responseConfig), `${typeName}.${fieldName}.res.vtl`)); } return this.resolverMap[resolverKey]; }; this.getQueryFieldNames = (type) => { var _a, _b, _c; const typeName = type.name.value; const fields = new Set(); const modelDirectiveConfig = this.modelDirectiveMap.get(type.name.value); if ((_a = modelDirectiveConfig === null || modelDirectiveConfig === void 0 ? void 0 : modelDirectiveConfig.queries) === null || _a === void 0 ? void 0 : _a.get) { fields.add({ typeName: 'Query', fieldName: modelDirectiveConfig.queries.get || (0, graphql_transformer_common_1.toCamelCase)(['get', typeName]), type: graphql_transformer_interfaces_1.QueryFieldType.GET, resolverLogicalId: graphql_transformer_common_1.ResolverResourceIDs.DynamoDBGetResolverResourceID(typeName), }); } if ((_b = modelDirectiveConfig === null || modelDirectiveConfig === void 0 ? void 0 : modelDirectiveConfig.queries) === null || _b === void 0 ? void 0 : _b.list) { fields.add({ typeName: 'Query', fieldName: modelDirectiveConfig.queries.list || (0, graphql_transformer_common_1.toCamelCase)(['list', typeName]), type: graphql_transformer_interfaces_1.QueryFieldType.LIST, resolverLogicalId: graphql_transformer_common_1.ResolverResourceIDs.DynamoDBListResolverResourceID(typeName), }); } if ((_c = modelDirectiveConfig === null || modelDirectiveConfig === void 0 ? void 0 : modelDirectiveConfig.queries) === null || _c === void 0 ? void 0 : _c.sync) { fields.add({ typeName: 'Query', fieldName: modelDirectiveConfig.queries.sync || (0, graphql_transformer_common_1.toCamelCase)(['sync', typeName]), type: graphql_transformer_interfaces_1.QueryFieldType.SYNC, resolverLogicalId: graphql_transformer_common_1.ResolverResourceIDs.SyncResolverResourceID(typeName), }); } return fields; }; this.getMutationFieldNames = (type) => { const typeName = type.name.value; const modelDirectiveConfig = this.modelDirectiveMap.get(typeName); const getMutationType = (mutationType) => { switch (mutationType) { case 'create': return graphql_transformer_interfaces_1.MutationFieldType.CREATE; case 'update': return graphql_transformer_interfaces_1.MutationFieldType.UPDATE; case 'delete': return graphql_transformer_interfaces_1.MutationFieldType.DELETE; default: throw new Error('Unknown mutation type'); } }; const getMutationResolverLogicalId = (mutationType) => { switch (mutationType) { case 'create': return graphql_transformer_common_1.ResolverResourceIDs.DynamoDBCreateResolverResourceID(typeName); case 'update': return graphql_transformer_common_1.ResolverResourceIDs.DynamoDBUpdateResolverResourceID(typeName); case 'delete': return graphql_transformer_common_1.ResolverResourceIDs.DynamoDBDeleteResolverResourceID(typeName); default: throw new Error('Unknown mutation type'); } }; const fieldNames = new Set(); Object.entries((modelDirectiveConfig === null || modelDirectiveConfig === void 0 ? void 0 : modelDirectiveConfig.mutations) || {}).forEach(([mutationType, mutationName]) => { if (mutationName) { fieldNames.add({ typeName: 'Mutation', fieldName: mutationName, type: getMutationType(mutationType), resolverLogicalId: getMutationResolverLogicalId(mutationType), }); } }); return fieldNames; }; this.getSubscriptionFieldNames = (type) => { var _a, _b, _c, _d, _e, _f, _g; const fields = new Set(); const modelDirectiveConfig = this.modelDirectiveMap.get(type.name.value); if (((_a = modelDirectiveConfig === null || modelDirectiveConfig === void 0 ? void 0 : modelDirectiveConfig.subscriptions) === null || _a === void 0 ? void 0 : _a.level) !== directive_1.SubscriptionLevel.off) { if (((_b = modelDirectiveConfig === null || modelDirectiveConfig === void 0 ? void 0 : modelDirectiveConfig.subscriptions) === null || _b === void 0 ? void 0 : _b.onCreate) && ((_c = modelDirectiveConfig.mutations) === null || _c === void 0 ? void 0 : _c.create)) { modelDirectiveConfig.subscriptions.onCreate.forEach((fieldName) => { fields.add({ typeName: 'Subscription', fieldName, type: graphql_transformer_interfaces_1.SubscriptionFieldType.ON_CREATE, resolverLogicalId: graphql_transformer_common_1.ResolverResourceIDs.ResolverResourceID('Subscription', fieldName), }); }); } if (((_d = modelDirectiveConfig === null || modelDirectiveConfig === void 0 ? void 0 : modelDirectiveConfig.subscriptions) === null || _d === void 0 ? void 0 : _d.onUpdate) && ((_e = modelDirectiveConfig.mutations) === null || _e === void 0 ? void 0 : _e.update)) { modelDirectiveConfig.subscriptions.onUpdate.forEach((fieldName) => { fields.add({ typeName: 'Subscription', fieldName, type: graphql_transformer_interfaces_1.SubscriptionFieldType.ON_UPDATE, resolverLogicalId: graphql_transformer_common_1.ResolverResourceIDs.ResolverResourceID('Subscription', fieldName), }); }); } if (((_f = modelDirectiveConfig === null || modelDirectiveConfig === void 0 ? void 0 : modelDirectiveConfig.subscriptions) === null || _f === void 0 ? void 0 : _f.onDelete) && ((_g = modelDirectiveConfig.mutations) === null || _g === void 0 ? void 0 : _g.delete)) { modelDirectiveConfig.subscriptions.onDelete.forEach((fieldName) => { fields.add({ typeName: 'Subscription', fieldName, type: graphql_transformer_interfaces_1.SubscriptionFieldType.ON_DELETE, resolverLogicalId: graphql_transformer_common_1.ResolverResourceIDs.ResolverResourceID('Subscription', fieldName), }); }); } } return fields; }; this.options = options; } getGeneratorType() { return this.generatorType; } isEnabled() { return this.enabled; } isProvisioned() { return this.provisioned; } isUnprovisioned() { return this.unprovisioned; } enableGenerator() { this.enabled = true; } enableProvisioned() { this.provisioned = true; } enableUnprovisioned() { this.unprovisioned = true; } addModelDefinition(def, config) { this.models.push(def); this.modelDirectiveMap.set(def.name.value, config); } generateResolvers(context) { this.models.forEach((def) => { var _a, _b, _c; const queryFields = this.getQueryFieldNames(def); queryFields.forEach((query) => { let resolver; switch (query.type) { case graphql_transformer_interfaces_1.QueryFieldType.GET: resolver = this.generateGetResolver(context, def, query.typeName, query.fieldName, query.resolverLogicalId); break; case graphql_transformer_interfaces_1.QueryFieldType.LIST: resolver = this.generateListResolver(context, def, query.typeName, query.fieldName, query.resolverLogicalId); break; case graphql_transformer_interfaces_1.QueryFieldType.SYNC: resolver = this.generateSyncResolver(context, def, query.typeName, query.fieldName, query.resolverLogicalId); break; default: throw new Error('Unknown query field type'); } resolver.addVtlFunctionToSlot('postAuth', graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString((0, resolvers_1.generatePostAuthExpression)(context.transformParameters.sandboxModeEnabled, context.synthParameters.enableIamAccess), `${query.typeName}.${query.fieldName}.{slotName}.{slotIndex}.req.vtl`)); resolver.setScope(context.stackManager.getScopeFor(query.resolverLogicalId, def.name.value)); context.resolvers.addResolver(query.typeName, query.fieldName, resolver); }); const mutationFields = this.getMutationFieldNames(def); mutationFields.forEach((mutation) => { let resolver; switch (mutation.type) { case graphql_transformer_interfaces_1.MutationFieldType.CREATE: resolver = this.generateCreateResolver(context, def, mutation.typeName, mutation.fieldName, mutation.resolverLogicalId); break; case graphql_transformer_interfaces_1.MutationFieldType.DELETE: resolver = this.generateDeleteResolver(context, def, mutation.typeName, mutation.fieldName, mutation.resolverLogicalId); break; case graphql_transformer_interfaces_1.MutationFieldType.UPDATE: resolver = this.generateUpdateResolver(context, def, this.modelDirectiveMap.get(def.name.value), mutation.typeName, mutation.fieldName, mutation.resolverLogicalId); break; default: throw new Error('Unknown mutation field type'); } resolver.addVtlFunctionToSlot('postAuth', graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString((0, resolvers_1.generatePostAuthExpression)(context.transformParameters.sandboxModeEnabled, context.synthParameters.enableIamAccess), `${mutation.typeName}.${mutation.fieldName}.{slotName}.{slotIndex}.req.vtl`)); resolver.setScope(context.stackManager.getScopeFor(mutation.resolverLogicalId, def.name.value)); context.resolvers.addResolver(mutation.typeName, mutation.fieldName, resolver); }); const subscriptionLevel = (_c = (_b = (_a = this.modelDirectiveMap.get(def.name.value)) === null || _a === void 0 ? void 0 : _a.subscriptions) === null || _b === void 0 ? void 0 : _b.level) !== null && _c !== void 0 ? _c : directive_1.SubscriptionLevel.on; if (subscriptionLevel !== directive_1.SubscriptionLevel.off) { const subscriptionFields = this.getSubscriptionFieldNames(def); subscriptionFields.forEach((subscription) => { let resolver; switch (subscription.type) { case graphql_transformer_interfaces_1.SubscriptionFieldType.ON_CREATE: resolver = this.generateOnCreateResolver(context, subscription.typeName, subscription.fieldName, subscription.resolverLogicalId); break; case graphql_transformer_interfaces_1.SubscriptionFieldType.ON_UPDATE: resolver = this.generateOnUpdateResolver(context, subscription.typeName, subscription.fieldName, subscription.resolverLogicalId); break; case graphql_transformer_interfaces_1.SubscriptionFieldType.ON_DELETE: resolver = this.generateOnDeleteResolver(context, subscription.typeName, subscription.fieldName, subscription.resolverLogicalId); break; default: throw new Error('Unknown subscription field type'); } if (subscriptionLevel === directive_1.SubscriptionLevel.on) { resolver.addVtlFunctionToSlot('postAuth', graphql_transformer_core_1.MappingTemplate.s3MappingTemplateFromString((0, resolvers_1.generatePostAuthExpression)(context.transformParameters.sandboxModeEnabled, context.synthParameters.enableIamAccess), `${subscription.typeName}.${subscription.fieldName}.{slotName}.{slotIndex}.req.vtl`)); } resolver.setScope(context.stackManager.getScopeFor(subscription.resolverLogicalId, def.name.value)); context.resolvers.addResolver(subscription.typeName, subscription.fieldName, resolver); }); } }); } } exports.ModelResourceGenerator = ModelResourceGenerator; //# sourceMappingURL=model-resource-generator.js.map