feat: naming strategy (#19848)

* feat: naming strategy

* feat: detect renames
This commit is contained in:
Jason Rasmussen
2025-07-11 11:35:10 -04:00
committed by GitHub
parent 1d19d308e2
commit 9e48ae3052
35 changed files with 517 additions and 127 deletions

View File

@@ -0,0 +1,50 @@
import { sha1 } from 'src/sql-tools/helpers';
import { NamingItem } from 'src/sql-tools/naming/naming.interface';
const asSnakeCase = (name: string): string => name.replaceAll(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();
export class DefaultNamingStrategy {
getName(item: NamingItem): string {
switch (item.type) {
case 'database': {
return asSnakeCase(item.name);
}
case 'table': {
return asSnakeCase(item.name);
}
case 'column': {
return item.name;
}
case 'primaryKey': {
return `${item.tableName}_pkey`;
}
case 'foreignKey': {
return `${item.tableName}_${item.columnNames.join('_')}_fkey`;
}
case 'check': {
return `${item.tableName}_${sha1(item.expression).slice(0, 8)}_chk`;
}
case 'unique': {
return `${item.tableName}_${item.columnNames.join('_')}_uq`;
}
case 'index': {
if (item.columnNames) {
return `${item.tableName}_${item.columnNames.join('_')}_idx`;
}
return `${item.tableName}_${sha1(item.expression || item.where || '').slice(0, 8)}_idx`;
}
case 'trigger': {
return `${item.tableName}_${item.functionName}`;
}
}
}
}

View File

@@ -0,0 +1,51 @@
import { sha1 } from 'src/sql-tools/helpers';
import { DefaultNamingStrategy } from 'src/sql-tools/naming/default.naming';
import { NamingInterface, NamingItem } from 'src/sql-tools/naming/naming.interface';
const fallback = new DefaultNamingStrategy();
const asKey = (prefix: string, tableName: string, values: string[]) =>
(prefix + sha1(`${tableName}_${values.toSorted().join('_')}`)).slice(0, 30);
export class HashNamingStrategy implements NamingInterface {
getName(item: NamingItem): string {
switch (item.type) {
case 'primaryKey': {
return asKey('PK_', item.tableName, item.columnNames);
}
case 'foreignKey': {
return asKey('FK_', item.tableName, item.columnNames);
}
case 'check': {
return asKey('CHK_', item.tableName, [item.expression]);
}
case 'unique': {
return asKey('UQ_', item.tableName, item.columnNames);
}
case 'index': {
const items: string[] = [];
for (const columnName of item.columnNames ?? []) {
items.push(columnName);
}
if (item.where) {
items.push(item.where);
}
return asKey('IDX_', item.tableName, items);
}
case 'trigger': {
return asKey('TR_', item.tableName, [...item.actions, item.scope, item.timing, item.functionName]);
}
default: {
return fallback.getName(item);
}
}
}
}

View File

@@ -0,0 +1,59 @@
import { TriggerAction, TriggerScope, TriggerTiming } from 'src/sql-tools/types';
export type NamingItem =
| {
type: 'database';
name: string;
}
| {
type: 'table';
name: string;
}
| {
type: 'column';
name: string;
}
| {
type: 'primaryKey';
tableName: string;
columnNames: string[];
}
| {
type: 'foreignKey';
tableName: string;
columnNames: string[];
referenceTableName: string;
referenceColumnNames: string[];
}
| {
type: 'check';
tableName: string;
expression: string;
}
| {
type: 'unique';
tableName: string;
columnNames: string[];
}
| {
type: 'index';
tableName: string;
columnNames?: string[];
expression?: string;
where?: string;
}
| {
type: 'trigger';
tableName: string;
functionName: string;
actions: TriggerAction[];
scope: TriggerScope;
timing: TriggerTiming;
columnNames?: string[];
expression?: string;
where?: string;
};
export interface NamingInterface {
getName(item: NamingItem): string;
}