@comapeo/core 6.0.2 → 7.0.1
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/blob-store/downloader.d.ts +4 -9
- package/dist/blob-store/downloader.d.ts.map +1 -1
- package/dist/blob-store/hyperdrive-index.d.ts +4 -5
- package/dist/blob-store/hyperdrive-index.d.ts.map +1 -1
- package/dist/blob-store/index.d.ts +4 -5
- package/dist/blob-store/index.d.ts.map +1 -1
- package/dist/core-manager/index.d.ts +4 -23
- package/dist/core-manager/index.d.ts.map +1 -1
- package/dist/datastore/index.d.ts +1 -1
- package/dist/generated/extensions.d.ts +0 -30
- package/dist/generated/extensions.d.ts.map +1 -1
- package/dist/generated/rpc.d.ts +30 -0
- package/dist/generated/rpc.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/local-peers.d.ts +12 -0
- package/dist/local-peers.d.ts.map +1 -1
- package/dist/mapeo-manager.d.ts +41 -3
- package/dist/mapeo-manager.d.ts.map +1 -1
- package/dist/mapeo-project.d.ts +3 -76
- package/dist/mapeo-project.d.ts.map +1 -1
- package/dist/schema/project.d.ts +1 -1
- package/dist/sync/namespace-sync-state.d.ts +1 -1
- package/dist/sync/peer-sync-controller.d.ts +1 -1
- package/dist/sync/sync-api.d.ts.map +1 -1
- package/dist/utils.d.ts +3 -3
- package/dist/utils.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/blob-store/downloader.js +12 -4
- package/src/blob-store/hyperdrive-index.js +22 -3
- package/src/blob-store/index.js +18 -7
- package/src/core-manager/index.js +16 -70
- package/src/generated/extensions.d.ts +0 -30
- package/src/generated/extensions.js +0 -165
- package/src/generated/extensions.ts +0 -204
- package/src/generated/rpc.d.ts +30 -0
- package/src/generated/rpc.js +191 -0
- package/src/generated/rpc.ts +236 -0
- package/src/index.js +2 -2
- package/src/local-peers.js +33 -0
- package/src/mapeo-manager.js +93 -35
- package/src/mapeo-project.js +18 -106
- package/src/utils.js +2 -2
package/src/mapeo-project.js
CHANGED
|
@@ -3,7 +3,6 @@ import Database from 'better-sqlite3'
|
|
|
3
3
|
import { decodeBlockPrefix, decode, parseVersionId } from '@comapeo/schema'
|
|
4
4
|
import { drizzle } from 'drizzle-orm/better-sqlite3'
|
|
5
5
|
import { sql, count, eq } from 'drizzle-orm'
|
|
6
|
-
import { TypedEmitter } from 'tiny-typed-emitter'
|
|
7
6
|
import ZipArchive from 'zip-stream-promise'
|
|
8
7
|
import * as b4a from 'b4a'
|
|
9
8
|
import mime from 'mime/lite'
|
|
@@ -39,18 +38,13 @@ import {
|
|
|
39
38
|
getWinner,
|
|
40
39
|
mapAndValidateCoreOwnership,
|
|
41
40
|
} from './core-ownership.js'
|
|
42
|
-
import {
|
|
43
|
-
BLOCKED_ROLE_ID,
|
|
44
|
-
Roles,
|
|
45
|
-
LEFT_ROLE_ID,
|
|
46
|
-
INACTIVE_MEMBER_ROLE_IDS,
|
|
47
|
-
} from './roles.js'
|
|
41
|
+
import { BLOCKED_ROLE_ID, Roles, LEFT_ROLE_ID } from './roles.js'
|
|
48
42
|
import {
|
|
49
43
|
buildBlobId,
|
|
50
44
|
getDeviceId,
|
|
45
|
+
noop,
|
|
51
46
|
projectKeyToId,
|
|
52
47
|
projectKeyToPublicId,
|
|
53
|
-
validateMapShareExtension,
|
|
54
48
|
valueOf,
|
|
55
49
|
} from './utils.js'
|
|
56
50
|
import { migrate } from './lib/drizzle-helpers.js'
|
|
@@ -73,7 +67,6 @@ import {
|
|
|
73
67
|
ExhaustivenessError,
|
|
74
68
|
nullIfNotFound,
|
|
75
69
|
GeoJSONExportError,
|
|
76
|
-
InvalidMapShareError,
|
|
77
70
|
MultipleCategoryImportsError,
|
|
78
71
|
UnexpectedDocSchemaError,
|
|
79
72
|
} from './errors.js'
|
|
@@ -81,10 +74,14 @@ import { WebSocket } from 'ws'
|
|
|
81
74
|
import fs from 'node:fs'
|
|
82
75
|
|
|
83
76
|
import ensureError from 'ensure-error'
|
|
77
|
+
import ReadyResource from 'ready-resource'
|
|
78
|
+
|
|
84
79
|
/** @import { MapShareExtension } from './generated/extensions.js' */
|
|
85
80
|
/** @import { ProjectSettingsValue, Observation, Track } from '@comapeo/schema' */
|
|
86
81
|
/** @import { Attachment, CoreStorage, BlobFilter, BlobId, BlobStoreEntriesStream, KeyPair, Namespace, ReplicationStream, GenericBlobFilter, MapeoValueMap, MapeoDocMap } from './types.js' */
|
|
87
82
|
/** @import {Role} from './roles.js' */
|
|
83
|
+
/** @import { TypedEmitter } from 'tiny-typed-emitter' */
|
|
84
|
+
|
|
88
85
|
/** @typedef {Omit<ProjectSettingsValue, 'schemaName'>} EditableProjectSettings */
|
|
89
86
|
/** @typedef {ProjectSettingsValue['configMetadata']} ConfigMetadata */
|
|
90
87
|
/** @typedef {Map<string,Attachment>} SeenAttachments*/
|
|
@@ -129,36 +126,16 @@ const VARIANT_EXPORT_ORDER = ['original', 'preview', 'thumbnail']
|
|
|
129
126
|
* @property {Role & {reason: string | undefined}} role
|
|
130
127
|
*/
|
|
131
128
|
|
|
132
|
-
/**
|
|
133
|
-
* @typedef {object} AugmentedMapShareProperties
|
|
134
|
-
* @property {readonly [number, number, number, number]} bounds - Bounding box of the shared map [W, S, E, N].
|
|
135
|
-
* @property {readonly [string, ...string[]]} mapShareUrls - URLs associated with the map share.
|
|
136
|
-
* @property {number} mapShareReceivedAt - Timestamp when the map share was received.
|
|
137
|
-
* @property {string} senderDeviceId - The ID of the device that sent the map share.
|
|
138
|
-
* @property {string} [senderDeviceName] - The name of the device that sent the map share.
|
|
139
|
-
* @property {string} receiverDeviceId - The deviceId of the peer the map share was sent to
|
|
140
|
-
*/
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* @typedef {Omit<MapShareExtension, 'bounds' | 'mapShareUrls' | 'receiverDeviceKey'> & AugmentedMapShareProperties} MapShare
|
|
144
|
-
*/
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* @typedef {Omit<MapShare, 'mapShareReceivedAt' | 'senderDeviceId' | 'senderDeviceName'>} MapShareSend
|
|
148
|
-
*/
|
|
149
|
-
|
|
150
129
|
/**
|
|
151
130
|
* @typedef {object} ProjectEvents
|
|
152
131
|
* @property {() => void} close Project resources have been cleared up
|
|
153
132
|
* @property {(changeEvent: RoleChangeEvent) => void} own-role-change
|
|
154
|
-
* @property {(e: Error, mapShare: MapShareExtension) => void} map-share-error - Emitted when an incoming map share fails to be recieved due to formatting issues
|
|
155
|
-
* @property {(mapShare: MapShare) => void} map-share - Emitted when a map share is recieved from someone on the project
|
|
156
133
|
*/
|
|
157
134
|
|
|
158
135
|
/**
|
|
159
|
-
* @
|
|
136
|
+
* @type {ReadyResource & TypedEmitter<ProjectEvents>}
|
|
160
137
|
*/
|
|
161
|
-
export class MapeoProject extends
|
|
138
|
+
export class MapeoProject extends ReadyResource {
|
|
162
139
|
#projectKey
|
|
163
140
|
#deviceId
|
|
164
141
|
#identityKeypair
|
|
@@ -563,22 +540,17 @@ export class MapeoProject extends TypedEmitter {
|
|
|
563
540
|
}
|
|
564
541
|
})
|
|
565
542
|
|
|
566
|
-
this.#coreManager.on('map-share', (mapShareBase, senderDeviceId) =>
|
|
567
|
-
this.#handleMapShare(mapShareBase, senderDeviceId).catch((e) => {
|
|
568
|
-
this.emit('map-share-error', e, mapShareBase)
|
|
569
|
-
this.#l.log(
|
|
570
|
-
'Error: Unable to handle incoming Map Share',
|
|
571
|
-
ensureError(e)
|
|
572
|
-
)
|
|
573
|
-
})
|
|
574
|
-
)
|
|
575
|
-
|
|
576
543
|
this.once('close', () => {
|
|
577
544
|
localPeers.off('peer-add', onPeerAdd)
|
|
578
545
|
localPeers.off('discovery-key', onDiscoverykey)
|
|
579
546
|
})
|
|
580
547
|
|
|
581
548
|
this.#l.log('Created project instance %h, %s', projectKey, isArchiveDevice)
|
|
549
|
+
|
|
550
|
+
// Not necessary, because coreManager and blobStore "auto-open", but leaving
|
|
551
|
+
// this here defensively in case we add additional resources to _open() in
|
|
552
|
+
// the future
|
|
553
|
+
this.ready().catch(noop)
|
|
582
554
|
}
|
|
583
555
|
|
|
584
556
|
/**
|
|
@@ -620,23 +592,23 @@ export class MapeoProject extends TypedEmitter {
|
|
|
620
592
|
|
|
621
593
|
/**
|
|
622
594
|
* Resolves when hypercores have all loaded
|
|
623
|
-
*
|
|
624
595
|
* @returns {Promise<void>}
|
|
625
596
|
*/
|
|
626
|
-
|
|
627
|
-
|
|
597
|
+
async _open() {
|
|
598
|
+
await this.#coreManager.ready()
|
|
599
|
+
await this.#blobStore.ready()
|
|
628
600
|
}
|
|
629
601
|
|
|
630
602
|
/**
|
|
631
603
|
*/
|
|
632
|
-
async
|
|
604
|
+
async _close() {
|
|
633
605
|
this.#l.log('closing project %h', this.#projectId)
|
|
634
|
-
this.#blobStore.close()
|
|
635
606
|
const dataStorePromises = []
|
|
636
607
|
for (const dataStore of Object.values(this.#dataStores)) {
|
|
637
608
|
dataStorePromises.push(dataStore.close())
|
|
638
609
|
}
|
|
639
610
|
await Promise.all(dataStorePromises)
|
|
611
|
+
await this.#blobStore.close()
|
|
640
612
|
await this.#coreManager.close()
|
|
641
613
|
|
|
642
614
|
this.#sqlite.close()
|
|
@@ -805,43 +777,6 @@ export class MapeoProject extends TypedEmitter {
|
|
|
805
777
|
this.emit('own-role-change', { role })
|
|
806
778
|
}
|
|
807
779
|
|
|
808
|
-
/**
|
|
809
|
-
* @param {MapShareExtension} mapShareBase
|
|
810
|
-
* @param {string} senderDeviceId
|
|
811
|
-
*/
|
|
812
|
-
async #handleMapShare(mapShareBase, senderDeviceId) {
|
|
813
|
-
const mapShareReceivedAt = Date.now()
|
|
814
|
-
|
|
815
|
-
validateMapShareExtension(mapShareBase)
|
|
816
|
-
|
|
817
|
-
const sender = await this.$member.getById(senderDeviceId)
|
|
818
|
-
|
|
819
|
-
if (INACTIVE_MEMBER_ROLE_IDS.includes(sender.role.roleId)) {
|
|
820
|
-
throw new InvalidMapShareError(
|
|
821
|
-
`Map Share Sender is not an active member of the project (role: ${sender.role.name})`
|
|
822
|
-
)
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
const { receiverDeviceKey, ...mapShareData } = mapShareBase
|
|
826
|
-
|
|
827
|
-
const receiverDeviceId = receiverDeviceKey.toString('hex')
|
|
828
|
-
|
|
829
|
-
if (receiverDeviceId !== this.#deviceId) {
|
|
830
|
-
throw new Error('Got map share intended for a different peer')
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
/** @type {MapShare} */
|
|
834
|
-
const mapShare = {
|
|
835
|
-
...mapShareData,
|
|
836
|
-
senderDeviceId,
|
|
837
|
-
senderDeviceName: sender.name,
|
|
838
|
-
mapShareReceivedAt,
|
|
839
|
-
receiverDeviceId,
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
this.emit('map-share', mapShare)
|
|
843
|
-
}
|
|
844
|
-
|
|
845
780
|
/**
|
|
846
781
|
* @deprecated
|
|
847
782
|
* @param {string} originalVersionId The `originalVersionId` from a document.
|
|
@@ -1490,29 +1425,6 @@ export class MapeoProject extends TypedEmitter {
|
|
|
1490
1425
|
this.#importingCategories = false
|
|
1491
1426
|
}
|
|
1492
1427
|
}
|
|
1493
|
-
|
|
1494
|
-
/**
|
|
1495
|
-
* Send a map share offer to the peer with device ID `mapShare.receiverDeviceId`
|
|
1496
|
-
*
|
|
1497
|
-
* @param {MapShareSend} mapShare
|
|
1498
|
-
* @param {object} [options]
|
|
1499
|
-
* @param {boolean} [options.__testOnlyBypassValidation=false] Warning: Do not use!
|
|
1500
|
-
*/
|
|
1501
|
-
async $sendMapShare(mapShare, { __testOnlyBypassValidation = false } = {}) {
|
|
1502
|
-
const { receiverDeviceId, ...mapShareData } = mapShare
|
|
1503
|
-
const receiverDeviceKey = Buffer.from(receiverDeviceId, 'hex')
|
|
1504
|
-
|
|
1505
|
-
/** @type {MapShareExtension} */
|
|
1506
|
-
// @ts-expect-error readonly fields being assigned as mutable
|
|
1507
|
-
const shareExtension = {
|
|
1508
|
-
...mapShareData,
|
|
1509
|
-
receiverDeviceKey,
|
|
1510
|
-
}
|
|
1511
|
-
if (!__testOnlyBypassValidation) {
|
|
1512
|
-
validateMapShareExtension(shareExtension)
|
|
1513
|
-
}
|
|
1514
|
-
await this.#coreManager.sendMapShare(shareExtension)
|
|
1515
|
-
}
|
|
1516
1428
|
}
|
|
1517
1429
|
|
|
1518
1430
|
/**
|
package/src/utils.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from './errors.js'
|
|
12
12
|
import pTimeout, { TimeoutError as pTimeoutError } from 'p-timeout'
|
|
13
13
|
|
|
14
|
-
/** @import { MapShareExtension } from './generated/
|
|
14
|
+
/** @import { MapShareExtension } from './generated/rpc.js' */
|
|
15
15
|
/** @import {Attachment, BlobId} from "./types.js" */
|
|
16
16
|
|
|
17
17
|
const PROJECT_INVITE_ID_SALT = Buffer.from('mapeo project invite id', 'ascii')
|
|
@@ -267,7 +267,7 @@ export async function timeoutPromise(promise, opts) {
|
|
|
267
267
|
* Does not validate device ID or device name
|
|
268
268
|
*
|
|
269
269
|
* @param {MapShareExtension} mapShare
|
|
270
|
-
* @returns {asserts mapShare is { [K in keyof MapShareExtension]: import('./mapeo-
|
|
270
|
+
* @returns {asserts mapShare is { [K in keyof MapShareExtension]: import('./mapeo-manager.js').MapShare[K] }} - this validates the properties that MapShareExtension and MapShare have in common - bounds tuple and mapShareUrls
|
|
271
271
|
*/
|
|
272
272
|
export function validateMapShareExtension(mapShare) {
|
|
273
273
|
const {
|