( originalCallback: (changes: Array<ChangeMessage<T>>) => void, options: SubscribeChangesOptions<T, TKey>, )
| 248 | * @returns A filtered callback function |
| 249 | */ |
| 250 | export function createFilteredCallback< |
| 251 | T extends object, |
| 252 | TKey extends string | number = string | number, |
| 253 | >( |
| 254 | originalCallback: (changes: Array<ChangeMessage<T>>) => void, |
| 255 | options: SubscribeChangesOptions<T, TKey>, |
| 256 | ): (changes: Array<ChangeMessage<T>>) => void { |
| 257 | const filterFn = createFilterFunctionFromExpression(options.whereExpression!) |
| 258 | |
| 259 | return (changes: Array<ChangeMessage<T>>) => { |
| 260 | const filteredChanges: Array<ChangeMessage<T>> = [] |
| 261 | |
| 262 | for (const change of changes) { |
| 263 | if (change.type === `insert`) { |
| 264 | // For inserts, check if the new value matches the filter |
| 265 | if (filterFn(change.value)) { |
| 266 | filteredChanges.push(change) |
| 267 | } |
| 268 | } else if (change.type === `update`) { |
| 269 | // For updates, we need to check both old and new values |
| 270 | const newValueMatches = filterFn(change.value) |
| 271 | const oldValueMatches = change.previousValue |
| 272 | ? filterFn(change.previousValue) |
| 273 | : false |
| 274 | |
| 275 | if (newValueMatches && oldValueMatches) { |
| 276 | // Both old and new match: emit update |
| 277 | filteredChanges.push(change) |
| 278 | } else if (newValueMatches && !oldValueMatches) { |
| 279 | // New matches but old didn't: emit insert |
| 280 | filteredChanges.push({ |
| 281 | ...change, |
| 282 | type: `insert`, |
| 283 | }) |
| 284 | } else if (!newValueMatches && oldValueMatches) { |
| 285 | // Old matched but new doesn't: emit delete |
| 286 | filteredChanges.push({ |
| 287 | ...change, |
| 288 | type: `delete`, |
| 289 | value: change.previousValue!, // Use the previous value for the delete |
| 290 | }) |
| 291 | } |
| 292 | // If neither matches, don't emit anything |
| 293 | } else { |
| 294 | // For deletes, include if the previous value would have matched |
| 295 | // (so subscribers know something they were tracking was deleted) |
| 296 | if (filterFn(change.value)) { |
| 297 | filteredChanges.push(change) |
| 298 | } |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | // Always call the original callback if we have filtered changes OR |
| 303 | // if the original changes array was empty (which indicates a ready signal) |
| 304 | if (filteredChanges.length > 0 || changes.length === 0) { |
| 305 | originalCallback(filteredChanges) |
| 306 | } |
| 307 | } |
no test coverage detected