Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement can store ls and can upload ls #45

Merged
merged 17 commits into from
Mar 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 27 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ w3 up recipies.txt
* [`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) <sup>coming soon!</sup>
* [`w3 can store ls`](#w3-can-store-ls)
* [`w3 can store rm`](#w3-can-store-rm-car-cid) <sup>coming soon!</sup>
* [`w3 can upload add`](#w3-can-upload-add-root-cid-shard-cid-shard-cid)
* [`w3 can upload ls`](#w3-can-upload-ls) <sup>coming soon!</sup>
* [`w3 can upload ls`](#w3-can-upload-ls)
* [`w3 can upload rm`](#w3-can-upload-rm-root-cid) <sup>coming soon!</sup>

---
Expand All @@ -68,24 +68,24 @@ w3 up recipies.txt

travis marked this conversation as resolved.
Show resolved Hide resolved
Upload file(s) to web3.storage. The IPFS Content ID (CID) for your files is calculated on your machine, and sent up along with your files. web3.storage makes your content available on the IPFS network

- `--no-wrap` Don't wrap input files with a directory.
- `-H, --hidden` Include paths that start with ".".
- `-c, --car` File is a CAR file.
- `--shard-size` Shard uploads into CAR files of approximately this size in bytes.
- `--concurrent-requests` Send up to this many CAR shards concurrently.
* `--no-wrap` Don't wrap input files with a directory.
* `-H, --hidden` Include paths that start with ".".
* `-c, --car` File is a CAR file.
* `--shard-size` Shard uploads into CAR files of approximately this size in bytes.
* `--concurrent-requests` Send up to this many CAR shards concurrently.

### `w3 ls`

List all the uploads registered in the current space.

- `--json` Format as newline delimted JSON
- `--shards` Pretty print with shards in output
* `--json` Format as newline delimited JSON
* `--shards` Pretty print with shards in output

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

Remove an upload from the uploads listing. Note that this command does not remove the data from the IPFS network, nor does it remove it from space storage (by default).

- `--shards` Also remove all shards referenced by the upload from the store. Use with caution and ensure other uploads do not reference the same shards.
* `--shards` Also remove all shards referenced by the upload from the store. Use with caution and ensure other uploads do not reference the same shards.

### `w3 open <cid>`

Expand Down Expand Up @@ -136,7 +136,7 @@ Create a delegation to the passed audience for the given abilities with the _cur

List delegations created by this agent for others.

- `--json` Format as newline delimted JSON
* `--json` Format as newline delimited JSON

### `w3 proof add <proof.ucan>`

Expand All @@ -146,7 +146,7 @@ Add a proof delegated to this agent. The proof is a CAR encoded delegation to _t

List proofs of delegated capabilities. Proofs are delegations with an audience matching the agent DID.

- `--json` Format as newline delimted JSON
* `--json` Format as newline delimited JSON

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

Expand All @@ -158,6 +158,13 @@ Store a [CAR](https://ipld.io/specs/transport/car/carv1/) file to web3.storage.

### `w3 can store ls`

List CARs in the current space.
travis marked this conversation as resolved.
Show resolved Hide resolved

* `--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 <car-cid>`

### `w3 can upload add <root-cid> <shard-cid> [shard-cid...]`
Expand All @@ -166,6 +173,14 @@ Register an upload - a DAG with the given root data CID that is stored in the gi

### `w3 can upload ls`

List uploads in the current space.

* `--json` Format as newline delimited JSON
* `--shards` Pretty print with shards in output
* `--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 upload rm <root-cid>`

## Contributing
Expand Down
29 changes: 24 additions & 5 deletions bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import {
} from './index.js'
import {
storeAdd,
uploadAdd
storeList,
uploadAdd,
uploadList
} from './can.js'

const cli = sade('w3')
Expand All @@ -46,7 +48,7 @@ cli.command('open <cid>')
cli.command('ls')
.alias('list')
.describe('List uploads in the current space')
.option('--json', 'Format as newline delimted JSON')
.option('--json', 'Format as newline delimited JSON')
.option('--shards', 'Pretty print with shards in output')
.action(list)

Expand Down Expand Up @@ -94,26 +96,43 @@ cli.command('delegation create <audience-did>')

cli.command('delegation ls')
.describe('List delegations created by this agent for others.')
.option('--json', 'Format as newline delimted JSON')
.option('--json', 'Format as newline delimited JSON')
.action(listDelegations)

cli.command('proof add <proof>')
.describe('Add a proof delegated to this agent.')
.option('--json', 'Format as newline delimted JSON')
.option('--json', 'Format as newline delimited JSON')
.option('--dry-run', 'Decode and view the proof but do not add it')
.action(addProof)

cli.command('proof ls')
.describe('List proofs of capabilities delegated to this agent.')
.option('--json', 'Format as newline delimted JSON')
.option('--json', 'Format as newline delimited JSON')
.action(listProofs)

cli.command('can store add <car-path>')
.describe('Store a CAR file with the service.')
.action(storeAdd)

cli.command('can store ls')
.describe('List CAR files 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 store/list response that allows the service to provide the next "page" of results')
.option('--pre', 'If true, return the page of results preceding the cursor')
.action(storeList)

cli.command('can upload add <root-cid> <shard-cid>')
.describe('Register an upload - a DAG with the given root data CID that is stored in the given CAR shard(s), identified by CAR CIDs.')
.action(uploadAdd)

cli.command('can upload ls')
.describe('List uploads in the current space.')
.option('--json', 'Format as newline delimited JSON')
.option('--shards', 'Pretty print with shards in output')
.option('--size', 'The desired number of results to return')
.option('--cursor', 'An opaque string included in a prior upload/list response that allows the service to provide the next "page" of results')
.option('--pre', 'If true, return the page of results preceding the cursor')
.action(uploadList)

cli.parse(process.argv)
57 changes: 56 additions & 1 deletion can.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import fs from 'fs'
import { CID } from 'multiformats'
import ora from 'ora'
import { getClient } from './lib.js'
import { getClient, uploadListResponseToString, storeListResponseToString } from './lib.js'

/**
* @param {string} carPath
Expand All @@ -27,6 +27,33 @@ export async function storeAdd (carPath) {
spinner.stopAndPersist({ symbol: '⁂', text: `Stored ${cid}` })
}

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

const spinner = ora('Listing CARs').start()
travis marked this conversation as resolved.
Show resolved Hide resolved
const res = await client.capability.store.list(listOptions)
spinner.stop()
console.log(storeListResponseToString(res, opts))
}

/**
* @param {string} root
* @param {string} shard
Expand Down Expand Up @@ -60,3 +87,31 @@ export async function uploadAdd (root, shard, opts) {
await client.capability.upload.add(rootCID, shards)
spinner.stopAndPersist({ symbol: '⁂', text: `Upload added ${rootCID}` })
}

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

const spinner = ora('Listing uploads').start()
const res = await client.capability.upload.list(listOptions)
spinner.stop()
console.log(uploadListResponseToString(res, opts))
}
22 changes: 3 additions & 19 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import fs from 'fs'
import ora, { oraPromise } from 'ora'
import tree from 'pretty-tree'
import { Readable } from 'stream'
import { CID } from 'multiformats/cid'
import * as DID from '@ipld/dag-ucan/did'
import { CarWriter } from '@ipld/car'
import { getClient, checkPathsExist, filesize, readProof, filesFromPaths } from './lib.js'
import { getClient, checkPathsExist, filesize, readProof, filesFromPaths, uploadListResponseToString } from './lib.js'

/**
* @param {string} firstPath
Expand Down Expand Up @@ -55,30 +54,15 @@ export async function upload (firstPath, opts) {
* @param {boolean} [opts.json]
* @param {boolean} [opts.shards]
*/
export async function list (opts) {
export async function list (opts = {}) {
const client = await getClient()
let count = 0
let res
do {
res = await client.capability.upload.list()
travis marked this conversation as resolved.
Show resolved Hide resolved
count += res.results.length
if (res.results.length) {
if (opts.json) {
console.log(res.results.map(({ root, shards }) => JSON.stringify({
root: root.toString(),
shards: shards?.map(s => s.toString())
})).join('\n'))
} else if (opts.shards) {
console.log(res.results.map(({ root, shards }) => tree({
label: root.toString(),
nodes: [{
label: 'shards',
leaf: shards?.map(s => s.toString())
}]
})).join('\n'))
} else {
console.log(res.results.map(({ root }) => root.toString()).join('\n'))
}
console.log(uploadListResponseToString(res, opts))
}
} while (res.cursor && res.results.length)

Expand Down
48 changes: 48 additions & 0 deletions lib.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'fs'
import path from 'path'
import tree from 'pretty-tree'
import { Readable } from 'stream'
import { importDAG } from '@ucanto/core/delegation'
import { connect } from '@ucanto/client'
Expand All @@ -13,6 +14,9 @@ import { CarReader } from '@ipld/car'

/**
* @typedef {import('@web3-storage/w3up-client/types').FileLike & { size: number }} FileLike
* @typedef {import('@web3-storage/w3up-client/types').ListResponse} ListResponse
* @typedef {import('@web3-storage/w3up-client/types').StoreListResult} StoreListResult
* @typedef {import('@web3-storage/w3up-client/types').UploadListResult} UploadListResult
*/

export function getPkg () {
Expand Down Expand Up @@ -193,3 +197,47 @@ async function * filesFromDir (dir, filter) {
}
}
}

/**
* @param {ListResponse<UploadListResult>} res
* @param {boolean} [opts.raw]
* @param {boolean} [opts.json]
* @param {boolean} [opts.shards]
* @returns {string}
*/
export function uploadListResponseToString (res, opts = {}) {
if (opts.json) {
return res.results.map(({ root, shards }) => JSON.stringify({
root: root.toString(),
shards: shards?.map(s => s.toString())
})).join('\n')
} else if (opts.shards) {
return res.results.map(({ root, shards }) => tree({
label: root.toString(),
nodes: [{
label: 'shards',
leaf: shards?.map(s => s.toString())
}]
})).join('\n')
} else {
return res.results.map(({ root }) => root.toString()).join('\n')
}
}

/**
* @param {ListResponse<StoreListResult>} res
* @param {boolean} [opts.raw]
* @param {boolean} [opts.json]
* @returns {string}
*/
export function storeListResponseToString (res, opts = {}) {
if (opts.json) {
return res.results.map(({ link, size, insertedAt }) => JSON.stringify({
link: link.toString(),
size,
insertedAt
})).join('\n')
} else {
return res.results.map(({ link }) => link.toString()).join('\n')
}
}
Loading