feat: kv list ordering toggle + addressable path improvements (#3843)
Maintain Release Merge PR / update-release-pr (push) Canceled after 0s
Notify HeyPuter / notify (push) Canceled after 0s
release-please / release-please (push) Canceled after 0s

* fix: put-1787

* feat: kv list reverse
This commit is contained in:
Daniel Salazar
2026-09-09 17:24:03 -07:00
committed by GitHub
parent 9b465aba9f
commit a8a78736bb
15 changed files with 706 additions and 165 deletions
+1 -1
View File
@@ -223,7 +223,7 @@ These Key-Value Store features are supported out of the box when using Puter.js:
- **[`puter.kv.del()`](/KV/del/)** - Delete a key-value pair
- **[`puter.kv.expire()`](/KV/expire/)** - Set key expiration in seconds
- **[`puter.kv.expireAt()`](/KV/expireAt/)** - Set key expiration timestamp
- **[`puter.kv.list()`](/KV/list/)** - List all keys
- **[`puter.kv.list()`](/KV/list/)** - List keys in ascending or descending order
- **[`puter.kv.flush()`](/KV/flush/)** - Clear all data
## Examples
+3 -1
View File
@@ -27,10 +27,12 @@ An array is appended element by element, so wrap a single value in an array to a
#### `pathAndValue` (Object) (optional)
An object where each key is a dot-separated path (for example, `"profile.tags"`) and each value is the value (or values) to add at that path.
An object where each key is a path (for example, `"profile.tags"`) and each value is the value (or values) to add at that path.
Appended values follow the same limits as [`puter.kv.set()`](/KV/set/): **400 KB**, and every number within **±9,007,199,254,740,991** — a larger one is stored clamped to that bound.
Paths support dot notation, array indexes at any level (`[0]`, `items[0]`, or `some.path[1].to.value`), and quoted property names (`["key.with.dots"]`). An empty path (`""`) targets the whole stored value. Use non-negative integer indexes in brackets to address arrays. When a path continues through an array element (for example, `[0].score`), that element must already exist. Missing object parents are created automatically; sparse array elements are not created.
## Return value
Returns a `Promise` that resolves to the updated value stored at `key`.
+2
View File
@@ -29,6 +29,8 @@ When `amount` is an object: Decrements a property within an object value stored
- Key: the path to the property (e.g., `"user.score"`)
- Value: the amount to decrement by
Paths support dot notation, array indexes at any level (`[0]`, `items[0]`, or `some.path[1].to.value`), and quoted property names (`["key.with.dots"]`). An empty path (`""`) targets the whole stored value. Use non-negative integer indexes in brackets to address arrays. When a path continues through an array element (for example, `[0].score`), that element must already exist. Missing object parents are created automatically; sparse array elements are not created.
## Return Value
Returns the new value of the key after the decrement operation.
+2
View File
@@ -31,6 +31,8 @@ When `amount` is an object: Increments a property within an object value stored
`amount` must be within **±9,007,199,254,740,991** (`Number.MAX_SAFE_INTEGER`); a larger one is applied clamped to that bound. A counter stays exact only while its total is inside the same range — store anything that has to count past it as a string with [`puter.kv.set()`](/KV/set/).
Paths support dot notation, array indexes at any level (`[0]`, `items[0]`, or `some.path[1].to.value`), and quoted property names (`["key.with.dots"]`). An empty path (`""`) targets the whole stored value. Use non-negative integer indexes in brackets to address arrays. When a path continues through an array element (for example, `[0].score`), that element must already exist. Missing object parents are created automatically; sparse array elements are not created.
## Return Value
Returns the new value of the key after the increment operation.
+21 -2
View File
@@ -6,7 +6,7 @@ platforms: [websites, apps, nodejs, workers]
Returns an array of all keys in the user's key-value store for the current app. If the user has no keys, the array will be empty.
Results are sorted lexicographically (string order) by key.
Results are sorted lexicographically (string order) by key, ascending by default. Pass `reverse: true` to list keys in descending order.
## Syntax
@@ -36,8 +36,9 @@ An object with the following optional properties:
- `pattern` (String): Same as the `pattern` parameter.
- `returnValues` (Boolean): Same as the `returnValues` parameter.
- `reverse` (Boolean): Lists keys in descending order when `true`. Defaults to `false`. Works with full listings, pagination, and streams; by itself, it keeps the plain-array return shape.
- `limit` (Number): Maximum number of items to return in a single call.
- `cursor` (String): A pagination cursor from a previous call. Pass the `cursor` value returned by the previous page to fetch the next one.
- `cursor` (String): A pagination cursor from a previous call. Pass the `cursor` value returned by the previous page to fetch the next one. The cursor preserves the listing direction; omit `reverse` to keep it, or pass the same value. A conflicting direction is rejected.
- `offset` (Number): Skips the given number of items before the page starts. Not recommended — requests get slower and more expensive the larger the offset; prefer `cursor`. Maximum `5000`, and cannot be combined with `cursor`.
- `includeTotal` (Boolean): If `true`, the result includes a `total` count of every item matching the query (across all pages). The count is metered and its cost grows with the size of your store — request it once (on the first page) and avoid it in hot paths. If you only need to know whether more pages exist, check for `cursor` instead of counting.
- `fetchUntilFull` (Boolean): A page can come back with fewer than `limit` items even when more exist (for example when expired keys are excluded). If `true`, the page is filled up to `limit` items when possible. Requires `limit`.
@@ -69,6 +70,24 @@ for await (const page of puter.kv.list({ pattern: 'log:*', stream: true })) {
## Examples
<strong class="example-title">List keys in reverse order</strong>
```html;kv-list-reverse
<html>
<body>
<script src="https://js.puter.com/v2/"></script>
<script>
(async () => {
await puter.kv.set('reverse-demo:a', 1);
await puter.kv.set('reverse-demo:b', 2);
const keys = await puter.kv.list({ pattern: 'reverse-demo:*', reverse: true });
puter.print(JSON.stringify(keys));
})();
</script>
</body>
</html>
```
<strong class="example-title">Retrieve all keys in the user's key-value store for the current app</strong>
```html;kv-list
+4 -2
View File
@@ -4,7 +4,7 @@ description: Remove values at one or more paths from a key in the user's own key
platforms: [websites, apps, nodejs, workers]
---
Remove values from an existing key by path. Paths use dot notation to target nested fields.
Remove values from an existing key by path. Paths can target nested fields and array elements.
## Syntax
@@ -20,7 +20,9 @@ The key to remove values from.
#### `paths` (String[]) (required)
One or more dot-separated paths to remove (for example, `"profile.bio"`).
One or more paths to remove (for example, `"profile.bio"`).
Paths support dot notation, array indexes at any level (`[0]`, `items[0]`, or `some.path[1].to.value`), and quoted property names (`["key.with.dots"]`). An empty path (`""`) targets the whole stored value. Use non-negative integer indexes in brackets to address arrays. Removing an array element shifts later elements down by one index.
## Return value
+20 -1
View File
@@ -22,7 +22,7 @@ The key to update.
#### `pathAndValueMap` (Object) (required)
An object where each key is a dot-separated path (for example, `"profile.name"`) and each value is the new value for that path.
An object where each key is a path (for example, `"profile.name"`) and each value is the new value for that path.
Each value follows the same limits as [`puter.kv.set()`](/KV/set/): **400 KB**, and every number within **±9,007,199,254,740,991** — a larger one is stored clamped to that bound.
@@ -30,12 +30,31 @@ Each value follows the same limits as [`puter.kv.set()`](/KV/set/): **400 KB**,
Time-to-live for the key, in seconds.
Paths support dot notation, array indexes at any level (`[0]`, `items[0]`, or `some.path[1].to.value`), and quoted property names (`["key.with.dots"]`). An empty path (`""`) targets the whole stored value. Use non-negative integer indexes in brackets to address arrays. When a path continues through an array element (for example, `[0].score`), that element must already exist. Missing object parents are created automatically; sparse array elements are not created.
## Return value
Returns a `Promise` that resolves to the updated value stored at `key`.
## Examples
<strong class="example-title">Update an element of a root array</strong>
```html;kv-update-root-array
<html>
<body>
<script src="https://js.puter.com/v2/"></script>
<script>
(async () => {
await puter.kv.set('players', [{ score: 1 }, { score: 2 }]);
const updated = await puter.kv.update('players', { '[0].score': 10 });
puter.print(JSON.stringify(updated));
})();
</script>
</body>
</html>
```
<strong class="example-title">Update nested fields and refresh the TTL</strong>
```html;kv-update