I use transaction.local for this determination since its name implies its meaning. That said, I don’t know if there is a technical reason to prefer other methods.
You should prefer transaction.local to determine if a transaction was created locally. All changes from the providers are local = false.
The third method won’t work when you only delete a property (as there is no item created with an id).
If possible, you should actually use transaction.origin to determine the origin of a transaction. If the change was created by a provider (or an editor-binding) the provider-instance will be set as the origin (respectively the editor-binding instance). I want to establish a pattern that each library set the origin when they create a change. Users can create changes with just null or create their own origin.
If the change was created by a provider (or an editor-binding) the provider-instance will be set as the origin (respectively the editor-binding instance).
Seems this is not true with y-indexeddb, from my testing, transaction from y-indexeddb has local=true and origin=null, it does not set the origin correctly to be identified as a provider.