@aws-amplify/appsync-modelgen-plugin
Version:
266 lines • 12.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppSyncModelIntrospectionVisitor = void 0;
const visitor_plugin_common_1 = require("@graphql-codegen/visitor-plugin-common");
const scalars_1 = require("../scalars");
const process_connections_1 = require("../utils/process-connections");
const appsync_visitor_1 = require("./appsync-visitor");
const fieldUtils_1 = require("../utils/fieldUtils");
const process_conversation_1 = require("../utils/process-conversation");
const fieldUtils_2 = require("../utils/fieldUtils");
const validateModelIntrospectionSchema = require('../validate-cjs');
;
;
class AppSyncModelIntrospectionVisitor extends appsync_visitor_1.AppSyncModelVisitor {
constructor(schema, rawConfig, additionalConfig, defaultScalars = visitor_plugin_common_1.DEFAULT_SCALARS) {
super(schema, rawConfig, additionalConfig, defaultScalars);
this.introspectionVersion = 1;
this.isUnionFieldType = (obj) => {
return typeof obj === 'object' && typeof obj.union === 'string';
};
this.isInterfaceFieldType = (obj) => {
return typeof obj === 'object' && typeof obj.interface === 'string';
};
}
generate() {
const shouldUseModelNameFieldInHasManyAndBelongsTo = false;
const shouldImputeKeyForUniDirectionalHasMany = true;
const shouldUseFieldsInAssociatedWithInHasOne = true;
this.processDirectives(shouldUseModelNameFieldInHasManyAndBelongsTo, shouldImputeKeyForUniDirectionalHasMany, shouldUseFieldsInAssociatedWithInHasOne);
const modelIntrosepctionSchema = this.generateModelIntrospectionSchema();
if (!validateModelIntrospectionSchema(modelIntrosepctionSchema)) {
throw new Error(`Data did not validate against the supplied schema. Underlying errors were ${JSON.stringify(validateModelIntrospectionSchema.errors)}`);
}
return JSON.stringify(modelIntrosepctionSchema, null, 4);
}
generateModelIntrospectionSchema() {
let result = {
version: this.introspectionVersion,
models: {},
enums: {},
nonModels: {},
};
const models = Object.values(this.getSelectedModels()).reduce((acc, model) => {
return { ...acc, [model.name]: this.generateModelMetadata(model) };
}, {});
const nonModels = Object.values(this.getSelectedNonModels()).reduce((acc, nonModel) => {
return { ...acc, [nonModel.name]: this.generateNonModelMetadata(nonModel) };
}, {});
const enums = Object.values(this.enumMap).reduce((acc, enumObj) => {
return { ...acc, [this.getEnumName(enumObj)]: this.generateEnumMetadata(enumObj) };
}, {});
result = { ...result, models, nonModels, enums };
const queries = Object.values(this.queryMap).reduce((acc, queryObj) => {
const fieldType = this.getType(queryObj.type);
if (this.isUnionFieldType(fieldType) || this.isInterfaceFieldType(fieldType) || (0, fieldUtils_1.containsGenerationDirective)(queryObj)) {
return acc;
}
return { ...acc, [queryObj.name]: this.generateGraphQLOperationMetadata(queryObj) };
}, {});
const generations = Object.values(this.queryMap).reduce((acc, queryObj) => {
const fieldType = this.getType(queryObj.type);
if (this.isUnionFieldType(fieldType) || this.isInterfaceFieldType(fieldType) || !(0, fieldUtils_1.containsGenerationDirective)(queryObj)) {
return acc;
}
return { ...acc, [queryObj.name]: this.generateGenerationMetadata(queryObj) };
}, {});
const mutations = Object.values(this.mutationMap).reduce((acc, mutationObj) => {
const fieldType = this.getType(mutationObj.type);
if (this.isUnionFieldType(fieldType) || this.isInterfaceFieldType(fieldType) || (0, fieldUtils_2.containsConversationDirective)(mutationObj)) {
return acc;
}
return { ...acc, [mutationObj.name]: this.generateGraphQLOperationMetadata(mutationObj) };
}, {});
const conversations = Object.values(this.mutationMap).reduce((acc, mutationObj) => {
if (!(0, fieldUtils_2.containsConversationDirective)(mutationObj)) {
return acc;
}
return { ...acc, [mutationObj.name]: this.generateConversationMetadata(mutationObj) };
}, {});
const subscriptions = Object.values(this.subscriptionMap).reduce((acc, subscriptionObj) => {
const fieldType = this.getType(subscriptionObj.type);
if (this.isUnionFieldType(fieldType) || this.isInterfaceFieldType(fieldType)) {
return acc;
}
return { ...acc, [subscriptionObj.name]: this.generateGraphQLOperationMetadata(subscriptionObj) };
}, {});
const inputs = Object.values(this.inputObjectMap).reduce((acc, inputObj) => {
return { ...acc, [inputObj.name]: this.generateGraphQLInputMetadata(inputObj) };
}, {});
if (Object.keys(queries).length > 0) {
result = { ...result, queries };
}
if (Object.keys(generations).length > 0) {
result = { ...result, generations };
}
if (Object.keys(mutations).length > 0) {
result = { ...result, mutations };
}
if (Object.keys(conversations).length > 0) {
result = { ...result, conversations };
}
if (Object.keys(subscriptions).length > 0) {
result = { ...result, subscriptions };
}
if (Object.keys(inputs).length > 0) {
result = { ...result, inputs };
}
return result;
}
getFieldAssociation(field) {
var _a;
if (field.connectionInfo) {
const { connectionInfo } = field;
const connectionAttribute = { connectionType: connectionInfo.kind };
if (connectionInfo.kind === process_connections_1.CodeGenConnectionType.HAS_MANY) {
connectionAttribute.associatedWith = connectionInfo.associatedWithFields.map(f => this.getFieldName(f));
}
else if (connectionInfo.kind === process_connections_1.CodeGenConnectionType.HAS_ONE) {
connectionAttribute.associatedWith = connectionInfo.associatedWithFields.map(f => this.getFieldName(f));
connectionAttribute.targetNames = (_a = connectionInfo.targetNames) !== null && _a !== void 0 ? _a : [];
}
else {
connectionAttribute.targetNames = connectionInfo.targetNames;
}
return connectionAttribute;
}
}
generateModelAttributes(model) {
return model.directives.map(d => ({
type: d.name,
properties: d.arguments,
}));
}
generateModelMetadata(model) {
return {
...this.generateNonModelMetadata(model),
syncable: true,
pluralName: this.pluralizeModelName(model),
attributes: this.generateModelAttributes(model),
primaryKeyInfo: this.generateModelPrimaryKeyInfo(model),
};
}
generateNonModelMetadata(nonModel) {
return {
name: this.getModelName(nonModel),
fields: nonModel.fields.reduce((acc, field) => {
const fieldType = this.getType(field.type);
if (this.isUnionFieldType(fieldType) || this.isInterfaceFieldType(fieldType)) {
return acc;
}
const fieldMeta = {
name: this.getFieldName(field),
isArray: field.isList,
type: fieldType,
isRequired: !field.isNullable,
attributes: [],
};
if (field.isListNullable !== undefined) {
fieldMeta.isArrayNullable = field.isListNullable;
}
if (field.isReadOnly !== undefined) {
fieldMeta.isReadOnly = field.isReadOnly;
}
const association = this.getFieldAssociation(field);
if (association) {
fieldMeta.association = association;
}
acc[field.name] = fieldMeta;
return acc;
}, {}),
};
}
generateEnumMetadata(enumObj) {
return {
name: enumObj.name,
values: Object.values(enumObj.values),
};
}
generateGraphQLInputMetadata(inputObj) {
return {
name: inputObj.name,
attributes: inputObj.inputValues.reduce((acc, param) => {
const arg = {
name: param.name,
isArray: param.isList,
type: this.getType(param.type),
isRequired: !param.isNullable
};
if (param.isListNullable !== undefined) {
arg.isArrayNullable = param.isListNullable;
}
return { ...acc, [param.name]: arg };
}, {}),
};
}
generateGraphQLOperationMetadata(operationObj) {
const operationMeta = {
name: operationObj.name,
isArray: operationObj.isList,
type: this.getType(operationObj.type),
isRequired: !operationObj.isNullable,
};
if (operationObj.isListNullable !== undefined) {
operationMeta.isArrayNullable = operationObj.isListNullable;
}
if (operationObj.parameters && operationObj.parameters.length > 0) {
operationMeta.arguments = operationObj.parameters.reduce((acc, param) => {
const arg = {
name: param.name,
isArray: param.isList,
type: this.getType(param.type),
isRequired: !param.isNullable
};
if (param.isListNullable !== undefined) {
arg.isArrayNullable = param.isListNullable;
}
return { ...acc, [param.name]: arg };
}, {});
}
return operationMeta;
}
generateGenerationMetadata(generationObj) {
return this.generateGraphQLOperationMetadata(generationObj);
}
generateConversationMetadata(mutationObj) {
return (0, process_conversation_1.processConversationRoute)(mutationObj, this.generateGraphQLOperationMetadata);
}
getType(gqlType) {
if (gqlType in scalars_1.METADATA_SCALAR_MAP) {
return scalars_1.METADATA_SCALAR_MAP[gqlType];
}
if (gqlType in this.enumMap) {
return { enum: this.enumMap[gqlType].name };
}
if (gqlType in this.nonModelMap) {
return { nonModel: gqlType };
}
if (gqlType in this.modelMap) {
return { model: gqlType };
}
if (gqlType in this.inputObjectMap) {
return { input: gqlType };
}
if (gqlType in this.unionMap) {
return { union: gqlType };
}
if (gqlType in this.interfaceMap) {
return { interface: gqlType };
}
throw new Error(`Unknown type ${gqlType} found during model introspection schema generation`);
}
generateModelPrimaryKeyInfo(model) {
const primaryKeyField = this.getModelPrimaryKeyField(model);
if (primaryKeyField && primaryKeyField.primaryKeyInfo) {
const { primaryKeyType, sortKeyFields } = primaryKeyField.primaryKeyInfo;
return {
isCustomPrimaryKey: primaryKeyType === appsync_visitor_1.CodeGenPrimaryKeyType.CustomId,
primaryKeyFieldName: this.getFieldName(primaryKeyField),
sortKeyFieldNames: sortKeyFields.map(field => this.getFieldName(field))
};
}
throw new Error(`No primary key found for model ${model.name}`);
}
}
exports.AppSyncModelIntrospectionVisitor = AppSyncModelIntrospectionVisitor;
//# sourceMappingURL=appsync-model-introspection-visitor.js.map