diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f545ed7..fa67261 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ on: branches: [ "main" ] env: - VERSION: 0.1.1 + VERSION: 0.2.0 jobs: node: @@ -19,7 +19,7 @@ jobs: strategy: matrix: - node-version: [16.x, 18.x, 20.x, 21.x] + node-version: [18.x, 20.x, 21.x] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: @@ -34,9 +34,13 @@ jobs: - run: npm run blockset-prepare - run: npm test - node-windows: + node-os: - runs-on: windows-latest + strategy: + matrix: + os: [windows-latest, macos-13] + + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 @@ -57,7 +61,7 @@ jobs: - run: cargo install blockset - run: npm run blockset-prepare # - run: deno run --quiet --allow-read --allow-env --allow-net --allow-hrtime ./test.mjs - - run: deno run --quiet --allow-read --allow-write ./test.mjs + - run: deno run --quiet --allow-read --allow-write --allow-net --allow-hrtime ./test.mjs bun: @@ -82,7 +86,7 @@ jobs: path: blockset-js-${{ env.VERSION }}.tgz name: blockset-js.tgz - test-install: + test-install-local: needs: pack runs-on: ubuntu-latest @@ -95,4 +99,16 @@ jobs: - run: echo "Hello World !" > _example.txt - run: blockset add ./_example.txt - run: npx blockset-js hsdfs1zs8fnf810v8f9k6pjdkz7b4y95sembmswac5sjt _out.txt - - run: blockset add ./_out.txt \ No newline at end of file + - run: blockset add ./_out.txt + + test-install-net: + + needs: pack + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v3 + with: + name: blockset-js.tgz + - run: npm install -g blockset-js-${{ env.VERSION }}.tgz + - run: npx blockset-js awt9x8564999k276wap2e5b7n10575ffy946kencva4ve _out.txt 410f5a49.blockset-js-test.pages.dev + - run: less ./_out.txt \ No newline at end of file diff --git a/README.md b/README.md index 8de99a0..ce2392e 100644 --- a/README.md +++ b/README.md @@ -26,5 +26,19 @@ npm uninstall -g blockset-js Get a file by address: ```console -npx blockset-js hsdfs1zs8fnf810v8f9k6pjdkz7b4y95sembmswac5sjt out.txt +npx blockset-js
[hostName] +``` + +### Examples + +Get a file from remote storage: + +```console +npx blockset-js awt9x8564999k276wap2e5b7n10575ffy946kencva4ve out.txt 410f5a49.blockset-js-test.pages.dev ``` + +Get a file from local storage: + +```console +npx blockset-js hsdfs1zs8fnf810v8f9k6pjdkz7b4y95sembmswac5sjt out.txt +``` \ No newline at end of file diff --git a/cli.mjs b/cli.mjs index a205917..3c00e60 100644 --- a/cli.mjs +++ b/cli.mjs @@ -1,15 +1,16 @@ #!/usr/bin/env node import index from './index.mjs' -const { getAsync } = index +const { get, asyncFileProvider, fetchProvider } = index var args = process.argv.slice(2) -console.log(`args = ${args}`); -if (args.length !== 2) { - console.log("Warning: Requires 2 arguments"); - console.log("npx blockset-js [address] [outputFile]"); +if (args.length < 2) { + console.log("Warning: Requires 2 or more arguments"); + console.log("npx blockset-js
[hostName]"); process.exit(); } -getAsync([args[0], args[1]]) \ No newline at end of file +const hostName = args[2] +const provider = hostName === undefined ? asyncFileProvider : fetchProvider(hostName) +get(provider)([args[0], args[1]]) \ No newline at end of file diff --git a/index.mjs b/index.mjs index 95f0dbe..ae78eac 100644 --- a/index.mjs +++ b/index.mjs @@ -140,13 +140,12 @@ const nextState = state => { } } - -/** @type {Provider} */ -const fetchProvider = { - read: address => fetch(`https://410f5a49.blockset-js-test.pages.dev/${getPath(address)}`) +/** @type {(hostName: string) => Provider} */ +const fetchProvider = hostName => ({ + read: address => fetch(`https://${hostName}/${getPath(address)}`) .then(async (resp) => resp.arrayBuffer().then(buffer => new Uint8Array(buffer))), write: path => buffer => fsPromises.appendFile(path, buffer) -} +}) /** @type {Provider} */ const asyncFileProvider = { @@ -169,7 +168,7 @@ const syncFileProvider = { // } /** @type {(provider: Provider) => (root: [string, string]) => Promise} */ -const getAsyncWithProvider = ({ read, write }) => async ([root, file]) => { +const get = ({ read, write }) => async ([root, file]) => { const tempFile = `_temp_${root}` /** @type {State} */ let state = [[[root, true], null]] @@ -223,48 +222,9 @@ const getAsyncWithProvider = ({ read, write }) => async ([root, file]) => { } } - -/** @type {(root: [string, string]) => Promise} */ -const getAsync = getAsyncWithProvider(asyncFileProvider) - -/** @type {(root: [string, string]) => Promise} */ -const getSync = getAsyncWithProvider(syncFileProvider) - -/** @type {(root: string) => (file: string) => number} */ -const get = root => file => { - /** @type {State} */ - let state = [[[root, true], null]] - let buffer = new Uint8Array() - try { - while (true) { - const blockLast = state.at(-1) - if (blockLast === undefined) { - fs.writeFileSync(file, buffer) - return 0 - } - - const address = blockLast[0] - const path = getPath(address) - const data = fs.readFileSync(path) - insertBlock(state)([address, data]) - const next = nextState(state) - if (next[0] === 'error') { - console.error(`${next[1]}`) - return -1 - } - - for (let w of next[1]) { - buffer = new Uint8Array([...buffer, ...w]); - } - } - } catch (err) { - console.error(err); - return -1 - } -} - export default { get, - getAsync, - getSync + syncFileProvider, + asyncFileProvider, + fetchProvider } \ No newline at end of file diff --git a/package.json b/package.json index ac05a3b..f4ac7b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "blockset-js", - "version": "0.1.1", + "version": "0.2.0", "description": "BLOCKSET on JavaScript", "keywords": ["blockset", "content-addressable", "storage", "cdt", "content-dependent-tree", "hash"], "main": "index.mjs", diff --git a/test.mjs b/test.mjs index 63e914a..15ac7b7 100644 --- a/test.mjs +++ b/test.mjs @@ -8,12 +8,13 @@ import fs from 'node:fs' import fsPromises from 'node:fs/promises' /** @typedef {import('./subtree.mjs').State} StateSubTree */ /** @typedef {import('./tree.mjs').State} StateTree */ +/** @typedef {import('./index.mjs').Provider} Provider */ const { toAddress, getParityBit } = base32 const { compress } = sha224 const { merge, byteToDigest, len } = digest256 const { highestOne256, height, push: pushSubTree } = subtree const { push: pushTree, end: endTree } = tree -const { get, getAsync, getSync } = index +const { get, syncFileProvider, asyncFileProvider, fetchProvider } = index console.log(`test start`) @@ -187,10 +188,10 @@ console.log(`test start`) if (result !== null) { throw result } result = pushSubTree(state)(b) if (result !== null) { throw result } - if (state.length !== 2 ) { throw state.length } + if (state.length !== 2) { throw state.length } result = pushSubTree(state)(a) if (result !== null) { throw result } - if (state.length !== 2 ) { throw state.length } + if (state.length !== 2) { throw state.length } result = pushSubTree(state)(a) const mergeCB_AA = merge(merge(c)(b))(merge(a)(a)) if (result != mergeCB_AA) { throw result } @@ -214,7 +215,7 @@ console.log(`test start`) const readExample = file => { let buffer = fs.readFileSync(file) let temp = [] - for(let ch of buffer) { + for (let ch of buffer) { if (ch !== 13) { temp.push(ch) } @@ -223,72 +224,18 @@ const readExample = file => { } /** @type {(f: () => Promise | void) => Promise} */ -const runTest = async(f) => { +const runTest = async (f) => { const t0 = performance.now(); await f() const t1 = performance.now(); console.log(`Call to ${f.name} took ${t1 - t0} milliseconds.`); } -const testGetSyncOld1 = () => { - const exitCode = get('vqra44skpkefw4bq9k96xt9ks84221dmk1pzaym86cqd6')('_out_list1') - if (exitCode !== 0) { throw exitCode } - - const bufferIn = readExample(`examples/list.txt`) - const bufferOut = fs.readFileSync(`_out_list1`) - if (!bufferOut.equals(bufferIn)) { throw 'files are different' } -} - -const testGetSyncOld2 = () => -{ - const exitCode = get('awt9x8564999k276wap2e5b7n10575ffy946kencva4ve')('examples/_out_list2') - if (exitCode !== 0) { throw exitCode } - - const bufferIn = readExample(`examples/list2.txt`) - const bufferOut = fs.readFileSync(`examples/_out_list2`) - if (!bufferOut.equals(bufferIn)) { throw 'files are different' } -} - -const testGetSyncOldRepeat = () => -{ - const exitCode = get('d963x31mwgb8svqe0jmkxh8ar1f8p2dawebnan4aj6hvd')('_out_repeat') - if (exitCode !== 0) { throw exitCode } - - const bufferIn = readExample(`examples/repeat.txt`) - const bufferOut = fs.readFileSync(`_out_repeat`) - if (!bufferOut.equals(bufferIn)) { throw 'files are different' } -} - -const testGetSync1 = async() => { - const exitCode = await getSync(['vqra44skpkefw4bq9k96xt9ks84221dmk1pzaym86cqd6', '_out_list1_async']) - if (exitCode !== 0) { throw exitCode } - - const bufferIn = readExample(`examples/list.txt`) - const bufferOut = await fsPromises.readFile(`_out_list1_async`) - if (!bufferOut.equals(bufferIn)) { throw 'files are different' } -} - -const testGetSync2 = async() => { - const exitCode = await getSync(['awt9x8564999k276wap2e5b7n10575ffy946kencva4ve', 'examples/_out_list2_async']) - if (exitCode !== 0) { throw exitCode } - - const bufferIn = readExample(`examples/list2.txt`) - const bufferOut = await fsPromises.readFile(`examples/_out_list2_async`) - if (!bufferOut.equals(bufferIn)) { throw 'files are different' } -} - -const testGetSyncRepeat = async() => { - const exitCode = await getSync(['d963x31mwgb8svqe0jmkxh8ar1f8p2dawebnan4aj6hvd', '_out_repeat_async']) - if (exitCode !== 0) { throw exitCode } - - const bufferIn = readExample(`examples/repeat.txt`) - const bufferOut = await fsPromises.readFile(`_out_repeat_async`) - if (!bufferOut.equals(bufferIn)) { throw 'files are different' } -} - -{ - const testGetAsync1 = async() => { - const exitCode = await getAsync(['vqra44skpkefw4bq9k96xt9ks84221dmk1pzaym86cqd6', '_out_list1_async']) +/** @type {(provider: Provider) => Promise} */ +const runTestsGet = async (provider) => { + const getWithProvider = get(provider) + const testGet1 = async () => { + const exitCode = await getWithProvider(['vqra44skpkefw4bq9k96xt9ks84221dmk1pzaym86cqd6', '_out_list1_async']) if (exitCode !== 0) { throw exitCode } const bufferIn = readExample(`examples/list.txt`) @@ -296,8 +243,8 @@ const testGetSyncRepeat = async() => { if (!bufferOut.equals(bufferIn)) { throw 'files are different' } } - const testGetAsync2 = async() => { - const exitCode = await getAsync(['awt9x8564999k276wap2e5b7n10575ffy946kencva4ve', 'examples/_out_list2_async']) + const testGet2 = async () => { + const exitCode = await getWithProvider(['awt9x8564999k276wap2e5b7n10575ffy946kencva4ve', 'examples/_out_list2_async']) if (exitCode !== 0) { throw exitCode } const bufferIn = readExample(`examples/list2.txt`) @@ -305,8 +252,8 @@ const testGetSyncRepeat = async() => { if (!bufferOut.equals(bufferIn)) { throw 'files are different' } } - const testGetAsyncRepeat = async() => { - const exitCode = await getAsync(['d963x31mwgb8svqe0jmkxh8ar1f8p2dawebnan4aj6hvd', '_out_repeat_async']) + const testGetRepeat = async () => { + const exitCode = await getWithProvider(['d963x31mwgb8svqe0jmkxh8ar1f8p2dawebnan4aj6hvd', '_out_repeat_async']) if (exitCode !== 0) { throw exitCode } const bufferIn = readExample(`examples/repeat.txt`) @@ -314,17 +261,20 @@ const testGetSyncRepeat = async() => { if (!bufferOut.equals(bufferIn)) { throw 'files are different' } } - const mainTestAsync = async() => { - await runTest(testGetSyncOld1) - await runTest(testGetSyncOld2) - await runTest(testGetSyncOldRepeat) - await runTest(testGetSync1) - await runTest(testGetSync2) - await runTest(testGetSyncRepeat) - await runTest(testGetAsync1) - await runTest(testGetAsync2) - await runTest(testGetAsyncRepeat) - } + await runTest(testGet1) + await runTest(testGet2) + await runTest(testGetRepeat) +} + +const testFetchProvider = fetchProvider('410f5a49.blockset-js-test.pages.dev') + +const mainTestAsync = async () => { + console.log('sync provider') + await runTestsGet(syncFileProvider) + console.log('async provider') + await runTestsGet(asyncFileProvider) + console.log('fetch provider') + await runTestsGet(testFetchProvider) +} - mainTestAsync() -} \ No newline at end of file +mainTestAsync() \ No newline at end of file