Open kbanman opened 1 year ago
I’d be happy to take a contribution. Propose an interface change and I’ll give you guidance
I always meant for this interface to take operations and not just be key:value pairs
Here's a first attempt:
type SetValuesDocument = {
[path: string]: Operand;
};
type SetChange = [string | KeyPath, Operand];
type Operand = KeyPath | LiteralValue | FunctionOperand;
interface FunctionOperand {
$fn: [string, KeyPath | LiteralValue, KeyPath | LiteralValue];
}
type LiteralValue = any;
An attribute upsert would then look like
{
$set: {
price: { $fn: ['if_not_exists', ['price'], 123] },
}
}
But this doesn't hold up as well for a list append:
{
$set: {
// #tags = list_append(#tags, :vals)
tags: { $fn: ['list_append', ['tags'], ['newtag']] },
}
}
The ['newtag']
member is ambiguous: it could be interpreted as a list of strings or as a KeyPath
to the newtag
attribute. The logic would need to use the fact that list_append
needs an array as the second argument and require paths to be declared using the array notation nested inside that array.
list_append
also allows swapping the arguments to append to the beginning of a list.
Binary operations (+
and -
) would also require paths to use the array notation to disambiguate from string values:
{
$set: {
// #quantity = #quantity + 1
quantity: { $fn: ['+', ['quantity'], 1] },
// #quantity = #quantity + #min_order_qty
quantity: { $fn: ['+', ['quantity'], ['min_order_qty']] },
}
}
Helper functions could be exposed to improve the dev experience.
There is still potential for ambiguity between KeyPath
and a literal nested list of strings. I haven't come up with a solution for that
I see what you mean by the ambiguity - would it help if we "broke" the API (removing backwards compatibility) and redesigned it from scratch?
I think I've run into a limitation with the library for this scenario:
Increment a numeric value by a given amount (
UpdateExpression = 'SET #usage = #usage + :increase'
)It seems to me that
updateById
only supports literal values. Do you have any plans to support this scenario?Could follow the lead of libraries like knex, which allows you to wrap values in a "raw" container. The tricky thing here is that the final value would need to be dependent on the compiled attribute names and attribute values.
Maybe simply making an escape hatch more readily available code be enough. In any case please let me know your thoughts; I'd be happy to contribute something