storage/src/node.ts

83 lines
2.1 KiB
TypeScript

import { KeyValueStorage } from "./basic";
/**
* Key-value store, using local file-system
*/
export class NodeDirectoryStorage implements KeyValueStorage {
readonly directory: string
private checked = false
constructor(appname: string) {
if (typeof require === "undefined") {
throw new Error("Storage only available in nodejs");
}
const path = require("path");
this.directory = path.join(NodeDirectoryStorage.findUserData(), "tk-storage", appname);
}
/**
* Find the writable user data directory
*/
static findUserData(): string {
const result = process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Preferences' : process.env.HOME + "/.local/share");
if (!result) {
throw new Error("Cannot locate user data directory");
}
return result;
}
/**
* Get the file path for a key
*/
getPath(key: string): string {
const path = require("path");
return path.join(this.directory, key);
}
async get(key: string): Promise<string | null> {
const fs = require("fs");
return new Promise((resolve, reject) => {
fs.readFile(this.getPath(key), { encoding: 'utf8' }, (err: any, data: string) => {
resolve(err ? null : data);
});
});
}
async set(key: string, value: string | null): Promise<void> {
const fs = require("fs");
if (!this.checked) {
await new Promise((resolve, reject) => {
fs.mkdir(this.directory, { recursive: true }, (err: any) => {
if (err && err.code !== 'EEXIST') {
reject(err);
} else {
resolve();
}
});
});
this.checked = true;
}
return new Promise((resolve, reject) => {
if (value === null) {
fs.unlink(this.getPath(key), (err: any) => {
if (err) {
reject(err);
} else {
resolve();
}
});
} else {
fs.writeFile(this.getPath(key), value, { encoding: 'utf8' }, (err: any) => {
if (err) {
reject(err);
} else {
resolve();
}
});
}
});
}
}