@aws-amplify/graphql-schema-generator
Version:
Amplify GraphQL schema generator
241 lines • 8.27 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostgresStringDataSourceAdapter = exports.expectedColumns = 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");
exports.expectedColumns = [
'enum_name',
'enum_values',
'table_name',
'column_name',
'column_default',
'ordinal_position',
'data_type',
'udt_name',
'is_nullable',
'character_maximum_length',
'index_columns',
'indexname',
'constraint_type',
];
class PostgresStringDataSourceAdapter extends string_datasource_adapter_1.StringDataSourceAdapter {
constructor() {
super(...arguments);
this.PRIMARY_KEY_INDEX_NAME = 'PRIMARY';
}
setSchema(schema) {
this.setEnums(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 = exports.expectedColumns.every((column) => columns.includes(column));
if (!hasAllExpectedColumns) {
throw new string_datasource_adapter_1.InvalidSchemaError(schema, exports.expectedColumns);
}
return true;
}
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.find((index) => index.tableName === tableName && index.constraintType === 'PRIMARY KEY');
if (!key || key.columns.length == 0) {
return null;
}
const index = new schema_representation_1.Index(key.indexName);
index.setFields(key.columns);
return index;
}
getIndexes(tableName) {
const indexNames = [
...new Set(this.indexes.filter((i) => i.tableName === tableName && i.constraintType !== 'PRIMARY KEY').map((i) => i.indexName)),
];
const tableIndexes = indexNames.map((indexName) => {
const key = this.indexes.find((index) => index.tableName == tableName && index.indexName === indexName);
const index = new schema_representation_1.Index(indexName);
index.setFields(key.columns);
return index;
});
return tableIndexes;
}
generateEnumName(tableName, fieldName) {
return (0, graphql_transformer_common_1.toPascalCase)([tableName, fieldName]);
}
setEnums(parsedSchema) {
this.enums = new Map();
parsedSchema
.filter(({ enum_name }) => !!enum_name)
.forEach((row) => {
const tableName = row.table_name;
const columnName = row.column_name;
const enumName = this.generateEnumName(tableName, columnName);
const enumValues = row.enum_values.substring(1, row.enum_values.length - 1).split(',');
const enumType = {
kind: 'Enum',
name: enumName,
values: enumValues,
};
this.enums.set(enumName, enumType);
});
}
setTables(parsedSchema) {
this.tables = Array.from(new Set(parsedSchema.map(({ table_name }) => table_name)));
}
setFields(fields) {
this.fields = fields.map((item) => ({
tableName: item.table_name,
columnName: item.column_name,
default: item.column_default,
sequence: item.ordinal_position,
datatype: item.data_type,
columnType: item.udt_name,
nullable: item.is_nullable === 'YES',
length: item.character_maximum_length,
}));
}
setIndexes(indexes) {
this.indexes = indexes
.filter(({ index_columns }) => !!index_columns)
.map((item) => ({
tableName: item.table_name,
columns: item.index_columns.split(', '),
indexName: item.indexname,
columnName: item.column_name,
constraintType: item.constraint_type,
}));
}
mapDataType(datatype, nullable, tableName, fieldName, columntype) {
let fieldDatatype = 'String';
let listtype = false;
if (columntype.startsWith('_')) {
listtype = true;
columntype = columntype.slice(1);
}
switch (columntype.toUpperCase()) {
case 'VARCHAR':
case 'CHAR':
case 'TEXT':
fieldDatatype = 'String';
break;
case 'BOOLEAN':
case 'BOOL':
fieldDatatype = 'Boolean';
break;
case 'BIGINT':
case 'INT8':
case 'BIGSERIAL':
case 'BIT':
case 'INT':
case 'INT4':
case 'INT2':
case 'SMALLINT':
case 'SMALLSERIAL':
case 'SERIAL':
case 'SERIAL4':
fieldDatatype = 'Int';
break;
case 'FLOAT8':
case 'MONEY':
case 'NUMERIC':
case 'DECIMAL':
case 'REAL':
case 'FLOAT4':
fieldDatatype = 'Float';
break;
case 'UUID':
fieldDatatype = 'ID';
break;
case 'DATE':
fieldDatatype = 'AWSDate';
break;
case 'TIMESTAMP':
case 'DATETIME':
fieldDatatype = 'AWSDateTime';
break;
case 'TIME':
fieldDatatype = 'AWSTime';
break;
case 'BOX':
case 'CIRCLE':
case 'JSON':
case 'JSONB':
case 'LINE':
case 'LSEG':
case 'PATH':
case 'POINT':
case 'POLYGON':
fieldDatatype = 'AWSJSON';
break;
case 'CIDR':
case 'INET':
fieldDatatype = 'AWSIPAddress';
break;
default:
if (this.enums.has(this.generateEnumName(tableName, fieldName))) {
fieldDatatype = 'ENUM';
}
break;
}
let result;
if (fieldDatatype === 'ENUM') {
const enumRef = this.enums.get(this.generateEnumName(tableName, fieldName));
result = {
kind: 'Enum',
values: enumRef.values,
name: enumRef.name,
};
}
else {
result = {
kind: 'Scalar',
name: fieldDatatype,
};
}
if (!nullable) {
result = {
kind: 'NonNull',
type: result,
};
}
if (listtype) {
result = {
kind: 'List',
type: result,
};
}
return result;
}
}
exports.PostgresStringDataSourceAdapter = PostgresStringDataSourceAdapter;
//# sourceMappingURL=pg-string-datasource-adapter.js.map