Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: decode with coreDiscoveryId as well as coreDiscoveryKey #267

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions src/decode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import cenc from 'compact-encoding'
import { DATA_TYPE_ID_BYTES, SCHEMA_VERSION_BYTES } from './constants.js'
import {
ExhaustivenessError,
VersionIdObject,
VersionObject,
getOwn,
getProtoTypeName,
} from './lib/utils.js'
Expand All @@ -42,12 +42,9 @@ for (const [schemaName, dataTypeId] of Object.entries(dataTypeIds) as Array<
* Decode a Buffer as an object validated against the corresponding schema
*
* @param buf Buffer to be decoded
* @param versionObj public key (coreKey) of the core where this block is stored, and the index of the block in the core.
* @param versionObj discovery key or discovery id of the core where this block is stored, and the index of the block in the core.
* */
export function decode(
buf: Buffer,
versionObj: VersionIdObject
): MapeoDocDecode {
export function decode(buf: Buffer, versionObj: VersionObject): MapeoDocDecode {
const schemaDef = decodeBlockPrefix(buf)

const encodedMsg = buf.subarray(
Expand Down
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ export {
getVersionId,
parseVersionId,
valueOf,
type VersionIdObject,
/** Deprecated: rename VersionIdObject to VersionObject */
type VersionObject as VersionIdObject,
type VersionObject,
} from './lib/utils.js'

export * from './schema/index.js'
Expand Down
6 changes: 3 additions & 3 deletions src/lib/decode-conversions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ import {
assert,
ExhaustivenessError,
getVersionId,
VersionIdObject,
VersionObject,
} from './utils.js'

/** Function type for converting a protobuf type of any version for a particular
* schema name, and returning the most recent JSONSchema type */
type ConvertFunction<TSchemaName extends SchemaName> = (
message: Extract<ProtoTypesWithSchemaInfo, { schemaName: TSchemaName }>,
versionObj: VersionIdObject
versionObj: VersionObject
) => FilterBySchemaName<MapeoDocDecode, TSchemaName>

function ensure(
Expand Down Expand Up @@ -465,7 +465,7 @@ function convertTagPrimitive({

function convertCommon(
common: ProtoTypesWithSchemaInfo['common'],
versionObj: VersionIdObject
versionObj: VersionObject
): Omit<MapeoCommon, 'schemaName'> {
if (
!common ||
Expand Down
44 changes: 32 additions & 12 deletions src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,48 @@ function capitalize<T extends string>(str: T): Capitalize<T> {
return (str.charAt(0).toUpperCase() + str.slice(1)) as any
}

export type VersionIdObject = {
export type VersionObject = VersionDiscoveryKeyObject | VersionDiscoveryIdObject

export type VersionDiscoveryKeyObject = {
coreDiscoveryKey: Buffer
index: number
}

export type VersionDiscoveryIdObject = {
coreDiscoveryId: string
index: number
}

export const VERSION_ID_SEPARATOR = '/'

/**
* Get a string versionId from a core key and index in that core. A versionId
* uniquely identifies a record in the underlying Hypercore storage used by
* Mapeo
* Get a string versionId from a core discovery key or discovery id and index in
* that core. A versionId uniquely identifies a record in the underlying
* Hypercore storage used by Mapeo
* @param versionIdObject
* @returns versionId string
*/
export function getVersionId({ coreDiscoveryKey, index }: VersionIdObject) {
assert(
coreDiscoveryKey.byteLength >= 32,
'version ID core discovery key must be have at least 32 bytes'
)
export function getVersionId(versionIdObject: VersionObject) {
const { index } = versionIdObject
assert(
Number.isSafeInteger(index) && index >= 0,
'version ID index must be a non-negative integer'
)
return coreDiscoveryKey.toString('hex') + '/' + index
let discoveryId
if ('coreDiscoveryId' in versionIdObject) {
discoveryId = versionIdObject.coreDiscoveryId
assert(
discoveryId.length > 0,
'version ID core discovery id must be non-empty string'
)
} else {
assert(
versionIdObject.coreDiscoveryKey.byteLength >= 32,
'version ID core discovery key must be have at least 32 bytes'
)
discoveryId = versionIdObject.coreDiscoveryKey.toString('hex')
}
return discoveryId + VERSION_ID_SEPARATOR + index
}

/**
Expand All @@ -68,8 +88,8 @@ export function getVersionId({ coreDiscoveryKey, index }: VersionIdObject) {
* @param versionId hex-encoded 32-byte core key and index in the core, separated with `/`
* @returns coreKey as a Buffer and index in the core
*/
export function parseVersionId(versionId: string): VersionIdObject {
const items = versionId.split('/')
export function parseVersionId(versionId: string): VersionDiscoveryKeyObject {
const items = versionId.split(VERSION_ID_SEPARATOR)
if (!items[0] || !items[1]) throw new Error('Invalid versionId')
const coreDiscoveryKey = Buffer.from(items[0], 'hex')
if (coreDiscoveryKey.length !== 32) throw new Error('Invalid versionId')
Expand Down
Loading