rawsql-ts
Version:
[beta]High-performance SQL parser and AST analyzer written in TypeScript. Provides fast parsing and advanced transformation capabilities.
194 lines • 7.08 kB
JavaScript
/**
* Schema Manager for rawsql-ts
* Provides unified schema definition and automatic conversion to various formats
* Eliminates code duplication and provides type-safe schema management
*/
// === Schema Manager Class ===
/**
* Central schema management utility for rawsql-ts
* Converts user-defined schemas to various internal formats
*/
export class SchemaManager {
constructor(schemas) {
this.schemas = schemas;
this.validateSchemas();
}
/**
* Validate schema definitions for consistency
* Ensures each table has a primary key (required for UPDATE/DELETE operations)
* and validates relationship references
*/
validateSchemas() {
const tableNames = Object.keys(this.schemas);
const errors = [];
// Validate each table
Object.entries(this.schemas).forEach(([tableName, table]) => {
var _a;
// Check primary key exists (required for UPDATE/DELETE WHERE conditions)
const primaryKeys = Object.entries(table.columns)
.filter(([_, col]) => col.isPrimaryKey)
.map(([name, _]) => name);
if (primaryKeys.length === 0) {
errors.push(`Table '${tableName}' has no primary key defined`);
}
// Validate foreign key references
(_a = table.relationships) === null || _a === void 0 ? void 0 : _a.forEach(rel => {
if (!tableNames.includes(rel.table)) {
errors.push(`Table '${tableName}' references unknown table '${rel.table}' in relationship`);
}
});
});
if (errors.length > 0) {
throw new Error(`Schema validation failed:\\n${errors.join('\\n')}`);
}
}
/**
* Get table column names for SqlParamInjector TableColumnResolver
* @param tableName Name of the table
* @returns Array of column names
*/
getTableColumns(tableName) {
const table = this.schemas[tableName];
if (!table) {
return [];
}
return Object.keys(table.columns);
}
/**
* Create TableColumnResolver function for SqlParamInjector
* @returns Function compatible with SqlParamInjector
*/
createTableColumnResolver() {
return (tableName) => this.getTableColumns(tableName);
}
/**
* Generate JSON mapping configuration for PostgresJsonQueryBuilder
* @param rootTableName Root table for the JSON structure
* @returns JSON mapping configuration
*/
createJsonMapping(rootTableName) {
var _a;
const rootTable = this.schemas[rootTableName];
if (!rootTable) {
throw new Error(`Table '${rootTableName}' not found in schema registry`);
}
// Build root entity columns mapping
const rootColumns = {};
Object.entries(rootTable.columns).forEach(([columnName, column]) => {
rootColumns[columnName] = column.jsonAlias || column.name;
});
// Build nested entities from relationships
const nestedEntities = [];
(_a = rootTable.relationships) === null || _a === void 0 ? void 0 : _a.forEach(rel => {
const relatedTable = this.schemas[rel.table];
if (!relatedTable) {
throw new Error(`Related table '${rel.table}' not found in schema registry`);
}
// Build columns mapping for related table
const relatedColumns = {};
Object.entries(relatedTable.columns).forEach(([columnName, column]) => {
relatedColumns[columnName] = column.jsonAlias || column.name;
});
// Determine relationship type for JSON builder
const relationshipType = rel.type;
nestedEntities.push({
id: rel.propertyName,
name: relatedTable.displayName || rel.table,
parentId: rootTableName,
propertyName: rel.propertyName,
relationshipType: relationshipType,
columns: relatedColumns
});
});
return {
rootName: rootTableName,
rootEntity: {
id: rootTableName,
name: rootTable.displayName || rootTableName,
columns: rootColumns
},
nestedEntities,
useJsonb: true,
resultFormat: "single"
};
}
/**
* Get all table names in the schema
* @returns Array of table names
*/
getTableNames() {
return Object.keys(this.schemas);
}
/**
* Get table definition by name
* @param tableName Name of the table
* @returns Table definition or undefined
*/
getTable(tableName) {
return this.schemas[tableName];
}
/**
* Get primary key column name for a table
* Used by QueryBuilder.buildUpdateQuery for WHERE clause conditions
* @param tableName Name of the table
* @returns Primary key column name or undefined
*/
getPrimaryKey(tableName) {
const table = this.schemas[tableName];
if (!table)
return undefined;
const primaryKeyEntry = Object.entries(table.columns)
.find(([_, col]) => col.isPrimaryKey);
return primaryKeyEntry ? primaryKeyEntry[0] : undefined;
}
/**
* Get foreign key relationships for a table
* @param tableName Name of the table
* @returns Array of foreign key relationships
*/
getForeignKeys(tableName) {
const table = this.schemas[tableName];
if (!table)
return [];
const foreignKeys = [];
Object.entries(table.columns).forEach(([columnName, column]) => {
if (column.foreignKey) {
foreignKeys.push({
column: columnName,
referencedTable: column.foreignKey.table,
referencedColumn: column.foreignKey.column
});
}
});
return foreignKeys;
}
}
// === Convenience Functions ===
/**
* Create a SchemaManager instance from schema definitions
* @param schemas Schema registry object
* @returns SchemaManager instance
*/
export function createSchemaManager(schemas) {
return new SchemaManager(schemas);
}
/**
* Create TableColumnResolver function from schema definitions
* @param schemas Schema registry object
* @returns TableColumnResolver function for SqlParamInjector
*/
export function createTableColumnResolver(schemas) {
const manager = new SchemaManager(schemas);
return manager.createTableColumnResolver();
}
/**
* Create JSON mapping from schema definitions
* @param schemas Schema registry object
* @param rootTableName Root table name
* @returns JSON mapping for PostgresJsonQueryBuilder
*/
export function createJsonMappingFromSchema(schemas, rootTableName) {
const manager = new SchemaManager(schemas);
return manager.createJsonMapping(rootTableName);
}
//# sourceMappingURL=SchemaManager.js.map