@aws-amplify/graphql-schema-generator
Version:
Amplify GraphQL schema generator
225 lines • 7.88 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MySQLStringDataSourceAdapter = void 0;
const schema_representation_1 = require("../schema-representation");
const string_datasource_adapter_1 = require("./string-datasource-adapter");
const graphql_transformer_common_1 = require("graphql-transformer-common");
const expectedColumns = [
'TABLE_NAME',
'COLUMN_NAME',
'COLUMN_DEFAULT',
'ORDINAL_POSITION',
'DATA_TYPE',
'COLUMN_TYPE',
'IS_NULLABLE',
'CHARACTER_MAXIMUM_LENGTH',
'INDEX_NAME',
'NON_UNIQUE',
'SEQ_IN_INDEX',
'NULLABLE',
];
class MySQLStringDataSourceAdapter extends string_datasource_adapter_1.StringDataSourceAdapter {
constructor() {
super(...arguments);
this.enums = new Map();
this.PRIMARY_KEY_INDEX_NAME = 'PRIMARY';
}
setSchema(schema) {
this.setFields(schema);
this.setIndexes(schema);
this.setTables(schema);
}
validateSchema(schema) {
if (schema.length === 0) {
throw new string_datasource_adapter_1.EmptySchemaError();
}
const columns = Object.keys(schema[0]);
const hasAllExpectedColumns = expectedColumns.every((column) => columns.includes(column));
if (!hasAllExpectedColumns) {
throw new string_datasource_adapter_1.InvalidSchemaError(schema, expectedColumns);
}
return true;
}
setFields(parsedSchema) {
this.fields = parsedSchema.map((item) => ({
tableName: item.TABLE_NAME,
columnName: item.COLUMN_NAME,
default: item.COLUMN_DEFAULT,
sequence: item.ORDINAL_POSITION,
datatype: item.DATA_TYPE,
columnType: item.COLUMN_TYPE,
nullable: item.IS_NULLABLE === 'YES',
length: item.CHARACTER_MAXIMUM_LENGTH,
}));
}
setIndexes(parsedSchema) {
this.indexes = parsedSchema
.filter(({ INDEX_NAME }) => !!INDEX_NAME)
.map((item) => ({
tableName: item.TABLE_NAME,
indexName: item.INDEX_NAME,
nonUnique: item.NON_UNIQUE,
columnName: item.COLUMN_NAME,
sequence: item.SEQ_IN_INDEX,
nullable: item.NULLABLE === 'YES',
}));
}
setTables(parsedSchema) {
this.tables = Array.from(new Set(parsedSchema.map(({ TABLE_NAME }) => TABLE_NAME)));
}
getTablesList() {
return this.tables;
}
getFields(tableName) {
const fieldsName = [
...new Set(this.fields
.filter((f) => f.tableName === tableName)
.sort((a, b) => a.sequence - b.sequence)
.map((f) => f.columnName)),
];
const modelFields = fieldsName.map((columnName) => {
const dbField = this.fields.find((field) => field.tableName === tableName && field.columnName === columnName);
const field = {
name: dbField.columnName,
type: this.mapDataType(dbField.datatype, dbField.nullable, tableName, dbField.columnName, dbField.columnType),
length: dbField.length,
default: dbField.default
? {
kind: 'DB_GENERATED',
value: dbField.default,
}
: undefined,
};
return field;
});
return modelFields;
}
getPrimaryKey(tableName) {
const key = this.indexes
.filter((index) => index.tableName === tableName && index.indexName === this.PRIMARY_KEY_INDEX_NAME)
.sort((a, b) => a.sequence - b.sequence);
if (!key || key.length == 0) {
return null;
}
const index = new schema_representation_1.Index(key[0].indexName);
index.setFields(key.map((k) => k.columnName));
return index;
}
getIndexes(tableName) {
const indexNames = [
...new Set(this.indexes.filter((i) => i.tableName === tableName && i.indexName !== this.PRIMARY_KEY_INDEX_NAME).map((i) => i.indexName)),
];
const tableIndexes = indexNames.map((indexName) => {
const key = this.indexes
.filter((index) => index.tableName == tableName && index.indexName === indexName)
.sort((a, b) => a.sequence - b.sequence);
const index = new schema_representation_1.Index(indexName);
index.setFields(key.map((k) => k.columnName));
return index;
});
return tableIndexes;
}
mapDataType(datatype, nullable, tableName, fieldName, columntype) {
let fieldDatatype = 'String';
let listtype = false;
switch (datatype.toUpperCase()) {
case 'VARCHAR':
case 'CHAR':
case 'BINARY':
case 'VARBINARY':
case 'TINYBLOB':
case 'TINYTEXT':
case 'TEXT':
case 'BLOB':
case 'MEDIUMTEXT':
case 'MEDIUMBLOB':
case 'LONGTEXT':
case 'LONGBLOB':
fieldDatatype = 'String';
break;
case 'SET':
fieldDatatype = 'String';
listtype = true;
break;
case 'BOOLEAN':
case 'BOOL':
fieldDatatype = 'Boolean';
break;
case 'BIT':
case 'TINYINT':
case 'SMALLINT':
case 'MEDIUMINT':
case 'INT':
case 'INTEGER':
case 'BIGINT':
case 'YEAR':
fieldDatatype = 'Int';
break;
case 'FLOAT':
case 'DOUBLE':
case 'DECIMAL':
case 'DEC':
case 'NUMERIC':
fieldDatatype = 'Float';
break;
case 'DATE':
fieldDatatype = 'AWSDate';
break;
case 'TIMESTAMP':
case 'DATETIME':
fieldDatatype = 'AWSDateTime';
break;
case 'TIME':
fieldDatatype = 'AWSTime';
break;
case 'JSON':
fieldDatatype = 'AWSJSON';
break;
case 'ENUM':
fieldDatatype = 'ENUM';
break;
default:
fieldDatatype = 'String';
break;
}
let result;
if (fieldDatatype === 'ENUM') {
const enumName = this.generateEnumName(tableName, fieldName);
result = {
kind: 'Enum',
values: this.getEnumValues(columntype),
name: this.generateEnumName(tableName, fieldName),
};
this.enums.set(enumName, result);
}
else {
result = {
kind: 'Scalar',
name: fieldDatatype,
};
}
if (!nullable) {
result = {
kind: 'NonNull',
type: result,
};
}
return result;
}
getEnumValues(value) {
const regex = /(["'])(?:(?=(\\?))\2.)*?\1/g;
return value.match(regex).map((a) => a.slice(1, -1));
}
generateEnumName(tableName, fieldName) {
const enumNamePrefix = (0, graphql_transformer_common_1.toPascalCase)([tableName, fieldName]);
let enumName = enumNamePrefix;
let counter = 0;
while (this.enums.has(enumName)) {
enumName = (0, graphql_transformer_common_1.toPascalCase)([enumNamePrefix, counter.toString()]);
counter++;
}
return enumName;
}
}
exports.MySQLStringDataSourceAdapter = MySQLStringDataSourceAdapter;
//# sourceMappingURL=mysql-string-datasource-adapter.js.map