Include deltas in modify/changed events

Apologies if this exists, I did try to search.

The Vault.on(‘modify’)and metadataCache.on('changed') event tells you when something changes, but not what changed.

In my plugin, I’m looking for changes to specific frontmatter fields. In order to do that today, I have to scan the whole vault at startup to track the initial state.

It would be easy enough if these events just included the entire previous frontmatter and file contents in the event handler. (In my case, just the frontmatter would be fine.)

An alternative improvement might be to provide an API for the snapshots feature, so previous versions could be recalled on demand. That feels like maybe a security issue though.

I think inside Vault.on('modify'), if you call await app.vault.cachedRead(file), you get the previous version of the file, so you can calculate the diff.

Thanks for the reply. I gave it a shot but no luck.

// Test 1: Direct content modification
(async () => {
  const testFile = app.vault.getAbstractFileByPath('People/John Doe.md');
  
  // Set up listener to capture both cachedRead and read results when modify fires
  const listener = async (file) => {
    if (file.path !== testFile.path) return;
    
    const cached = await app.vault.cachedRead(file);
    const actual = await app.vault.read(file);
    
    console.log({
      test: 'modify event fired',
      cachedSame: cached === actual,
      cachedHasTest: cached.includes('TEST-MARKER'),
      actualHasTest: actual.includes('TEST-MARKER')
    });
  };
  
  app.vault.on('modify', listener);
  
  // Modify the file
  const content = await app.vault.read(testFile);
  await app.vault.modify(testFile, content + '\nTEST-MARKER');
  
  // Clean up
  setTimeout(() => app.vault.off('modify', listener), 1000);
  return 'Test started - check console';
})()

// Result: {"test":"modify event fired","cachedSame":true,"cachedHasTest":true,"actualHasTest":true}
// Both methods return the NEW content with TEST-MARKER


// Test 2: Frontmatter modification via processFrontMatter
(async () => {
  const testFile = app.vault.getAbstractFileByPath('People/John Doe.md');
  
  const listener = async (file) => {
    if (file.path !== testFile.path) return;
    
    const cached = await app.vault.cachedRead(file);
    const actual = await app.vault.read(file);
    
    // Extract the test field from frontmatter
    const cachedMatch = cached.match(/test:\s*(.+)/);
    const actualMatch = actual.match(/test:\s*(.+)/);
    
    console.log({
      test: 'modify event fired',
      cachedSame: cached === actual,
      cachedTest: cachedMatch?.[1],
      actualTest: actualMatch?.[1],
      bothHaveTest: !!cachedMatch && !!actualMatch
    });
  };
  
  app.vault.on('modify', listener);
  
  // Modify frontmatter
  await app.fileManager.processFrontMatter(testFile, (fm) => {
    fm.test = `test-value-${Date.now()}`;
  });
  
  setTimeout(() => app.vault.off('modify', listener), 1000);
  return 'Test started - check console';
})()

// Result: {"test":"modify event fired","cachedSame":true,"cachedTest":"test-value-1769660147094","actualTest":"test-value-1769660147094","bothHaveTest":true}
// Both methods return the NEW content with the same timestamp

Yes, I was wrong, cache is updated before the modify event handled