UNPKG

modern-valhalla

Version:
200 lines (170 loc) 4.75 kB
'use strict'; const async = require('async'); const AWS = require('aws-sdk'); const Cache = require('nice-cache'); const format = require('stringformat'); const fs = require('fs-extra'); const nodeDir = require('node-dir'); const _ = require('lodash'); const getFileInfo = require('../../utils/get-file-info'); const getNextYear = require('../../utils/get-next-year'); const strings = require('../../resources'); module.exports = function(conf) { AWS.config.update({ accessKeyId: conf.s3.key, secretAccessKey: conf.s3.secret, region: conf.s3.region, httpOptions: {timeout: conf.s3.timeout || 10000}, }); const bucket = conf.s3.bucket; const cache = new Cache({ verbose: !!conf.verbosity, refreshInterval: conf.refreshInterval, }); const getClient = () => new AWS.S3(); const getFile = (filePath, force, callback) => { if (_.isFunction(force)) { callback = force; force = false; } const getFromAws = (cb) => { getClient().getObject( { Bucket: bucket, Key: filePath, }, (err, data) => { if (err) { return callback( err.code === 'NoSuchKey' ? { code: strings.errors.s3.FILE_NOT_FOUND_CODE, msg: format(strings.errors.s3.FILE_NOT_FOUND, filePath), } : err ); } cb(null, data.Body.toString()); } ); }; if (force) { return getFromAws(callback); } const cached = cache.get('s3-file', filePath); if (cached) { return callback(null, cached); } getFromAws((err, result) => { if (err) { return callback(err); } cache.set('s3-file', filePath, result); cache.sub('s3-file', filePath, getFromAws); callback(null, result); }); }; const getJson = (filePath, force, callback) => { if (_.isFunction(force)) { callback = force; force = false; } getFile(filePath, force, (err, file) => { if (err) { return callback(err); } try { callback(null, JSON.parse(file)); } catch (er) { return callback({ code: strings.errors.s3.FILE_NOT_VALID_CODE, msg: format(strings.errors.s3.FILE_NOT_VALID, filePath), }); } }); }; const listSubDirectories = (dir, callback) => { const normalisedPath = dir.lastIndexOf('/') === dir.length - 1 && dir.length > 0 ? dir : dir + '/'; getClient().listObjects( { Bucket: bucket, Prefix: normalisedPath, Delimiter: '/', }, (err, data) => { if (err) { return callback(err); } if (data.CommonPrefixes.length === 0) { return callback({ code: strings.errors.s3.DIR_NOT_FOUND_CODE, msg: format(strings.errors.s3.DIR_NOT_FOUND, dir), }); } const result = _.map(data.CommonPrefixes, (commonPrefix) => commonPrefix.Prefix.substr( normalisedPath.length, commonPrefix.Prefix.length - normalisedPath.length - 1 ) ); callback(null, result); } ); }; const putDir = (dirInput, dirOutput, callback) => { nodeDir.paths(dirInput, (err, paths) => { async.each( paths.files, (file, cb) => { const relativeFile = file.substr(dirInput.length); const url = (dirOutput + relativeFile).replace(/\\/g, '/'); putFile(file, url, relativeFile === '/server.js', cb); }, (errors) => { if (errors) { return callback(_.compact(errors)); } callback(null, 'ok'); } ); }); }; const putFileContent = (fileContent, fileName, isPrivate, callback) => { const fileInfo = getFileInfo(fileName); const obj = { Bucket: bucket, Key: fileName, Body: fileContent, ACL: isPrivate ? 'authenticated-read' : 'public-read', ServerSideEncryption: 'AES256', Expires: getNextYear(), }; if (fileInfo.mimeType) { obj.ContentType = fileInfo.mimeType; } if (fileInfo.gzip) { obj.ContentEncoding = 'gzip'; } getClient().putObject(obj, callback); }; const putFile = (filePath, fileName, isPrivate, callback) => { fs.readFile(filePath, (err, fileContent) => { if (err) { return callback(err); } putFileContent(fileContent, fileName, isPrivate, callback); }); }; return { getFile, getJson, listSubDirectories, maxConcurrentRequests: 20, putDir, putFile, putFileContent, }; };