Skip to content

Commit

Permalink
Merge branch 'main' into fix/mdns-socket-error
Browse files Browse the repository at this point in the history
* main:
  feat: NamespaceSyncState improvements (#339)
  chore: update better-sqlite3 to 8.7.0 (#337)
  chore: update @mapeo/crypto to latest (#336)
  fix: write own device info when creating and adding projects (#297)
  Feat: add DataStore.writeRaw method (#334)
  feat: Add NamespaceSyncState (#313)
  chore: run CI on PRs against any branch (#330)
  feat: add capabilities.getAll() (#326)
  • Loading branch information
gmaclennan committed Oct 20, 2023
2 parents 2e21605 + 110d6d8 commit c303115
Show file tree
Hide file tree
Showing 22 changed files with 1,008 additions and 459 deletions.
1 change: 0 additions & 1 deletion .github/workflows/node.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
Expand Down
81 changes: 32 additions & 49 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"@types/node": "^18.16.3",
"@types/sinonjs__fake-timers": "^8.1.2",
"@types/streamx": "^2.9.1",
"@types/throttle-debounce": "^5.0.0",
"@types/varint": "^6.0.1",
"bitfield": "^4.1.0",
"brittle": "^3.2.1",
Expand Down Expand Up @@ -110,13 +111,13 @@
"@digidem/types": "^2.1.0",
"@fastify/type-provider-typebox": "^3.3.0",
"@hyperswarm/secret-stream": "^6.1.2",
"@mapeo/crypto": "^1.0.0-alpha.8",
"@mapeo/crypto": "^1.0.0-alpha.10",
"@mapeo/schema": "^3.0.0-next.11",
"@mapeo/sqlite-indexer": "^1.0.0-alpha.6",
"@sinclair/typebox": "^0.29.6",
"b4a": "^1.6.3",
"base32.js": "^0.1.0",
"better-sqlite3": "^8.3.0",
"better-sqlite3": "^8.7.0",
"big-sparse-array": "^1.0.3",
"bogon": "^1.1.0",
"bonjour-service": "^1.1.1",
Expand All @@ -142,6 +143,7 @@
"sodium-universal": "^4.0.0",
"start-stop-state-machine": "^1.2.0",
"sub-encoder": "^2.1.1",
"throttle-debounce": "^5.0.0",
"tiny-typed-emitter": "^2.1.0",
"varint": "^6.0.0",
"z32": "^1.0.1"
Expand Down
38 changes: 38 additions & 0 deletions src/capabilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,44 @@ export class Capabilities {
return capabilities
}

/**
* Get capabilities of all devices in the project. For your own device, if you
* have not yet synced your own role record, the "no role" capabilties is
* returned. The project creator will have `CREATOR_CAPABILITIES` unless a
* different role has been assigned.
*
* @returns {Promise<Record<string, Capability>>} Map of deviceId to Capability
*/
async getAll() {
const roles = await this.#dataType.getMany()
let projectCreatorDeviceId
try {
projectCreatorDeviceId = await this.#coreOwnership.getOwner(
this.#projectCreatorAuthCoreId
)
} catch (e) {
// Not found, we don't know who the project creator is so we can't include
// them in the returned map
}
/** @type {Record<string, Capability>} */
const capabilities = {}
for (const role of roles) {
const deviceId = role.docId
if (!isKnownRoleId(role.roleId)) continue
capabilities[deviceId] = DEFAULT_CAPABILITIES[role.roleId]
}
const includesSelf = Boolean(capabilities[this.#ownDeviceId])
if (!includesSelf) {
const isProjectCreator = this.#ownDeviceId === projectCreatorDeviceId
if (isProjectCreator) {
capabilities[this.#ownDeviceId] = CREATOR_CAPABILITIES
} else {
capabilities[this.#ownDeviceId] = NO_ROLE_CAPABILITIES
}
}
return capabilities
}

/**
* Assign a role to the specified `deviceId`. Devices without an assigned role
* are unable to sync, except the project creator that defaults to having all
Expand Down
22 changes: 22 additions & 0 deletions src/datastore/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,26 @@ export class DataStore extends TypedEmitter {
if (!block) throw new Error('Not Found')
return decode(block, { coreDiscoveryKey, index })
}

/** @param {Buffer} buf} */
async writeRaw(buf) {
const { length } = await this.#writerCore.append(buf)
const index = length - 1
const coreDiscoveryKey = this.#writerCore.discoveryKey
if (!coreDiscoveryKey) {
throw new Error('Writer core is not ready')
}
const versionId = getVersionId({ coreDiscoveryKey, index })
return versionId
}

/** @param {string} versionId */
async readRaw(versionId) {
const { coreDiscoveryKey, index } = parseVersionId(versionId)
const core = this.#coreManager.getCoreByDiscoveryKey(coreDiscoveryKey)
if (!core) throw new Error('core not found')
const block = await core.get(index, { wait: false })
if (!block) throw new Error('Not Found')
return block
}
}
2 changes: 1 addition & 1 deletion src/discovery/mdns.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import debug from 'debug'
import { isPrivate } from 'bogon'
import StartStopStateMachine from 'start-stop-state-machine'
import pTimeout from 'p-timeout'
import { projectKeyToPublicId as keyToPublicId } from '@mapeo/crypto'
import { keyToPublicId } from '@mapeo/crypto'

/** @typedef {{ publicKey: Buffer, secretKey: Buffer }} Keypair */

Expand Down
27 changes: 25 additions & 2 deletions src/mapeo-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { drizzle } from 'drizzle-orm/better-sqlite3'
import { migrate } from 'drizzle-orm/better-sqlite3/migrator'
import Hypercore from 'hypercore'
import { IndexWriter } from './index-writer/index.js'
import { MapeoProject } from './mapeo-project.js'
import { MapeoProject, kSetOwnDeviceInfo } from './mapeo-project.js'
import {
localDeviceInfoTable,
projectKeysTable,
Expand Down Expand Up @@ -219,10 +219,16 @@ export class MapeoManager {
// 5. Write project name and any other relevant metadata to project instance
await project.$setProjectSettings(settings)

// 6. Write device info into project
const deviceInfo = await this.getDeviceInfo()
if (deviceInfo.name) {
await project[kSetOwnDeviceInfo]({ name: deviceInfo.name })
}

// TODO: Close the project instance instead of keeping it around
this.#activeProjects.set(projectPublicId, project)

// 6. Return project public id
// 7. Return project public id
return projectPublicId
}

Expand Down Expand Up @@ -365,6 +371,14 @@ export class MapeoManager {
projectInfo,
})

// 5. Write device info into project
const deviceInfo = await this.getDeviceInfo()

if (deviceInfo.name) {
const project = await this.getProject(projectPublicId)
await project[kSetOwnDeviceInfo]({ name: deviceInfo.name })
}

return projectPublicId
}

Expand All @@ -382,6 +396,15 @@ export class MapeoManager {
set: values,
})
.run()

const listedProjects = await this.listProjects()

await Promise.all(
listedProjects.map(async ({ projectId }) => {
const project = await this.getProject(projectId)
await project[kSetOwnDeviceInfo](deviceInfo)
})
)
}

/**
Expand Down
Loading

0 comments on commit c303115

Please sign in to comment.