diff --git a/package-lock.json b/package-lock.json index b0e1eca9..7eb1882f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,19 +25,20 @@ "@serverless-stack/resources": "^1.18.0", "@tsconfig/node16": "^1.0.3", "@types/git-rev-sync": "^2.0.0", - "@ucanto/client": "^4.0.3", - "@ucanto/core": "^4.0.3", - "@ucanto/principal": "^4.0.3", - "@ucanto/transport": "^4.0.3", + "@ucanto/client": "^4.2.3", + "@ucanto/core": "^4.2.3", + "@ucanto/principal": "^4.2.3", + "@ucanto/transport": "^4.2.3", "@web-std/blob": "^3.0.4", "@web-std/fetch": "^4.1.0", "@web3-storage/access": "^9.2.0", - "@web3-storage/w3up-client": "^4.0.1", + "@web3-storage/w3up-client": "^4.1.0", "ava": "^4.3.3", "dotenv": "^16.0.3", "git-rev-sync": "^3.0.2", "hd-scripts": "^3.0.2", "lint-staged": "^13.0.3", + "multiformats": "^11.0.1", "p-wait-for": "^5.0.0", "typescript": "^4.9.3" } @@ -7390,12 +7391,13 @@ "license": "BSD-3-Clause" }, "node_modules/@ipld/car": { - "version": "5.0.1", - "license": "Apache-2.0 OR MIT", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ipld/car/-/car-5.1.0.tgz", + "integrity": "sha512-k9pO0YqJvmFGY5pJDhF2Ocz+mRp3C3r4ikr1NrUXkzN/z4JzhE7XbQzUCcm7daq8k4tRqap0fWPjxZwjS9PUcQ==", "dependencies": { - "@ipld/dag-cbor": "^8.0.0", + "@ipld/dag-cbor": "^9.0.0", "cborg": "^1.9.0", - "multiformats": "^10.0.2", + "multiformats": "^11.0.0", "varint": "^6.0.0" }, "engines": { @@ -7403,6 +7405,19 @@ "npm": ">=7.0.0" } }, + "node_modules/@ipld/car/node_modules/@ipld/dag-cbor": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-9.0.0.tgz", + "integrity": "sha512-zdsiSiYDEOIDW7mmWOYWC9gukjXO+F8wqxz/LfN7iSwTfIyipC8+UQrCbPupFMRb/33XQTZk8yl3My8vUQBRoA==", + "dependencies": { + "cborg": "^1.10.0", + "multiformats": "^11.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@ipld/dag-cbor": { "version": "8.0.0", "license": "Apache-2.0 OR MIT", @@ -7415,12 +7430,22 @@ "npm": ">=7.0.0" } }, + "node_modules/@ipld/dag-cbor/node_modules/multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@ipld/dag-json": { - "version": "9.0.1", - "license": "Apache-2.0 OR MIT", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@ipld/dag-json/-/dag-json-10.0.1.tgz", + "integrity": "sha512-XE1Eqw3eNVrSfOhtqCM/gwCxEgYFBzkDlkwhEeMmMvhd0rLBfSyVzXbahZSlv97tiTPEIx5rt41gcFAda3W8zg==", "dependencies": { - "cborg": "^1.5.4", - "multiformats": "^10.0.2" + "cborg": "^1.10.0", + "multiformats": "^11.0.0" }, "engines": { "node": ">=16.0.0", @@ -7439,13 +7464,37 @@ "npm": ">=7.0.0" } }, + "node_modules/@ipld/dag-pb/node_modules/multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", + "dev": true, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@ipld/dag-ucan": { - "version": "3.0.1", - "license": "(Apache-2.0 AND MIT)", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ipld/dag-ucan/-/dag-ucan-3.2.0.tgz", + "integrity": "sha512-CTClaGx4F3iEMJgYaYVOVBEvtNXzPc77Mi6p3vBtylSzDWhbf1Gou9ij7PlblOqWKA1H7XI8fp6yweTb6iXNKQ==", "dependencies": { - "@ipld/dag-cbor": "^8.0.0", - "@ipld/dag-json": "^9.0.1", - "multiformats": "^10.0.0" + "@ipld/dag-cbor": "^9.0.0", + "@ipld/dag-json": "^10.0.0", + "multiformats": "^11.0.0" + } + }, + "node_modules/@ipld/dag-ucan/node_modules/@ipld/dag-cbor": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-9.0.0.tgz", + "integrity": "sha512-zdsiSiYDEOIDW7mmWOYWC9gukjXO+F8wqxz/LfN7iSwTfIyipC8+UQrCbPupFMRb/33XQTZk8yl3My8vUQBRoA==", + "dependencies": { + "cborg": "^1.10.0", + "multiformats": "^11.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" } }, "node_modules/@ipld/unixfs": { @@ -7486,6 +7535,16 @@ "web-streams-polyfill": "^3.1.1" } }, + "node_modules/@ipld/unixfs/node_modules/multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", + "dev": true, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@noble/ed25519": { "version": "1.7.1", "funding": [ @@ -8338,79 +8397,105 @@ } }, "node_modules/@ucanto/client": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/client/-/client-4.0.3.tgz", - "integrity": "sha512-Kr+6A9VB/m2sFEatEKWzJk7Ccwg7AURdqdFyzhzUGU6YvUe4Z/wcly+yz1hswHmGc77dVPo+b19k2U/jjwnSKA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/client/-/client-4.2.3.tgz", + "integrity": "sha512-vIa0drEAeolQpSePpHtsW1bx8lzDdxtXi2fEdQ4f34xbI2VSOQuAgUURJTtRVmRXa5MweQoEGI9CHPKL4CMyFQ==", "dependencies": { - "@ucanto/interface": "^4.0.3", - "multiformats": "^10.0.2" + "@ucanto/interface": "^4.1.0", + "multiformats": "^11.0.0" } }, "node_modules/@ucanto/core": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/core/-/core-4.0.3.tgz", - "integrity": "sha512-5Uc6vdmKZzlA9NFvAN6BC1Tp1Npz0sepp2up1ZWU4BqArQ0w4U0YMtL9KPdBnL3TDAyDNgS9PgK+vHpjcSoeiQ==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/core/-/core-4.2.3.tgz", + "integrity": "sha512-udvp7IMRCE3XFhPYiKISt52r8QjbrqG7d1papdtWwF6RAzTbIWhgXSwAjEbroYCr/gQst7U8aYsgr4xvG2miUQ==", "dependencies": { - "@ipld/car": "^5.0.0", - "@ipld/dag-cbor": "^8.0.0", - "@ipld/dag-ucan": "^3.0.1", - "@ucanto/interface": "^4.0.3", - "multiformats": "^10.0.2" + "@ipld/car": "^5.0.3", + "@ipld/dag-cbor": "^9.0.0", + "@ipld/dag-ucan": "^3.2.0", + "@ucanto/interface": "^4.1.0", + "multiformats": "^11.0.0" + } + }, + "node_modules/@ucanto/core/node_modules/@ipld/dag-cbor": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-9.0.0.tgz", + "integrity": "sha512-zdsiSiYDEOIDW7mmWOYWC9gukjXO+F8wqxz/LfN7iSwTfIyipC8+UQrCbPupFMRb/33XQTZk8yl3My8vUQBRoA==", + "dependencies": { + "cborg": "^1.10.0", + "multiformats": "^11.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" } }, "node_modules/@ucanto/interface": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/interface/-/interface-4.0.3.tgz", - "integrity": "sha512-ip1ZziMUhi9nFm9jPLEDLs8zX4HleYsuHHITH5w8GjST7chbRz1LBSq43A3nMUgea17cuIp+rr7i4QcOSFgXHw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/interface/-/interface-4.2.3.tgz", + "integrity": "sha512-IoccqMc2/vqaPT6U061ylC138mQ3pLp6coqjXTDmlL9OHmskLcEeQh5Mxe0AYHWMhO1ZuB0LRIysBXk7xoK25Q==", "dependencies": { - "@ipld/dag-ucan": "^3.0.1", - "multiformats": "^10.0.2" + "@ipld/dag-ucan": "^3.2.0", + "multiformats": "^11.0.0" } }, "node_modules/@ucanto/principal": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/principal/-/principal-4.0.3.tgz", - "integrity": "sha512-mR9BTkXWDDSFDCf5gminNeDte/jwurohjFJE8oVfGfUnkzSjYwfm4h5GQ47qeze6xgm17SS5pQwipSvCGHfvkg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/principal/-/principal-4.2.3.tgz", + "integrity": "sha512-S02cKaMcIQhxk9uJfUCUb+f98zEEFsC+5BZC6aBoYVCEpXwVZD6+hc9xI0yIQl8zJyQVA3nnUUpLfLynsSox2A==", "dependencies": { - "@ipld/dag-ucan": "^3.0.1", + "@ipld/dag-ucan": "^3.2.0", "@noble/ed25519": "^1.7.1", - "@ucanto/interface": "^4.0.3", - "multiformats": "^10.0.2", + "@ucanto/interface": "^4.1.0", + "multiformats": "^11.0.0", "one-webcrypto": "^1.0.3" } }, "node_modules/@ucanto/server": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/server/-/server-4.0.3.tgz", - "integrity": "sha512-4s7XQNrj8O9EVGwYne5zVTKl10S9Cgbea64LJomfSlx5gYf7cQTMpOaRCNudi91rutOxDzEtQAVCc2vb1WWrbw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/server/-/server-4.2.3.tgz", + "integrity": "sha512-lmDC0d9mVGYfiqwzpiTG6CFZpGVw1GnFx9EOtozKPa+v2nzwqDAkwYAQwNrJ2nbJWQQeFi7/Jiaec9EmdPEpsg==", "dependencies": { - "@ucanto/core": "^4.0.3", - "@ucanto/interface": "^4.0.3", - "@ucanto/validator": "^4.0.3" + "@ucanto/core": "^4.1.0", + "@ucanto/interface": "^4.1.0", + "@ucanto/validator": "^4.1.0" } }, "node_modules/@ucanto/transport": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/transport/-/transport-4.0.3.tgz", - "integrity": "sha512-yrJoqoxmMCpPElR+iEb2AKIjUEmM+JGCcM1TZLXVbMlzaAt6ndYDMPajfnh3PBQMk7edIodZi+UxCLKvc8yelg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/transport/-/transport-4.2.3.tgz", + "integrity": "sha512-ZtHB5ybSB/1dBLhzJqjxGDEE+TTTNzc9HMrVA1AP5KHvaHPu2UtAmS2IMr+HrhSjcwWwdavK0qMQbXSfLWM+kg==", "dependencies": { - "@ipld/car": "^5.0.0", - "@ipld/dag-cbor": "^8.0.0", - "@ucanto/core": "^4.0.3", - "@ucanto/interface": "^4.0.3", - "multiformats": "^10.0.2" + "@ipld/car": "^5.0.3", + "@ipld/dag-cbor": "^9.0.0", + "@ucanto/core": "^4.1.0", + "@ucanto/interface": "^4.1.0", + "multiformats": "^11.0.0" + } + }, + "node_modules/@ucanto/transport/node_modules/@ipld/dag-cbor": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-9.0.0.tgz", + "integrity": "sha512-zdsiSiYDEOIDW7mmWOYWC9gukjXO+F8wqxz/LfN7iSwTfIyipC8+UQrCbPupFMRb/33XQTZk8yl3My8vUQBRoA==", + "dependencies": { + "cborg": "^1.10.0", + "multiformats": "^11.0.0" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" } }, "node_modules/@ucanto/validator": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/validator/-/validator-4.0.3.tgz", - "integrity": "sha512-GLsOIq4R7ixu4D1NMNEJZhOelLPIpd/qtTyOjpxqrrSfsDfOoCsHkSxBy0gTwS/4ZIFMM5sa2LBPJw+ZXobgzw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/validator/-/validator-4.2.3.tgz", + "integrity": "sha512-7lA9PK+c0Hu857eHuZIVX3ZBooqvOT25/CXUxGjqs5YFCY7dUhrNCxJYnWsPZnEdriq6x6VSj8pZPwN8I7CyQw==", "dependencies": { - "@ipld/car": "^5.0.0", + "@ipld/car": "^5.0.3", "@ipld/dag-cbor": "^8.0.0", - "@ucanto/core": "^4.0.3", - "@ucanto/interface": "^4.0.3", - "multiformats": "^10.0.2" + "@ucanto/core": "^4.1.0", + "@ucanto/interface": "^4.1.0", + "multiformats": "^11.0.0" } }, "node_modules/@web-std/blob": { @@ -8500,6 +8585,15 @@ "node": ">=14.0.0" } }, + "node_modules/@web3-storage/access/node_modules/multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@web3-storage/access/node_modules/type-fest": { "version": "3.3.0", "license": "(MIT OR CC0-1.0)", @@ -8511,15 +8605,15 @@ } }, "node_modules/@web3-storage/capabilities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@web3-storage/capabilities/-/capabilities-2.1.0.tgz", - "integrity": "sha512-6rbcushGhbaeHC38iTEW8t6QapJutfDxLoKPEVMHTJYUGfKE/bL7M7VYXws6Vdp1XCFaLbLv88OSIR/nq9M9lg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@web3-storage/capabilities/-/capabilities-2.3.0.tgz", + "integrity": "sha512-+vg61eqK1eqQ+QD1hvChDDx6CXLGFnUsEA+W+g9yagCpq+H9yAqROncEEt+oluIGvAqNbFMrUb+bWRWxk0Tmuw==", "dependencies": { - "@ucanto/core": "^4.0.2", - "@ucanto/interface": "^4.0.2", - "@ucanto/principal": "^4.0.2", - "@ucanto/transport": "^4.0.2", - "@ucanto/validator": "^4.0.2" + "@ucanto/core": "^4.2.3", + "@ucanto/interface": "^4.2.3", + "@ucanto/principal": "^4.2.3", + "@ucanto/transport": "^4.2.3", + "@ucanto/validator": "^4.2.3" } }, "node_modules/@web3-storage/multipart-parser": { @@ -8544,6 +8638,16 @@ "p-retry": "^5.1.2" } }, + "node_modules/@web3-storage/upload-client/node_modules/multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", + "dev": true, + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/@web3-storage/w3infra-carpark": { "resolved": "carpark", "link": true @@ -8565,9 +8669,9 @@ "link": true }, "node_modules/@web3-storage/w3up-client": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@web3-storage/w3up-client/-/w3up-client-4.0.1.tgz", - "integrity": "sha512-8UEkZ6BWhOOlZ/FezV+GAW+T826iqELCgMW0Dhtt36jqxiuXYWVJb/ONsaSXlr3ZGw02BPvH3O5mG6BjDKWRAw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@web3-storage/w3up-client/-/w3up-client-4.1.0.tgz", + "integrity": "sha512-ekLo576uFJHYpWG3QXJETydV/Xq+GniouVDN1S6ND5QSBmb/TBRbEnzplohqwLztvlPSrkd1/VL+t+IDuosubQ==", "dev": true, "dependencies": { "@ipld/dag-ucan": "^3.0.1", @@ -8578,7 +8682,7 @@ "@ucanto/transport": "^4.0.2", "@web3-storage/access": "^9.1.1", "@web3-storage/capabilities": "^2.0.0", - "@web3-storage/upload-client": "^5.2.0" + "@web3-storage/upload-client": "^5.3.0" } }, "node_modules/@zxing/text-encoding": { @@ -9984,8 +10088,9 @@ } }, "node_modules/cborg": { - "version": "1.9.6", - "license": "Apache-2.0", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/cborg/-/cborg-1.10.0.tgz", + "integrity": "sha512-/eM0JCaL99HDHxjySNQJLaolZFVdl6VA0/hEKIoiQPcQzE5LrG5QHdml0HaBt31brgB9dNe1zMr3f8IVrpotRQ==", "bin": { "cborg": "cli.js" } @@ -14043,8 +14148,9 @@ "license": "MIT" }, "node_modules/multiformats": { - "version": "10.0.2", - "license": "Apache-2.0 OR MIT", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-11.0.1.tgz", + "integrity": "sha512-atWruyH34YiknSdL5yeIir00EDlJRpHzELYQxG7Iy29eCyL+VrZHpPrX5yqlik3jnuqpLpRKVZ0SGVb9UzKaSA==", "engines": { "node": ">=16.0.0", "npm": ">=7.0.0" @@ -16616,6 +16722,15 @@ "npm": ">=7.0.0" } }, + "node_modules/uint8arrays/node_modules/multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "dev": true, @@ -17150,7 +17265,7 @@ "@ipld/car": "^5.0.1", "@ipld/dag-pb": "^3.0.0", "ava": "^4.3.3", - "multiformats": "^10.0.2", + "multiformats": "^11.0.0", "nanoid": "^4.0.0", "testcontainers": "^8.13.0", "uint8arrays": "^4.0.2" @@ -17165,7 +17280,7 @@ "@ipld/car": "^5.0.1", "@sentry/serverless": "^7.22.0", "cardex": "^1.0.0", - "multiformats": "^10.0.2", + "multiformats": "^11.0.1", "uint8arrays": "^4.0.2" }, "devDependencies": { @@ -17201,15 +17316,15 @@ "@ipld/dag-ucan": "^3.0.1", "@sentry/serverless": "^7.22.0", "@serverless-stack/node": "^1.18.2", - "@ucanto/client": "^4.0.3", - "@ucanto/interface": "^4.0.3", - "@ucanto/principal": "^4.0.3", - "@ucanto/server": "^4.0.3", - "@ucanto/transport": "^4.0.3", + "@ucanto/client": "^4.2.3", + "@ucanto/interface": "^4.2.3", + "@ucanto/principal": "^4.2.3", + "@ucanto/server": "^4.2.3", + "@ucanto/transport": "^4.2.3", "@web-std/fetch": "^4.1.0", "@web3-storage/access": "^9.0.0", "@web3-storage/capabilities": "^2.0.0", - "multiformats": "^10.0.2", + "multiformats": "^11.0.1", "p-retry": "^5.1.2", "uint8arrays": "^4.0.2" }, @@ -22583,12 +22698,25 @@ "dev": true }, "@ipld/car": { - "version": "5.0.1", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ipld/car/-/car-5.1.0.tgz", + "integrity": "sha512-k9pO0YqJvmFGY5pJDhF2Ocz+mRp3C3r4ikr1NrUXkzN/z4JzhE7XbQzUCcm7daq8k4tRqap0fWPjxZwjS9PUcQ==", "requires": { - "@ipld/dag-cbor": "^8.0.0", + "@ipld/dag-cbor": "^9.0.0", "cborg": "^1.9.0", - "multiformats": "^10.0.2", + "multiformats": "^11.0.0", "varint": "^6.0.0" + }, + "dependencies": { + "@ipld/dag-cbor": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-9.0.0.tgz", + "integrity": "sha512-zdsiSiYDEOIDW7mmWOYWC9gukjXO+F8wqxz/LfN7iSwTfIyipC8+UQrCbPupFMRb/33XQTZk8yl3My8vUQBRoA==", + "requires": { + "cborg": "^1.10.0", + "multiformats": "^11.0.0" + } + } } }, "@ipld/dag-cbor": { @@ -22596,13 +22724,22 @@ "requires": { "cborg": "^1.6.0", "multiformats": "^10.0.2" + }, + "dependencies": { + "multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==" + } } }, "@ipld/dag-json": { - "version": "9.0.1", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@ipld/dag-json/-/dag-json-10.0.1.tgz", + "integrity": "sha512-XE1Eqw3eNVrSfOhtqCM/gwCxEgYFBzkDlkwhEeMmMvhd0rLBfSyVzXbahZSlv97tiTPEIx5rt41gcFAda3W8zg==", "requires": { - "cborg": "^1.5.4", - "multiformats": "^10.0.2" + "cborg": "^1.10.0", + "multiformats": "^11.0.0" } }, "@ipld/dag-pb": { @@ -22610,14 +22747,35 @@ "dev": true, "requires": { "multiformats": "^10.0.2" + }, + "dependencies": { + "multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", + "dev": true + } } }, "@ipld/dag-ucan": { - "version": "3.0.1", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@ipld/dag-ucan/-/dag-ucan-3.2.0.tgz", + "integrity": "sha512-CTClaGx4F3iEMJgYaYVOVBEvtNXzPc77Mi6p3vBtylSzDWhbf1Gou9ij7PlblOqWKA1H7XI8fp6yweTb6iXNKQ==", "requires": { - "@ipld/dag-cbor": "^8.0.0", - "@ipld/dag-json": "^9.0.1", - "multiformats": "^10.0.0" + "@ipld/dag-cbor": "^9.0.0", + "@ipld/dag-json": "^10.0.0", + "multiformats": "^11.0.0" + }, + "dependencies": { + "@ipld/dag-cbor": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-9.0.0.tgz", + "integrity": "sha512-zdsiSiYDEOIDW7mmWOYWC9gukjXO+F8wqxz/LfN7iSwTfIyipC8+UQrCbPupFMRb/33XQTZk8yl3My8vUQBRoA==", + "requires": { + "cborg": "^1.10.0", + "multiformats": "^11.0.0" + } + } } }, "@ipld/unixfs": { @@ -22659,6 +22817,12 @@ "requires": { "web-streams-polyfill": "^3.1.1" } + }, + "multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", + "dev": true } } }, @@ -23270,79 +23434,101 @@ } }, "@ucanto/client": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/client/-/client-4.0.3.tgz", - "integrity": "sha512-Kr+6A9VB/m2sFEatEKWzJk7Ccwg7AURdqdFyzhzUGU6YvUe4Z/wcly+yz1hswHmGc77dVPo+b19k2U/jjwnSKA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/client/-/client-4.2.3.tgz", + "integrity": "sha512-vIa0drEAeolQpSePpHtsW1bx8lzDdxtXi2fEdQ4f34xbI2VSOQuAgUURJTtRVmRXa5MweQoEGI9CHPKL4CMyFQ==", "requires": { - "@ucanto/interface": "^4.0.3", - "multiformats": "^10.0.2" + "@ucanto/interface": "^4.1.0", + "multiformats": "^11.0.0" } }, "@ucanto/core": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/core/-/core-4.0.3.tgz", - "integrity": "sha512-5Uc6vdmKZzlA9NFvAN6BC1Tp1Npz0sepp2up1ZWU4BqArQ0w4U0YMtL9KPdBnL3TDAyDNgS9PgK+vHpjcSoeiQ==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/core/-/core-4.2.3.tgz", + "integrity": "sha512-udvp7IMRCE3XFhPYiKISt52r8QjbrqG7d1papdtWwF6RAzTbIWhgXSwAjEbroYCr/gQst7U8aYsgr4xvG2miUQ==", "requires": { - "@ipld/car": "^5.0.0", - "@ipld/dag-cbor": "^8.0.0", - "@ipld/dag-ucan": "^3.0.1", - "@ucanto/interface": "^4.0.3", - "multiformats": "^10.0.2" + "@ipld/car": "^5.0.3", + "@ipld/dag-cbor": "^9.0.0", + "@ipld/dag-ucan": "^3.2.0", + "@ucanto/interface": "^4.1.0", + "multiformats": "^11.0.0" + }, + "dependencies": { + "@ipld/dag-cbor": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-9.0.0.tgz", + "integrity": "sha512-zdsiSiYDEOIDW7mmWOYWC9gukjXO+F8wqxz/LfN7iSwTfIyipC8+UQrCbPupFMRb/33XQTZk8yl3My8vUQBRoA==", + "requires": { + "cborg": "^1.10.0", + "multiformats": "^11.0.0" + } + } } }, "@ucanto/interface": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/interface/-/interface-4.0.3.tgz", - "integrity": "sha512-ip1ZziMUhi9nFm9jPLEDLs8zX4HleYsuHHITH5w8GjST7chbRz1LBSq43A3nMUgea17cuIp+rr7i4QcOSFgXHw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/interface/-/interface-4.2.3.tgz", + "integrity": "sha512-IoccqMc2/vqaPT6U061ylC138mQ3pLp6coqjXTDmlL9OHmskLcEeQh5Mxe0AYHWMhO1ZuB0LRIysBXk7xoK25Q==", "requires": { - "@ipld/dag-ucan": "^3.0.1", - "multiformats": "^10.0.2" + "@ipld/dag-ucan": "^3.2.0", + "multiformats": "^11.0.0" } }, "@ucanto/principal": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/principal/-/principal-4.0.3.tgz", - "integrity": "sha512-mR9BTkXWDDSFDCf5gminNeDte/jwurohjFJE8oVfGfUnkzSjYwfm4h5GQ47qeze6xgm17SS5pQwipSvCGHfvkg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/principal/-/principal-4.2.3.tgz", + "integrity": "sha512-S02cKaMcIQhxk9uJfUCUb+f98zEEFsC+5BZC6aBoYVCEpXwVZD6+hc9xI0yIQl8zJyQVA3nnUUpLfLynsSox2A==", "requires": { - "@ipld/dag-ucan": "^3.0.1", + "@ipld/dag-ucan": "^3.2.0", "@noble/ed25519": "^1.7.1", - "@ucanto/interface": "^4.0.3", - "multiformats": "^10.0.2", + "@ucanto/interface": "^4.1.0", + "multiformats": "^11.0.0", "one-webcrypto": "^1.0.3" } }, "@ucanto/server": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/server/-/server-4.0.3.tgz", - "integrity": "sha512-4s7XQNrj8O9EVGwYne5zVTKl10S9Cgbea64LJomfSlx5gYf7cQTMpOaRCNudi91rutOxDzEtQAVCc2vb1WWrbw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/server/-/server-4.2.3.tgz", + "integrity": "sha512-lmDC0d9mVGYfiqwzpiTG6CFZpGVw1GnFx9EOtozKPa+v2nzwqDAkwYAQwNrJ2nbJWQQeFi7/Jiaec9EmdPEpsg==", "requires": { - "@ucanto/core": "^4.0.3", - "@ucanto/interface": "^4.0.3", - "@ucanto/validator": "^4.0.3" + "@ucanto/core": "^4.1.0", + "@ucanto/interface": "^4.1.0", + "@ucanto/validator": "^4.1.0" } }, "@ucanto/transport": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/transport/-/transport-4.0.3.tgz", - "integrity": "sha512-yrJoqoxmMCpPElR+iEb2AKIjUEmM+JGCcM1TZLXVbMlzaAt6ndYDMPajfnh3PBQMk7edIodZi+UxCLKvc8yelg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/transport/-/transport-4.2.3.tgz", + "integrity": "sha512-ZtHB5ybSB/1dBLhzJqjxGDEE+TTTNzc9HMrVA1AP5KHvaHPu2UtAmS2IMr+HrhSjcwWwdavK0qMQbXSfLWM+kg==", "requires": { - "@ipld/car": "^5.0.0", - "@ipld/dag-cbor": "^8.0.0", - "@ucanto/core": "^4.0.3", - "@ucanto/interface": "^4.0.3", - "multiformats": "^10.0.2" + "@ipld/car": "^5.0.3", + "@ipld/dag-cbor": "^9.0.0", + "@ucanto/core": "^4.1.0", + "@ucanto/interface": "^4.1.0", + "multiformats": "^11.0.0" + }, + "dependencies": { + "@ipld/dag-cbor": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-9.0.0.tgz", + "integrity": "sha512-zdsiSiYDEOIDW7mmWOYWC9gukjXO+F8wqxz/LfN7iSwTfIyipC8+UQrCbPupFMRb/33XQTZk8yl3My8vUQBRoA==", + "requires": { + "cborg": "^1.10.0", + "multiformats": "^11.0.0" + } + } } }, "@ucanto/validator": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@ucanto/validator/-/validator-4.0.3.tgz", - "integrity": "sha512-GLsOIq4R7ixu4D1NMNEJZhOelLPIpd/qtTyOjpxqrrSfsDfOoCsHkSxBy0gTwS/4ZIFMM5sa2LBPJw+ZXobgzw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@ucanto/validator/-/validator-4.2.3.tgz", + "integrity": "sha512-7lA9PK+c0Hu857eHuZIVX3ZBooqvOT25/CXUxGjqs5YFCY7dUhrNCxJYnWsPZnEdriq6x6VSj8pZPwN8I7CyQw==", "requires": { - "@ipld/car": "^5.0.0", + "@ipld/car": "^5.0.3", "@ipld/dag-cbor": "^8.0.0", - "@ucanto/core": "^4.0.3", - "@ucanto/interface": "^4.0.3", - "multiformats": "^10.0.2" + "@ucanto/core": "^4.1.0", + "@ucanto/interface": "^4.1.0", + "multiformats": "^11.0.0" } }, "@web-std/blob": { @@ -23420,21 +23606,26 @@ "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.22.0.tgz", "integrity": "sha512-ZE3qWtnqLOalodzfK5QUEcm7AEulhxsPNuKaGFsC3XiqO92vMLm+mAHk/NnbSIOtC4RmGm0nsv700i8KDp1gfQ==" }, + "multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==" + }, "type-fest": { "version": "3.3.0" } } }, "@web3-storage/capabilities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@web3-storage/capabilities/-/capabilities-2.1.0.tgz", - "integrity": "sha512-6rbcushGhbaeHC38iTEW8t6QapJutfDxLoKPEVMHTJYUGfKE/bL7M7VYXws6Vdp1XCFaLbLv88OSIR/nq9M9lg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@web3-storage/capabilities/-/capabilities-2.3.0.tgz", + "integrity": "sha512-+vg61eqK1eqQ+QD1hvChDDx6CXLGFnUsEA+W+g9yagCpq+H9yAqROncEEt+oluIGvAqNbFMrUb+bWRWxk0Tmuw==", "requires": { - "@ucanto/core": "^4.0.2", - "@ucanto/interface": "^4.0.2", - "@ucanto/principal": "^4.0.2", - "@ucanto/transport": "^4.0.2", - "@ucanto/validator": "^4.0.2" + "@ucanto/core": "^4.2.3", + "@ucanto/interface": "^4.2.3", + "@ucanto/principal": "^4.2.3", + "@ucanto/transport": "^4.2.3", + "@ucanto/validator": "^4.2.3" } }, "@web3-storage/multipart-parser": { @@ -23456,6 +23647,14 @@ "multiformats": "^10.0.2", "p-queue": "^7.3.0", "p-retry": "^5.1.2" + }, + "dependencies": { + "multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==", + "dev": true + } } }, "@web3-storage/w3infra-carpark": { @@ -23479,7 +23678,7 @@ "@ipld/dag-pb": "^3.0.0", "@sentry/serverless": "^7.22.0", "ava": "^4.3.3", - "multiformats": "^10.0.2", + "multiformats": "^11.0.0", "nanoid": "^4.0.0", "testcontainers": "^8.13.0", "uint8arrays": "^4.0.2" @@ -23496,7 +23695,7 @@ "@serverless-stack/resources": "*", "ava": "^4.3.3", "cardex": "^1.0.0", - "multiformats": "^10.0.2", + "multiformats": "^11.0.1", "nanoid": "^4.0.0", "testcontainers": "^8.13.0", "uint8arrays": "^4.0.2" @@ -23526,18 +23725,18 @@ "@serverless-stack/node": "^1.18.2", "@serverless-stack/resources": "*", "@types/aws-lambda": "^8.10.108", - "@ucanto/client": "^4.0.3", + "@ucanto/client": "^4.2.3", "@ucanto/core": "^4.0.2", - "@ucanto/interface": "^4.0.3", - "@ucanto/principal": "^4.0.3", - "@ucanto/server": "^4.0.3", - "@ucanto/transport": "^4.0.3", + "@ucanto/interface": "^4.2.3", + "@ucanto/principal": "^4.2.3", + "@ucanto/server": "^4.2.3", + "@ucanto/transport": "^4.2.3", "@web-std/blob": "3.0.4", "@web-std/fetch": "^4.1.0", "@web3-storage/access": "^9.0.0", "@web3-storage/capabilities": "^2.0.0", "ava": "^4.3.3", - "multiformats": "^10.0.2", + "multiformats": "^11.0.1", "nanoid": "^4.0.0", "p-retry": "^5.1.2", "testcontainers": "^8.13.0", @@ -23545,9 +23744,9 @@ } }, "@web3-storage/w3up-client": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@web3-storage/w3up-client/-/w3up-client-4.0.1.tgz", - "integrity": "sha512-8UEkZ6BWhOOlZ/FezV+GAW+T826iqELCgMW0Dhtt36jqxiuXYWVJb/ONsaSXlr3ZGw02BPvH3O5mG6BjDKWRAw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@web3-storage/w3up-client/-/w3up-client-4.1.0.tgz", + "integrity": "sha512-ekLo576uFJHYpWG3QXJETydV/Xq+GniouVDN1S6ND5QSBmb/TBRbEnzplohqwLztvlPSrkd1/VL+t+IDuosubQ==", "dev": true, "requires": { "@ipld/dag-ucan": "^3.0.1", @@ -23558,7 +23757,7 @@ "@ucanto/transport": "^4.0.2", "@web3-storage/access": "^9.1.1", "@web3-storage/capabilities": "^2.0.0", - "@web3-storage/upload-client": "^5.2.0" + "@web3-storage/upload-client": "^5.3.0" } }, "@zxing/text-encoding": { @@ -24461,7 +24660,9 @@ } }, "cborg": { - "version": "1.9.6" + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/cborg/-/cborg-1.10.0.tgz", + "integrity": "sha512-/eM0JCaL99HDHxjySNQJLaolZFVdl6VA0/hEKIoiQPcQzE5LrG5QHdml0HaBt31brgB9dNe1zMr3f8IVrpotRQ==" }, "chalk": { "version": "4.1.2", @@ -26961,7 +27162,9 @@ "dev": true }, "multiformats": { - "version": "10.0.2" + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-11.0.1.tgz", + "integrity": "sha512-atWruyH34YiknSdL5yeIir00EDlJRpHzELYQxG7Iy29eCyL+VrZHpPrX5yqlik3jnuqpLpRKVZ0SGVb9UzKaSA==" }, "mute-stream": { "version": "0.0.8" @@ -28510,6 +28713,13 @@ "version": "4.0.2", "requires": { "multiformats": "^10.0.0" + }, + "dependencies": { + "multiformats": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-10.0.3.tgz", + "integrity": "sha512-K2yGSmstS/oEmYiEIieHb53jJCaqp4ERPDQAYrm5sV3UUrVDZeshJQCK6GHAKyIGufU1vAcbS0PdAAZmC7Tzcw==" + } } }, "unbox-primitive": { diff --git a/package.json b/package.json index 34e324ec..2758c2d2 100644 --- a/package.json +++ b/package.json @@ -21,21 +21,22 @@ "@serverless-stack/resources": "^1.18.0", "@tsconfig/node16": "^1.0.3", "@types/git-rev-sync": "^2.0.0", - "@ucanto/core": "^4.0.3", - "@ucanto/client": "^4.0.3", - "@ucanto/principal": "^4.0.3", - "@ucanto/transport": "^4.0.3", - "@web3-storage/access": "^9.2.0", - "@web3-storage/w3up-client": "^4.0.1", + "@ucanto/client": "^4.2.3", + "@ucanto/core": "^4.2.3", + "@ucanto/principal": "^4.2.3", + "@ucanto/transport": "^4.2.3", "@web-std/blob": "^3.0.4", "@web-std/fetch": "^4.1.0", + "@web3-storage/access": "^9.2.0", + "@web3-storage/w3up-client": "^4.1.0", "ava": "^4.3.3", "dotenv": "^16.0.3", "git-rev-sync": "^3.0.2", "hd-scripts": "^3.0.2", "lint-staged": "^13.0.3", "p-wait-for": "^5.0.0", - "typescript": "^4.9.3" + "typescript": "^4.9.3", + "multiformats": "^11.0.1" }, "dependencies": { "@serverless-stack/node": "^1.18.0", diff --git a/replicator/package.json b/replicator/package.json index da24d49b..be8e7f18 100644 --- a/replicator/package.json +++ b/replicator/package.json @@ -13,7 +13,7 @@ "@ipld/car": "^5.0.1", "@ipld/dag-pb": "^3.0.0", "ava": "^4.3.3", - "multiformats": "^10.0.2", + "multiformats": "^11.0.0", "nanoid": "^4.0.0", "testcontainers": "^8.13.0", "uint8arrays": "^4.0.2" diff --git a/satnav/package.json b/satnav/package.json index cac762c8..625675c4 100644 --- a/satnav/package.json +++ b/satnav/package.json @@ -11,7 +11,7 @@ "@sentry/serverless": "^7.22.0", "@ipld/car": "^5.0.1", "cardex": "^1.0.0", - "multiformats": "^10.0.2", + "multiformats": "^11.0.1", "uint8arrays": "^4.0.2" }, "devDependencies": { diff --git a/upload-api/package.json b/upload-api/package.json index 6472fea2..043c88c7 100644 --- a/upload-api/package.json +++ b/upload-api/package.json @@ -14,15 +14,15 @@ "@ipld/dag-ucan": "^3.0.1", "@sentry/serverless": "^7.22.0", "@serverless-stack/node": "^1.18.2", - "@ucanto/client": "^4.0.3", - "@ucanto/interface": "^4.0.3", - "@ucanto/principal": "^4.0.3", - "@ucanto/server": "^4.0.3", - "@ucanto/transport": "^4.0.3", + "@ucanto/client": "^4.2.3", + "@ucanto/interface": "^4.2.3", + "@ucanto/principal": "^4.2.3", + "@ucanto/server": "^4.2.3", + "@ucanto/transport": "^4.2.3", "@web-std/fetch": "^4.1.0", "@web3-storage/access": "^9.0.0", "@web3-storage/capabilities": "^2.0.0", - "multiformats": "^10.0.2", + "multiformats": "^11.0.1", "p-retry": "^5.1.2", "uint8arrays": "^4.0.2" }, diff --git a/upload-api/service/store/list.js b/upload-api/service/store/list.js index 4efcaf95..c798f429 100644 --- a/upload-api/service/store/list.js +++ b/upload-api/service/store/list.js @@ -17,12 +17,13 @@ export function storeListProvider(context) { return Server.provide( Store.list, async ({ capability }) => { - const { cursor, size } = capability.nb + const { cursor, size, pre } = capability.nb const space = Server.DID.parse(capability.with).did() return await context.storeTable.list(space, { size, - cursor + cursor, + pre }) } ) diff --git a/upload-api/service/types.ts b/upload-api/service/types.ts index 1db96c01..2befc261 100644 --- a/upload-api/service/types.ts +++ b/upload-api/service/types.ts @@ -116,11 +116,15 @@ export interface UploadListItem extends UploadAddResult { export interface ListOptions { size?: number, - cursor?: string + cursor?: string, + pre?: boolean } export interface ListResponse { + // cursor is deprecated in favor of endCursor and will be removed in a future version cursor?: string, + startCursor?: string, + endCursor?: string, size: number, results: R[] } diff --git a/upload-api/service/upload/list.js b/upload-api/service/upload/list.js index 607be4af..f9b6ce5a 100644 --- a/upload-api/service/upload/list.js +++ b/upload-api/service/upload/list.js @@ -16,12 +16,13 @@ export function uploadListProvider(context) { return Server.provide( Upload.list, async ({ capability }) => { - const { cursor, size } = capability.nb + const { cursor, size, pre } = capability.nb const space = Server.DID.parse(capability.with).did() return await context.uploadTable.list(space, { size, - cursor + cursor, + pre }) }) } diff --git a/upload-api/tables/store.js b/upload-api/tables/store.js index 709909c9..46a9326e 100644 --- a/upload-api/tables/store.js +++ b/upload-api/tables/store.js @@ -119,20 +119,25 @@ export function createStoreTable (region, tableName, options = {}) { AttributeValueList: [{ S: space }], }, }, + ScanIndexForward: ! options.pre, ExclusiveStartKey: exclusiveStartKey, AttributesToGet: ['link', 'size', 'origin', 'insertedAt'], }) const response = await dynamoDb.send(cmd) const results = response.Items?.map(i => toStoreListResult(unmarshall(i))) ?? [] + const startCursor = results[0] ? results[0].link.toString() : undefined // Get cursor of the item where list operation stopped (inclusive). // This value can be used to start a new operation to continue listing. const lastKey = response.LastEvaluatedKey && unmarshall(response.LastEvaluatedKey) - const cursor = lastKey ? lastKey.link : undefined + const endCursor = lastKey ? lastKey.link : undefined return { size: results.length, - cursor, + // cursor is deprecated and will be removed in a future version + cursor: endCursor, + startCursor, + endCursor, results } } diff --git a/upload-api/tables/upload.js b/upload-api/tables/upload.js index 8a3f3338..aaea605b 100644 --- a/upload-api/tables/upload.js +++ b/upload-api/tables/upload.js @@ -143,6 +143,7 @@ export function createUploadTable (region, tableName, options = {}) { AttributeValueList: [{ S: space }], }, }, + ScanIndexForward: ! options.pre, ExclusiveStartKey: exclusiveStartKey, AttributesToGet: ['space', 'root', 'shards', 'insertedAt', 'updatedAt'], }) @@ -150,16 +151,20 @@ export function createUploadTable (region, tableName, options = {}) { /** @type {UploadListItem[]} */ const results = response.Items?.map(i => toUploadListItem(unmarshall(i))) || [] + const startCursor = results[0] ? results[0].root.toString() : undefined // Get cursor of the item where list operation stopped (inclusive). // This value can be used to start a new operation to continue listing. const lastKey = response.LastEvaluatedKey && unmarshall(response.LastEvaluatedKey) - const cursor = lastKey ? lastKey.root : undefined + const endCursor = lastKey ? lastKey.root : undefined return { size: results.length, - results, - cursor + // cursor is deprecated and will be removed in a future version + cursor: endCursor, + startCursor, + endCursor, + results } }, } diff --git a/upload-api/test/helpers/random.js b/upload-api/test/helpers/random.js index d5111434..283e4cf2 100644 --- a/upload-api/test/helpers/random.js +++ b/upload-api/test/helpers/random.js @@ -1,6 +1,5 @@ import { webcrypto } from 'crypto' import { Blob } from '@web-std/blob' - import { CarWriter } from '@ipld/car' import { CID } from 'multiformats/cid' import * as raw from 'multiformats/codecs/raw' diff --git a/upload-api/test/service/store.test.js b/upload-api/test/service/store.test.js index 7f0c9ef2..22d3e122 100644 --- a/upload-api/test/service/store.test.js +++ b/upload-api/test/service/store.test.js @@ -89,7 +89,7 @@ test('store/add returns signed url for uploading', async (t) => { nb: { link, size }, proofs: [proof] }) - + // invoke a store/add with proof const storeAdd = await invocation.execute(connection) @@ -146,7 +146,7 @@ test('store/add should create a presigned url that can only PUT a payload with t tableName, bucketName }) - + const data = new Uint8Array([11, 22, 34, 44, 55]) const longer = new Uint8Array([11, 22, 34, 44, 55, 66]) const link = await CAR.codec.link(data) @@ -159,7 +159,7 @@ test('store/add should create a presigned url that can only PUT a payload with t nb: { link, size }, proofs: [proof] }).execute(connection) - + if (storeAdd.error) { throw new Error('invocation failed', { cause: storeAdd }) } @@ -192,7 +192,7 @@ test('store/add should create a presigned url that can only PUT the exact bytes tableName, bucketName }) - + const data = new Uint8Array([11, 22, 34, 44, 55]) const other = new Uint8Array([10, 22, 34, 44, 55]) const link = await CAR.codec.link(data) @@ -205,7 +205,7 @@ test('store/add should create a presigned url that can only PUT the exact bytes nb: { link, size }, proofs: [proof] }).execute(connection) - + if (storeAdd.error) { throw new Error('invocation failed', { cause: storeAdd }) } @@ -214,7 +214,7 @@ test('store/add should create a presigned url that can only PUT the exact bytes if (!url) { throw new Error('Expected presigned url in response') } - + const failChecksum = await fetch(url, { method: 'PUT', mode: 'cors', @@ -255,7 +255,7 @@ test('store/add returns done if already uploaded', async (t) => { nb: { link, size: data.byteLength }, proofs: [proof] }) - + const storeAdd = await storeAddInvocation.execute(connection) if (storeAdd.error) { @@ -365,7 +365,7 @@ test('store/add fails when size to large to PUT', async (t) => { tableName, bucketName }) - + const data = new Uint8Array([11, 22, 34, 44, 55]) const link = await CAR.codec.link(data) const size = MAX_S3_PUT_SIZE + 1 @@ -484,12 +484,12 @@ test('store/list does not fail for empty list', async (t) => { tableName, bucketName }) - + const storeList = await StoreCapabilities.list.invoke({ issuer: alice, audience: uploadService, with: spaceDid, - proofs: [ proof ], + proofs: [proof], nb: {} }).execute(connection) @@ -508,14 +508,14 @@ test('store/list returns items previously stored by the user', async (t) => { bucketName }) - const data = [ new Uint8Array([11, 22, 34, 44, 55]), new Uint8Array([22, 34, 44, 55, 66]) ] + const data = [new Uint8Array([11, 22, 34, 44, 55]), new Uint8Array([22, 34, 44, 55, 66])] const links = [] for (const datum of data) { const storeAdd = await StoreCapabilities.add.invoke({ issuer: alice, audience: uploadService, with: spaceDid, - nb: { link: await CAR.codec.link(datum) , size: datum.byteLength }, + nb: { link: await CAR.codec.link(datum), size: datum.byteLength }, proofs: [proof] }).execute(connection) if (storeAdd.error) { @@ -530,7 +530,7 @@ test('store/list returns items previously stored by the user', async (t) => { issuer: alice, audience: uploadService, with: spaceDid, - proofs: [ proof ], + proofs: [proof], nb: {} }).execute(connection) @@ -561,7 +561,7 @@ test('store/list can be paginated with custom size', async (t) => { bucketName }) - const data = [ new Uint8Array([11, 22, 34, 44, 55]), new Uint8Array([22, 34, 44, 55, 66]) ] + const data = [new Uint8Array([11, 22, 34, 44, 55]), new Uint8Array([22, 34, 44, 55, 66])] const links = [] for (const datum of data) { @@ -569,7 +569,7 @@ test('store/list can be paginated with custom size', async (t) => { issuer: alice, audience: uploadService, with: spaceDid, - nb: { link: await CAR.codec.link(datum) , size: datum.byteLength }, + nb: { link: await CAR.codec.link(datum), size: datum.byteLength }, proofs: [proof] }).execute(connection) if (storeAdd.error) { @@ -590,7 +590,7 @@ test('store/list can be paginated with custom size', async (t) => { issuer: alice, audience: uploadService, with: spaceDid, - proofs: [ proof ], + proofs: [proof], nb: { size, cursor @@ -600,8 +600,8 @@ test('store/list can be paginated with custom size', async (t) => { if (storeList.error) { throw new Error('invocation failed', { cause: storeList }) } - - cursor = storeList.cursor + + cursor = storeList.endCursor // Add page if it has size storeList.size && listPages.push(storeList.results) } while (cursor) @@ -619,12 +619,86 @@ test('store/list can be paginated with custom size', async (t) => { } }) +test('store/list can page backwards', async (t) => { + const { tableName, bucketName } = await prepareResources(t.context.dynamoClient, t.context.s3Client) + + const uploadService = await Signer.generate() + const alice = await Signer.generate() + const { proof, spaceDid } = await createSpace(alice) + const connection = await getClientConnection(uploadService, { + ...t.context, + tableName, + bucketName + }) + + const data = [new Uint8Array([11, 22, 34, 44, 55]), new Uint8Array([22, 34, 44, 55, 66]), new Uint8Array([33, 44, 55, 66, 77])] + const links = [] + + for (const datum of data) { + const storeAdd = await StoreCapabilities.add.invoke({ + issuer: alice, + audience: uploadService, + with: spaceDid, + nb: { link: await CAR.codec.link(datum), size: datum.byteLength }, + proofs: [proof] + }).execute(connection) + if (storeAdd.error) { + throw new Error('invocation failed', { cause: storeAdd }) + } + + links.push(storeAdd.link) + } + + const size = 3 + let cursor + + /** @type {Server.Result} */ + const listResponse = await StoreCapabilities.list.invoke({ + issuer: alice, + audience: uploadService, + with: spaceDid, + proofs: [proof], + nb: { + size, + cursor + } + }).execute(connection) + + if (listResponse.error) { + throw new Error('invocation failed', { cause: listResponse.error }) + } + + /** @type {Server.Result} */ + const reverseListResponse = await StoreCapabilities.list.invoke({ + issuer: alice, + audience: uploadService, + with: spaceDid, + proofs: [proof], + nb: { + size, + cursor: listResponse.endCursor, + pre: true + } + }).execute(connection) + + if (reverseListResponse.error) { + throw new Error('invocation failed', { cause: reverseListResponse.error }) + } + + t.is(listResponse.results.length, 3) + // we initially listed forward and got 3 results. we then used the "end cursor" of that list and listed backwards, + // which means the first result of the reverse list response should be the middle result of the inital response + // and the second result of the reverse list should be the first result of the initial response + t.like(reverseListResponse.results[0], listResponse.results[1]) + t.like(reverseListResponse.results[1], listResponse.results[0]) +}) + /** * @param {import("@aws-sdk/client-dynamodb").DynamoDBClient} dynamoClient * @param {import("@aws-sdk/client-s3").S3Client} s3Client */ -async function prepareResources (dynamoClient, s3Client) { - const [ tableName, bucketName ] = await Promise.all([ +async function prepareResources(dynamoClient, s3Client) { + const [tableName, bucketName] = await Promise.all([ createDynamoStoreTable(dynamoClient), createBucket(s3Client) ]) diff --git a/upload-api/test/service/ucan-invocation.test.js b/upload-api/test/service/ucan-invocation.test.js index f5a39a52..8793d5dd 100644 --- a/upload-api/test/service/ucan-invocation.test.js +++ b/upload-api/test/service/ucan-invocation.test.js @@ -4,6 +4,7 @@ import { GetObjectCommand } from '@aws-sdk/client-s3' import * as Signer from '@ucanto/principal/ed25519' import { CAR } from '@ucanto/transport' import * as UCAN from '@ipld/dag-ucan' +import * as ucanto from '@ucanto/core'; import { createSpace } from '../helpers/ucanto.js' import { createS3, createBucket } from '../helpers/resources.js' @@ -30,7 +31,7 @@ test('parses ucan invocation request', async t => { const can = 'store/add' const request = await CAR.encode([ - { + await ucanto.delegate({ issuer: alice, audience: uploadService, capabilities: [{ @@ -39,7 +40,7 @@ test('parses ucan invocation request', async t => { nb }], proofs: [proof], - } + }) ]) // @ts-expect-error different type interface in AWS expected request @@ -81,7 +82,7 @@ test('persists ucan invocation CAR file', async t => { const can = 'store/add' const request = await CAR.encode([ - { + await ucanto.delegate({ issuer: alice, audience: uploadService, capabilities: [{ @@ -90,7 +91,7 @@ test('persists ucan invocation CAR file', async t => { nb }], proofs: [proof], - } + }) ]) // @ts-expect-error different type interface in AWS expected request diff --git a/upload-api/test/service/upload.test.js b/upload-api/test/service/upload.test.js index 04850883..3e53cb4b 100644 --- a/upload-api/test/service/upload.test.js +++ b/upload-api/test/service/upload.test.js @@ -21,7 +21,7 @@ const BATCH_MAX_SAFE_LIMIT = 25 * @typedef {import('../../service/types').ListResponse} ListResponse */ - test.before(async t => { +test.before(async t => { // Dynamo DB const { client: dynamo, @@ -343,7 +343,7 @@ test('upload/remove removes an upload', async (t) => { issuer: alice, audience: uploadService, with: spaceDid, - nb: { root: car.roots[0], shards: [ car.cid ] }, + nb: { root: car.roots[0], shards: [car.cid] }, proofs: [proof] }).execute(connection) if (uploadAdd.error) { @@ -501,7 +501,7 @@ test('upload/remove removes all entries when larger than batch limit', async (t) if (uploadAdd.error) { throw new Error('invocation failed', { cause: uploadAdd }) } - + t.is(uploadAdd.shards?.length, shards.length) // Validate DB before remove @@ -533,12 +533,12 @@ test('upload/list does not fail for empty list', async (t) => { tableName, bucketName }) - + const uploadList = await UploadCapabilities.list.invoke({ issuer: alice, audience: uploadService, with: spaceDid, - proofs: [ proof ], + proofs: [proof], nb: {} }).execute(connection) @@ -577,7 +577,7 @@ test('upload/list returns entries previously uploaded by the user', async (t) => issuer: alice, audience: uploadService, with: spaceDid, - proofs: [ proof ], + proofs: [proof], nb: {} }).execute(connection) if (uploadList.error) { @@ -585,7 +585,7 @@ test('upload/list returns entries previously uploaded by the user', async (t) => } t.is(uploadList.size, cars.length) - + for (const car of cars) { const root = car.roots[0] const item = uploadList.results.find((x) => x.root.toString() === root.toString()) @@ -634,7 +634,7 @@ test('upload/list can be paginated with custom size', async (t) => { issuer: alice, audience: uploadService, with: spaceDid, - proofs: [ proof ], + proofs: [proof], nb: { size, cursor @@ -644,7 +644,7 @@ test('upload/list can be paginated with custom size', async (t) => { if (uploadList.error) { throw new Error('invocation failed', { cause: uploadList }) } - + cursor = uploadList.cursor // Add page if it has size uploadList.size && listPages.push(uploadList.results) @@ -655,10 +655,81 @@ test('upload/list can be paginated with custom size', async (t) => { // Inspect content const uploadList = listPages.flat() for (const entry of uploadList) { - t.truthy(cars.find(car => car.roots[0].toString() === entry.root.toString() )) + t.truthy(cars.find(car => car.roots[0].toString() === entry.root.toString())) } }) +test('upload/list can page backwards', async (t) => { + const { tableName, bucketName } = await prepareResources(t.context.dynamoClient, t.context.s3Client) + + const uploadService = await Signer.generate() + const alice = await Signer.generate() + const { proof, spaceDid } = await createSpace(alice) + const connection = await getClientConnection(uploadService, { + ...t.context, + tableName, + bucketName + }) + + // invoke multiple upload/add with proof + const cars = [ + await randomCAR(128), + await randomCAR(128), + await randomCAR(128) + ] + + for (const car of cars) { + await UploadCapabilities.add.invoke({ + issuer: alice, + audience: uploadService, + with: spaceDid, + nb: { root: car.roots[0], shards: [car.cid] }, + proofs: [proof] + }).execute(connection) + } + + const size = 3 + + /** @type {import('@ucanto/server').Result} */ + const listResponse = await UploadCapabilities.list.invoke({ + issuer: alice, + audience: uploadService, + with: spaceDid, + proofs: [proof], + nb: { + size + } + }).execute(connection) + + if (listResponse.error) { + throw new Error('invocation failed', { cause: listResponse.error }) + } + + /** @type {import('@ucanto/server').Result} */ + const reverseListResponse = await UploadCapabilities.list.invoke({ + issuer: alice, + audience: uploadService, + with: spaceDid, + proofs: [proof], + nb: { + size, + cursor: listResponse.endCursor, + pre: true + } + }).execute(connection) + + if (reverseListResponse.error) { + throw new Error('invocation failed', { cause: reverseListResponse.error }) + } + + t.is(listResponse.results.length, 3) + // we initially listed forward and got 3 results. we then used the "end cursor" of that list and listed backwards, + // which means the first result of the reverse list response should be the middle result of the inital response + // and the second result of the reverse list should be the first result of the initial response + t.like(reverseListResponse.results[0], listResponse.results[1]) + t.like(reverseListResponse.results[1], listResponse.results[0]) +}) + test('can invoke when serviceSigner has a did:web did', async (t) => { const serviceDid = DID.parse('did:web:example.com') const serviceKeySigner = (await Signer.generate()) @@ -691,7 +762,7 @@ test('can invoke when serviceSigner has a did:web did', async (t) => { t.not(resultOfInvocationWithWrongAudience, undefined, 'result is not undefined - it should be an error') if (resultOfInvocationWithWrongAudience?.error) { t.is(resultOfInvocationWithWrongAudience.name, 'InvalidAudience', 'result of sending invocation with wrong audience is InvalidAudience') - t.is(/** @type {import('@ucanto/server').InvalidAudience} */ (resultOfInvocationWithWrongAudience).audience?.toString(), serviceDid.did()) + t.is(/** @type {import('@ucanto/server').InvalidAudience} */(resultOfInvocationWithWrongAudience).audience?.toString(), serviceDid.did()) } }) @@ -721,8 +792,8 @@ async function createNoopRemoveInovocation(options) { * @param {import("@aws-sdk/client-dynamodb").DynamoDBClient} dynamoClient * @param {import("@aws-sdk/client-s3").S3Client} s3Client */ -async function prepareResources (dynamoClient, s3Client) { - const [ tableName, bucketName ] = await Promise.all([ +async function prepareResources(dynamoClient, s3Client) { + const [tableName, bucketName] = await Promise.all([ createDynamoUploadTable(dynamoClient), createBucket(s3Client) ]) @@ -736,7 +807,7 @@ async function prepareResources (dynamoClient, s3Client) { /** * @param {import("@aws-sdk/client-dynamodb").DynamoDBClient} dynamo */ - async function createDynamoUploadTable(dynamo) { +async function createDynamoUploadTable(dynamo) { const id = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz', 10) const tableName = id() @@ -759,7 +830,7 @@ async function prepareResources (dynamoClient, s3Client) { * @param {object} [options] * @param {number} [options.limit] */ - async function getUploadsForSpace(dynamo, tableName, spaceDid, options = {}) { +async function getUploadsForSpace(dynamo, tableName, spaceDid, options = {}) { const cmd = new QueryCommand({ TableName: tableName, Limit: options.limit || 30, @@ -783,7 +854,7 @@ async function prepareResources (dynamoClient, s3Client) { * @param {string} bucketName * @param {string} dataCid */ -async function getMappingItemsForUpload (s3Client, bucketName, dataCid) { +async function getMappingItemsForUpload(s3Client, bucketName, dataCid) { const listCmd = new ListObjectsV2Command({ Bucket: bucketName, Prefix: dataCid