jdxcode/npm-register

View on GitHub
lib/storage/fs.js

Summary

Maintainability
A
0 mins
Test Coverage
const config = require('../config')
const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs-extra'))
const path = require('path')
const Stream = require('stream')
const klaw = require('klaw')

class FS extends require('./base') {
  constructor () {
    super()
    this.directory = path.resolve(config.fs.directory)
    console.log(`Saving files to local filesystem at ${this.directory}`)
    if (!config.fs.directory) console.error('Set NPM_REGISTER_FS_DIRECTORY to change directory')
  }

  get (key) {
    return fs.readFileAsync(this._genpath(key), 'utf8')
      .catch(err => {
        if (err.code !== 'ENOENT') throw err
      })
  }

  getAllPackageInfo (prefix) {
    const response = []
    const dir = this._genpath(prefix)
    return new Promise((resolve, reject) => {
      klaw(dir)
        .on('data', item => {
          if (!item.stats.isDirectory()) {
            let json = JSON.parse(fs.readFileSync(item.path, 'utf8'))
            let packageDetails = this.createPackageDetails(json)
            if (packageDetails) {
              response.push(packageDetails)
            }
          }
        })
        .on('error', err => {
          if (err.code === 'ENOENT') resolve([])
          else reject(err)
        })
        .on('end', () => resolve(response))
    })
  }

  stream (key) {
    let file = this._genpath(key)
    return fs.statAsync(file)
      .then(info => {
        return {
          stream: fs.createReadStream(file),
          size: info.size
        }
      }).catch(err => {
        if (err.code !== 'ENOENT') throw err
      })
  }

  put (key, data) {
    let file = this._genpath(key)
    console.log(`Writing ${file}`)
    fs.mkdirpSync(path.dirname(file))
    if (data instanceof Stream) {
      return new Promise((resolve, reject) => {
        let output = fs.createWriteStream(file)
        output.on('error', reject)
        data.pipe(output)
        data.on('error', reject)
        output.on('finish', resolve)
      })
    } else if (data instanceof Buffer) {
      return fs.outputFileAsync(file, data)
    } else {
      data = JSON.stringify(data)
      return fs.outputFileAsync(file, data)
    }
  }

  delete (key) {
    let file = this._genpath(key)
    return fs.unlinkAsync(file)
  }

  list (prefix) {
    let file = this._genpath(prefix)
    return new Promise((resolve, reject) => {
      let items = []
      klaw(file)
        .on('data', item => {
          if (!item.stats.isDirectory()) {
            items.push(item.path.replace(this.directory, ''))
          }
        })
        .on('error', err => {
          if (err.code === 'ENOENT') resolve([])
          else reject(err)
        })
        .on('end', () => resolve(items))
    })
  }

  _genpath (key) {
    return path.join(this.directory, key)
  }
}

module.exports = FS