import type { Db } from './db.js';
import { attributes, auditLog, categories, categoryStoreData, inventorySalable, inventorySourceItems, products, productStoreData, stores } from './schema.js';
export type StoreRow = typeof stores.$inferInsert;
export type AttributeRow = typeof attributes.$inferInsert;
export type CategoryRow = typeof categories.$inferInsert;
export type CategoryStoreRow = typeof categoryStoreData.$inferInsert;
export type ProductRow = typeof products.$inferInsert;
export type ProductStoreRow = typeof productStoreData.$inferInsert;
export type SourceItemRow = typeof inventorySourceItems.$inferInsert;
/** A product as read from Magento's default (`all`) scope: global data + store-0 content + children. */
export interface ProductRecord {
    product: ProductRow;
    storeData: ProductStoreRow;
    relations: Array<{
        childSku: string;
        kind: 'configurable' | 'bundle' | 'grouped';
    }>;
    links: Array<{
        linkType: string;
        linkedSku: string;
        position: number;
    }>;
    categories: Array<{
        categoryId: number;
        position: number;
    }>;
    images: Array<{
        file: string;
        label: string | null;
        position: number;
        roles: string[];
        disabled: boolean;
        mediaType: string;
    }>;
}
export declare function upsertStores(db: Db, rows: StoreRow[]): Promise<void>;
export declare function upsertAttributes(db: Db, rows: AttributeRow[]): Promise<void>;
export declare function replaceAttributeSet(db: Db, set: {
    attributeSetId: number;
    name: string;
}, members: Array<{
    attributeCode: string;
    isRequired: boolean;
}>): Promise<void>;
export declare function upsertCategories(db: Db, rows: CategoryRow[], storeRows: CategoryStoreRow[]): Promise<void>;
/** Remove categories Magento no longer returns (only call with the complete id list). */
export declare function deleteCategoriesNotIn(db: Db, categoryIds: number[]): Promise<number>;
/** Upsert products from the default scope, replacing their child collections. */
export declare function upsertProducts(db: Db, records: ProductRecord[]): Promise<void>;
/** Upsert store-view content for products that already exist (default scope is synced first). */
export declare function upsertProductStoreData(db: Db, rows: ProductStoreRow[]): Promise<number>;
/** Soft-delete live products whose id is not in `seenIds` (the complete set from Magento). */
export declare function softDeleteProductsNotIn(db: Db, seenIds: number[]): Promise<number>;
export declare function upsertSourceItems(db: Db, rows: SourceItemRow[]): Promise<void>;
/** After a full inventory sweep, drop source rows not touched since `sweepStartedAt`. */
export declare function deleteStaleSourceItems(db: Db, sweepStartedAt: Date): Promise<number>;
export declare function upsertSalable(db: Db, row: typeof inventorySalable.$inferInsert): Promise<void>;
export declare function getCursor(db: Db, stream: string): Promise<string | null>;
export declare function setCursor(db: Db, stream: string, cursor: string | null): Promise<void>;
/** Record a job run around `fn`; the stats object it returns is stored on the run. */
export declare function recordRun<T extends Record<string, number>>(db: Db, job: string, fn: () => Promise<T>): Promise<T>;
export declare function softDeleteSku(db: Db, sku: string): Promise<number>;
export declare function skusByProductIds(db: Db, ids: number[]): Promise<Map<number, string>>;
export declare function writeAudit(db: Db, row: typeof auditLog.$inferInsert): Promise<void>;
/** True when a run of `job` started in the last `withinMinutes` and has not finished (crashed runs age out). */
export declare function isRunning(db: Db, job: string, withinMinutes?: number): Promise<boolean>;
//# sourceMappingURL=writes.d.ts.map