update server
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const { randomUUID } = require("node:crypto");
|
||||
|
||||
const EMPTY_DATABASE = {
|
||||
fileRecords: [],
|
||||
functionConfigs: [],
|
||||
panelInbox: [],
|
||||
identificationFiles: [],
|
||||
identificationFeedback: [],
|
||||
volumeConfigRequests: [],
|
||||
userInfo: [],
|
||||
companies: [],
|
||||
productionLines: [],
|
||||
licenses: []
|
||||
};
|
||||
|
||||
class JsonStore {
|
||||
constructor(dataDirectory) {
|
||||
this.dataDirectory = dataDirectory;
|
||||
this.filesDirectory = path.join(dataDirectory, "files");
|
||||
this.modelsDirectory = path.join(dataDirectory, "models");
|
||||
this.databasePath = path.join(dataDirectory, "database.json");
|
||||
this.writeQueue = Promise.resolve();
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
await fs.promises.mkdir(this.filesDirectory, { recursive: true });
|
||||
try {
|
||||
await fs.promises.access(this.databasePath);
|
||||
} catch {
|
||||
await this.writeDatabase(structuredClone(EMPTY_DATABASE));
|
||||
}
|
||||
}
|
||||
|
||||
async read() {
|
||||
const content = await fs.promises.readFile(this.databasePath, "utf8");
|
||||
return { ...structuredClone(EMPTY_DATABASE), ...JSON.parse(content) };
|
||||
}
|
||||
|
||||
async update(mutator) {
|
||||
const operation = this.writeQueue.then(async () => {
|
||||
const database = await this.read();
|
||||
const result = await mutator(database);
|
||||
await this.writeDatabase(database);
|
||||
return result;
|
||||
});
|
||||
this.writeQueue = operation.catch(() => undefined);
|
||||
return operation;
|
||||
}
|
||||
|
||||
async writeDatabase(database) {
|
||||
await fs.promises.mkdir(this.dataDirectory, { recursive: true });
|
||||
const temporaryPath = `${this.databasePath}.${process.pid}.tmp`;
|
||||
await fs.promises.writeFile(
|
||||
temporaryPath,
|
||||
`${JSON.stringify(database, null, 2)}\n`,
|
||||
"utf8"
|
||||
);
|
||||
await fs.promises.rename(temporaryPath, this.databasePath);
|
||||
}
|
||||
|
||||
createId(prefix) {
|
||||
return `${prefix}_${randomUUID()}`;
|
||||
}
|
||||
|
||||
resolveStoredFile(fileID) {
|
||||
if (typeof fileID !== "string") return null;
|
||||
const isModel = fileID.startsWith("model://");
|
||||
if (!isModel && !fileID.startsWith("local://")) return null;
|
||||
const rootDirectory = isModel ? this.modelsDirectory : this.filesDirectory;
|
||||
const relativePath = fileID.slice(isModel ? "model://".length : "local://".length).replace(/\\/g, "/");
|
||||
const absolutePath = path.resolve(rootDirectory, relativePath);
|
||||
const relativeToRoot = path.relative(rootDirectory, absolutePath);
|
||||
if (relativeToRoot.startsWith("..") || path.isAbsolute(relativeToRoot)) return null;
|
||||
return absolutePath;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { EMPTY_DATABASE, JsonStore };
|
||||
Reference in New Issue
Block a user