import {Dataset, ReadonlyDataset} from "@opennetwork/rdf-dataset" import {getEnvironmentConfig} from "@opennetwork/environment" import {DefaultDataFactory, Quad} from "@opennetwork/rdf-data-model" import * as ns from "../namespace" import {literal} from "@opennetwork/rdf-namespace-javascript" export async function hashDataset(dataset: Dataset): Promise { const usedNs = [ ns.engine.datasetHash, ns.engine.datasetHashCreatedAt ] const string = await toString( dataset.except(quad => usedNs.findIndex(node => node.equals(quad.predicate)) === -1) ) const hashed = await hash() const { subject } = getEnvironmentConfig() // Reference as hash const object = DefaultDataFactory.namedNode(`https://conventions.opennetwork.dev/engine/hash/${hashed}`) if (dataset.match({ predicate: ns.engine.datasetHash, object, subject, graph: object }).empty) { dataset.add(new Quad( subject, ns.engine.datasetHash, object, object )) dataset.add(new Quad( object, ns.engine.datasetHashCreatedAt, literal(new Date()), object )) } async function toString(dataset: ReadonlyDataset) { const canonize = await import("rdf-canonize").catch(() => undefined) const array = dataset.toArray() if (canonize) { return canonize.default.canonize(array, { algorithm: "URDNA2015" }) } return JSON.stringify(array) } async function hash(): Promise { if (typeof crypto !== "undefined" && typeof TextEncoder !== "undefined" && typeof TextDecoder !== "undefined") { const array = new TextEncoder().encode(string) const digest = await crypto.subtle.digest("sha-256", array) return new TextDecoder().decode(digest) } else { const module = await import("crypto").catch(() => undefined) if (!module) { throw new Error("Unable to create hash") } const hasher = module.createHash("sha256") hasher.update(string) return hasher.digest("hex") } } async function apply(hash: string) { } }