Skip to content

Commit

Permalink
feat: add support for list pagination in list capability invocations (#…
Browse files Browse the repository at this point in the history
…184)

Adds support for list pagination in `store/list` and `upload/list`.

Relevant notes on decisions made:
- unfortunately, Databases like DynamoDB does not support pagination by
just giving `pageNumber` and `size`. Aiming to have something generic
(that works in DynamoDB, but also other DBs), chosen approach is to rely
on `cursor` and `size` .
- at first, attempted to make `cursor` a Link property of the
capability. And it worked well for `store/list`, but then I got to use
cases (`upload/list` for instance) where it cannot be a link. This is
because Upload Table primary key contains `${dataCid}#${carCid}` to be
unique. So, in this case that is the cursor we need to have. There might
be other kind of use cases, so having this as string is really the most
flexible approach to support pagination.

BREAKING CHANGE: store/list and upload/list types now require nb object
with optional properties
  • Loading branch information
vasco-santos authored Nov 22, 2022
1 parent 38228bc commit ced23db
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 2 deletions.
11 changes: 11 additions & 0 deletions packages/access-client/src/capabilities/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,17 @@ export const list = base.derive({
* be stored.
*/
with: URI.match({ protocol: 'did:' }),
nb: {
/**
* A pointer that can be moved back and forth on the list.
* It can be used to paginate a list for instance.
*/
cursor: Schema.string().optional(),
/**
* Maximum number of items per page.
*/
size: Schema.integer().optional(),
},
derives: (claimed, delegated) => {
if (claimed.with !== delegated.with) {
return new Failure(
Expand Down
15 changes: 13 additions & 2 deletions packages/access-client/src/capabilities/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
* @module
*/
import { capability, Link, URI } from '@ucanto/validator'
import { capability, Link, URI, Schema } from '@ucanto/validator'
import { codec as CAR } from '@ucanto/transport/car'
import { equalWith, fail, equal } from './utils.js'
import { top } from './top.js'
Expand Down Expand Up @@ -140,6 +140,17 @@ export const list = base.derive({
to: capability({
can: 'upload/list',
with: URI.match({ protocol: 'did:' }),
nb: {
/**
* A pointer that can be moved back and forth on the list.
* It can be used to paginate a list for instance.
*/
cursor: Schema.string().optional(),
/**
* Maximum number of items per page.
*/
size: Schema.integer().optional(),
},
}),
/**
* `upload/list` can be derived from the `upload/*` & `*` capability
Expand All @@ -150,4 +161,4 @@ export const list = base.derive({

// ⚠️ We export imports here so they are not omited in generated typedefs
// @see https://github.com/microsoft/TypeScript/issues/51548
export { Link }
export { Link, Schema }
4 changes: 4 additions & 0 deletions packages/access-client/test/capabilities/upload.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ describe('upload capabilities', function () {
audience: w3,
with: account.did(),
proofs: [await any],
nb: {},
})

const result = await access(await list.delegate(), {
Expand Down Expand Up @@ -357,6 +358,7 @@ describe('upload capabilities', function () {
issuer: bob,
with: account.did(),
proofs: [await upload.delegate()],
nb: {},
})

const result = await access(await list.delegate(), {
Expand All @@ -379,13 +381,15 @@ describe('upload capabilities', function () {
audience: bob,
with: account.did(),
proofs: [await any],
nb: {},
})

const list = Upload.list.invoke({
audience: w3,
issuer: bob,
with: account.did(),
proofs: [await delegation.delegate()],
nb: {},
})

const result = await access(await list.delegate(), {
Expand Down

0 comments on commit ced23db

Please sign in to comment.