import { mock, type Mock } from 'node:test'; import path from 'node:path'; import { type SerializedError, type EmigrateReporter, type FailedMigrationHistoryEntry, type MigrationHistoryEntry, type MigrationMetadata, type NonFailedMigrationHistoryEntry, type Storage, } from '@emigrate/types'; export type Mocked = { // @ts-expect-error - This is a mock [K in keyof T]: Mock; }; export async function noop() { // noop } export function getErrorCause(error: Error | undefined): Error | SerializedError | undefined { if (error?.cause instanceof Error) { return error.cause; } if (typeof error?.cause === 'object' && error.cause !== null) { return error.cause as unknown as SerializedError; } return undefined; } export function getMockedStorage(historyEntries: Array) { const storage: Mocked = { lock: mock.fn(async (migrations) => migrations), unlock: mock.fn(async () => { // void }), getHistory: mock.fn(async function* () { yield* toEntries(historyEntries); }), remove: mock.fn(), onSuccess: mock.fn(), onError: mock.fn(), end: mock.fn(), }; return storage; } export function getMockedReporter(): Mocked> { return { onFinished: mock.fn(noop), onInit: mock.fn(noop), onAbort: mock.fn(noop), onCollectedMigrations: mock.fn(noop), onLockedMigrations: mock.fn(noop), onNewMigration: mock.fn(noop), onMigrationStart: mock.fn(noop), onMigrationSuccess: mock.fn(noop), onMigrationError: mock.fn(noop), onMigrationSkip: mock.fn(noop), }; } export function toMigration(cwd: string, directory: string, name: string): MigrationMetadata { return { name, filePath: `${cwd}/${directory}/${name}`, relativeFilePath: `${directory}/${name}`, extension: path.extname(name), directory, cwd, }; } export function toMigrations(cwd: string, directory: string, names: string[]): MigrationMetadata[] { return names.map((name) => toMigration(cwd, directory, name)); } export function toEntry(name: MigrationHistoryEntry): MigrationHistoryEntry; export function toEntry( name: string, status?: S, ): S extends 'failed' ? FailedMigrationHistoryEntry : NonFailedMigrationHistoryEntry; export function toEntry(name: string | MigrationHistoryEntry, status?: 'done' | 'failed'): MigrationHistoryEntry { if (typeof name !== 'string') { return name.status === 'failed' ? name : name; } if (status === 'failed') { return { name, status, date: new Date(), error: { name: 'Error', message: 'Failed' }, }; } return { name, status: status ?? 'done', date: new Date(), }; } export function toEntries( names: Array, status?: MigrationHistoryEntry['status'], ): MigrationHistoryEntry[] { return names.map((name) => (typeof name === 'string' ? toEntry(name, status) : name)); }