8000 [pear-next] CLI `$ pear data assets` by AndreiRegiani · Pull Request #741 · holepunchto/pear · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[pear-next] CLI $ pear data assets #741

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

Merged
merged 6 commits into from
May 27, 2025
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
30 changes: 25 additions & 5 deletions cmd/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,23 @@ const manifestOutput = (manifest) => {
return `version: ${ansi.bold(manifest.version)}\n`
}

const assetsOutput = (assets) => {
if (!assets.length) return placeholder
let out = ''
for (const asset of assets) {
out += `- ${ansi.bold(asset.link)}\n`
out += `${padding}path: ${ansi.dim(asset.path)}\n`
out += '\n'
}
return out
}

const output = outputter('data', {
apps: (result) => appsOutput(result),
link: (result) => appsOutput([result]),
dht: (result) => dhtOutput(result),
gc: (result) => gcOutput(result),
manifest: (result) => manifestOutput(result)
manifest: (result) => manifestOutput(result),
assets: (result) => assetsOutput(result)
})

module.exports = (ipc) => new Data(ipc)
Expand All @@ -66,10 +77,8 @@ class Data {
if (link) {
const parsed = plink.parse(link)
if (!parsed) throw ERR_INVALID_INPUT(`Link "${link}" is not a valid key`)
await output(json, this.ipc.data({ resource: 'link', secrets, link }), { tag: 'link' }, this.ipc)
} else {
await output(json, this.ipc.data({ resource: 'apps', secrets }), { tag: 'apps' }, this.ipc)
}
await output(json, this.ipc.data({ resource: 'apps', secrets, link }), { tag: 'apps' }, this.ipc)
}

async dht (cmd) {
Expand All @@ -89,4 +98,15 @@ class Data {
const { json } = command.parent.flags
await output(json, this.ipc.data({ resource: 'manifest' }), { tag: 'manifest' }, this.ipc)
}

async assets (cmd) {
const { command } = cmd
const { json } = command.parent.flags
const link = command.args.link
if (link) {
const parsed = plink.parse(link)
if (!parsed) throw ERR_INVALID_INPUT(`Link "${link}" is not a valid key`)
}
await output(json, this.ipc.data({ resource: 'assets', link }), { tag: 'assets' }, this.ipc)
}
}
10000 3 changes: 2 additions & 1 deletion cmd/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ module.exports = async (ipc, argv = Bare.argv.slice(1)) => {
command('apps', summary('Installed apps'), arg('[link]', 'Filter by link'), (cmd) => runners.data(ipc).apps(cmd)),
command('dht', summary('DHT known-nodes cache'), (cmd) => runners.data(ipc).dht(cmd)),
command('gc', summary('Garbage collection records'), (cmd) => runners.data(ipc).gc(cmd)),
command('manifest', summary('database internal versioning'), (cmd) => runners.data(ipc).manifest(cmd)),
command('manifest', summary('Database internal versioning'), (cmd) => runners.data(ipc).manifest(cmd)),
command('assets', summary('On-disk assets for app'), arg('[link]', 'Filter by link'), (cmd) => runners.data(ipc).assets(cmd)),
flag('--secrets', 'Show sensitive information'),
flag('--json', 'Newline delimited JSON output'),
() => { console.log(data.help()) }
Expand Down
12 changes: 12 additions & 0 deletions subsystems/sidecar/lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,18 @@ module.exports = class Model {
return asset
}

async getAsset (link) {
const get = { link }
LOG.trace('db', 'GET', '@pear/asset', get)
const asset = await this.db.get('@pear/asset', get)
return asset
}

async allAssets () {
LOG.trace('db', 'FIND', '@pear/asset')
return await this.db.find('@pear/asset').toArray()
}

async getDhtNodes () {
LOG.trace('db', 'GET', '@pear/dht', '[nodes]')
return (await this.db.get('@pear/dht'))?.nodes || []
Expand Down
25 changes: 18 additions & 7 deletions subsystems/sidecar/ops/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ module.exports = class Data extends Opstream {
await this.sidecar.ready()

if (resource === 'apps') {
let bundles = await this.sidecar.model.allBundles()
let bundles
if (link) {
const bundle = await this.sidecar.model.getBundle(link)
bundles = bundle ? [bundle] : []
} else {
bundles = await this.sidecar.model.allBundles()
}
if (!secrets) bundles = bundles.map(({ encryptionKey, ...rest }) => rest)
this.push({ tag: 'apps', data: bundles })
}

if (resource === 'link') {
const bundle = await this.sidecar.model.getBundle(link)
if (bundle && !secrets) bundle.encryptionKey = undefined
this.push({ tag: 'link', data: bundle })
}

if (resource === 'dht') {
const nodes = await this.sidecar.model.getDhtNodes()
this.push({ tag: 'dht', data: nodes })
Expand All @@ -35,5 +35,16 @@ module.exports = class Data extends Opstream {
const manifest = await this.sidecar.model.getManifest()
this.push({ tag: 'manifest', data: manifest })
}

if (resource === 'assets') {
let assets
if (link) {
const asset = await this.sidecar.model.getAsset(link)
assets = asset ? [asset] : []
} else {
assets = await this.sidecar.model.allAssets()
}
this.push({ tag: 'assets', data: assets })
}
}
}
6 changes: 3 additions & 3 deletions test/01-smoke.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ test('local app', async function ({ ok, is, teardown }) {
is(versions.app.key, null, 'app key is null')
await Helper.untilClose(run.pipe)

const data = await helper.data({ resource: 'link', link: tmpdir })
const dataResult = await Helper.pick(data, [{ tag: 'link' }])
const bundle = await dataResult.link
const data = await helper.data({ resource: 'apps', link: tmpdir })
const dataResult = await Helper.pick(data, [{ tag: 'apps' }])
const bundle = (await dataResult.apps)[0]

is(bundle.link, pathToFileURL(tmpdir).href, 'href of the directory is the app bundle key')
ok(bundle.appStorage.includes('by-random'), 'application by storage has been generate randomly and persisted')
Expand Down
12 changes: 6 additions & 6 deletions test/09-data.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,18 @@ test('pear data', async function ({ ok, is, plan, comment, timeout, teardown })
is(typeof bundles[0].appStorage, 'string', 'Field appStorage is a string')

comment('pear data apps [link]')
data = await helper.data({ resource: 'link', link })
result = await Helper.pick(data, [{ tag: 'link' }])
let bundle = await result.link
data = await helper.data({ resource: 'apps', link })
result = await Helper.pick(data, [{ tag: 'apps' }])
let bundle = (await result.apps)[0]
ok(bundle.encryptionKey === undefined, 'Encryption key is hidden without --secrets')
ok(bundle.link.startsWith('pear://'), 'Link starts with pear://')
is(bundle.link, link, 'Link matches to the one just created')
is(typeof bundle.appStorage, 'string', 'Field appStorage is a string')

comment('pear data --secrets apps [link]')
data = await helper.data({ resource: 'link', link, secrets: true })
result = await Helper.pick(data, [{ tag: 'link' }])
bundle = await result.link
data = await helper.data({ resource: 'apps', link, secrets: true })
result = await Helper.pick(data, [{ tag: 'apps' }])
bundle = (await result.apps)[0]
is(bundle.encryptionKey.toString('hex'), ek.toString('hex'), 'Encryption key from bundle matches')
ok(bundle.link.startsWith('pear://'), 'Link starts with pear://')
is(bundle.link, link, 'Link matches to the one just created')
Expand Down
0