You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
65 lines
1.6 KiB
TypeScript
65 lines
1.6 KiB
TypeScript
2 years ago
|
import { writeFileSync } from "node:fs";
|
||
|
import { writeFile, readFile } from "node:fs/promises";
|
||
|
import path from "node:path";
|
||
|
import { onExit } from "./util";
|
||
|
|
||
|
const store = <T extends Object>(
|
||
|
name: string,
|
||
|
init: () => T,
|
||
|
{ persistInterval = 60 * 1000 } = {}
|
||
|
) => {
|
||
|
let state = init();
|
||
|
(state as any)._storeName = name;
|
||
|
|
||
|
const filePath = path.join(process.cwd(), `${name}.json`);
|
||
|
|
||
|
const persist = (sync = false) => {
|
||
|
const write = sync ? writeFileSync : writeFile;
|
||
|
return write(filePath, JSON.stringify(state));
|
||
|
};
|
||
|
const load = async () => {
|
||
|
try {
|
||
|
const newState = await readFile(filePath, { encoding: "utf8" });
|
||
|
state = JSON.parse(newState);
|
||
|
if ((state as any)._storeName !== name) {
|
||
|
console.error(`File at "${filePath}" expected to be a Rappli store`);
|
||
|
process.exit(1);
|
||
|
}
|
||
|
} catch (err) {
|
||
|
if (typeof err === "object" && (err as any).code !== "ENOENT") {
|
||
|
console.dir(err);
|
||
|
process.exit(1);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const globals = globalThis as any;
|
||
|
|
||
|
(async () => {
|
||
|
await load();
|
||
|
const intervalKey = `_store-persist-${name}`;
|
||
|
|
||
|
if (globals[intervalKey] != null) {
|
||
|
clearInterval(globals[intervalKey]);
|
||
|
}
|
||
|
globals[intervalKey] = setInterval(function () {
|
||
|
persist();
|
||
|
}, persistInterval);
|
||
|
})();
|
||
|
|
||
|
const exitKey = `_store-exit-${name}`;
|
||
|
if (globals[exitKey]) {
|
||
|
globals[exitKey]();
|
||
|
}
|
||
|
globals[exitKey] = onExit(() => persist(true));
|
||
|
|
||
|
const getState = () => state;
|
||
|
|
||
|
return [getState] as [typeof getState];
|
||
|
};
|
||
|
|
||
|
export const [state] = store("data", () => ({
|
||
|
version: 0,
|
||
|
likes: 0,
|
||
|
}));
|