📦 deps(thirdparty): update snapshots
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const { fsyncDirectorySync } = require("../durability");
|
||||
const { canonicalJson, sha256 } = require("../canonical-json");
|
||||
const { transactionError } = require("./errors");
|
||||
const { validateInstance } = require("../schema-validator");
|
||||
|
||||
function compareStrings(left, right) {
|
||||
return left < right ? -1 : (left > right ? 1 : 0);
|
||||
}
|
||||
|
||||
function publicEntries(entries) {
|
||||
return entries.map(({ skillId, treeDigest, catalogIntegrity }) => ({ skillId, treeDigest, catalogIntegrity }))
|
||||
.sort((left, right) => compareStrings(left.skillId, right.skillId));
|
||||
}
|
||||
|
||||
function digestManagedEntries(entries) {
|
||||
return sha256(canonicalJson({ schemaVersion: 1, entries: publicEntries(entries) }));
|
||||
}
|
||||
|
||||
function buildManagedState({ target, catalog, entries, completedPlanDigests }) {
|
||||
const normalizedEntries = entries.map((entry) => ({ ...entry }))
|
||||
.sort((left, right) => compareStrings(left.skillId, right.skillId));
|
||||
const state = {
|
||||
schemaVersion: 1,
|
||||
target: { ...target },
|
||||
catalog: { ...catalog },
|
||||
entries: normalizedEntries,
|
||||
completedPlanDigests: [...new Set(completedPlanDigests)].sort(compareStrings).slice(-256),
|
||||
stateDigest: digestManagedEntries(normalizedEntries),
|
||||
};
|
||||
return state;
|
||||
}
|
||||
|
||||
function readManagedState(stateFile) {
|
||||
if (!fs.existsSync(stateFile)) return null;
|
||||
const stat = fs.lstatSync(stateFile);
|
||||
if (stat.isSymbolicLink() || !stat.isFile() || stat.nlink !== 1 || stat.size > 1024 * 1024) {
|
||||
throw transactionError("AAS_TRANSACTION_STATE_UNSAFE", "filesystem", {});
|
||||
}
|
||||
let state;
|
||||
try {
|
||||
state = JSON.parse(fs.readFileSync(stateFile, "utf8"));
|
||||
} catch (cause) {
|
||||
throw transactionError("AAS_TRANSACTION_STATE_CORRUPT", "integrity", {}, cause);
|
||||
}
|
||||
if (!state || state.schemaVersion !== 1 || !Array.isArray(state.entries) || !Array.isArray(state.completedPlanDigests)) {
|
||||
throw transactionError("AAS_TRANSACTION_STATE_CORRUPT", "integrity", {});
|
||||
}
|
||||
validateInstance("managed-state.schema.json", state, "AAS_TRANSACTION_STATE_SCHEMA_INVALID");
|
||||
const ids = new Set();
|
||||
for (const entry of state.entries) {
|
||||
if (!entry || typeof entry.skillId !== "string" || ids.has(entry.skillId)
|
||||
|| typeof entry.treeDigest !== "string" || typeof entry.catalogIntegrity !== "string"
|
||||
|| typeof entry.installedByPlanDigest !== "string") {
|
||||
throw transactionError("AAS_TRANSACTION_STATE_CORRUPT", "integrity", {});
|
||||
}
|
||||
ids.add(entry.skillId);
|
||||
}
|
||||
if (state.stateDigest !== digestManagedEntries(state.entries)) {
|
||||
throw transactionError("AAS_TRANSACTION_STATE_DIGEST_MISMATCH", "integrity", {});
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
function fsyncDirectory(directory) {
|
||||
fsyncDirectorySync(directory);
|
||||
}
|
||||
|
||||
function writeFileDurable(filePath, bytes, mode = 0o600) {
|
||||
const descriptor = fs.openSync(filePath, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, mode);
|
||||
try {
|
||||
fs.writeFileSync(descriptor, bytes);
|
||||
fs.fsyncSync(descriptor);
|
||||
} finally {
|
||||
fs.closeSync(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
function atomicWriteManagedState(stateFile, state, transactionRoot) {
|
||||
const temporary = path.join(transactionRoot, "managed-state.next.json");
|
||||
if (fs.existsSync(temporary)) fs.rmSync(temporary, { force: true });
|
||||
writeFileDurable(temporary, `${canonicalJson(state)}\n`);
|
||||
fs.renameSync(temporary, stateFile);
|
||||
fsyncDirectory(path.dirname(stateFile));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
atomicWriteManagedState,
|
||||
buildManagedState,
|
||||
digestManagedEntries,
|
||||
fsyncDirectory,
|
||||
publicEntries,
|
||||
readManagedState,
|
||||
writeFileDurable,
|
||||
};
|
||||
Reference in New Issue
Block a user