Skip to content

Commit

Permalink
feat: w3 name CLI (#878)
Browse files Browse the repository at this point in the history
Adds some simple CLI commands for managing w3 names.
  • Loading branch information
Alan Shaw authored Jan 19, 2022
1 parent 0bb853c commit 3fc09db
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 54 deletions.
38 changes: 23 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions packages/w3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,36 @@ Paste in a token to save a new one. Pass in `--delete` to remove a previously sa

- `--api` URL for the Web3 Storage API. Default: https://api.web3.storage
- `--delete` Delete a previously saved token

### `w3 name create`

**❗️Experimental** this command may not work, may change, and may be removed.

Create a new name and associated signing key that can be used to create and publish IPNS record revisions. Prints the IPNS name and stores the signing key in config.

### `w3 name list`

**❗️Experimental** this command may not work, may change, and may be removed.

List IPNS names managed by this utility.

### `w3 name publish <keyId> <value>`

Publish a name revision to Web3.Storage.

**❗️Experimental** this command may not work, may change, and may be removed.

⚠️ Name records are not _yet_ published to or updated from the IPFS network.
Working with name records simply updates the Web3.Storage cache of data.

### `w3 name resolve <keyId>`

**❗️Experimental** this command may not work, may change, and may be removed.

Resolve the current IPNS record revision for the passed name.

### `w3 name rm <keyId>`

**❗️Experimental** this command may not work, may change, and may be removed.

Remove an IPNS name managed by this utility. Note: this does NOT unpublish the IPNS name, it simply removes the IPNS name and signing key from local config.
27 changes: 26 additions & 1 deletion packages/w3/bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import 'hard-rejection/register.js' // throw on unhandled promise rejection in node 14.
import sade from 'sade'
import { get, list, put, putCar, status, token, getPkg } from './index.js'
import { get, list, put, putCar, status, token } from './index.js'
import * as Name from './name.js'
import { getPkg } from './lib.js'

const cli = sade('w3')

Expand Down Expand Up @@ -49,4 +51,27 @@ cli.command('status <cid>')
.example('status bafkreigh2akiscaildcqabsyg3dfr6chu3fgpregiymsck7e7aqa4s52zy')
.action(status)

cli.command('name create')
.describe('Create a new IPNS name and associated signing key that can be used to create and publish IPNS record revisions. Prints the IPNS name and stores the signing key in config.')
.action(Name.create)

cli.command('name list')
.describe('List IPNS names managed by this utility.')
.action(Name.list)

cli.command('name publish <keyId> <value>')
.describe('Publish a name revision to Web3.Storage.')
.example('name publish k51qzi5uqu5dlcuzv5xhg1zqn48gobcvn2mx13uoig7zfj8rz6zvqdxsugka9z /ipfs/bafkreid7fbwjx4swwewit5txzttoja4t4xnkj3rx3q7dlbj76gvixuq35y')
.action(Name.publish)

cli.command('name resolve <keyId>')
.describe('Resolve the current IPNS record revision for the passed name.')
.example('name resolve k51qzi5uqu5dlcuzv5xhg1zqn48gobcvn2mx13uoig7zfj8rz6zvqdxsugka9z')
.action(Name.resolve)

cli.command('name rm <keyId>')
.describe('Remove an IPNS name managed by this utility. Note: this does NOT unpublish the IPNS name, it simply removes the IPNS name and signing key from local config.')
.example('name rm k51qzi5uqu5dlcuzv5xhg1zqn48gobcvn2mx13uoig7zfj8rz6zvqdxsugka9z')
.action(Name.rm)

cli.parse(process.argv)
39 changes: 2 additions & 37 deletions packages/w3/index.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,11 @@
import { Web3Storage, filesFromPath } from 'web3.storage'
import { filesFromPath } from 'web3.storage'
import { writeFiles } from 'ipfs-car/unpack/fs'
import enquirer from 'enquirer'
import Conf from 'conf'
import path from 'path'
import ora from 'ora'
import fs from 'fs'
import { CarIndexedReader } from '@ipld/car'

const API = 'https://api.web3.storage'

const config = new Conf({
projectName: 'w3',
projectVersion: getPkg().version
})

/**
* Get a new API client configured either from opts or config
* @param {object} opts
* @param {string} [opts.api]
* @param {string} [opts.token]
* @param {boolean} [opts.json]
*/
function getClient ({
api = config.get('api') || API,
token = config.get('token'),
json = false
}) {
if (!token) {
console.log('! run `w3 token` to set an API token to use')
process.exit(-1)
}
const endpoint = new URL(api)
if (api !== API && !json) {
// note if we're using something other than prod.
console.log(`⁂ using ${endpoint.hostname}`)
}
return new Web3Storage({ token, endpoint })
}
import { config, getClient, API } from './lib.js'

/**
* Set the token and optionally the api to use
Expand Down Expand Up @@ -250,10 +219,6 @@ function filesize (bytes) {
return `${size.toFixed(1)}MB`
}

export function getPkg () {
return JSON.parse(fs.readFileSync(new URL('./package.json', import.meta.url)))
}

function checkPathsExist (paths) {
paths = Array.isArray(paths) ? paths : [paths]
for (const p of paths) {
Expand Down
39 changes: 39 additions & 0 deletions packages/w3/lib.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import fs from 'fs'
import Conf from 'conf'
import { Web3Storage } from 'web3.storage'

export const API = 'https://api.web3.storage'

export const config = new Conf({
projectName: 'w3',
projectVersion: getPkg().version,
configFileMode: 0o600
})

export function getPkg () {
return JSON.parse(fs.readFileSync(new URL('./package.json', import.meta.url)))
}

/**
* Get a new API client configured either from opts or config
* @param {object} opts
* @param {string} [opts.api]
* @param {string} [opts.token]
* @param {boolean} [opts.json]
*/
export function getClient ({
api = config.get('api') || API,
token = config.get('token'),
json = false
}) {
if (!token) {
console.log('! run `w3 token` to set an API token to use')
process.exit(-1)
}
const endpoint = new URL(api)
if (api !== API && !json) {
// note if we're using something other than prod.
console.log(`⁂ using ${endpoint.hostname}`)
}
return new Web3Storage({ token, endpoint })
}
59 changes: 59 additions & 0 deletions packages/w3/name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as Name from 'web3.storage/name'
import * as uint8arrays from 'uint8arrays'
import { config, getClient } from './lib.js'

export async function create () {
const name = await Name.create()
config.set(`name.${name}`, uint8arrays.toString(name.key.bytes, 'base64pad'))
console.log(name.toString())
}

export function list () {
Object.keys(config.store.name || {}).forEach(keyId => console.log(keyId))
}

/**
* @param {string} keyId
* @param {string} value
* @param {string} [opts.api]
* @param {string} [opts.token]
*/
export async function publish (keyId, value, opts) {
const b64SigningKey = config.get(`name.${keyId}`)
if (!b64SigningKey) {
throw new Error('missing signing key')
}

const client = getClient(opts)
const name = await Name.from(uint8arrays.fromString(b64SigningKey, 'base64pad'))
/** @type {Name.Revision} */
let revision
try {
revision = await Name.resolve(client, name)
revision = await Name.increment(revision, value)
} catch (err) {
if (!err.message.includes('not found')) throw err
revision = await Name.v0(name, value)
}

await Name.publish(client, revision, name.key)
}

/**
* @param {string} keyId
* @param {object} opts
* @param {string} [opts.api]
* @param {string} [opts.token]
*/
export async function resolve (keyId, opts) {
const name = Name.parse(keyId)
const revision = await Name.resolve(getClient(opts), name)
console.log(revision.value)
}

/**
* @param {string} keyId
*/
export function rm (keyId) {
config.delete(`name.${keyId}`)
}
3 changes: 2 additions & 1 deletion packages/w3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@
"homepage": "https://web3.storage",
"dependencies": {
"@ipld/car": "^3.1.16",
"conf": "^10.0.1",
"conf": "^10.1.1",
"enquirer": "^2.3.6",
"hard-rejection": "^2.1.0",
"ipfs-car": "^0.6.1",
"ora": "^5.4.1",
"sade": "^1.7.4",
"uint8arrays": "^3.0.0",
"web3.storage": "^3.5.2"
},
"devDependencies": {
Expand Down

0 comments on commit 3fc09db

Please sign in to comment.