151 lines
4.0 KiB
TypeScript
151 lines
4.0 KiB
TypeScript
import { PrismaMssql } from "@prisma/adapter-mssql";
|
|
import { Prisma, PrismaClient } from "./generated/prisma/client";
|
|
|
|
const connectionString = process.env.DATABASE_URL;
|
|
if (!connectionString) {
|
|
throw new Error("DATABASE_URL is not set.");
|
|
}
|
|
|
|
const adapter = new PrismaMssql(connectionString);
|
|
const prisma = new PrismaClient({ adapter });
|
|
|
|
type CandidateTable = { table_name: string };
|
|
type CandidateColumn = { table_name: string; column_name: string };
|
|
|
|
type DmmfField = {
|
|
name: string;
|
|
dbName: string | null;
|
|
};
|
|
|
|
type DmmfModel = {
|
|
name: string;
|
|
dbName: string | null;
|
|
fields: DmmfField[];
|
|
};
|
|
|
|
const TABLE_PATTERN = /config|configur/i;
|
|
const VALUE_COLUMN_PATTERN = /value|field|question|token/i;
|
|
const TOP_CONFIG_LIMIT = 150;
|
|
const CONFIG_KEY_COLUMNS = new Set([
|
|
"Config_RecID",
|
|
"Configuration_RecID",
|
|
"Configuration_RecId",
|
|
]);
|
|
|
|
function byName(a: string, b: string) {
|
|
return a.localeCompare(b);
|
|
}
|
|
|
|
try {
|
|
const models = Prisma.dmmf.datamodel.models as unknown as DmmfModel[];
|
|
|
|
const configModels = models
|
|
.map((model) => ({
|
|
model,
|
|
tableName: model.dbName ?? model.name,
|
|
}))
|
|
.filter(({ tableName }) => TABLE_PATTERN.test(tableName));
|
|
|
|
const candidateTables: CandidateTable[] = configModels
|
|
.map(({ tableName }) => ({ table_name: tableName }))
|
|
.sort((a, b) => byName(a.table_name, b.table_name));
|
|
|
|
const candidateColumns: CandidateColumn[] = configModels
|
|
.flatMap(({ model, tableName }) =>
|
|
model.fields
|
|
.map((field) => field.dbName ?? field.name)
|
|
.filter((columnName) => VALUE_COLUMN_PATTERN.test(columnName))
|
|
.map((columnName) => ({
|
|
table_name: tableName,
|
|
column_name: columnName,
|
|
}))
|
|
)
|
|
.sort(
|
|
(a, b) =>
|
|
byName(a.table_name, b.table_name) ||
|
|
byName(a.column_name, b.column_name)
|
|
);
|
|
|
|
const valueTablesWithConfigKey: CandidateTable[] = configModels
|
|
.filter(({ model }) => {
|
|
const columnNames = model.fields.map(
|
|
(field) => field.dbName ?? field.name
|
|
);
|
|
const hasConfigKey = columnNames.some((column) =>
|
|
CONFIG_KEY_COLUMNS.has(column)
|
|
);
|
|
const hasValueLikeColumn = columnNames.some((column) =>
|
|
VALUE_COLUMN_PATTERN.test(column)
|
|
);
|
|
return hasConfigKey && hasValueLikeColumn;
|
|
})
|
|
.map(({ tableName }) => ({ table_name: tableName }))
|
|
.sort((a, b) => byName(a.table_name, b.table_name));
|
|
|
|
const [
|
|
configRows,
|
|
auditRows,
|
|
auditValueRows,
|
|
nonNullCustomFields,
|
|
groupedAuditTokens,
|
|
topConfigs,
|
|
] = await prisma.$transaction([
|
|
prisma.configuration.count(),
|
|
prisma.configurationAudit.count(),
|
|
prisma.configurationAuditValue.count(),
|
|
prisma.configuration.findMany({
|
|
where: { customField: { not: null } },
|
|
select: { customField: true },
|
|
}),
|
|
prisma.configurationAuditValue.groupBy({
|
|
by: ["auditToken"],
|
|
_count: true,
|
|
orderBy: [{ _count: { auditToken: "desc" } }, { auditToken: "asc" }],
|
|
take: 20,
|
|
}),
|
|
prisma.configuration.findMany({
|
|
take: TOP_CONFIG_LIMIT,
|
|
orderBy: { configRecId: "asc" },
|
|
include: {
|
|
configurationAudits: {
|
|
orderBy: { configurationAuditRecId: "asc" },
|
|
include: {
|
|
configurationValues: {
|
|
orderBy: { configurationAuditValueRecId: "asc" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
]);
|
|
|
|
const configCustomFieldNonempty = nonNullCustomFields.reduce((count, row) => {
|
|
return row.customField?.trim() ? count + 1 : count;
|
|
}, 0);
|
|
|
|
const rowStats = {
|
|
config_rows: configRows,
|
|
config_custom_field_nonempty: configCustomFieldNonempty,
|
|
audit_rows: auditRows,
|
|
audit_value_rows: auditValueRows,
|
|
};
|
|
|
|
const topAuditTokens = groupedAuditTokens.map(({ auditToken, _count }) => ({
|
|
audit_token: auditToken,
|
|
row_count: _count,
|
|
}));
|
|
|
|
const output = {
|
|
candidateTables,
|
|
candidateColumns,
|
|
valueTablesWithConfigKey,
|
|
rowStats,
|
|
topAuditTokens,
|
|
topConfigs,
|
|
};
|
|
|
|
console.log(JSON.stringify(output, null, 2));
|
|
} finally {
|
|
await prisma.$disconnect();
|
|
}
|