@comapeo/core 3.0.0-0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated/rpc.d.ts +47 -0
- package/dist/generated/rpc.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/invite/invite-api.d.ts +4 -5
- package/dist/invite/invite-api.d.ts.map +1 -1
- package/dist/local-peers.d.ts +31 -0
- package/dist/local-peers.d.ts.map +1 -1
- package/dist/mapeo-manager.d.ts +30 -22
- package/dist/mapeo-manager.d.ts.map +1 -1
- package/dist/mapeo-project.d.ts +39 -1
- package/dist/mapeo-project.d.ts.map +1 -1
- package/dist/member-api.d.ts +15 -1
- package/dist/member-api.d.ts.map +1 -1
- package/dist/schema/client.d.ts +26 -3
- package/dist/schema/client.d.ts.map +1 -1
- package/dist/sync/sync-api.d.ts +4 -1
- package/dist/sync/sync-api.d.ts.map +1 -1
- package/drizzle/client/0002_brief_demogoblin.sql +2 -0
- package/drizzle/client/meta/0002_snapshot.json +220 -0
- package/drizzle/client/meta/_journal.json +7 -0
- package/package.json +3 -3
- package/src/generated/rpc.d.ts +47 -0
- package/src/generated/rpc.js +241 -3
- package/src/generated/rpc.ts +280 -1
- package/src/invite/invite-api.js +15 -3
- package/src/local-peers.js +258 -21
- package/src/mapeo-manager.js +60 -20
- package/src/mapeo-project.js +21 -3
- package/src/member-api.js +67 -10
- package/src/schema/client.js +3 -2
- package/src/sync/sync-api.js +6 -2
- package/dist/blob-store/live-download.d.ts +0 -107
- package/dist/blob-store/live-download.d.ts.map +0 -1
- package/dist/capabilities.d.ts +0 -121
- package/dist/capabilities.d.ts.map +0 -1
- package/dist/core-manager/compat.d.ts +0 -4
- package/dist/core-manager/compat.d.ts.map +0 -1
- package/dist/discovery/dns-sd.d.ts +0 -54
- package/dist/discovery/dns-sd.d.ts.map +0 -1
- package/dist/fastify-plugins/maps/index.d.ts +0 -11
- package/dist/fastify-plugins/maps/index.d.ts.map +0 -1
- package/dist/fastify-plugins/maps/offline-fallback-map.d.ts +0 -12
- package/dist/fastify-plugins/maps/offline-fallback-map.d.ts.map +0 -1
- package/dist/fastify-plugins/maps/static-maps.d.ts +0 -11
- package/dist/fastify-plugins/maps/static-maps.d.ts.map +0 -1
- package/dist/invite-api.d.ts +0 -70
- package/dist/invite-api.d.ts.map +0 -1
- package/dist/lib/timing-safe-equal.d.ts +0 -15
- package/dist/lib/timing-safe-equal.d.ts.map +0 -1
- package/dist/media-server.d.ts +0 -36
- package/dist/media-server.d.ts.map +0 -1
- package/dist/server/ws-core-replicator.d.ts +0 -6
- package/dist/server/ws-core-replicator.d.ts.map +0 -1
package/src/mapeo-project.js
CHANGED
|
@@ -57,6 +57,7 @@ import { IconApi } from './icon-api.js'
|
|
|
57
57
|
import { readConfig } from './config-import.js'
|
|
58
58
|
import TranslationApi from './translation-api.js'
|
|
59
59
|
import { NotFoundError, nullIfNotFound } from './errors.js'
|
|
60
|
+
import { WebSocket } from 'ws'
|
|
60
61
|
/** @import { ProjectSettingsValue } from '@comapeo/schema' */
|
|
61
62
|
/** @import { CoreStorage, BlobFilter, BlobStoreEntriesStream, KeyPair, Namespace, ReplicationStream, GenericBlobFilter } from './types.js' */
|
|
62
63
|
|
|
@@ -116,6 +117,7 @@ export class MapeoProject extends TypedEmitter {
|
|
|
116
117
|
* @param {IndexWriter} opts.sharedIndexWriter
|
|
117
118
|
* @param {CoreStorage} opts.coreStorage Folder to store all hypercore data
|
|
118
119
|
* @param {(mediaType: 'blobs' | 'icons') => Promise<string>} opts.getMediaBaseUrl
|
|
120
|
+
* @param {(url: string) => WebSocket} [opts.makeWebsocket]
|
|
119
121
|
* @param {import('./local-peers.js').LocalPeers} opts.localPeers
|
|
120
122
|
* @param {boolean} opts.isArchiveDevice Whether this device is an archive device
|
|
121
123
|
* @param {Logger} [opts.logger]
|
|
@@ -132,6 +134,7 @@ export class MapeoProject extends TypedEmitter {
|
|
|
132
134
|
projectSecretKey,
|
|
133
135
|
encryptionKeys,
|
|
134
136
|
getMediaBaseUrl,
|
|
137
|
+
makeWebsocket = (url) => new WebSocket(url),
|
|
135
138
|
localPeers,
|
|
136
139
|
logger,
|
|
137
140
|
isArchiveDevice,
|
|
@@ -350,6 +353,7 @@ export class MapeoProject extends TypedEmitter {
|
|
|
350
353
|
getProjectName: this.#getProjectName.bind(this),
|
|
351
354
|
projectKey,
|
|
352
355
|
rpc: localPeers,
|
|
356
|
+
makeWebsocket,
|
|
353
357
|
getReplicationStream,
|
|
354
358
|
waitForInitialSyncWithPeer: (deviceId, abortSignal) =>
|
|
355
359
|
this.$sync[kWaitForInitialSyncWithPeer](deviceId, abortSignal),
|
|
@@ -400,6 +404,7 @@ export class MapeoProject extends TypedEmitter {
|
|
|
400
404
|
roles: this.#roles,
|
|
401
405
|
blobStore: this.#blobStore,
|
|
402
406
|
logger: this.#l,
|
|
407
|
+
makeWebsocket,
|
|
403
408
|
getServerWebsocketUrls: async () => {
|
|
404
409
|
const members = await this.#memberApi.getMany()
|
|
405
410
|
/** @type {string[]} */
|
|
@@ -410,9 +415,9 @@ export class MapeoProject extends TypedEmitter {
|
|
|
410
415
|
member.selfHostedServerDetails
|
|
411
416
|
) {
|
|
412
417
|
const { baseUrl } = member.selfHostedServerDetails
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
418
|
+
serverWebsocketUrls.push(
|
|
419
|
+
baseUrlToWS(baseUrl, this.#projectPublicId)
|
|
420
|
+
)
|
|
416
421
|
}
|
|
417
422
|
}
|
|
418
423
|
return serverWebsocketUrls
|
|
@@ -1086,3 +1091,16 @@ function mapAndValidateDeviceInfo(doc, { coreDiscoveryKey }) {
|
|
|
1086
1091
|
}
|
|
1087
1092
|
return doc
|
|
1088
1093
|
}
|
|
1094
|
+
|
|
1095
|
+
/**
|
|
1096
|
+
*
|
|
1097
|
+
* @param {string} baseUrl
|
|
1098
|
+
* @param {string} projectPublicId
|
|
1099
|
+
* @returns {string}
|
|
1100
|
+
*/
|
|
1101
|
+
export function baseUrlToWS(baseUrl, projectPublicId) {
|
|
1102
|
+
const wsUrl = new URL(`/sync/${projectPublicId}`, baseUrl)
|
|
1103
|
+
wsUrl.protocol = wsUrl.protocol === 'http:' ? 'ws:' : 'wss:'
|
|
1104
|
+
|
|
1105
|
+
return wsUrl.href
|
|
1106
|
+
}
|
package/src/member-api.js
CHANGED
|
@@ -19,7 +19,12 @@ import { isHostnameIpAddress } from './lib/is-hostname-ip-address.js'
|
|
|
19
19
|
import { ErrorWithCode, getErrorMessage } from './lib/error.js'
|
|
20
20
|
import { InviteAbortedError } from './errors.js'
|
|
21
21
|
import { wsCoreReplicator } from './lib/ws-core-replicator.js'
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
BLOCKED_ROLE_ID,
|
|
24
|
+
MEMBER_ROLE_ID,
|
|
25
|
+
ROLES,
|
|
26
|
+
isRoleIdForNewInvite,
|
|
27
|
+
} from './roles.js'
|
|
23
28
|
/**
|
|
24
29
|
* @import {
|
|
25
30
|
* DeviceInfo,
|
|
@@ -57,6 +62,7 @@ export class MemberApi extends TypedEmitter {
|
|
|
57
62
|
#getProjectName
|
|
58
63
|
#projectKey
|
|
59
64
|
#rpc
|
|
65
|
+
#makeWebsocket
|
|
60
66
|
#getReplicationStream
|
|
61
67
|
#waitForInitialSyncWithPeer
|
|
62
68
|
#dataTypes
|
|
@@ -73,6 +79,7 @@ export class MemberApi extends TypedEmitter {
|
|
|
73
79
|
* @param {() => Promisable<undefined | string>} opts.getProjectName
|
|
74
80
|
* @param {Buffer} opts.projectKey
|
|
75
81
|
* @param {import('./local-peers.js').LocalPeers} opts.rpc
|
|
82
|
+
* @param {(url: string) => WebSocket} [opts.makeWebsocket]
|
|
76
83
|
* @param {() => ReplicationStream} opts.getReplicationStream
|
|
77
84
|
* @param {(deviceId: string, abortSignal: AbortSignal) => Promise<void>} opts.waitForInitialSyncWithPeer
|
|
78
85
|
* @param {Object} opts.dataTypes
|
|
@@ -87,6 +94,7 @@ export class MemberApi extends TypedEmitter {
|
|
|
87
94
|
getProjectName,
|
|
88
95
|
projectKey,
|
|
89
96
|
rpc,
|
|
97
|
+
makeWebsocket = (url) => new WebSocket(url),
|
|
90
98
|
getReplicationStream,
|
|
91
99
|
waitForInitialSyncWithPeer,
|
|
92
100
|
dataTypes,
|
|
@@ -99,6 +107,7 @@ export class MemberApi extends TypedEmitter {
|
|
|
99
107
|
this.#getProjectName = getProjectName
|
|
100
108
|
this.#projectKey = projectKey
|
|
101
109
|
this.#rpc = rpc
|
|
110
|
+
this.#makeWebsocket = makeWebsocket
|
|
102
111
|
this.#getReplicationStream = getReplicationStream
|
|
103
112
|
this.#waitForInitialSyncWithPeer = waitForInitialSyncWithPeer
|
|
104
113
|
this.#dataTypes = dataTypes
|
|
@@ -157,12 +166,17 @@ export class MemberApi extends TypedEmitter {
|
|
|
157
166
|
const projectName = project.name
|
|
158
167
|
assert(projectName, 'Project must have a name to invite people')
|
|
159
168
|
|
|
169
|
+
const projectColor = project.projectColor
|
|
170
|
+
const projectDescription = project.projectDescription
|
|
171
|
+
|
|
160
172
|
abortSignal.throwIfAborted()
|
|
161
173
|
|
|
162
174
|
const invite = {
|
|
163
175
|
inviteId,
|
|
164
176
|
projectInviteId,
|
|
165
177
|
projectName,
|
|
178
|
+
projectColor,
|
|
179
|
+
projectDescription,
|
|
166
180
|
roleName,
|
|
167
181
|
roleDescription,
|
|
168
182
|
invitorName,
|
|
@@ -186,18 +200,16 @@ export class MemberApi extends TypedEmitter {
|
|
|
186
200
|
case InviteResponse_Decision.DECISION_UNSPECIFIED:
|
|
187
201
|
return InviteResponse_Decision.REJECT
|
|
188
202
|
case InviteResponse_Decision.ACCEPT:
|
|
189
|
-
// We should assign the role locally *before* sharing the project details
|
|
190
|
-
// so that they're part of the project even if they don't receive the
|
|
191
|
-
// project details message.
|
|
192
|
-
|
|
193
|
-
await this.#roles.assignRole(deviceId, roleId)
|
|
194
|
-
|
|
195
203
|
await this.#rpc.sendProjectJoinDetails(deviceId, {
|
|
196
204
|
inviteId,
|
|
197
205
|
projectKey: this.#projectKey,
|
|
198
206
|
encryptionKeys: this.#encryptionKeys,
|
|
199
207
|
})
|
|
200
208
|
|
|
209
|
+
// Only add after we know they got the details
|
|
210
|
+
// Otherwise the joiner will be stuck unable to join
|
|
211
|
+
await this.#roles.assignRole(deviceId, roleId)
|
|
212
|
+
|
|
201
213
|
return inviteResponse.decision
|
|
202
214
|
default:
|
|
203
215
|
throw new ExhaustivenessError(inviteResponse.decision)
|
|
@@ -314,6 +326,46 @@ export class MemberApi extends TypedEmitter {
|
|
|
314
326
|
})
|
|
315
327
|
}
|
|
316
328
|
|
|
329
|
+
/**
|
|
330
|
+
* Remove a server peer. Only works when the peer is reachable
|
|
331
|
+
*
|
|
332
|
+
* @param {string} serverDeviceId
|
|
333
|
+
* @param {object} [options]
|
|
334
|
+
* @param {boolean} [options.dangerouslyAllowInsecureConnections] Allow insecure network connections. Should only be used in tests.
|
|
335
|
+
* @returns {Promise<void>}
|
|
336
|
+
*/
|
|
337
|
+
async removeServerPeer(
|
|
338
|
+
serverDeviceId,
|
|
339
|
+
{ dangerouslyAllowInsecureConnections = false } = {}
|
|
340
|
+
) {
|
|
341
|
+
// Get device ID for URL
|
|
342
|
+
// Parse through URL to ensure end pathname if missing
|
|
343
|
+
const member = await this.getById(serverDeviceId)
|
|
344
|
+
|
|
345
|
+
if (!member.selfHostedServerDetails) {
|
|
346
|
+
throw new ErrorWithCode(
|
|
347
|
+
'DEVICE_ID_NOT_FOR_SERVER',
|
|
348
|
+
'DeviceId is not for a server peer'
|
|
349
|
+
)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (member.role.roleId === BLOCKED_ROLE_ID) {
|
|
353
|
+
throw new ErrorWithCode('ALREADY_BLOCKED', 'Server peer already blocked')
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const { baseUrl } = member.selfHostedServerDetails
|
|
357
|
+
|
|
358
|
+
// Add blocked role to project
|
|
359
|
+
await this.#roles.assignRole(serverDeviceId, BLOCKED_ROLE_ID)
|
|
360
|
+
|
|
361
|
+
// TODO: Catch fail and sync with server after
|
|
362
|
+
await this.#waitForInitialSyncWithServer({
|
|
363
|
+
baseUrl,
|
|
364
|
+
serverDeviceId,
|
|
365
|
+
dangerouslyAllowInsecureConnections,
|
|
366
|
+
})
|
|
367
|
+
}
|
|
368
|
+
|
|
317
369
|
/**
|
|
318
370
|
* @param {string} baseUrl Server base URL. Should already be validated.
|
|
319
371
|
* @returns {Promise<{ serverDeviceId: string }>}
|
|
@@ -378,7 +430,7 @@ export class MemberApi extends TypedEmitter {
|
|
|
378
430
|
? 'ws:'
|
|
379
431
|
: 'wss:'
|
|
380
432
|
|
|
381
|
-
const websocket =
|
|
433
|
+
const websocket = this.#makeWebsocket(websocketUrl.href)
|
|
382
434
|
|
|
383
435
|
try {
|
|
384
436
|
await pEvent(websocket, 'open', { rejectionEvents: ['error'] })
|
|
@@ -400,7 +452,7 @@ export class MemberApi extends TypedEmitter {
|
|
|
400
452
|
const onErrorPromise = pEvent(websocket, 'error')
|
|
401
453
|
|
|
402
454
|
const replicationStream = this.#getReplicationStream()
|
|
403
|
-
wsCoreReplicator(websocket, replicationStream)
|
|
455
|
+
const streamPromise = wsCoreReplicator(websocket, replicationStream)
|
|
404
456
|
|
|
405
457
|
const syncAbortController = new AbortController()
|
|
406
458
|
const syncPromise = this.#waitForInitialSyncWithPeer(
|
|
@@ -408,7 +460,11 @@ export class MemberApi extends TypedEmitter {
|
|
|
408
460
|
syncAbortController.signal
|
|
409
461
|
)
|
|
410
462
|
|
|
411
|
-
const errorEvent = await Promise.race([
|
|
463
|
+
const errorEvent = await Promise.race([
|
|
464
|
+
onErrorPromise,
|
|
465
|
+
syncPromise,
|
|
466
|
+
streamPromise,
|
|
467
|
+
])
|
|
412
468
|
|
|
413
469
|
if (errorEvent) {
|
|
414
470
|
syncAbortController.abort()
|
|
@@ -445,6 +501,7 @@ export class MemberApi extends TypedEmitter {
|
|
|
445
501
|
result.name = deviceInfo.name
|
|
446
502
|
result.deviceType = deviceInfo.deviceType
|
|
447
503
|
result.joinedAt = deviceInfo.createdAt
|
|
504
|
+
result.selfHostedServerDetails = deviceInfo.selfHostedServerDetails
|
|
448
505
|
} catch (err) {
|
|
449
506
|
// Attempting to get someone else may throw because sync hasn't occurred or completed
|
|
450
507
|
// Only throw if attempting to get themself since the relevant information should be available
|
package/src/schema/client.js
CHANGED
|
@@ -7,9 +7,10 @@ import { jsonSchemaToDrizzleColumns as toColumns } from './schema-to-drizzle.js'
|
|
|
7
7
|
import { backlinkTable, customJson } from './utils.js'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
+
* @import { ProjectSettings } from '@comapeo/schema'
|
|
11
|
+
*
|
|
10
12
|
* @internal
|
|
11
|
-
* @typedef {
|
|
12
|
-
* @prop {string} [name]
|
|
13
|
+
* @typedef {Pick<ProjectSettings, 'name' | 'projectColor' | 'projectDescription'>} ProjectInfo
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
16
|
const projectInfoColumn =
|
package/src/sync/sync-api.js
CHANGED
|
@@ -99,12 +99,14 @@ export class SyncApi extends TypedEmitter {
|
|
|
99
99
|
#getReplicationStream
|
|
100
100
|
/** @type {Map<string, WebSocket>} */
|
|
101
101
|
#serverWebsockets = new Map()
|
|
102
|
+
#makeWebsocket
|
|
102
103
|
|
|
103
104
|
/**
|
|
104
105
|
* @param {object} opts
|
|
105
106
|
* @param {import('../core-manager/index.js').CoreManager} opts.coreManager
|
|
106
107
|
* @param {CoreOwnership} opts.coreOwnership
|
|
107
108
|
* @param {import('../roles.js').Roles} opts.roles
|
|
109
|
+
* @param {(url: string) => WebSocket} [opts.makeWebsocket]
|
|
108
110
|
* @param {() => Promise<Iterable<string>>} opts.getServerWebsocketUrls
|
|
109
111
|
* @param {() => ReplicationStream} opts.getReplicationStream
|
|
110
112
|
* @param {import('../blob-store/index.js').BlobStore} opts.blobStore
|
|
@@ -115,6 +117,7 @@ export class SyncApi extends TypedEmitter {
|
|
|
115
117
|
coreManager,
|
|
116
118
|
throttleMs = 200,
|
|
117
119
|
roles,
|
|
120
|
+
makeWebsocket = (url) => new WebSocket(url),
|
|
118
121
|
getServerWebsocketUrls,
|
|
119
122
|
getReplicationStream,
|
|
120
123
|
logger,
|
|
@@ -126,6 +129,7 @@ export class SyncApi extends TypedEmitter {
|
|
|
126
129
|
this.#coreManager = coreManager
|
|
127
130
|
this.#coreOwnership = coreOwnership
|
|
128
131
|
this.#roles = roles
|
|
132
|
+
this.#makeWebsocket = makeWebsocket
|
|
129
133
|
this.#getServerWebsocketUrls = getServerWebsocketUrls
|
|
130
134
|
this.#getReplicationStream = getReplicationStream
|
|
131
135
|
this[kSyncState] = new SyncState({
|
|
@@ -332,7 +336,7 @@ export class SyncApi extends TypedEmitter {
|
|
|
332
336
|
continue
|
|
333
337
|
}
|
|
334
338
|
|
|
335
|
-
const websocket =
|
|
339
|
+
const websocket = this.#makeWebsocket(url)
|
|
336
340
|
|
|
337
341
|
/** @param {Error} err */
|
|
338
342
|
const onWebsocketError = (err) => {
|
|
@@ -354,7 +358,7 @@ export class SyncApi extends TypedEmitter {
|
|
|
354
358
|
websocket.on('unexpected-response', onWebsocketUnexpectedResponse)
|
|
355
359
|
|
|
356
360
|
const replicationStream = this.#getReplicationStream()
|
|
357
|
-
wsCoreReplicator(websocket, replicationStream)
|
|
361
|
+
wsCoreReplicator(websocket, replicationStream).catch(noop)
|
|
358
362
|
|
|
359
363
|
this.#serverWebsockets.set(url, websocket)
|
|
360
364
|
websocket.once('close', () => {
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reduce multiple states into one. Factored out for unit testing because I
|
|
3
|
-
* don't trust my coding. Probably a smarter way to do this, but this works.
|
|
4
|
-
*
|
|
5
|
-
* @param {Iterable<{ state: BlobDownloadState | BlobDownloadStateError }>} liveDownloads
|
|
6
|
-
* @param {{ signal?: AbortSignal }} options
|
|
7
|
-
* @returns {BlobDownloadState | BlobDownloadStateError}
|
|
8
|
-
*/
|
|
9
|
-
export function combineStates(liveDownloads: Iterable<{
|
|
10
|
-
state: BlobDownloadState | BlobDownloadStateError;
|
|
11
|
-
}>, { signal }?: {
|
|
12
|
-
signal?: AbortSignal;
|
|
13
|
-
}): BlobDownloadState | BlobDownloadStateError;
|
|
14
|
-
/**
|
|
15
|
-
* @typedef {object} BlobDownloadState
|
|
16
|
-
* @property {number} haveCount The number of files already downloaded
|
|
17
|
-
* @property {number} haveBytes The bytes already downloaded
|
|
18
|
-
* @property {number} wantCount The number of files pending download
|
|
19
|
-
* @property {number} wantBytes The bytes pending download
|
|
20
|
-
* @property {null} error If status = 'error' then this will be an Error object
|
|
21
|
-
* @property {'checking' | 'downloading' | 'downloaded' | 'aborted'} status
|
|
22
|
-
*/
|
|
23
|
-
/** @typedef {Omit<BlobDownloadState, 'error' | 'status'> & { status: 'error', error: Error }} BlobDownloadStateError */
|
|
24
|
-
/**
|
|
25
|
-
* @typedef {object} BlobDownloadEvents
|
|
26
|
-
* @property {(state: BlobDownloadState | BlobDownloadStateError ) => void} state Emitted with the current download state whenever it changes (not emitted during initial 'checking' status)
|
|
27
|
-
*/
|
|
28
|
-
/**
|
|
29
|
-
* LiveDownload class
|
|
30
|
-
* @extends {TypedEmitter<BlobDownloadEvents>}
|
|
31
|
-
*/
|
|
32
|
-
export class LiveDownload extends TypedEmitter<BlobDownloadEvents> {
|
|
33
|
-
/**
|
|
34
|
-
* Like drive.download() but 'live', and for multiple drives
|
|
35
|
-
* @param {Iterable<import('hyperdrive')>} drives
|
|
36
|
-
* @param {import('./index.js').InternalDriveEmitter} emitter
|
|
37
|
-
* @param {object} options
|
|
38
|
-
* @param {import('../types.js').BlobFilter} [options.filter] Filter blobs of specific types and/or sizes to download
|
|
39
|
-
* @param {AbortSignal} [options.signal]
|
|
40
|
-
*/
|
|
41
|
-
constructor(drives: Iterable<import("hyperdrive")>, emitter: import("./index.js").InternalDriveEmitter, { filter, signal }: {
|
|
42
|
-
filter?: import("../types.js").BlobFilter | undefined;
|
|
43
|
-
signal?: AbortSignal | undefined;
|
|
44
|
-
});
|
|
45
|
-
/**
|
|
46
|
-
* @returns {BlobDownloadState | BlobDownloadStateError}
|
|
47
|
-
*/
|
|
48
|
-
get state(): BlobDownloadState | BlobDownloadStateError;
|
|
49
|
-
#private;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* LiveDownload class
|
|
53
|
-
* @extends {TypedEmitter<BlobDownloadEvents>}
|
|
54
|
-
*/
|
|
55
|
-
export class DriveLiveDownload extends TypedEmitter<BlobDownloadEvents> {
|
|
56
|
-
/**
|
|
57
|
-
* Like drive.download() but 'live',
|
|
58
|
-
* @param {import('hyperdrive')} drive
|
|
59
|
-
* @param {object} options
|
|
60
|
-
* @param {import('../types.js').BlobFilter} [options.filter] Filter blobs of specific types and/or sizes to download
|
|
61
|
-
* @param {AbortSignal} [options.signal]
|
|
62
|
-
*/
|
|
63
|
-
constructor(drive: import("hyperdrive"), { filter, signal }?: {
|
|
64
|
-
filter?: import("../types.js").BlobFilter | undefined;
|
|
65
|
-
signal?: AbortSignal | undefined;
|
|
66
|
-
});
|
|
67
|
-
/**
|
|
68
|
-
* @returns {BlobDownloadState | BlobDownloadStateError}
|
|
69
|
-
*/
|
|
70
|
-
get state(): BlobDownloadState | BlobDownloadStateError;
|
|
71
|
-
#private;
|
|
72
|
-
}
|
|
73
|
-
export type BlobDownloadState = {
|
|
74
|
-
/**
|
|
75
|
-
* The number of files already downloaded
|
|
76
|
-
*/
|
|
77
|
-
haveCount: number;
|
|
78
|
-
/**
|
|
79
|
-
* The bytes already downloaded
|
|
80
|
-
*/
|
|
81
|
-
haveBytes: number;
|
|
82
|
-
/**
|
|
83
|
-
* The number of files pending download
|
|
84
|
-
*/
|
|
85
|
-
wantCount: number;
|
|
86
|
-
/**
|
|
87
|
-
* The bytes pending download
|
|
88
|
-
*/
|
|
89
|
-
wantBytes: number;
|
|
90
|
-
/**
|
|
91
|
-
* If status = 'error' then this will be an Error object
|
|
92
|
-
*/
|
|
93
|
-
error: null;
|
|
94
|
-
status: "checking" | "downloading" | "downloaded" | "aborted";
|
|
95
|
-
};
|
|
96
|
-
export type BlobDownloadStateError = Omit<BlobDownloadState, "error" | "status"> & {
|
|
97
|
-
status: "error";
|
|
98
|
-
error: Error;
|
|
99
|
-
};
|
|
100
|
-
export type BlobDownloadEvents = {
|
|
101
|
-
/**
|
|
102
|
-
* Emitted with the current download state whenever it changes (not emitted during initial 'checking' status)
|
|
103
|
-
*/
|
|
104
|
-
state: (state: BlobDownloadState | BlobDownloadStateError) => void;
|
|
105
|
-
};
|
|
106
|
-
import { TypedEmitter } from 'tiny-typed-emitter';
|
|
107
|
-
//# sourceMappingURL=live-download.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"live-download.d.ts","sourceRoot":"","sources":["../../src/blob-store/live-download.js"],"names":[],"mappings":"AA+RA;;;;;;;GAOG;AACH,6CAJW,QAAQ,CAAC;IAAE,KAAK,EAAE,iBAAiB,GAAG,sBAAsB,CAAA;CAAE,CAAC,eAC/D;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GACtB,iBAAiB,GAAG,sBAAsB,CAqCtD;AApUD;;;;;;;;GAQG;AAEH,wHAAwH;AAExH;;;GAGG;AAEH;;;GAGG;AACH;IAKE;;;;;;;OAOG;IACH,oBANW,QAAQ,CAAC,OAAO,YAAY,CAAC,CAAC,WAC9B,OAAO,YAAY,EAAE,oBAAoB,sBAEjD;QAAmD,MAAM;QAC3B,MAAM;KAAC,EAiCvC;IAED;;OAEG;IACH,wDAEC;;CACF;AAED;;;GAGG;AACH;IAaE;;;;;;OAMG;IACH,mBALW,OAAO,YAAY,CAAC,uBAE5B;QAAmD,MAAM;QAC3B,MAAM;KAAC,EAmBvC;IAED;;OAEG;IACH,wDAyBC;;CAqIF;;;;;eArRa,MAAM;;;;eACN,MAAM;;;;eACN,MAAM;;;;eACN,MAAM;;;;WACN,IAAI;YACJ,UAAU,GAAG,aAAa,GAAG,YAAY,GAAG,SAAS;;qCAGrD,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,QAAQ,CAAC,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE;;;;;WAI/E,CAAC,KAAK,EAAE,iBAAiB,GAAG,sBAAsB,KAAM,IAAI;;6BApB7C,oBAAoB"}
|
package/dist/capabilities.d.ts
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
export const COORDINATOR_ROLE_ID: "f7c150f5a3a9a855";
|
|
2
|
-
export const MEMBER_ROLE_ID: "012fd2d431c0bf60";
|
|
3
|
-
export const BLOCKED_ROLE_ID: "9e6d29263cba36c9";
|
|
4
|
-
export const LEFT_ROLE_ID: "8ced989b1904606b";
|
|
5
|
-
/**
|
|
6
|
-
* @typedef {object} DocCapability
|
|
7
|
-
* @property {boolean} readOwn - can read own data
|
|
8
|
-
* @property {boolean} writeOwn - can write own data
|
|
9
|
-
* @property {boolean} readOthers - can read other's data
|
|
10
|
-
* @property {boolean} writeOthers - can edit or delete other's data
|
|
11
|
-
*/
|
|
12
|
-
/**
|
|
13
|
-
* @typedef {object} Capability
|
|
14
|
-
* @property {string} name
|
|
15
|
-
* @property {Record<import('@mapeo/schema').MapeoDoc['schemaName'], DocCapability>} docs
|
|
16
|
-
* @property {RoleId[]} roleAssignment
|
|
17
|
-
* @property {Record<import('./core-manager/core-index.js').Namespace, 'allowed' | 'blocked'>} sync
|
|
18
|
-
*/
|
|
19
|
-
/**
|
|
20
|
-
* @typedef {typeof COORDINATOR_ROLE_ID | typeof MEMBER_ROLE_ID | typeof BLOCKED_ROLE_ID | typeof LEFT_ROLE_ID} RoleId
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* This is currently the same as 'Coordinator' capabilities, but defined
|
|
24
|
-
* separately because the creator should always have ALL capabilities, but we
|
|
25
|
-
* could edit 'Coordinator' capabilities in the future
|
|
26
|
-
*
|
|
27
|
-
* @type {Capability}
|
|
28
|
-
*/
|
|
29
|
-
export const CREATOR_CAPABILITIES: Capability;
|
|
30
|
-
/**
|
|
31
|
-
* These are the capabilities assumed for a device when no capability record can
|
|
32
|
-
* be found. This can happen when an invited device did not manage to sync with
|
|
33
|
-
* the device that invited them, and they then try to sync with someone else. We
|
|
34
|
-
* want them to be able to sync the auth and config store, because that way they
|
|
35
|
-
* may be able to receive their role record, and they can get the project config
|
|
36
|
-
* so that they can start collecting data.
|
|
37
|
-
*
|
|
38
|
-
* @type {Capability}
|
|
39
|
-
*/
|
|
40
|
-
export const NO_ROLE_CAPABILITIES: Capability;
|
|
41
|
-
/** @type {Record<RoleId, Capability>} */
|
|
42
|
-
export const DEFAULT_CAPABILITIES: Record<RoleId, Capability>;
|
|
43
|
-
export class Capabilities {
|
|
44
|
-
static NO_ROLE_CAPABILITIES: Capability;
|
|
45
|
-
/**
|
|
46
|
-
*
|
|
47
|
-
* @param {object} opts
|
|
48
|
-
* @param {import('./datatype/index.js').DataType<
|
|
49
|
-
* import('./datastore/index.js').DataStore<'auth'>,
|
|
50
|
-
* typeof import('./schema/project.js').roleTable,
|
|
51
|
-
* 'role',
|
|
52
|
-
* import('@mapeo/schema').Role,
|
|
53
|
-
* import('@mapeo/schema').RoleValue
|
|
54
|
-
* >} opts.dataType
|
|
55
|
-
* @param {import('./core-ownership.js').CoreOwnership} opts.coreOwnership
|
|
56
|
-
* @param {import('./core-manager/index.js').CoreManager} opts.coreManager
|
|
57
|
-
* @param {Buffer} opts.projectKey
|
|
58
|
-
* @param {Buffer} opts.deviceKey public key of this device
|
|
59
|
-
*/
|
|
60
|
-
constructor({ dataType, coreOwnership, coreManager, projectKey, deviceKey }: {
|
|
61
|
-
dataType: import('./datatype/index.js').DataType<import('./datastore/index.js').DataStore<'auth'>, typeof import('./schema/project.js').roleTable, 'role', import('@mapeo/schema').Role, import('@mapeo/schema').RoleValue>;
|
|
62
|
-
coreOwnership: import('./core-ownership.js').CoreOwnership;
|
|
63
|
-
coreManager: import('./core-manager/index.js').CoreManager;
|
|
64
|
-
projectKey: Buffer;
|
|
65
|
-
deviceKey: Buffer;
|
|
66
|
-
});
|
|
67
|
-
/**
|
|
68
|
-
* Get the capabilities for device `deviceId`.
|
|
69
|
-
*
|
|
70
|
-
* @param {string} deviceId
|
|
71
|
-
* @returns {Promise<Capability>}
|
|
72
|
-
*/
|
|
73
|
-
getCapabilities(deviceId: string): Promise<Capability>;
|
|
74
|
-
/**
|
|
75
|
-
* Get capabilities of all devices in the project. For your own device, if you
|
|
76
|
-
* have not yet synced your own role record, the "no role" capabilties is
|
|
77
|
-
* returned. The project creator will have `CREATOR_CAPABILITIES` unless a
|
|
78
|
-
* different role has been assigned.
|
|
79
|
-
*
|
|
80
|
-
* @returns {Promise<Record<string, Capability>>} Map of deviceId to Capability
|
|
81
|
-
*/
|
|
82
|
-
getAll(): Promise<Record<string, Capability>>;
|
|
83
|
-
/**
|
|
84
|
-
* Assign a role to the specified `deviceId`. Devices without an assigned role
|
|
85
|
-
* are unable to sync, except the project creator that defaults to having all
|
|
86
|
-
* capabilities. Only the project creator can assign their own role. Will
|
|
87
|
-
* throw if the device trying to assign the role lacks the `roleAssignment`
|
|
88
|
-
* capability for the given roleId
|
|
89
|
-
*
|
|
90
|
-
* @param {string} deviceId
|
|
91
|
-
* @param {keyof typeof DEFAULT_CAPABILITIES} roleId
|
|
92
|
-
*/
|
|
93
|
-
assignRole(deviceId: string, roleId: keyof typeof DEFAULT_CAPABILITIES): Promise<void>;
|
|
94
|
-
#private;
|
|
95
|
-
}
|
|
96
|
-
export type DocCapability = {
|
|
97
|
-
/**
|
|
98
|
-
* - can read own data
|
|
99
|
-
*/
|
|
100
|
-
readOwn: boolean;
|
|
101
|
-
/**
|
|
102
|
-
* - can write own data
|
|
103
|
-
*/
|
|
104
|
-
writeOwn: boolean;
|
|
105
|
-
/**
|
|
106
|
-
* - can read other's data
|
|
107
|
-
*/
|
|
108
|
-
readOthers: boolean;
|
|
109
|
-
/**
|
|
110
|
-
* - can edit or delete other's data
|
|
111
|
-
*/
|
|
112
|
-
writeOthers: boolean;
|
|
113
|
-
};
|
|
114
|
-
export type Capability = {
|
|
115
|
-
name: string;
|
|
116
|
-
docs: Record<import('@mapeo/schema').MapeoDoc['schemaName'], DocCapability>;
|
|
117
|
-
roleAssignment: RoleId[];
|
|
118
|
-
sync: Record<import('./core-manager/core-index.js').Namespace, 'allowed' | 'blocked'>;
|
|
119
|
-
};
|
|
120
|
-
export type RoleId = typeof COORDINATOR_ROLE_ID | typeof MEMBER_ROLE_ID | typeof BLOCKED_ROLE_ID | typeof LEFT_ROLE_ID;
|
|
121
|
-
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.js"],"names":[],"mappings":"AAKA,qDAAqD;AACrD,gDAAgD;AAChD,iDAAiD;AACjD,8CAA8C;AAE9C;;;;;;GAMG;AAEH;;;;;;GAMG;AAEH;;GAEG;AAEH;;;;;;GAMG;AACH,mCAFU,UAAU,CAkBnB;AAED;;;;;;;;;GASG;AACH,mCAFU,UAAU,CAkBnB;AAED,yCAAyC;AACzC,mCADW,OAAO,MAAM,EAAE,UAAU,CAAC,CAgFpC;AAED;IAOE,wCAAkD;IAElD;;;;;;;;;;;;;;OAcG;IACH;QANW,QAAQ,EANR,OAAO,qBAAqB,EAAE,QAAQ,CAChD,OAAW,sBAAsB,EAAE,SAAS,CAAC,MAAM,CAAC,EACpD,cAAkB,qBAAqB,EAAE,SAAS,EAClD,MAAU,EACV,OAAW,eAAe,EAAE,IAAI,EAChC,OAAW,eAAe,EAAE,SAAS,CAClC;QACyD,aAAa,EAA/D,OAAO,qBAAqB,EAAE,aAAa;QACS,WAAW,EAA/D,OAAO,yBAAyB,EAAE,WAAW;QAChC,UAAU,EAAvB,MAAM;QACO,SAAS,EAAtB,MAAM;OAQhB;IAED;;;;;OAKG;IACH,0BAHW,MAAM,GACJ,QAAQ,UAAU,CAAC,CAuB/B;IAED;;;;;;;OAOG;IACH,UAFa,QAAQ,OAAO,MAAM,EAAE,UAAU,CAAC,CAAC,CAkC/C;IAED;;;;;;;;;OASG;IACH,qBAHW,MAAM,UACN,MAAM,2BAA2B,iBAyD3C;;CAQF;;;;;aAzUa,OAAO;;;;cACP,OAAO;;;;gBACP,OAAO;;;;iBACP,OAAO;;;UAKP,MAAM;UACN,OAAO,OAAO,eAAe,EAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC;oBACrE,MAAM,EAAE;UACR,OAAO,OAAO,8BAA8B,EAAE,SAAS,EAAE,SAAS,GAAG,SAAS,CAAC;;qBAIhF,0BAA0B,GAAG,qBAAqB,GAAG,sBAAsB,GAAG,mBAAmB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../../src/core-manager/compat.js"],"names":[],"mappings":";AAOA,sCAAwB"}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @typedef {object} MapeoService
|
|
3
|
-
* @property {string} address IPv4 address of service
|
|
4
|
-
* @property {number} port
|
|
5
|
-
* @property {string} name Instance name
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {object} DnsSdEvents
|
|
9
|
-
* @property {(service: MapeoService) => void} up
|
|
10
|
-
* @property {(service: MapeoService) => void} down
|
|
11
|
-
*/
|
|
12
|
-
/**
|
|
13
|
-
* @extends {TypedEmitter<DnsSdEvents>}
|
|
14
|
-
*/
|
|
15
|
-
export class DnsSd extends TypedEmitter<DnsSdEvents> {
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
* @param {object} [opts]
|
|
19
|
-
* @param {string} [opts.name]
|
|
20
|
-
* @param {boolean} [opts.disableIpv6]
|
|
21
|
-
* @param {Logger} [opts.logger]
|
|
22
|
-
*/
|
|
23
|
-
constructor({ name, disableIpv6, logger }?: {
|
|
24
|
-
name?: string | undefined;
|
|
25
|
-
disableIpv6?: boolean | undefined;
|
|
26
|
-
logger?: Logger | undefined;
|
|
27
|
-
} | undefined);
|
|
28
|
-
get name(): string;
|
|
29
|
-
/** @param {number} port */
|
|
30
|
-
advertise(port: number): Promise<void>;
|
|
31
|
-
browse(): void;
|
|
32
|
-
stopAdvertising(): Promise<void>;
|
|
33
|
-
stopBrowsing(): void;
|
|
34
|
-
destroy(): Promise<void>;
|
|
35
|
-
#private;
|
|
36
|
-
}
|
|
37
|
-
export type MapeoService = {
|
|
38
|
-
/**
|
|
39
|
-
* IPv4 address of service
|
|
40
|
-
*/
|
|
41
|
-
address: string;
|
|
42
|
-
port: number;
|
|
43
|
-
/**
|
|
44
|
-
* Instance name
|
|
45
|
-
*/
|
|
46
|
-
name: string;
|
|
47
|
-
};
|
|
48
|
-
export type DnsSdEvents = {
|
|
49
|
-
up: (service: MapeoService) => void;
|
|
50
|
-
down: (service: MapeoService) => void;
|
|
51
|
-
};
|
|
52
|
-
import { TypedEmitter } from 'tiny-typed-emitter';
|
|
53
|
-
import { Logger } from '../logger.js';
|
|
54
|
-
//# sourceMappingURL=dns-sd.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dns-sd.d.ts","sourceRoot":"","sources":["../../src/discovery/dns-sd.js"],"names":[],"mappings":"AAUA;;;;;GAKG;AAEH;;;;GAIG;AAEH;;GAEG;AACH;IAoDE;;;;;;OAMG;IACH;;;;mBAMC;IAED,mBAEC;IAED,2BAA2B;IAC3B,gBADY,MAAM,iBA+BjB;IAED,eAiBC;IAED,iCAeC;IAED,qBAKC;IAED,yBA0BC;;CA+BF;;;;;aA1Na,MAAM;UACN,MAAM;;;;UACN,MAAM;;;kBAKI,YAAY,KAAK,IAAI;oBACrB,YAAY,KAAK,IAAI;;6BApBhB,oBAAoB;uBAM1B,cAAc"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export const PLUGIN_NAME: "mapeo-maps";
|
|
2
|
-
export const DEFAULT_MAPBOX_STYLE_URL: "https://api.mapbox.com/styles/v1/mapbox/outdoors-v12";
|
|
3
|
-
export function plugin(instance: import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>, opts: MapsPluginOpts): Promise<void>;
|
|
4
|
-
export type MapsPluginOpts = {
|
|
5
|
-
prefix?: string | undefined;
|
|
6
|
-
defaultOnlineStyleUrl?: string | undefined;
|
|
7
|
-
};
|
|
8
|
-
export type MapsPluginContext = {
|
|
9
|
-
getStyleJsonUrl: () => Promise<string>;
|
|
10
|
-
};
|
|
11
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fastify-plugins/maps/index.js"],"names":[],"mappings":"AAYA,uCAAuC;AACvC,8FACwD;;;;;;;qBA8B1C,MAAM,OAAO,CAAC,MAAM,CAAC"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export const PLUGIN_NAME: "mapeo-static-maps";
|
|
2
|
-
export function plugin(instance: import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>, opts: OfflineFallbackMapPluginOpts): Promise<void>;
|
|
3
|
-
export type OfflineFallbackMapPluginOpts = {
|
|
4
|
-
prefix?: string | undefined;
|
|
5
|
-
styleJsonPath: string;
|
|
6
|
-
sourcesDir: string;
|
|
7
|
-
};
|
|
8
|
-
export type FallbackMapPluginDecorator = {
|
|
9
|
-
getResolvedStyleJson: (serverAddress: string) => Promise<any>;
|
|
10
|
-
getStyleJsonStats: () => Promise<import("node:fs").Stats>;
|
|
11
|
-
};
|
|
12
|
-
//# sourceMappingURL=offline-fallback-map.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"offline-fallback-map.d.ts","sourceRoot":"","sources":["../../../src/fastify-plugins/maps/offline-fallback-map.js"],"names":[],"mappings":"AAWA,8CAA8C;;;;mBAUhC,MAAM;gBACN,MAAM;;;0BAKN,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC;uBACvC,MAAM,OAAO,CAAC,OAAO,SAAS,EAAE,KAAK,CAAC"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export const PLUGIN_NAME: "mapeo-static-maps";
|
|
2
|
-
export function plugin(instance: import("fastify").FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>, opts: StaticMapsPluginOpts): Promise<void>;
|
|
3
|
-
export type StaticMapsPluginOpts = {
|
|
4
|
-
prefix?: string | undefined;
|
|
5
|
-
staticRootDir: string;
|
|
6
|
-
};
|
|
7
|
-
export type StaticMapsPluginDecorator = {
|
|
8
|
-
getResolvedStyleJson: (styleId: string, serverAddress: string) => Promise<string>;
|
|
9
|
-
getStyleJsonStats: (styleId: string) => Promise<import("node:fs").Stats>;
|
|
10
|
-
};
|
|
11
|
-
//# sourceMappingURL=static-maps.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static-maps.d.ts","sourceRoot":"","sources":["../../../src/fastify-plugins/maps/static-maps.js"],"names":[],"mappings":"AAeA,8CAA8C;;;;mBAUhC,MAAM;;;0BAKN,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC;uBAC3D,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,SAAS,EAAE,KAAK,CAAC"}
|