/** * configureDb — DB 풀 주입 * * 앱 시작 시 한 번만 호출한다. mysql2/promise Pool과 호환되는 인터페이스를 받는다. * global 에 저장하므로 Next.js 개발 모드 hot reload 에도 풀이 유지된다. * * @example * import pool from "./config/db"; * import { configureDb } from "@sunkim4638/admin-modules/db"; * configureDb(pool); */ interface DbConnection { query(sql: string, params?: any[]): Promise<[any, any]>; beginTransaction(): Promise; commit(): Promise; rollback(): Promise; release(): void; } interface DbPool { query(sql: string, params?: any[]): Promise<[any, any]>; getConnection(): Promise; } declare global { var __adminModulesDbPool__: DbPool | undefined; } declare function configureDb(pool: DbPool): void; declare function getPool(): DbPool; /** * DB 헬퍼 — queryOne / queryAll / insert / update / remove * * 모든 함수는 마지막 인자로 conn(커넥션)을 받을 수 있다. * conn을 넘기면 해당 커넥션을 사용하고, 생략하면 풀에서 자동으로 커넥션을 꺼낸다. * 트랜잭션 내에서 사용할 때는 반드시 conn을 넘겨야 한다. * * @example * // 단순 조회 * const user = await queryOne("SELECT * FROM users WHERE id = ?", [1]); * * // 트랜잭션 내 사용 * await withTransaction(async (conn) => { * const id = await insert("orders", { userId: 1, amount: 5000 }, conn); * await update("users", { point: 0 }, { id: 1 }, conn); * }); */ /** 단일 row 조회. 결과가 없으면 null 반환. */ declare const queryOne: (sql: string, params?: any[], conn?: DbConnection) => Promise; /** 리스트 조회. 결과가 없으면 빈 배열 반환. */ declare const queryAll: (sql: string, params?: any[], conn?: DbConnection) => Promise; /** * INSERT * @returns 삽입된 row의 insertId */ declare const insert: (table: string, row: Record, conn?: DbConnection) => Promise; /** * UPDATE * where 조건: null(IS NULL), 배열(IN), 일반값(=) 모두 지원. * @returns affectedRows */ declare const update: (table: string, row: Record, where: Record, conn?: DbConnection) => Promise; /** * DELETE * where 조건: null(IS NULL), 배열(IN), 일반값(=) 모두 지원. * @returns affectedRows */ declare const remove: (table: string, where: Record, conn?: DbConnection) => Promise; /** * 트랜잭션 / 커넥션 관리 유틸 * * @example * // 트랜잭션 (에러 시 자동 롤백) * await withTransaction(async (conn) => { * const id = await insert("orders", { userId: 1 }, conn); * await update("users", { balance: 0 }, { id: 1 }, conn); * }); * * @example * // 단일 커넥션 (트랜잭션 없이 커넥션 재사용) * await withConnection(async (conn) => { * const user = await queryOne("SELECT ...", [], conn); * const logs = await queryAll("SELECT ...", [], conn); * }); */ /** 트랜잭션 — 에러 시 자동 롤백 후 예외를 다시 던진다. */ declare const withTransaction: (callback: (conn: DbConnection) => Promise) => Promise; /** 단일 커넥션으로 여러 쿼리 처리 (트랜잭션 없음, 커넥션 자동 반환). */ declare const withConnection: (callback: (conn: DbConnection) => Promise) => Promise; /** * createWhere — SQL WHERE 절 빌더 * * 메서드 체이닝으로 조건을 추가하고, build()로 SQL과 바인딩 값을 반환한다. * 값이 undefined / null / 빈 문자열이면 자동으로 스킵한다. * * @example * const w = createWhere(); * * w.equal("U.status", data.status); // undefined면 스킵 * w.like("U.name", data.keyword); // → U.name LIKE '%keyword%' * w.likeAny(["U.name", "U.email"], data.keyword); // 검색 유형이 "전체"일 때 → (U.name LIKE ? OR U.email LIKE ?) * w.between("U.createdAt", data.startDate, data.endDate); * w.in("U.role", ["admin", "manager"]); * w.raw("U.deletedAt IS NULL"); * * const { whereSql, whereValues } = w.build(); * // whereSql → " WHERE U.name LIKE ? AND U.createdAt BETWEEN ? AND ? AND U.deletedAt IS NULL" * // whereValues → ["%keyword%", startDate, endDate] */ declare function createWhere(): { /** * col = ? * val이 undefined / null / ""이면 스킵 */ equal(col: string, val: unknown): /*elided*/ any; /** * col LIKE '%val%' * val이 falsy이면 스킵 */ like(col: string, val: unknown): /*elided*/ any; /** * (col1 LIKE ? OR col2 LIKE ? OR ...) * 키워드 검색 유형이 "전체"일 때처럼, 여러 컬럼에 동시에 LIKE 검색할 때 사용. * val이 falsy이거나 cols가 빈 배열이면 스킵. * @example w.likeAny(["U.name", "U.email"], data.keyword) */ likeAny(cols: string[], val: unknown): /*elided*/ any; /** * col BETWEEN ? AND ? * start 또는 end가 falsy이면 스킵 */ between(col: string, start: unknown, end: unknown): /*elided*/ any; /** * col IN (?, ?, ...) * vals가 빈 배열이면 스킵 */ in(col: string, vals: unknown[]): /*elided*/ any; /** * col IS NULL */ isNull(col: string): /*elided*/ any; /** * col IS NOT NULL */ isNotNull(col: string): /*elided*/ any; /** * 직접 SQL 조각과 바인딩 값을 추가 * @example w.raw("(U.role = ? OR U.role = ?)", ["admin", "manager"]) */ raw(sql: string, vals?: unknown[]): /*elided*/ any; /** WHERE 절 SQL과 바인딩 값 배열을 반환 */ build(): { whereSql: string; whereValues: unknown[]; }; }; /** * SQL 빌더 유틸 — ORDER BY / LIMIT OFFSET * * @example * const orderSql = buildOrderBy( * { name: "U.name", createdAt: "U.createAt" }, * data.sortKey, * data.sortType, * "U.id DESC" // 기본 정렬 (sortKey 없을 때) * ); * // → " ORDER BY U.name ASC" * * @example * const { sql: pageSql, values: pageValues } = buildPagination(data.page, data.pageSize); * // → { sql: " LIMIT ?, ?", values: [20, 20] } * * @example * const list = await queryAll( * `SELECT * FROM users ${orderSql} ${pageSql}`, * [...whereValues, ...pageValues] * ); */ /** 정렬 컬럼 맵 — { [sortKey]: "실제컬럼명" } */ type SortColumns = Record; /** * ORDER BY 절 생성 * @param columns sortKey → 실제 컬럼명 맵 * @param sortKey 요청에서 받은 정렬 키 * @param sortType "ASC" | "DESC" (대소문자 무관) * @param defaultSql sortKey가 없거나 맵에 없을 때 사용할 기본 정렬 SQL (컬럼명만, ORDER BY 제외) */ declare function buildOrderBy(columns: SortColumns, sortKey: string | undefined, sortType: string | undefined, defaultSql?: string): string; /** * LIMIT / OFFSET 절 생성 * page 또는 pageSize가 없으면 빈 문자열과 빈 배열을 반환한다. * @returns { sql, values } — values를 query params에 스프레드해서 사용 */ declare function buildPagination(page: number | undefined, pageSize: number | undefined): { sql: string; values: number[]; }; export { type DbConnection, type DbPool, type SortColumns, buildOrderBy, buildPagination, configureDb, createWhere, getPool, insert, queryAll, queryOne, remove, update, withConnection, withTransaction };