Skip to content

Commit

Permalink
feat: upgrade deps for blob (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos authored Jun 3, 2024
1 parent 0de22d2 commit 7f52cc0
Show file tree
Hide file tree
Showing 12 changed files with 669 additions and 323 deletions.
43 changes: 25 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@ w3 up recipies.txt
- UCAN-HTTP Bridge
- [`w3 bridge generate-tokens`](#w3-bridge-generate-tokens)
- Advanced usage
- [`w3 can blob add`](#w3-can-blob-add-path)
- [`w3 can blob ls`](#w3-can-blob-ls)
- [`w3 can blob rm`](#w3-can-blob-rm-multihash)
- [`w3 can index add`](#w3-can-index-add-cid)
- [`w3 can space info`](#w3-can-space-info-did) <sup>coming soon!</sup>
- [`w3 can space recover`](#w3-can-space-recover-email) <sup>coming soon!</sup>
- [`w3 can store add`](#w3-can-store-add-car-path)
- [`w3 can store ls`](#w3-can-store-ls)
- [`w3 can store rm`](#w3-can-store-rm-car-cid)
- [`w3 can upload add`](#w3-can-upload-add-root-cid-shard-cid-shard-cid)
- [`w3 can upload ls`](#w3-can-upload-ls)
- [`w3 can upload rm`](#w3-can-upload-rm-root-cid)
Expand Down Expand Up @@ -154,8 +155,15 @@ Create a delegation to the passed audience for the given abilities with the _cur
# delegate space/info to did:key:z6M..., output as a CAR
w3 delegation create did:key:z6M... --can space/info --output ./info.ucan

# delegate store/* and upload/* to did:key:z6M..., output as a string
w3 delegation create did:key:z6M... --can 'store/*' --can 'upload/*' --base64
# delegate admin capabilities to did:key:z6M..., output as a string
w3 delegation create did:key:z6M... --can 'space/*' --can 'upload/*' --can 'filecoin/*' --base64

# delegate write (not remove) capabilities to did:key:z6M..., output as a string
w3 delegation create did:key:z6M... \
--can 'space/blob/add' \
--can 'upload/add' \
--can 'filecoin/offer' \
--base64
```

### `w3 delegation ls`
Expand Down Expand Up @@ -197,30 +205,29 @@ on how these are expected to be used.
- `--expiration` Unix timestamp (in seconds) when the delegation is no longer valid. Zero indicates no expiration.
- `--json` If set, output JSON suitable to splat into the `headers` field of a `fetch` request.

### `w3 can space info <did>`

### `w3 can space recover <email>`

### `w3 can store add <car-path>`
### `w3 can blob add [path]`

Store a [CAR](https://ipld.io/specs/transport/car/carv1/) file to web3.storage.
Store a blob file to the service.

### `w3 can store ls`
### `w3 can blob ls`

List CARs in the current space.
List blobs in the current space.

- `--json` Format as newline delimited JSON
- `--size` The desired number of results to return
- `--cursor` An opaque string included in a prior upload/list response that allows the service to provide the next "page" of results
- `--pre` If true, return the page of results preceding the cursor

### `w3 can store rm <shard-cid>`
### `w3 can blob rm <multihash>`

Remove a blob from the store by base58btc encoded multihash.

Remove a CAR from the store.
### `w3 can space info <did>`

### `w3 can space recover <email>`

### `w3 can upload add <root-cid> <shard-cid> [shard-cid...]`

Register an upload - a DAG with the given root data CID that is stored in the given CAR shard(s), identified by CAR CIDs.
Register an upload - a DAG with the given root data CID that is stored in the given shard(s), identified by CID.

### `w3 can upload ls`

Expand All @@ -234,7 +241,7 @@ List uploads in the current space.

### `w3 can upload rm <root-cid>`

Remove an upload from the current space's upload list. Does not remove CAR from the store.
Remove an upload from the current space's upload list. Does not remove blobs from the store.

## Environment Variables

Expand Down
30 changes: 30 additions & 0 deletions bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ import {
reset,
} from './index.js'
import {
blobAdd,
blobList,
blobRemove,
indexAdd,
storeAdd,
storeList,
storeRemove,
Expand Down Expand Up @@ -264,6 +268,32 @@ cli
.describe('Claim delegated capabilities for the authorized account.')
.action(accessClaim)

cli
.command('can blob add [data-path]')
.describe('Store a blob with the service.')
.action(blobAdd)

cli
.command('can blob ls')
.describe('List blobs in the current space.')
.option('--json', 'Format as newline delimited JSON')
.option('--size', 'The desired number of results to return')
.option(
'--cursor',
'An opaque string included in a prior blob/list response that allows the service to provide the next "page" of results'
)
.action(blobList)

cli
.command('can blob rm <multihash>')
.describe('Remove a blob from the store by base58btc encoded multihash.')
.action(blobRemove)

cli
.command('can index add <cid>')
.describe('Register an "index" with the service.')
.action(indexAdd)

cli
.command('can store add <car-path>')
.describe('Store a CAR file with the service.')
Expand Down
107 changes: 100 additions & 7 deletions can.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/* eslint-env browser */
import fs from 'fs'
import { CID } from 'multiformats'
import fs from 'node:fs'
import { Readable } from 'node:stream'
import * as Link from 'multiformats/link'
import * as raw from 'multiformats/codecs/raw'
import { base58btc } from 'multiformats/bases/base58'
import * as Digest from 'multiformats/hashes/digest'
import { Piece } from '@web3-storage/data-segment'
import ora from 'ora'
import {
Expand All @@ -9,8 +13,98 @@ import {
storeListResponseToString,
filecoinInfoToString,
parseCarLink,
streamToBlob,
blobListResponseToString,
} from './lib.js'

/**
* @param {string} [blobPath]
*/
export async function blobAdd(blobPath) {
const client = await getClient()

const spinner = ora('Reading data').start()
/** @type {Blob} */
let blob
try {
blob = await streamToBlob(
/** @type {ReadableStream<Uint8Array>} */
(Readable.toWeb(blobPath ? fs.createReadStream(blobPath) : process.stdin))
)
} catch (/** @type {any} */ err) {
spinner.fail(`Error: failed to read data: ${err.message}`)
process.exit(1)
}

spinner.start('Storing')
const digest = await client.capability.blob.add(blob)
const cid = Link.create(raw.code, digest)
spinner.stopAndPersist({ symbol: '⁂', text: `Stored ${base58btc.encode(digest.bytes)} (${cid})` })
}

/**
* Print out all the blobs in the current space.
*
* @param {object} opts
* @param {boolean} [opts.json]
* @param {string} [opts.cursor]
* @param {number} [opts.size]
*/
export async function blobList(opts = {}) {
const client = await getClient()
const listOptions = {}
if (opts.size) {
listOptions.size = parseInt(String(opts.size))
}
if (opts.cursor) {
listOptions.cursor = opts.cursor
}

const spinner = ora('Listing Blobs').start()
const res = await client.capability.blob.list(listOptions)
spinner.stop()
console.log(blobListResponseToString(res, opts))
}

/**
* @param {string} digestStr
*/
export async function blobRemove(digestStr) {
const spinner = ora(`Removing ${digestStr}`).start()
let digest
try {
digest = Digest.decode(base58btc.decode(digestStr))
} catch {
spinner.fail(`Error: "${digestStr}" is not a base58btc encoded multihash`)
process.exit(1)
}
const client = await getClient()
try {
await client.capability.blob.remove(digest)
spinner.stopAndPersist({ symbol: '⁂', text: `Removed ${digestStr}` })
} catch (/** @type {any} */ err) {
spinner.fail(`Error: blob remove failed: ${err.message ?? err}`)
console.error(err)
process.exit(1)
}
}

/**
* @param {string} cidStr
*/
export async function indexAdd(cidStr) {
const client = await getClient()

const spinner = ora('Adding').start()
const cid = parseCarLink(cidStr)
if (!cid) {
spinner.fail(`Error: "${cidStr}" is not a valid index CID`)
process.exit(1)
}
await client.capability.index.add(cid)
spinner.stopAndPersist({ symbol: '⁂', text: `Added index ${cid}` })
}

/**
* @param {string} carPath
*/
Expand Down Expand Up @@ -73,7 +167,7 @@ export async function storeRemove(cidStr) {
}
const client = await getClient()
try {
client.capability.store.remove(shard)
await client.capability.store.remove(shard)
} catch (/** @type {any} */ err) {
console.error(`Store remove failed: ${err.message ?? err}`)
console.error(err)
Expand All @@ -92,7 +186,7 @@ export async function uploadAdd(root, shard, opts) {

let rootCID
try {
rootCID = CID.parse(root)
rootCID = Link.parse(root)
} catch (/** @type {any} */ err) {
console.error(`Error: failed to parse root CID: ${root}: ${err.message}`)
process.exit(1)
Expand All @@ -102,8 +196,7 @@ export async function uploadAdd(root, shard, opts) {
const shards = []
for (const str of [shard, ...opts._]) {
try {
// @ts-expect-error may not be a CAR CID...
shards.push(CID.parse(str))
shards.push(Link.parse(str))
} catch (/** @type {any} */ err) {
console.error(`Error: failed to parse shard CID: ${str}: ${err.message}`)
process.exit(1)
Expand Down Expand Up @@ -152,7 +245,7 @@ export async function uploadList(opts = {}) {
export async function uploadRemove(rootCid) {
let root
try {
root = CID.parse(rootCid.trim())
root = Link.parse(rootCid.trim())
} catch (/** @type {any} */ err) {
console.error(`Error: ${rootCid} is not a CID`)
process.exit(1)
Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fs from 'fs'
import ora, { oraPromise } from 'ora'
import ora from 'ora'
import { pipeline } from 'node:stream/promises'
import { CID } from 'multiformats/cid'
import { base64 } from 'multiformats/bases/base64'
Expand Down
Loading

0 comments on commit 7f52cc0

Please sign in to comment.