@aws-amplify/graphql-model-transformer
Version:
Amplify graphql @model transformer
416 lines • 28 kB
JavaScript
;
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