Thanks for adding onConflict(), it's a great addition.
One thing I noticed was that merge() doesn't seem to "process" the object in the same way insert, patch, etc do. As a simple example, columnNameMappers - like snakeCaseMappers - don't seem to be getting applied. Same for things like $parseJson as far as I can tell. Since merge can accept an optional record to update in the case of a conflict, I'd expect that record to be processed using the same hooks as insert, patch, etc