Source: storage/fs-storage-interface.js

import fs from 'fs';
import StorageInterface from './storage-interface';

function ensureExistsOrCreate(directory) {
  if (!fs.existsSync(directory)) {
    fs.mkdirSync(directory);
  }
}

function generateDocumentId() {
  return `doc${Math.floor(Math.random() * 10000)}`;
}

/** An example file system storage interface implementation. This is not secure and shouldn't be used in production */
class FSStorageInterface extends StorageInterface {
  constructor(directory) {
    super();
    this.directory = directory;
  }

  async get({ id }) {
    const content = JSON.parse(fs.readFileSync(this.buildFilePath(id)).toString('utf8'));
    return {
      id,
      content,
    };
  }

  async update(options) {
    return this.insert(options);
  }

  async delete({ document }) {
    fs.unlinkSync(this.buildFilePath(document.id));
  }

  async insert({ document }) {
    ensureExistsOrCreate(this.directory);
    const docId = document.id || generateDocumentId();
    fs.writeFileSync(this.buildFilePath(docId), JSON.stringify(document.content, null, 2));
    return {
      id: docId,
      document,
    };
  }

  async count(query) {
    const result = await this.find(query);
    return result.length;
  }

  async find({ has = undefined, equals = undefined } = {}) {
    ensureExistsOrCreate(this.directory);
    const dirResults = fs.readdirSync(this.directory);
    const documents = dirResults.map((filepath) => {
      if (filepath.indexOf('.json') !== -1) {
        const docId = filepath.replace('.json', '');
        const content = JSON.parse(fs.readFileSync(this.buildFilePath(filepath)).toString('utf8'));

        let matchesQuery = false;
        if (!has && !equals) { // Return all documents
          matchesQuery = true;
        } else if (equals && equals['content.id']) { // Basic "query" support for tests
          matchesQuery = content.id === equals['content.id'];
        }

        if (matchesQuery) {
          return {
            id: docId,
            content,
          };
        }
      }

      return null;
    }).filter((value) => !!value);
    return { documents };
  }

  buildFilePath(filepath) {
    let path = filepath;
    if (path.indexOf('.json') === -1) {
      path += '.json';
    }
    return `${this.directory}/${path}`;
  }
}

export default FSStorageInterface;