97 lines
2.6 KiB
TypeScript
Executable File
97 lines
2.6 KiB
TypeScript
Executable File
import db from '@adonisjs/lucid/services/db'
|
|
import { ModelQueryBuilderContract } from '@adonisjs/lucid/types/model'
|
|
|
|
export async function getDatabaseTables(): Promise<string[]> {
|
|
const result = await db
|
|
.from('information_schema.tables')
|
|
.select('table_name')
|
|
.where('table_schema', 'public')
|
|
.whereNotIn('table_name', [
|
|
'adonis_schema',
|
|
'adonis_schema_versions',
|
|
'auth_access_tokens',
|
|
'admins',
|
|
'permissions',
|
|
'roles',
|
|
'admin_roles',
|
|
'role_permissions',
|
|
'migrations',
|
|
'migrations_lock',
|
|
'pg_stat_statements',
|
|
'pg_stat_activity',
|
|
'pg_type',
|
|
'pg_enum',
|
|
'pg_class',
|
|
'pg_attribute',
|
|
'pg_index',
|
|
'pg_namespace',
|
|
'pg_tables',
|
|
])
|
|
.whereRaw(`table_name NOT LIKE 'pg_%'`)
|
|
.whereRaw(`table_name NOT LIKE 'sql_%'`)
|
|
|
|
return result.map((row) => row.table_name)
|
|
}
|
|
|
|
export async function getColumnsForTable(table: string) {
|
|
const rows = await db
|
|
.from('information_schema.columns')
|
|
.select('column_name', 'data_type', 'is_nullable')
|
|
.where('table_schema', 'public')
|
|
.andWhere('table_name', table)
|
|
|
|
return rows.map((row) => {
|
|
const col = {
|
|
...row,
|
|
isSpecial: ['created_at', 'updated_at', 'deleted_at'].includes(row.column_name),
|
|
}
|
|
return col
|
|
})
|
|
}
|
|
|
|
export async function getForeignKeysReferencing(table: string) {
|
|
return await db
|
|
.from('information_schema.columns')
|
|
.select('table_name', 'column_name')
|
|
.where('column_name', `${table}_id`)
|
|
.andWhere('table_schema', 'public')
|
|
}
|
|
|
|
export async function searchableColumns(table: string) {
|
|
const columns = await getColumnsForTable(table)
|
|
return {
|
|
string: columns
|
|
.filter((col) =>
|
|
['character varying', 'text', 'varchar', 'char', 'uuid'].includes(col.data_type)
|
|
)
|
|
.map((col) => col.column_name),
|
|
number: columns
|
|
.filter((col) => ['integer', 'int4', 'int8', 'numeric', 'bigint'].includes(col.data_type))
|
|
.map((col) => col.column_name),
|
|
}
|
|
}
|
|
|
|
export function addSearchFilter<T extends ModelQueryBuilderContract<any>>(
|
|
query: T,
|
|
columns: { string: string[]; number: string[] },
|
|
search: string
|
|
) {
|
|
const keywords = search.trim().split(/\s+/)
|
|
|
|
query.where((builder) => {
|
|
for (const keyword of keywords) {
|
|
builder.orWhere((subBuilder) => {
|
|
for (const column of columns.string) {
|
|
subBuilder.orWhereILike(column, `%${keyword}%`)
|
|
}
|
|
})
|
|
}
|
|
|
|
if (!Number.isNaN(Number(search))) {
|
|
for (const column of columns.number) {
|
|
builder.orWhere(column, Number(search))
|
|
}
|
|
}
|
|
})
|
|
}
|