import db from '@adonisjs/lucid/services/db' import { ModelQueryBuilderContract } from '@adonisjs/lucid/types/model' export async function getDatabaseTables(): Promise { 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', 'web_components', 'web_pages', 'web_settings', ]) .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>( 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)) } } }) }