Skip to content

Conversation

canadaduane
Copy link

@canadaduane canadaduane commented Aug 26, 2025

  • Adds an onOperation onChange hook that intercepts all proxy paths
  • Very minimal performance impact

I'm not sure if this addresses #72 , but I'm opening this PR for discussion since the onOperation hook as implemented by this PR addresses the sequence and interleaving issue I needed a solution to.

Disclosure: Used claude code, with personal review of code.

- Adds an onOperation hook that intercepts all proxy paths
- Very minimal performance impact
@unadlib
Copy link
Owner

unadlib commented Aug 26, 2025

Thanks for your PR. From an implementation perspective, it's cleaner to add an extra change hook in src/utils/mark.ts and use the JSON Patch structure.

@canadaduane
Copy link
Author

Ah, interesting. I didn't notice this "all paths lead to markChanged" control point. Thank you.

@canadaduane
Copy link
Author

canadaduane commented Aug 26, 2025

@unadlib What do you think about this latest version? Changes of note:

  • I've changed the name from onOperation to onChange, which is closer to your original proposal. I could also cut out hooks if needed. Removed hooks:.
  • I've consolidated the logic to center on markChanged.

To accomplish the 2nd point, I needed to add additional key and operation params in order to pass this in to onChanged. I worry this may impact performance. Perhaps we should split into two functions?

  • markChanged
  • markChangedWithOnChange

Then we could have a ternary at each call point:

    options.hooks?.onChange
      ? markChangedWithOnChange(target, key, { kind: 'set', prev: current, next: value })
      : markChanged(target);

I haven't benchmarked this as I'm not familiar with your best practices.

@canadaduane canadaduane changed the title Add onOperation hook Add onChange hook Aug 26, 2025
@canadaduane
Copy link
Author

canadaduane commented Aug 26, 2025

I'm just re-reading your comment about using JSON Patch. I'm not sure if I understand this part of your reply, because the ProxyDraft passed to markChanged does not contain JSON Patch data afaict.

EDIT: Ah, I see I missed finalities. But wouldn't that mean the onChange is only aware of final patch data, not the actual each-line-item changes as they occur? (I believe my use case requires the latter).

@unadlib
Copy link
Owner

unadlib commented Aug 27, 2025

I'm just re-reading your comment about using JSON Patch. I'm not sure if I understand this part of your reply, because the ProxyDraft passed to markChanged does not contain JSON Patch data afaict.

EDIT: Ah, I see I missed finalities. But wouldn't that mean the onChange is only aware of final patch data, not the actual each-line-item changes as they occur? (I believe my use case requires the latter).

In fact, we need to add new parameters to markChanged for collecting the op type of each change that executes this function, as well as the paths of the changed node. Then, we trigger the onChange callback. This is likely the most concise approach and also eliminates the need to consider finalities.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants