mirror of
https://github.com/Kong/insomnia
synced 2024-11-08 23:00:30 +00:00
6a1abbf3db
* initial implementation * take vcs as a parameter (so it's easier to mock and test) * update console log and exit early if not logged in * add unit tests for migration * add async filter and replace vcs find by root document * lint fix * fix memory driver and add test for hasProjectForRootDocument * setup check on interval * move migration logic and interval from main process to render process, because session state and a VCS instance dont work in the main process yet * update test * replace constructor with static class creator * replace interval with login logout hook * remove effect helpers * empty commit to trigger CI
157 lines
3.8 KiB
TypeScript
157 lines
3.8 KiB
TypeScript
import fs from 'fs';
|
|
import mkdirp from 'mkdirp';
|
|
import path from 'path';
|
|
|
|
import type { BaseDriver } from './base';
|
|
|
|
export default class FileSystemDriver implements BaseDriver {
|
|
_directory: string;
|
|
|
|
private constructor(config: { directory: string }) {
|
|
this._directory = config.directory;
|
|
console.log(`[FileSystemDriver] Initialized in "${this._directory}"`);
|
|
}
|
|
|
|
static create(dataDirectory: string) {
|
|
const directory = path.join(dataDirectory, 'version-control');
|
|
return new FileSystemDriver({ directory });
|
|
}
|
|
|
|
async hasItem(key: string) {
|
|
return new Promise<boolean>((resolve, reject) => {
|
|
fs.stat(this._getKeyPath(key), err => {
|
|
if (err && err.code === 'ENOENT') {
|
|
resolve(false);
|
|
} else if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve(true);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
setItem(key: string, value: Buffer) {
|
|
return new Promise<void>((resolve, reject) => {
|
|
const finalPath = this._getKeyPath(key);
|
|
|
|
// Temp path contains randomness to avoid race-condition collisions. This
|
|
// doesn't actually avoid race conditions but at least it won't fail.
|
|
const tmpPath = `${finalPath}.${Math.random()}.tmp`;
|
|
// This method implements atomic writes by first writing to a temporary
|
|
// file (non-atomic) then renaming the file to the final value (atomic)
|
|
fs.writeFile(tmpPath, value, 'utf8', err => {
|
|
if (err) {
|
|
return reject(err);
|
|
}
|
|
|
|
fs.rename(tmpPath, finalPath, err => {
|
|
if (err) {
|
|
return reject(err);
|
|
}
|
|
|
|
resolve();
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
getItem(key: string) {
|
|
return new Promise<Buffer | null>((resolve, reject) => {
|
|
fs.readFile(this._getKeyPath(key), (err, data) => {
|
|
if (err && err.code === 'ENOENT') {
|
|
resolve(null);
|
|
} else if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve(data);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
removeItem(key: string) {
|
|
return new Promise<void>((resolve, reject) => {
|
|
fs.unlink(this._getKeyPath(key), err => {
|
|
if (err && err.code === 'ENOENT') {
|
|
resolve();
|
|
} else if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
clear() {
|
|
return new Promise<void>((resolve, reject) => {
|
|
fs.readdir(this._directory, (err, names) => {
|
|
if (err) {
|
|
return reject(err);
|
|
}
|
|
|
|
for (const name of names) {
|
|
fs.unlinkSync(this._getKeyPath(name));
|
|
}
|
|
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
|
|
async keys(prefix: string, recursive: boolean) {
|
|
const next = dir => {
|
|
return new Promise<string[]>(async (resolve, reject) => {
|
|
let keys: string[] = [];
|
|
let names: string[] = [];
|
|
|
|
try {
|
|
names = fs.readdirSync(dir);
|
|
} catch (err) {
|
|
if (err.code !== 'ENOENT') {
|
|
reject(err);
|
|
}
|
|
}
|
|
|
|
for (const name of names) {
|
|
if (name.indexOf('.') === 0) {
|
|
// Skip any non-vcs files
|
|
continue;
|
|
}
|
|
|
|
const p = path.join(dir, name);
|
|
const isDir = fs.statSync(p).isDirectory();
|
|
|
|
if (isDir && recursive) {
|
|
const more = await next(p);
|
|
keys = [...keys, ...more];
|
|
} else if (!recursive && isDir) {
|
|
keys.push(p);
|
|
} else if (!isDir) {
|
|
keys.push(p);
|
|
}
|
|
}
|
|
|
|
resolve(keys);
|
|
});
|
|
};
|
|
|
|
const rawKeys = await next(this._getKeyPath(prefix));
|
|
const keys: string[] = [];
|
|
|
|
for (const rawKey of rawKeys) {
|
|
keys.push(rawKey.substring(this._directory.length));
|
|
}
|
|
|
|
return keys;
|
|
}
|
|
|
|
_getKeyPath(key: string) {
|
|
const p = path.join(this._directory, key);
|
|
// Create base directory
|
|
mkdirp.sync(path.dirname(p));
|
|
return p;
|
|
}
|
|
}
|