teqo-backup/src/utilities/drizzleBulk.ts
Francisco Solla f47c2645ac feat(C213): contadores anônimos de circulação por peça na Central de Conteúdos (Closes #1258)
Collection contentEvent (hidden, sem hooks, sem PII) + beacon público
POST /api/content-events fail-soft, download contado no servidor na rota
de mídia, agregação em uma query group-by e a coluna "Circulação" na lista
interna + painel na ficha (port classe-a-classe do artefato estendido,
crítica final do designer certificada).
2026-09-23 15:29:43 -03:00

81 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'server-only'
import { sql } from '@payloadcms/db-postgres'
import type { Payload } from 'payload'
export type DrizzleTables = Record<string, Record<string, unknown>>
type PayloadDbTables = {
tables: DrizzleTables
}
/** The raw-SQL executor Payload's Postgres adapter exposes (drizzle session). */
export type PayloadDrizzle = {
execute: (query: ReturnType<typeof sql>) => Promise<unknown>
}
/**
* The drizzle session of the Postgres adapter, or null when the database is
* not PostgreSQL or the session is unavailable. Single owner of the
* `payload.db` narrowing the raw-SQL readers share; callers decide whether
* that is an error (throw) or a degraded read (fail soft).
*/
export const getPayloadDrizzle = (payload: Pick<Payload, 'db'>): PayloadDrizzle | null => {
if (payload.db.name !== 'postgres') return null
const database = payload.db as unknown as { drizzle?: PayloadDrizzle }
return database.drizzle && typeof database.drizzle.execute === 'function'
? database.drizzle
: null
}
/** ~15-16 columns × 500 ≈ 7500-8000 bind params — well under PG's 65535 param limit. */
export const INSERT_CHUNK_SIZE = 500
export const chunk = <T>(rows: readonly T[], size: number): T[][] => {
const out: T[][] = []
for (let i = 0; i < rows.length; i += size) out.push(rows.slice(i, i + size))
return out
}
export const getDrizzleTables = (payload: Pick<Payload, 'db'>): DrizzleTables =>
(payload.db as unknown as PayloadDbTables).tables
export const requireTable = (tables: DrizzleTables, name: string): Record<string, unknown> => {
const table = tables[name]
if (!table) throw new Error(`Tabela drizzle ausente: ${name}. Rode as migrations.`)
return table
}
/**
* Fails fast when a drizzle table's JS-level column scaffold has drifted from
* what a bulk insert assumes (e.g. `contactId` vs `contact`) — catches the bug
* class before a silent bad insert instead of a runtime SQL error mid-import.
*/
export const assertDrizzleColumns = (
table: Record<string, unknown>,
tableName: string,
expectedColumns: readonly string[],
): void => {
const missing = expectedColumns.filter((column) => !(column in table))
if (missing.length > 0) {
throw new Error(
`Tabela drizzle "${tableName}" não tem as colunas esperadas: ${missing.join(', ')}. ` +
'O bulk insert usaria nomes de coluna divergentes do schema atual.',
)
}
}
/** Normalizes a drizzle `execute()` result (bare array vs `{ rows }`) into row objects. */
export const drizzleResultRows = (result: unknown): Array<Record<string, unknown>> => {
if (Array.isArray(result)) return result as Array<Record<string, unknown>>
if (
typeof result === 'object' &&
result !== null &&
'rows' in result &&
Array.isArray((result as { rows: unknown }).rows)
) {
return (result as { rows: Array<Record<string, unknown>> }).rows
}
return []
}