UNPKG

@dstanesc/o-o-o-o-o-o-o

Version:

O-O-O-O-O-O-O is a collection of content addressed persistent data structures

305 lines 12.8 kB
import { linkCodecFactory, valueCodecFactory, } from '../codecs'; import { graphStoreFactory } from '../graph-store'; import { compute_chunks } from '@dstanesc/wasm-chunking-fastcdc-node'; import { chunkerFactory } from '../chunking'; import { memoryBlockStoreFactory } from '../block-store'; import * as assert from 'assert'; import { versionStoreFactory } from '../version-store'; import { itemListFactory, readonlyItemList, } from '../item-list'; import { ElemType } from '../types'; describe('Minimal item list', function () { test('internal api, creation and retrieval by index', async () => { const { chunk } = chunkerFactory(512, compute_chunks); const linkCodec = linkCodecFactory(); const valueCodec = valueCodecFactory(); const blockStore = memoryBlockStoreFactory(); const versionStore = await versionStoreFactory({ chunk, linkCodec, valueCodec, blockStore, }); const graphStore = graphStoreFactory({ chunk, linkCodec, valueCodec, blockStore, }); /** * Create an item list */ let KeyTypes; (function (KeyTypes) { KeyTypes[KeyTypes["NAME"] = 1] = "NAME"; })(KeyTypes || (KeyTypes = {})); const itemList = itemListFactory(versionStore, graphStore); const tx = itemList.tx(); await tx.start(); await tx.push(new Map([[KeyTypes.NAME, 'item 0']])); await tx.push(new Map([[KeyTypes.NAME, 'item 1']])); await tx.push(new Map([[KeyTypes.NAME, 'item 2']])); const { root, index, blocks } = await tx.commit({ comment: 'First commit', tags: ['v0.0.1'], }); const len = await itemList.length(); assert.strictEqual(3, len); const item0 = await itemList.get(0); assert.strictEqual('item 0', item0.value.get(KeyTypes.NAME)); const item1 = await itemList.get(1); assert.strictEqual('item 1', item1.value.get(KeyTypes.NAME)); const item2 = await itemList.get(2); assert.strictEqual('item 2', item2.value.get(KeyTypes.NAME)); assert.equal('bafkreie2iaqxhv56xdtqyih57txqllfwswu7ixhgbnkmfts5weybfuodgu', root.toString()); /** * Add more items */ const tx2 = itemList.tx(); await tx2.start(); await tx2.push(new Map([[KeyTypes.NAME, 'item 3']])); await tx2.push(new Map([[KeyTypes.NAME, 'item 4']])); await tx2.push(new Map([[KeyTypes.NAME, 'item 5']])); const { root: root2, index: index2, blocks: blocks2, } = await tx2.commit({ comment: 'Second commit', tags: ['v0.0.2'], }); const len2 = await itemList.length(); assert.strictEqual(6, len2); const item3 = await itemList.get(3); assert.strictEqual('item 3', item3.value.get(KeyTypes.NAME)); const item4 = await itemList.get(4); assert.strictEqual('item 4', item4.value.get(KeyTypes.NAME)); const item5 = await itemList.get(5); assert.strictEqual('item 5', item5.value.get(KeyTypes.NAME)); assert.equal('bafkreie53yzg5oscjwtktgf46o33zipoyomm3ra42lclsv3eapksssflta', root2.toString()); /** * Rehydrate the item list from original version store */ const itemList2 = itemListFactory(versionStore, graphStore); const len3 = await itemList2.length(); assert.strictEqual(6, len3); const item6 = await itemList2.get(3); assert.strictEqual('item 3', item6.value.get(KeyTypes.NAME)); const item7 = await itemList2.get(4); assert.strictEqual('item 4', item7.value.get(KeyTypes.NAME)); const item8 = await itemList2.get(5); assert.strictEqual('item 5', item8.value.get(KeyTypes.NAME)); /** * Rehydrate the item list from root, fresh version store */ const versionRoot = linkCodec.parseString('bafkreie53yzg5oscjwtktgf46o33zipoyomm3ra42lclsv3eapksssflta'); const versionStore2 = await versionStoreFactory({ versionRoot, chunk, linkCodec, valueCodec, blockStore, }); const itemList3 = itemListFactory(versionStore2, graphStore); const len4 = await itemList3.length(); assert.strictEqual(6, len4); const item9 = await itemList3.get(0); assert.strictEqual('item 0', item9.value.get(KeyTypes.NAME)); const item10 = await itemList3.get(1); assert.strictEqual('item 1', item10.value.get(KeyTypes.NAME)); const item11 = await itemList3.get(2); assert.strictEqual('item 2', item11.value.get(KeyTypes.NAME)); const item12 = await itemList3.get(3); assert.strictEqual('item 3', item12.value.get(KeyTypes.NAME)); const item13 = await itemList3.get(4); assert.strictEqual('item 4', item13.value.get(KeyTypes.NAME)); const item14 = await itemList3.get(5); assert.strictEqual('item 5', item14.value.get(KeyTypes.NAME)); /** * Navigate back in time to the first commit */ versionStore.checkout(root); const itemList5 = itemListFactory(versionStore, graphStore); const len5 = await itemList5.length(); assert.strictEqual(3, len5); const item15 = await itemList5.get(0); assert.strictEqual('item 0', item15.value.get(KeyTypes.NAME)); const item16 = await itemList5.get(1); assert.strictEqual('item 1', item16.value.get(KeyTypes.NAME)); const item17 = await itemList5.get(2); assert.strictEqual('item 2', item17.value.get(KeyTypes.NAME)); }); test('internal api, creation and range retrieval', async () => { const { chunk } = chunkerFactory(512, compute_chunks); const linkCodec = linkCodecFactory(); const valueCodec = valueCodecFactory(); const blockStore = memoryBlockStoreFactory(); const versionStore = await versionStoreFactory({ chunk, linkCodec, valueCodec, blockStore, }); const graphStore = graphStoreFactory({ chunk, linkCodec, valueCodec, blockStore, }); /** * Create an item list */ let KeyTypes; (function (KeyTypes) { KeyTypes[KeyTypes["ID"] = 11] = "ID"; KeyTypes[KeyTypes["NAME"] = 33] = "NAME"; })(KeyTypes || (KeyTypes = {})); const itemList = itemListFactory(versionStore, graphStore); const tx = itemList.tx(); await tx.start(); for (let i = 0; i < 100; i++) { const itemValue = new Map(); itemValue.set(KeyTypes.ID, i); itemValue.set(KeyTypes.NAME, `item ${i}`); await tx.push(itemValue); } const { root, index, blocks } = await tx.commit({ comment: 'First commit', tags: ['v0.0.1'], }); /** * Item range from 25 to 75 */ const range = await itemList.range(25, 50); // start index, count assert.strictEqual(50, range.length); for (let i = 0; i < range.length; i++) { assert.strictEqual(`item ${i + 25}`, range[i].value.get(KeyTypes.NAME)); } }); test('internal api, readonlyItemList to retrieve external refs', async () => { const { chunk } = chunkerFactory(512, compute_chunks); const linkCodec = linkCodecFactory(); const valueCodec = valueCodecFactory(); const blockStore = memoryBlockStoreFactory(); { /** * Create the original item list containing the item to be referenced */ const versionStore = await versionStoreFactory({ chunk, linkCodec, valueCodec, blockStore, }); const graphStore = graphStoreFactory({ chunk, linkCodec, valueCodec, blockStore, }); let KeyTypes; (function (KeyTypes) { KeyTypes[KeyTypes["NAME"] = 1] = "NAME"; })(KeyTypes || (KeyTypes = {})); const itemList = itemListFactory(versionStore, graphStore); const tx = itemList.tx(); await tx.start(); const { index: item0Index, offset: item0Offset } = await tx.push(new Map([[KeyTypes.NAME, 'item 0']])); const itemRef1 = await tx.push(new Map([[KeyTypes.NAME, 'item 1']])); const itemRef2 = await tx.push(new Map([[KeyTypes.NAME, 'item 2']])); const { root, index, blocks } = await tx.commit({ comment: 'First commit', tags: ['v0.0.1'], }); } { /** * Create second item list to reference an item from the first item list */ const versionStore = await versionStoreFactory({ chunk, linkCodec, valueCodec, blockStore, }); const graphStore = graphStoreFactory({ chunk, linkCodec, valueCodec, blockStore, }); let KeyTypes; (function (KeyTypes) { KeyTypes[KeyTypes["ID"] = 11] = "ID"; KeyTypes[KeyTypes["NAME"] = 33] = "NAME"; KeyTypes[KeyTypes["EXT_REF"] = 55] = "EXT_REF"; })(KeyTypes || (KeyTypes = {})); const itemList = itemListFactory(versionStore, graphStore); const tx = itemList.tx(); await tx.start(); for (let i = 0; i < 100; i++) { const itemValue = new Map(); const elemOffset = i % 3; // for lists the logical offset seems better than the physical offset const extRef = { extRoot: 'bafkreie2iaqxhv56xdtqyih57txqllfwswu7ixhgbnkmfts5weybfuodgu', elemType: ElemType.VERTEX, elemOffset, }; itemValue.set(KeyTypes.ID, i); itemValue.set(KeyTypes.NAME, `item ${i}`); itemValue.set(KeyTypes.EXT_REF, extRef); await tx.push(itemValue); } const { root, index, blocks } = await tx.commit({ comment: 'First commit', tags: ['v0.0.1'], }); } { /** * Browse second item list, incl resolving external refs */ let KeyTypes; (function (KeyTypes) { KeyTypes[KeyTypes["ID"] = 11] = "ID"; KeyTypes[KeyTypes["NAME"] = 33] = "NAME"; KeyTypes[KeyTypes["EXT_REF"] = 55] = "EXT_REF"; })(KeyTypes || (KeyTypes = {})); const versionRoot = linkCodec.parseString('bafkreiawv6ftq2ggoepfhqsiywo26rlkpjcjyqwz7gqnywoy4sa3y2lx6q'); const versionStore = await versionStoreFactory({ readOnly: true, versionRoot, chunk, linkCodec, valueCodec, blockStore, }); const graphStore = graphStoreFactory({ chunk, linkCodec, valueCodec, blockStore, }); const itemList = itemListFactory(versionStore, graphStore); const item31 = await itemList.get(31); const extRef = item31.value.get(KeyTypes.EXT_REF); console.log('extRef', extRef); assert.strictEqual('bafkreie2iaqxhv56xdtqyih57txqllfwswu7ixhgbnkmfts5weybfuodgu', extRef.extRoot); assert.strictEqual(ElemType.VERTEX, extRef.elemType); assert.strictEqual(1, extRef.elemOffset); /** * Resolve external ref */ const { extRoot, elemOffset } = extRef; const extItemList = await readonlyItemList({ versionRoot: linkCodec.parseString(extRoot), chunk, linkCodec, valueCodec, blockStore, }); const extItem = await extItemList.get(elemOffset); let ExtKeyTypes; (function (ExtKeyTypes) { ExtKeyTypes[ExtKeyTypes["NAME"] = 1] = "NAME"; })(ExtKeyTypes || (ExtKeyTypes = {})); assert.strictEqual('item 1', extItem.value.get(ExtKeyTypes.NAME)); } }); }); //# sourceMappingURL=item-list.test.js.map