Skip to content

Commit

Permalink
feat(Insomnia Cloud Sync): Update filesystem driver for VCS sync (Kon…
Browse files Browse the repository at this point in the history
…g#7111)

* use fs/promises and uuid instead of math.random

* Update packages/insomnia/src/sync/store/drivers/file-system-driver.ts

* Update packages/insomnia/src/sync/store/drivers/file-system-driver.ts

---------

Co-authored-by: Jack Kavanagh <[email protected]>
  • Loading branch information
gatzjames and jackkav committed Mar 13, 2024
1 parent 44ccc69 commit 039821e
Showing 1 changed file with 49 additions and 74 deletions.
123 changes: 49 additions & 74 deletions packages/insomnia/src/sync/store/drivers/file-system-driver.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import fs from 'fs';
import fs from 'fs/promises';
import path from 'path';

import type { BaseDriver } from './base';
Expand All @@ -17,86 +17,62 @@ export default class FileSystemDriver implements BaseDriver {
}

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);
}
});
});
}
try {
const stats = await fs.stat(await this._getKeyPath(key));
const result = stats.isFile() || stats.isDirectory() || stats.isSymbolicLink();

setItem(key: string, value: Buffer) {
return new Promise<void>((resolve, reject) => {
const finalPath = this._getKeyPath(key);
return result;
} catch (err) {
if (err && 'code' in err && err.code === 'ENOENT') {
return false;
}

throw err;
}
}

async setItem(key: string, value: Buffer) {
console.log(`[FileSystemDriver] Writing to ${key}`);
const finalPath = await 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`;

const tmpPath = `${finalPath}.${crypto.randomUUID()}.tmp`;
console.log(`[FileSystemDriver] Writing to ${tmpPath} then renaming to ${finalPath}`);
// 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();
});
});
});
try {
await fs.writeFile(tmpPath, value, 'utf8');
await fs.rename(tmpPath, finalPath);
} catch (err) {
console.error(`[FileSystemDriver] Failed to write to ${tmpPath} then rename to ${finalPath}`, err);
throw err;
}
}

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);
}
});
});
}
async getItem(key: string) {
try {
const file = await fs.readFile(await this._getKeyPath(key));
return file;
} catch (err) {
if (err && 'code' in err && err.code === 'ENOENT') {
return null;
}

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();
}
});
});
throw err;
}
}

clear() {
return new Promise<void>((resolve, reject) => {
fs.readdir(this._directory, (err, names) => {
if (err) {
return reject(err);
}
async removeItem(key: string) {
await fs.unlink(await this._getKeyPath(key));
}

for (const name of names) {
fs.unlinkSync(this._getKeyPath(name));
}
async clear() {
const files = await fs.readdir(this._directory);

resolve();
});
});
for (const fileName of files) {
await fs.unlink(await this._getKeyPath(fileName));
}
}

async keys(prefix: string, recursive: boolean) {
Expand All @@ -106,7 +82,7 @@ export default class FileSystemDriver implements BaseDriver {
let names: string[] = [];

try {
names = fs.readdirSync(dir);
names = await fs.readdir(dir);
} catch (err) {
if (err.code !== 'ENOENT') {
reject(err);
Expand All @@ -120,7 +96,7 @@ export default class FileSystemDriver implements BaseDriver {
}

const p = path.join(dir, name);
const isDir = fs.statSync(p).isDirectory();
const isDir = (await fs.stat(p)).isDirectory();

if (isDir && recursive) {
const more = await next(p);
Expand All @@ -136,7 +112,7 @@ export default class FileSystemDriver implements BaseDriver {
});
};

const rawKeys = await next(this._getKeyPath(prefix));
const rawKeys = await next(await this._getKeyPath(prefix));
const keys: string[] = [];

for (const rawKey of rawKeys) {
Expand All @@ -146,11 +122,10 @@ export default class FileSystemDriver implements BaseDriver {
return keys;
}

_getKeyPath(key: string) {
async _getKeyPath(key: string) {
const p = path.join(this._directory, key);
// Create base directory
fs.mkdirSync(path.dirname(p), { recursive: true });

await fs.mkdir(path.dirname(p), { recursive: true });
return p;
}
}

0 comments on commit 039821e

Please sign in to comment.