Skip to content

Commit

Permalink
fix: use same dependencies as mapeo-mobile (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
EvanHahn authored Dec 11, 2024
1 parent f750541 commit 05e8000
Show file tree
Hide file tree
Showing 9 changed files with 306 additions and 560 deletions.
742 changes: 216 additions & 526 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@
"files": [
"README.md",
"LICENSE.md",
"patches",
"src",
"dist/src"
],
"scripts": {
"postinstall": "patch-package",
"prepack": "npm run build",
"format": "prettier --write .",
"build": "tsc",
Expand All @@ -34,10 +32,10 @@
"license": "MIT",
"dependencies": {
"archiver": "^7.0.1",
"hypercore": "^7.7.1",
"hypercore-crypto": "^3.4.2",
"multifeed": "^6.0.0",
"multifeed": "^4.3.0",
"p-event": "^6.0.1",
"patch-package": "^8.0.0",
"valibot": "^1.0.0-beta.9",
"yauzl-promise": "^4.0.0"
},
Expand Down
11 changes: 0 additions & 11 deletions patches/simple-hypercore-protocol+2.1.2.patch

This file was deleted.

18 changes: 7 additions & 11 deletions src/lib/hypercoreUtil.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
import { pEvent } from 'p-event'
/** @import { Hypercore } from 'hypercore' */

/**
* Wraps `Hypercore.prototype.ready` in a promise.
* Waits for a Hypercore to be ready.
*
* @param {Hypercore} hypercore
* @returns {Promise<void>}
*/
export const ready = (hypercore) =>
new Promise((resolve, reject) => {
hypercore.ready((err) => {
if (err) {
reject(err)
} else {
resolve()
}
})
})
export const ready = async (hypercore) => {
const isReady = Boolean(hypercore.key)
if (isReady) return
await pEvent(hypercore, 'ready')
}

/**
* Wraps `Hypercore.prototype.rootHashes` in a promise.
Expand Down
11 changes: 11 additions & 0 deletions src/lib/readableStreamToAsyncIterable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { pEventIterator } from 'p-event'

/**
* This is needed because the stream returned by
* `Hypercore.prototype.createReadStream` is not iterable with `for await`.
* Normally, Node streams don't need this wrapper.
* @param {NodeJS.ReadableStream} readable
* @returns {AsyncIterable<unknown>}
*/
export const readableStreamToAsyncIterable = (readable) =>
pEventIterator(readable, 'data', { resolutionEvents: ['end'] })
13 changes: 11 additions & 2 deletions src/writer.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import archiver from 'archiver'
import * as hypercoreCrypto from 'hypercore-crypto'
import hypercore from 'hypercore'
import multifeed from 'multifeed'
import fs from 'node:fs'
import { readdir } from 'node:fs/promises'
import * as path from 'node:path'
import { pEvent } from 'p-event'
import * as hypercoreUtil from './lib/hypercoreUtil.js'
import * as multifeedUtil from './lib/multifeedUtil.js'
import { readableStreamToAsyncIterable } from './lib/readableStreamToAsyncIterable.js'
import { noop } from './lib/noop.js'
/** @import { Hypercore } from 'hypercore' */
/** @import { HypercoreMetadata, DocumentVersion } from './types.js' */
Expand Down Expand Up @@ -65,7 +67,7 @@ export async function write(inputPath, outputPath) {
* @returns {AsyncGenerator<DocumentVersion>}
*/
async function* getInputDocuments(inputPath) {
const multi = multifeed(inputPath, {
const multi = multifeed(hypercore, inputPath, {
createIfMissing: false,
valueEncoding: 'json',
stats: false,
Expand All @@ -80,7 +82,7 @@ async function* getInputDocuments(inputPath) {

const hypercoreMetadata = await getHypercoreMetadata(hypercore)

for await (const document of stream) {
for await (const document of readableStreamToAsyncIterable(stream)) {
const { id, version } = parseDocument(document)
yield { id, version, document, hypercoreMetadata }
}
Expand All @@ -92,11 +94,18 @@ async function* getInputDocuments(inputPath) {
* @returns {Promise<HypercoreMetadata>}
*/
async function getHypercoreMetadata(hypercore) {
await hypercoreUtil.ready(hypercore)

if (!hypercore.key) {
throw new Error("Hypercore is missing a key even though it's ready")
}

const rootHashesPromise = hypercoreUtil.rootHashes(hypercore, 0)
const signaturePromise = hypercoreUtil.signature(
hypercore,
Math.max(0, hypercore.length - 1)
)

return {
rootHashChecksum: hypercoreCrypto
.tree(await rootHashesPromise)
Expand Down
47 changes: 47 additions & 0 deletions test/lib/readableStreamToAsyncIterable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import assert from 'node:assert/strict'
import test from 'node:test'
import { Readable } from 'node:stream'
import { readableStreamToAsyncIterable } from '../../src/lib/readableStreamToAsyncIterable.js'

class TestStream extends Readable {
#count = 0

/**
* @param {undefined | string} value
* @returns {void}
*/
#push(value) {
this.push(value ? Buffer.from(value) : null)
this.#count++
}

/**
* @override
*/
_read() {
this.#push(['foo', 'bar', 'baz'][this.#count])
}

/**
* @override
*/
[Symbol.asyncIterator]() {
// This is a hack to satisfy TypeScript, which will otherwise complain that
// this method returns the wrong type.
if (Date.now()) {
assert.fail('Wrapper should not call this method')
}
return super[Symbol.asyncIterator]()
}
}

test('returns an async iterable', async () => {
const result = readableStreamToAsyncIterable(new TestStream())

const chunks = []
for await (const chunk of result) chunks.push(chunk)
assert.deepEqual(
chunks,
['foo', 'bar', 'baz'].map((str) => Buffer.from(str))
)
})
12 changes: 7 additions & 5 deletions types/hypercore.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
* This is a subset of the types we actually use, so lots of things are missing.
*/
declare module 'hypercore' {
export class Hypercore {
get key(): Buffer
get length(): number
import { EventEmitter } from 'node:events'

ready(cb: (err: null | Error) => unknown): void
export class Hypercore extends EventEmitter {
get key(): null | Buffer
get length(): number

createReadStream(): AsyncIterable<unknown>
createReadStream(): NodeJS.ReadableStream

signature(
index: number,
Expand All @@ -26,4 +26,6 @@ declare module 'hypercore' {
) => unknown
): void
}

export default function hypercore(...args: unknown[]): Hypercore
}
6 changes: 5 additions & 1 deletion types/multifeed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,9 @@ declare module 'multifeed' {
feeds(): Hypercore[]
}

export default function multifeed(storage: string, opts?: unknown): Multifeed
export default function multifeed(
hypercore: () => Hypercore,
storage: string,
opts?: unknown
): Multifeed
}

0 comments on commit 05e8000

Please sign in to comment.