Skip to content

Commit

Permalink
feat(cli): in explore, allow copy to clipboard the text of identifier…
Browse files Browse the repository at this point in the history
… or credential or presentation (#902)

* feat(cli): in explore, allow user to copy to clipboard the text of identifier or credential or presentation

* feat(cli): add command to output selected credential or presentation
  • Loading branch information
trentlarson authored Jul 29, 2022
1 parent 3377930 commit d3b87f5
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 2 deletions.
35 changes: 35 additions & 0 deletions packages/cli/src/credential.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,38 @@ credential
console.error(e.message)
}
})

credential
.command('output')
.description('Print W3C Verifiable Credential to stdout')
.action(async (cmd) => {
const agent = getAgent(program.opts().config)

const credentials = await agent.dataStoreORMGetVerifiableCredentials()

if (credentials.length > 0) {
const list: any = []
for (const cred of credentials) {
list.push({
name:
JSON.stringify(cred.verifiableCredential.credentialSubject) +
' | Issuer: ' +
JSON.stringify(cred.verifiableCredential.issuer),
value: cred,
})
}

const answers = await inquirer.prompt([
{
type: 'list',
name: 'credential',
choices: list,
message: 'Select credential',
},
])

console.dir(answers.credential, { depth: 10 })
} else {
console.log('No credentials found.')
}
})
19 changes: 18 additions & 1 deletion packages/cli/src/explore/credentials.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import blessed, { Widgets } from 'blessed'
import { UniqueVerifiableCredential } from '@veramo/core'
import { shortDate, shortDid } from './utils'
import { shortDate, shortDid, copyToClipboard } from './utils'
import { ConfiguredAgent } from '../setup'
import { styles } from './styles'
import { asArray, extractIssuer } from '@veramo/utils'
Expand Down Expand Up @@ -64,6 +64,23 @@ export const getCredentialsTable = async (agent: ConfiguredAgent, screen: Widget

content: JSON.stringify(credential, null, 2),
})
credentialBox.key(['c'], function (ch, key) {
var messageBox = blessed.message({
parent: screen,
top: 'center',
left: 'center',
height: 'shrink',
width: 'shrink',
border: 'line',
shadow: true,
style: {
fg: 'green'
},
})
const success = copyToClipboard(JSON.stringify(credential, null, 2))
const message = success ? 'Copied to clipboard.' : 'Could not copy to clipboard.'
messageBox.display(message, () => {})
})
credentialBox.key(['escape'], function (ch, key) {
credentialBox.destroy()
screen.render()
Expand Down
18 changes: 18 additions & 0 deletions packages/cli/src/explore/managed-identifiers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import blessed, { Widgets } from 'blessed'
import { IIdentifier } from '@veramo/core'
import { copyToClipboard } from './utils'
import { ConfiguredAgent } from '../setup'
import { styles } from './styles'

Expand Down Expand Up @@ -53,6 +54,23 @@ export const getManagedIdentifiersTable = async (agent: ConfiguredAgent, screen:

content: JSON.stringify(identifier, null, 2),
})
identifierBox.key(['c'], function (ch, key) {
var messageBox = blessed.message({
parent: screen,
top: 'center',
left: 'center',
height: 'shrink',
width: 'shrink',
border: 'line',
shadow: true,
style: {
fg: 'green'
},
})
const success = copyToClipboard(JSON.stringify(identifier, null, 2))
const message = success ? 'Copied to clipboard.' : 'Could not copy to clipboard.'
messageBox.display(message, () => {})
})
identifierBox.key(['escape'], function (ch, key) {
identifierBox.destroy()
screen.render()
Expand Down
19 changes: 18 additions & 1 deletion packages/cli/src/explore/presentations.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import blessed, { Widgets } from 'blessed'
import { UniqueVerifiablePresentation } from '@veramo/core'
import { shortDate, shortDid } from './utils'
import { shortDate, shortDid, copyToClipboard } from './utils'
import { ConfiguredAgent } from '../setup'
import { styles } from './styles'
import { asArray } from '@veramo/utils'
Expand Down Expand Up @@ -64,6 +64,23 @@ export const getPresentationsTable = async (agent: ConfiguredAgent, screen: Widg

content: JSON.stringify(presentation, null, 2),
})
presentationBox.key(['c'], function (ch, key) {
var messageBox = blessed.message({
parent: screen,
top: 'center',
left: 'center',
height: 'shrink',
width: 'shrink',
border: 'line',
shadow: true,
style: {
fg: 'green'
},
})
const success = copyToClipboard(JSON.stringify(presentation, null, 2))
const message = success ? 'Copied to clipboard.' : 'Could not copy to clipboard.'
messageBox.display(message, () => {})
})
presentationBox.key(['escape'], function (ch, key) {
presentationBox.destroy()
screen.render()
Expand Down
20 changes: 20 additions & 0 deletions packages/cli/src/explore/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { formatDistanceToNow } from 'date-fns'
import os from 'os'

export function shortDid(did?: string): string {
if (!did) return ''
Expand All @@ -12,3 +13,22 @@ export function shortDate(date?: string): string {
if (!date) return ''
return formatDistanceToNow(new Date(date))
}

// return true if copy worked, false otherwise
export function copyToClipboard(text: string): boolean {
/**
* There's probably a better way than spawning. We tried and failed at the following:
* - screen.copyToClipboard didn't do anything (and is iTerm2-specific, anyway)
* - clipboardy wouldn't run due to error "Must use import to load ES Module" (even though we used import)
*/
if (os.platform() === 'darwin') {
const proc = require('child_process').spawn('pbcopy')
proc.stdin.write(text)
proc.stdin.end()
return true
} else if (os.platform() === 'win32') {
require('child_process').spawn('clip').stdin.end(text)
return true
}
return false
}
53 changes: 53 additions & 0 deletions packages/cli/src/presentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,56 @@ presentation
console.error('Presentation could not be verified.')
}
})

presentation
.command('output')
.description('Print W3C Verifiable Presentation to stdout')
.option('-t, --tag <string>', 'Optional. Specify the tag for the presentation.')
.action(async (options) => {
const agent = getAgent(program.opts().config)

const presentations = await agent.dataStoreORMGetVerifiablePresentations({})

if (presentations.length > 0) {

let selected = null
const list: any = []
if (options.tag) {
const matches = presentations.filter(pres => pres.verifiablePresentation.tag === options.tag)
if (matches.length > 1) {
console.log('Found multiple matching presentations. Only showing the first one.')
}
selected = matches[0]
} else {
for (const pres of presentations) {
list.push({
name:
'Issuance Date: ' +
pres.verifiablePresentation.issuanceDate +
' | Holder: ' +
pres.verifiablePresentation.holder +
' | Tag: ' +
pres.verifiablePresentation.tag,
value: pres,
})
}
const answers = await inquirer.prompt([
{
type: 'list',
name: 'presentation',
choices: list,
message: 'Select presentation',
},
])
selected = answers.presentation
}

if (selected) {
console.dir(selected, { depth: 10 })
} else {
console.log('Presentation not found.')
}
} else {
console.log('No presentations found.')
}
})

0 comments on commit d3b87f5

Please sign in to comment.