/
hyper.ts
86 lines (69 loc) · 2.28 KB
/
hyper.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import * as SDK from 'hyper-sdk'
import LocalDrive from 'localdrive'
import { Static } from '@sinclair/typebox'
import Protocol, { Ctx, SyncOptions } from './interfaces'
import { HyperProtocolFields } from '../api/schemas'
import createError from 'http-errors'
export interface HyperProtocolOptions {
path: string
}
export class HyperProtocol implements Protocol<Static<typeof HyperProtocolFields>> {
options: HyperProtocolOptions
sdk: SDK.SDK | null
drives: Map<string, any>
constructor (options: HyperProtocolOptions) {
this.options = options
this.sdk = null
this.drives = new Map<string, SDK.Hyperdrive>()
}
async load (): Promise<void> {
const { path } = this.options
this.sdk = await SDK.create({ storage: path })
}
async unload (): Promise<void> {
return await this.sdk?.close()
}
async getDrive (id: string): Promise<SDK.Hyperdrive> {
if (this.drives.has(id)) {
return this.drives.get(id)
}
if (this.sdk === null) {
throw createError(500, 'Hypercore SDK called before being initialized')
}
const drive = await this.sdk.getDrive(id)
this.drives.set(id, drive)
drive.once('close', () => {
this.drives.delete(id)
})
return drive
}
async sync (id: string, folderPath: string, options?: SyncOptions, ctx?: Ctx): Promise<Static<typeof HyperProtocolFields>> {
ctx?.logger.info('[hyper] Sync Start')
const drive = await this.getDrive(id)
const fs = new LocalDrive(folderPath)
const mirror = fs.mirror(drive)
for await (const change of mirror) {
ctx?.logger.debug(`[hyper] ${change.op}: ${change.key}`)
}
const raw = drive.url
const link = `hyper://${id}`
const key = raw.substring('hyper://'.length)
const subdomain = id.replaceAll('-', '--').replaceAll('.', '-')
// TODO: Pass in gateway from config
const gateway = `https://${subdomain}.hyper.hypha.coop/`
ctx?.logger.info(`[hyper] Published: ${link}`)
const dnslink = `/hyper/${key}`
return {
enabled: true,
link,
gateway,
raw,
dnslink
}
}
async unsync (id: string, _site: Static<typeof HyperProtocolFields>, ctx?: Ctx): Promise<void> {
const drive = await this.getDrive(id)
// TODO: Should we also clear the stored data?
await drive.close()
}
}