stackpress
Version:
Incept is a content management framework.
74 lines (73 loc) • 2.26 kB
JavaScript
import path from 'node:path';
import Registry from '../schema/Registry.js';
export default class Revisions {
static insert(root, loader, schema) {
const revisions = new Revisions(root, loader);
return revisions.insert(schema);
}
root;
loader;
_epochs = [];
constructor(root, loader) {
this.root = root;
this.loader = loader;
}
first(plus = 0) {
if (!this._epochs.length) {
return null;
}
return this.index(0 + plus);
}
index(index) {
if (!this._epochs[index]) {
return null;
}
return this.read(this._epochs[index]);
}
async insert(schema) {
const last = await this.last();
const from = last ? JSON.stringify(last.schema, null, 2) : '';
const to = JSON.stringify(schema, null, 2);
if (from === to) {
return this;
}
if (!await this.loader.fs.exists(this.root)) {
await this.loader.fs.mkdir(this.root, { recursive: true });
}
const epoch = Date.now();
this._epochs.push(epoch);
await this.loader.fs.writeFile(path.join(this.root, `${epoch}.json`), to);
return this;
}
async last(minus = 0) {
if (!this._epochs.length) {
if (await this.loader.fs.exists(this.root)) {
const glob = await import('fast-glob');
const results = glob.default.sync('*.json', { cwd: this.root });
this._epochs = results.map(filename => Number(filename.split('.')[0])).sort();
}
else {
return null;
}
}
return this.index(this._epochs.length - 1 - Math.abs(minus));
}
async read(epoch) {
if (!this._epochs.includes(epoch)) {
return null;
}
const filename = `${epoch}.json`;
const filepath = path.join(this.root, filename);
const schema = await this.loader.import(filepath);
return {
date: new Date(epoch),
file: filename,
path: filepath,
schema: schema,
registry: new Registry(schema)
};
}
size() {
return this._epochs.length;
}
}