/**
* @author Michael Hasenstein <hasenstein@yahoo.com>
* @copyright REFINIO GmbH 2022
* @license CC-BY-NC-SA-2.5; portions MIT License
* @version 0.0.1
*/
/**
* Helper function(s) to use the version-maps to get the hashes for ID hashes.
* @module
*/
import type {HashAndIdHashAndTimestamp} from '../object-graph-bottom-up-iterator';
import {getAllVersionMapEntries, getNthVersionMapEntry} from '../version-map-query';
import {flat} from './function';
import type {SHA256IdHash} from './type-checks';
/**
* An ID hash stands for 1...n concrete objects. When iterating over the graph we need to
* transform ID object links to their individual members. This function finds the member objects
* behind the given ID object hashes by querying the version map for each ID hash.
*
* An ID object also disrupts a fundamental property of our hash-link based directed graphs:
*
* Normally it is not possible to write a new linked object after the linking parent object has
* been written. While you can calculate hashes manually and not write an object to storage this
* is highly discouraged. Since you need to have all the data at that point in any case it makes
* no sense not to write the object right away, before you store the parent linking to it, since
* you could end up with an inconsistent or broken object graph for no gain at all (again, you
* already have all the data, or you could not calculate the hash of the microdata string).
*
* ID object links however make it possible to link to *future objects*, new versions belonging
* to the ID object.
*
* Normally we can therefore assume the creation timestamp of the root object is the latest
* date-time of any object in the graph. However, when we encounter an ID object link this
* assumption may break since it is only true for versions of the linked ID object written prior
* to the linking parent object. That is why when we encounter an ID link we start a new
* iteration with a new `createdAt` timestamp of what now is the new root of the graph hanging
* on the concrete version. We do this for all versions of the ID object.
*
* @private
* @param {SHA256IdHash[]} idHashes
* @returns {Promise<HashAndIdHashAndTimestamp[]>} Returns an object with hash, ID hash
* and object creation timestamp. There is one hash for one ID hash if `idObjectsLatestOnly ===
* true`, otherwise there may be many hashes for each ID hash.
*/
export async function getLatestHashesForIdHashes(
idHashes: readonly SHA256IdHash[]
): Promise<HashAndIdHashAndTimestamp[]> {
// 1:1 mapping per ID Reference (only latest version is used)
return await Promise.all(
idHashes.map(async idHash => {
const entry = await getNthVersionMapEntry(idHash);
return {
hash: entry.hash,
idHash,
timestamp: entry.timestamp
};
})
);
}
/**
* See {@link getLatestHashesForIdHashes}
* @private
* @param {SHA256IdHash[]} idHashes
* @returns {Promise<HashAndIdHashAndTimestamp[]>} Returns an object with hash, ID hash
* and object creation timestamp. There is one hash for one ID hash if `idObjectsLatestOnly ===
* true`, otherwise there may be many hashes for each ID hash.
*/
export async function getAllHashesForIdHashes(
idHashes: readonly SHA256IdHash[]
): Promise<HashAndIdHashAndTimestamp[]> {
// 1:n mapping per ID Reference (all versions are used)
return flat(
await Promise.all(
idHashes.map(async idHash => {
const entries = await getAllVersionMapEntries(idHash);
return entries.map(entry => ({
hash: entry.hash,
idHash,
timestamp: entry.timestamp
}));
})
)
);
}