Execute and Stream V2 Migration
In March 2024, Grafast gained support for "unary"
steps. This was critical for
making Grafast easier to integrate with other data sources that aren't as
capable as Postgres (and let's be honest, what other data sources are as
capable as Postgres?) but unfortunately it meant that we had to account for
singular values coming into execute methods. At first we added an executeV2
but this was really ugly and annoying to explain, so since we're still in beta
we made the hard decision to break this API, and replace execute.
Quick fix
If you just want what you had before to start working again, you can change
each of your execute methods:
executenow only accepts one argument; destructurecount,values(asnewValues) andextrafrom this argument.newValuesis a tuple of objects rather than arrays; to convert it back to the legacy form (a tuple of arrays): map over each entry,dep, innewValuesand:- if it's a batch entry (
dep.isBatch === true):- use the 
dep.entriesproperty 
 - use the 
 - otherwise:
- use an array of length 
count, where each entry in the array isdep.value. 
 - use an array of length 
 
- if it's a batch entry (
 
Here's an example diff of applying this change to your code:
- async execute(count: number, values: any[][], extra: ExecutionExtra) {
+ async execute({ count, values: newValues, extra }: ExecutionDetails) {
+   const values = newValues.map((dep) =>
+     dep.isBatch ? dep.entries : new Array(count).fill(dep.value)
+   );
Once done, your functions should work as they did before.
Better fix
The above is not the most efficient way of using the new system though (since
it requires creating a new array for each unary dependency in each step);
instead you should map over each incoming index via indexMap and use the
dep.at(i) method rather than dep[i] array syntax to access the value at
each index.
Before:
function execute(count: number, values: ReadonlyArray<[number, number]>) {
  const [allA, allB] = values;
  const results: number[] = [];
  for (let i = 0; i < count; i++) {
    const a = allA[i];
    const b = allB[i];
    results.push(a + b);
  }
  return results;
}
After:
function execute({ indexMap, values }: ExecutionDetails<[number, number]>) {
  const [allA, allB] = values;
  return indexMap((i) => {
    const a = allA.at(i);
    const b = allB.at(i);
    return a + b;
  });
}
stream
stream goes through the same transition as execute, except the type of the
details variable is StreamDetails rather than ExecutionDetails.