diff --git a/index.mjs b/index.mjs index d97f47c..ce80540 100644 --- a/index.mjs +++ b/index.mjs @@ -48,7 +48,7 @@ const getLocal = mem => io => async ([root, file]) => { const write = buffer => io.append(tempFile, buffer) const error = await get({ read, write })(root) if (error !== null) { - console.error(error) + io.console.error(error) return -1 } await io.rename(tempFile, file) @@ -65,7 +65,7 @@ const getRemote = mem => host => io => async ([root, file]) => { const write = buffer => io.append(tempFile, buffer) const error = await get({ read, write })(root) if (error !== null) { - console.error(error) + io.console.error(error) return -1 } await io.rename(tempFile, file) diff --git a/io/io.mjs b/io/io.mjs index 6efdc5c..77678b3 100644 --- a/io/io.mjs +++ b/io/io.mjs @@ -1,13 +1,23 @@ +/** @typedef {(log: string) => void} Logger */ + +/** + * @typedef {{ + * readonly log: Logger, + * readonly error: Logger + * }} Console + */ + /** * @typedef {{ -* readonly read: (path: string) => Promise, -* readonly append: (path: string, buffer: Uint8Array) => Promise, -* readonly write: (path: string, buffer: Uint8Array) => Promise, -* readonly rename: (oldPath: string, newPath: string) => Promise -* readonly fetch: (url: string) => Promise -* readonly document: Document | undefined -* }} IO -*/ + * readonly read: (path: string) => Promise, + * readonly append: (path: string, buffer: Uint8Array) => Promise, + * readonly write: (path: string, buffer: Uint8Array) => Promise, + * readonly rename: (oldPath: string, newPath: string) => Promise + * readonly fetch: (url: string) => Promise + * readonly console: Console + * readonly document: Document | undefined + * }} IO + */ export default { } \ No newline at end of file diff --git a/io/node.mjs b/io/node.mjs index 6c6ef89..961bdec 100644 --- a/io/node.mjs +++ b/io/node.mjs @@ -8,6 +8,7 @@ const node = { append: fsPromises.appendFile, write: fsPromises.writeFile, rename: fsPromises.rename, + console: {log: console.log, error: console.error}, fetch, document: undefined } @@ -18,6 +19,7 @@ const nodeSync = { append: async(path, buffer) => fs.appendFileSync(path, buffer), write: async(path, buffer) => fs.writeFileSync(path, buffer), rename: async(oldPath, newPath) => fs.renameSync(oldPath, newPath), + console: {log: console.log, error: console.error}, fetch, document: undefined } diff --git a/io/virtual.mjs b/io/virtual.mjs index adaa467..71a79e7 100644 --- a/io/virtual.mjs +++ b/io/virtual.mjs @@ -6,6 +6,13 @@ const notImplemented = () => { throw 'not implemented' } * @typedef {{[index: string]: Uint8Array}} FileSystem */ +/** + * @typedef {{ + * readonly fs: FileSystem, + * readonly console: { log: string, error: string } + * }} MemIo + */ + /** @type {(fs: FileSystem) => (path: string) => Promise} */ const read = fs => async (path) => { const buffer = fs[path] @@ -39,18 +46,29 @@ const rename = fs => async (oldPath, newPath) => { fs[newPath] = buffer } -/** @type {(fs: FileSystem) => IO} */ -const virtual = fs => { +/** @type {(memIo: MemIo) => IO} */ +const virtual = ({ fs, console }) => { return { read: read(fs), append: append(fs), write: write(fs), rename: rename(fs), fetch: notImplemented, + console: { log: text => console.log += `${text}\n`, error: text => console.error += `${text}\n` }, document: undefined } } +/** @type {() => MemIo} */ +const createMemIo = () => ({ + fs: {}, + console: { + log: '', + error: '' + } +}) + export default { - virtual + virtual, + createMemIo } \ No newline at end of file diff --git a/io/web.mjs b/io/web.mjs index af4512e..e5c2bb1 100644 --- a/io/web.mjs +++ b/io/web.mjs @@ -1,15 +1,19 @@ /** @typedef {import('./io.mjs').IO} IO */ +/** @typedef {import('./io.mjs').Console} Console */ const notImplemented = () => { throw 'not implemented' } -/** @type {IO} */ -const web = { - read: notImplemented, - append: notImplemented, - write: notImplemented, - rename: notImplemented, - fetch, - document +/** @type {(createConsole: (d: Document) => Console) => IO} */ +const web = createConsole => { + return { + read: notImplemented, + append: notImplemented, + write: notImplemented, + rename: notImplemented, + console: createConsole(document), + fetch, + document + } } export default { diff --git a/test.mjs b/test.mjs index 3f7d640..23b29be 100644 --- a/test.mjs +++ b/test.mjs @@ -8,10 +8,11 @@ import ioNode from './io/node.mjs' import fs from 'node:fs' import fsPromises from 'node:fs/promises' import ioVirtual from './io/virtual.mjs' +import assert from 'node:assert' /** @typedef {import('./cdt/sub-tree.mjs').State} StateSubTree */ /** @typedef {import('./cdt/main-tree.mjs').State} StateTree */ /** @typedef {import('./io/io.mjs').IO} IO */ -/** @typedef {import('./io/virtual.mjs').FileSystem} FileSystem */ +/** @typedef {import('./io/virtual.mjs').MemIo} MemIo */ /** @typedef {import('./index.mjs').Cache} Cache */ const { toBase32Hash, getParityBit } = base32 const { compress } = sha224 @@ -20,7 +21,7 @@ const { highestOne256, height, push: pushSubTree } = subTree const { push: pushTree, end: endTree } = mainTree const { getLocal, getRemote } = index const { node, nodeSync } = ioNode -const { virtual } = ioVirtual +const { virtual, createMemIo } = ioVirtual console.log(`test start`) @@ -206,9 +207,8 @@ console.log(`test start`) } const virtualFsTest = async () => { - /** @type {FileSystem} */ - const fs = {} - const io = virtual(fs) + const memIo = createMemIo() + const io = virtual(memIo) await io.write('test', new Uint8Array([0, 1, 2])) let buffer = await io.read('test') if (buffer.toString() !== '0,1,2') { throw buffer } diff --git a/web-test.mjs b/web-test.mjs index 7f39d9f..e8b1840 100644 --- a/web-test.mjs +++ b/web-test.mjs @@ -6,7 +6,17 @@ const { get } = forest const { web } = ioWeb const { fetchRead } = index -const d = web.document +const webIo = web(d => ({ + log: text => { + // @ts-ignore + d.getElementById('log').innerText += `${text}\n` + }, + error: text => { + // @ts-ignore + d.getElementById('log').innerText += `${text}\n` + } +})) +const d = webIo.document // @ts-ignore d.getElementById('download').addEventListener('click', () => { reset() @@ -15,23 +25,20 @@ d.getElementById('download').addEventListener('click', () => { // @ts-ignore const host = d.getElementById('input-host').value let buffer = new Uint8Array() - const fRead = fetchRead(host)(web) + const fRead = fetchRead(host)(webIo) /** @type {(forestNodeId: ForestNodeId) => Promise} */ const read = forestNodeId => { - // @ts-ignore - d.getElementById('log').innerText += `read from ${forestNodeId}\n` + webIo.console.log(`read from ${forestNodeId}`) return fRead(forestNodeId) } /** @type {(b: Uint8Array) => Promise} */ const write = async (b) => { - // @ts-ignore - d.getElementById('log').innerText += `write ${b.length}\n` - buffer = new Uint8Array([...buffer, ...b]) + webIo.console.log(`write ${b.length}`) + buffer = new Uint8Array([...buffer, ...b]) } get({ read, write })(hash).then(exitCode => { if (exitCode !== null) { - // @ts-ignore - d.getElementById('log').innerText += `error exit code = ${exitCode}\n` + webIo.console.error(`error exit code = ${exitCode}`) return } @@ -48,7 +55,7 @@ d.getElementById('download').addEventListener('click', () => { // @ts-ignore d.getElementById('output-text').style.display = 'block' // @ts-ignore - d.getElementById('output-text').innerText = new TextDecoder().decode(buffer) + d.getElementById('output-text').innerText = new TextDecoder().decode(buffer) }) });