Skip to content
This repository was archived by the owner on Dec 27, 2022. It is now read-only.

Commit bb3b1ab

Browse files
committed
Switch drive management to /system/drives.json and update related APIs and beaker://drives
1 parent aa622e8 commit bb3b1ab

13 files changed

Lines changed: 459 additions & 215 deletions

File tree

app/bg/filesystem/index.js

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,26 @@ import * as db from '../dbs/profile-data-db'
77
import * as users from './users'
88
import * as trash from './trash'
99
import { PATHS } from '../../lib/const'
10+
import lock from '../../lib/lock'
1011

1112
// typedefs
1213
// =
1314

1415
/**
1516
* @typedef {import('../dat/daemon').DaemonHyperdrive} DaemonHyperdrive
1617
* @typedef {import('./users').User} User
18+
*
19+
* @typedef {Object} DriveConfig
20+
* @property {string} key
21+
* @property {boolean} seeding
1722
*/
1823

1924
// globals
2025
// =
2126

2227
var browsingProfile
2328
var rootDrive
29+
var drives = []
2430

2531
// exported api
2632
// =
@@ -72,8 +78,6 @@ export async function setup () {
7278
await ensureDir(PATHS.LIBRARY_NS('media'))
7379
await ensureDir(PATHS.LIBRARY_NS('projects'))
7480
await ensureDir(PATHS.SYSTEM)
75-
await ensureDir(PATHS.SYSTEM_NS('drives'))
76-
await ensureDir(PATHS.SYSTEM_NS('templates'))
7781
await ensureDir(PATHS.SYSTEM_NS('webterm'))
7882
await ensureDir(PATHS.SYSTEM_NS('webterm/cmds'))
7983

@@ -87,6 +91,14 @@ export async function setup () {
8791
console.error('Error while constructing the root drive', e.toString())
8892
logger.error('Error while constructing the root drive', {error: e.toString()})
8993
}
94+
95+
// load drive config
96+
try {
97+
drives = JSON.parse(await rootDrive.pda.readFile(PATHS.SYSTEM_NS('drives.json'))).drives
98+
} catch (e) {
99+
console.error('Error while reading the drive configuration at /system/drives.json', e.toString())
100+
logger.error('Error while reading the drive configuration at /system/drives.json', {error: e.toString()})
101+
}
90102
}
91103

92104
/**
@@ -97,14 +109,51 @@ export async function setDefaultUser (url) {
97109
await ensureMount(PATHS.DEFAULT_USER, url)
98110
}
99111

112+
/**
113+
* @returns {Array<DriveConfig>}
114+
*/
115+
export function listDrives () {
116+
return drives
117+
}
118+
119+
/**
120+
* @param {string} url
121+
* @param {Object} [opts]
122+
* @param {Boolean} [opts.seeding]
123+
* @returns {Promise<void>}
124+
*/
125+
export async function configDrive (url, {seeding} = {seeding: false}) {
126+
var release = await lock('filesystem:drives')
127+
try {
128+
var key = await hyper.drives.fromURLToKey(url, true)
129+
var drive = drives.find(drive => drive.key === key)
130+
if (!drive) {
131+
drive = /** @type DriveConfig */({key, seeding})
132+
drives.push(drive)
133+
} else {
134+
drive.seeding = seeding
135+
}
136+
await rootDrive.pda.writeFile(PATHS.SYSTEM_NS('drives.json'), JSON.stringify({drives}, null, 2))
137+
} finally {
138+
release()
139+
}
140+
}
141+
100142
/**
101143
* @param {string} url
102-
* @param {string} title
103144
* @returns {Promise<void>}
104145
*/
105-
export async function addToLibrary (url, title) {
106-
var name = await getAvailableName(PATHS.SYSTEM_NS('drives'), slugify((title || '').trim() || 'untitled').toLowerCase())
107-
await ensureMount(joinPath(PATHS.SYSTEM_NS('drives'), name), url)
146+
export async function removeDrive (url) {
147+
var release = await lock('filesystem:drives')
148+
try {
149+
var key = await hyper.drives.fromURLToKey(url, true)
150+
var driveIndex = drives.findIndex(drive => drive.key === key)
151+
if (driveIndex === -1) return
152+
drives.splice(driveIndex, 1)
153+
await rootDrive.pda.writeFile(PATHS.SYSTEM_NS('drives.json'), JSON.stringify({drives}, null, 2))
154+
} finally {
155+
release()
156+
}
108157
}
109158

110159
/**

app/bg/hyper/drives.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import _debounce from 'lodash.debounce'
66
import pda from 'pauls-dat-api2'
77
import { wait } from '../../lib/functions'
88
import * as logLib from '../logger'
9+
import { listDrives } from '../filesystem/index'
910
const baseLogger = logLib.get()
1011
const logger = baseLogger.child({category: 'dat', subcategory: 'drives'})
1112

@@ -93,7 +94,7 @@ export async function setup () {
9394
*/
9495
export async function loadSavedDrives () {
9596
// load all saved drives
96-
var drives = [] // TODO uwg await datLibrary.list({isHosting: true})
97+
var drives = listDrives()
9798

9899
// HACK
99100
// load the drives one at a time and give 5 seconds between each
@@ -103,9 +104,11 @@ export async function loadSavedDrives () {
103104
// so spacing out the loads has no visible impact on the user
104105
// (except for reducing the overall load for the user)
105106
// -prf
106-
for (let a of drives) {
107-
loadDrive(a.key)
108-
await new Promise(r => setTimeout(r, 5e3)) // wait 5s
107+
for (let drive of drives) {
108+
if (drive.seeding) {
109+
loadDrive(drive.key)
110+
await new Promise(r => setTimeout(r, 5e3)) // wait 5s
111+
}
109112
}
110113
};
111114

app/bg/web-apis/bg/drives.js

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import hyperDns from '../../hyper/dns'
22
import * as drives from '../../hyper/drives'
33
import * as archivesDb from '../../dbs/archives'
4+
import { listDrives, configDrive, removeDrive, isRootUrl } from '../../filesystem/index'
45
import * as trash from '../../filesystem/trash'
56
import * as users from '../../filesystem/users'
67
import { PermissionsError } from 'beaker-error-constants'
@@ -19,6 +20,47 @@ export default {
1920
return status
2021
},
2122

23+
async get (key) {
24+
key = await drives.fromURLToKey(key, true)
25+
var drive = listDrives().find(drive => drive.key === key)
26+
var info = await drives.getDriveInfo(key).catch(e => {})
27+
var url = `hd://${key}`
28+
var ident = getIdent(url)
29+
return {
30+
key,
31+
url,
32+
info,
33+
saved: !!drive,
34+
seeding: ident.user || (drive ? drive.seeding : false),
35+
ident
36+
}
37+
},
38+
39+
async list () {
40+
var records = []
41+
for (let drive of listDrives()) {
42+
let url = `hd://${drive.key}`
43+
let ident = getIdent(url)
44+
records.push({
45+
key: drive.key,
46+
url,
47+
info: await drives.getDriveInfo(drive.key).catch(e => {}),
48+
saved: true,
49+
seeding: ident.user || drive.seeding,
50+
ident
51+
})
52+
}
53+
return records
54+
},
55+
56+
async configure (key, opts) {
57+
return configDrive(key, opts)
58+
},
59+
60+
async remove (key) {
61+
return removeDrive(key)
62+
},
63+
2264
async collectTrash () {
2365
return trash.collect({olderThan: 0})
2466
},
@@ -67,29 +109,8 @@ function assertDriveDeletable (key) {
67109
}
68110
}
69111

70-
function massageRecord (record) {
71-
return {
72-
key: record.key,
73-
url: `hd://${record.key}`,
74-
author: record.author ? {
75-
url: record.author.url,
76-
title: record.author.title,
77-
description: record.author.description,
78-
type: record.author.type,
79-
writable: record.author.writable
80-
} : undefined,
81-
meta: {
82-
title: record.meta.title,
83-
description: record.meta.description,
84-
type: record.meta.type,
85-
mtime: record.meta.mtime,
86-
size: record.meta.size,
87-
author: record.meta.author,
88-
writable: record.meta.writable
89-
},
90-
isSaved: record.isSaved,
91-
isHosting: record.isHosting,
92-
visibility: record.visibility,
93-
savedAt: Number(record.savedAt)
94-
}
112+
function getIdent (url) {
113+
var home = isRootUrl(url)
114+
var user = users.isUser(url)
115+
return {system: home || user, home, user}
95116
}

app/bg/web-apis/bg/hyperdrive.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export default {
5858
// create
5959
try {
6060
var newDrive = await drives.createNewDrive({title, description, type, author, links})
61-
await filesystem.addToLibrary(newDrive.url, title)
61+
await filesystem.configDrive(newDrive.url, {seeding: true})
6262
} catch (e) {
6363
console.log(e)
6464
throw e
@@ -119,7 +119,7 @@ export default {
119119
// create
120120
let key = await lookupUrlDriveKey(url)
121121
let newDrive = await drives.cloneDrive(key, {title, description, type, author, links})
122-
await filesystem.addToLibrary(newDrive.url, title)
122+
await filesystem.configDrive(newDrive.url, {seeding: true})
123123
newDriveUrl = newDrive.url
124124
}
125125

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { PermissionsError } from 'beaker-error-constants'
22
import * as sessionPerms from '../../lib/session-perms'
33
import * as filesystem from '../../filesystem/index'
4-
import * as users from '../../filesystem/users'
54
import _pick from 'lodash.pick'
65

76
// typedefs
@@ -13,11 +12,6 @@ import _pick from 'lodash.pick'
1312
*
1413
* @typedef {Object} NavigatorFilesystemPublicAPIRootRecord
1514
* @prop {string} url
16-
*
17-
* @typedef {Object} NavigatorFilesystemPublicAPIDriveInfo
18-
* @prop {boolean} isSystemDrive
19-
* @prop {boolean} isRoot
20-
* @prop {boolean} isUser
2115
*/
2216

2317
// exported api
@@ -35,22 +29,5 @@ export default {
3529
return {
3630
url: filesystem.get().url
3731
}
38-
},
39-
40-
/**
41-
* @param {string} url
42-
* @returns {Promise<NavigatorFilesystemPublicAPIDriveInfo>}
43-
*/
44-
async identifyDrive (url) {
45-
if (!(await sessionPerms.isTrustedApp(this.sender))) {
46-
throw new PermissionsError()
47-
}
48-
var isRoot = url === filesystem.get().url
49-
var isUser = users.isUser(url)
50-
return {
51-
isSystemDrive: isRoot || isUser,
52-
isRoot,
53-
isUser
54-
}
5532
}
5633
}

app/bg/web-apis/fg/beaker.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ export const setup = function (rpc) {
4949
// beaker.drives
5050
beaker.drives = new EventTarget()
5151
beaker.drives.status = drivesRPC.status
52+
beaker.drives.get = drivesRPC.get
53+
beaker.drives.list = drivesRPC.list
54+
beaker.drives.configure = drivesRPC.configure
55+
beaker.drives.remove = drivesRPC.remove
5256
beaker.drives.listTrash = drivesRPC.listTrash
5357
beaker.drives.collectTrash = drivesRPC.collectTrash
5458
beaker.drives.delete = drivesRPC.delete

app/bg/web-apis/fg/navigator-methods.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@ export const setup = function (rpc) {
2424
var filesystemApi = rpc.importAPI('navigator-filesystem', filesystemManifest, RPC_OPTS)
2525
try {
2626
navigator.filesystem = new Hyperdrive(filesystemApi.get().url)
27-
navigator.filesystem.identifyDrive = async (url) => {
28-
if (url instanceof Hyperdrive) {
29-
url = url.url
30-
}
31-
return filesystemApi.identifyDrive(url)
32-
}
3327
} catch (e) {
3428
// not supported
3529
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
export default {
2-
get: 'sync',
3-
identifyDrive: 'promise'
2+
get: 'sync'
43
}

app/bg/web-apis/manifests/internal/drives.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
export default {
22
status: 'promise',
3+
get: 'promise',
4+
list: 'promise',
5+
configure: 'promise',
6+
remove: 'promise',
37
listTrash: 'promise',
48
collectTrash: 'promise',
59
delete: 'promise',

app/userland/app-stdlib/js/strings.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,15 @@ export function toNiceDriveType (type = '') {
125125
if (!type) return 'files drive'
126126
if (type === 'unwalled.garden/person') return 'beaker user'
127127
if (type === 'unwalled.garden/template') return 'template'
128+
if (type === 'webterm.sh/cmd-pkg') return 'webterm command'
128129
return type
129130
}
130131

131132
export function getDriveTypeIcon (type = '') {
132133
switch (type) {
133134
case 'unwalled.garden/person': return 'fas fa-user'
134135
case 'unwalled.garden/template': return 'fas fa-drafting-compass'
136+
case 'webterm.sh/cmd-pkg': return 'fas fa-terminal'
135137
case 'module': return 'fas fa-cube'
136138
case 'website': return 'fas fa-desktop'
137139
default: return 'far fa-folder-open'

0 commit comments

Comments
 (0)