├── .eslintrc.yml ├── test ├── .eslintrc.yml ├── storages │ ├── S3Storage.test.js │ └── LocalStorage.test.js └── Giga.test.js ├── .coveralls.yml ├── index.js ├── .npmignore ├── .editorconfig ├── LICENSE ├── .circleci └── config.yml ├── package.json ├── storages ├── S3Storage.js └── LocalStorage.js ├── README.md ├── lib └── Giga.js └── .gitignore /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | extends: 2 | - 'omnious' 3 | -------------------------------------------------------------------------------- /test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | jest: true 3 | -------------------------------------------------------------------------------- /.coveralls.yml: -------------------------------------------------------------------------------- 1 | repo_token: QfmiG9DlOcuY1kphI4LkSFFyMf7tHc67W 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Giga = require('./lib/Giga'); 4 | 5 | 6 | module.exports = Giga; 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | coverage 2 | test 3 | .*.log 4 | .circleci 5 | .coveralls.yml 6 | .editorconfig 7 | .eslintrc* 8 | .npmignore 9 | .tern* 10 | .travis.yml -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = LF 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.js] 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [*.{yml,yaml,json}] 15 | indent_style = space 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /test/storages/S3Storage.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { PassThrough } = require('stream'); 4 | const S3Storage = require('../../storages/S3Storage'); 5 | 6 | 7 | describe('S3Storage', () => { 8 | const storage = new S3Storage({ bucket: 'test' }); 9 | 10 | describe('constructor(options)', () => { 11 | it('should create an instance of S3Storage', () => { 12 | expect(new S3Storage()).toBeInstanceOf(S3Storage); 13 | }); 14 | }); 15 | 16 | describe('download(filePath, options)', () => { 17 | it('should create an instance of PassThrough', async () => { 18 | const src = await storage.download('non-exist.jpg'); 19 | expect(src).toBeInstanceOf(PassThrough); 20 | }); 21 | }); 22 | 23 | describe('upload(src, filePath, options)', () => { 24 | }); 25 | 26 | describe('remove(filePath)', () => { 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/Giga.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Giga = require('../'); 4 | 5 | 6 | describe('Giga', () => { 7 | describe('constructor(options)', () => { 8 | it('should throw error when the storage is not provided', () => { 9 | expect(() => new Giga()).toThrow('Storage must be provided'); 10 | }); 11 | }); 12 | }); 13 | 14 | describe('Giga(LocalStorage)', () => { 15 | describe('constructor(options)', () => { 16 | it('should create an instance of Giga with LocalStorage'); 17 | }); 18 | 19 | describe('download(filePath, dst, options)', () => { 20 | }); 21 | 22 | describe('upload(src, options)', () => { 23 | }); 24 | 25 | describe('remove(filePath)', () => { 26 | }); 27 | }); 28 | 29 | describe('Giga(S3Storage)', () => { 30 | describe('constructor(options)', () => { 31 | it('should create an instance of Giga with LocalStorage'); 32 | }); 33 | 34 | describe('download(filePath, dst, options)', () => { 35 | }); 36 | 37 | describe('upload(src, options)', () => { 38 | }); 39 | 40 | describe('remove(filePath)', () => { 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Byungjin Park 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | build: 5 | docker: 6 | # Primary container 7 | - image: circleci/node:8.5.0 8 | environment: 9 | TZ: Asia/Seoul 10 | steps: 11 | - checkout 12 | - restore_cache: 13 | key: dependencies-{{ checksum "package.json" }} 14 | - run: 15 | name: Install Dependencies 16 | command: yarn && yarn add -D jest-junit 17 | - save_cache: 18 | key: dependencies-{{ checksum "package.json" }} 19 | paths: 20 | - ./node_modules 21 | - run: 22 | name: Lint and Test 23 | command: | 24 | mkdir -p ~/reports 25 | yarn lint -- --format junit --output-file ~/reports/eslint.xml 26 | JEST_JUNIT_OUTPUT=~/reports/test-results.xml yarn test:coverage -- --coverageDirectory ~/reports --testResultsProcessor ./node_modules/jest-junit 27 | - run: 28 | name: Upload Test Coverage to Coveralls 29 | command: yarn run coveralls < ~/reports/lcov.info 30 | - store_test_results: 31 | path: ~/reports 32 | - store_artifacts: 33 | path: ~/reports 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "giga", 3 | "version": "0.2.4", 4 | "description": "Easy streaming upload and download for storages(File System, AWS S3)", 5 | "license": "MIT", 6 | "author": "Claud D. Park (http://www.posquit0.com)", 7 | "contributors": [], 8 | "homepage": "https://github.com/posquit0/node-giga#readme", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/posquit0/node-giga.git" 12 | }, 13 | "bugs": { 14 | "url": "https://github.com/posquit0/node-giga/issues" 15 | }, 16 | "keywords": [ 17 | "streaming", 18 | "stream", 19 | "upload", 20 | "download", 21 | "filesystem", 22 | "file", 23 | "s3", 24 | "aws-s3", 25 | "storage", 26 | "transfer" 27 | ], 28 | "engines": { 29 | "node": ">=4" 30 | }, 31 | "files": [ 32 | "index.js", 33 | "lib/", 34 | "storages/" 35 | ], 36 | "main": "index", 37 | "scripts": { 38 | "test": "NODE_ENV=test jest --forceExit", 39 | "test:watch": "npm test -- --watch", 40 | "test:coverage": "npm test -- --coverage", 41 | "lint": "eslint lib test", 42 | "lint:lib": "eslint lib", 43 | "lint:test": "eslint test" 44 | }, 45 | "dependencies": { 46 | "aws-sdk": "^2.170.0", 47 | "debug": "^4.0.0", 48 | "uuid": "^3.1.0" 49 | }, 50 | "devDependencies": { 51 | "coveralls": "^3.0.0", 52 | "eslint": "^4.13.1", 53 | "eslint-config-omnious": "^0.4.0", 54 | "jest": "^21.2.1" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /test/storages/LocalStorage.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const { Readable } = require('stream'); 6 | const LocalStorage = require('../../storages/LocalStorage'); 7 | 8 | 9 | describe('LocalStorage', () => { 10 | const storage = new LocalStorage(); 11 | 12 | describe('constructor(options)', () => { 13 | it('should create an instance of LocalStorage', () => { 14 | expect(new LocalStorage()).toBeInstanceOf(LocalStorage); 15 | }); 16 | }); 17 | 18 | describe('download(filePath, options)', () => { 19 | it('should create an instance of ReadableStream', async () => { 20 | const src = await storage.download('non-exist.jpg'); 21 | expect(src).toBeInstanceOf(Readable); 22 | src.on('error', () => {}); 23 | }); 24 | it('should trigger ENOENT error event when try to download non-exist file', async () => { 25 | const src = await storage.download('non-exist.jpg'); 26 | expect(src).toBeInstanceOf(Readable); 27 | src.on('error', err => { 28 | expect(err.message).toMatch('ENOENT: no such file or directory'); 29 | }); 30 | }); 31 | }); 32 | 33 | describe('upload(src, filePath, options)', () => { 34 | it('should return `undefined` when upload is finished', async () => { 35 | const filename = 'test-upload'; 36 | const srcPath = path.join(process.cwd(), 'package.json'); 37 | const src = fs.createReadStream(srcPath); 38 | expect(storage.upload(src, filename)).resolves.toBe(); 39 | }); 40 | }); 41 | 42 | describe('remove(filePath)', () => { 43 | it('should reject with ENOENT error when try to remove non-exist file', async () => { 44 | try { 45 | await storage.remove('non-exist.jpg'); 46 | } catch (err) { 47 | expect(err.message).toMatch('ENOENT: no such file or directory'); 48 | } 49 | }); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /storages/S3Storage.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const debug = require('debug')('giga'); 4 | const url = require('url'); 5 | const S3 = require('aws-sdk/clients/s3'); 6 | 7 | 8 | /** 9 | * AWS S3 storage 10 | */ 11 | class S3Storage { 12 | /** 13 | * Create a new storage instance. 14 | * 15 | * @param {Object} [options={}] - The configuration of LocalStorage. 16 | */ 17 | constructor(options = {}) { 18 | this.options = Object.assign({ 19 | region: 'us-west-1', 20 | apiVersion: '2006-03-01', 21 | params: {} 22 | }, options); 23 | this.protocol = 's3'; 24 | this.bucket = this.options.bucket; 25 | const baseUrl = url.format({ 26 | protocol: this.protocol, 27 | host: this.bucket, 28 | slashes: true 29 | }); 30 | this.baseUrl = baseUrl.replace(/([^/])$/, '$1/'); 31 | this.options.params['Bucket'] = this.bucket; 32 | this.client = new S3(this.options); 33 | 34 | debug('[storage-s3] create an instance'); 35 | } 36 | 37 | /** 38 | * Create a readable stream to download the data from. 39 | * 40 | * @param {string} filePath - The file path to download. 41 | * @param {Object} [options={}] - The download options. 42 | * @returns {Promise} 43 | */ 44 | download(filePath, options = {}) { 45 | const params = Object.assign({ 46 | 'Bucket': this.bucket, 47 | 'Key': filePath 48 | }, options); 49 | const request = this.client.getObject(params); 50 | const src = request.createReadStream(); 51 | debug(`[storage-s3:download] Bucket=${params['Bucket']} Key=${params['Key']}`); 52 | 53 | return new Promise((resolve, reject) => { 54 | request.on('error', reject); 55 | return resolve(src); 56 | }); 57 | } 58 | 59 | /** 60 | * Upload the data as a readable stream to. 61 | * 62 | * @param {stream.Readable} src - The source stream. 63 | * @param {string} filePath - The file path to upload. 64 | * @param {Object} [options={}] - The upload options. 65 | * @returns {Promise} 66 | */ 67 | upload(src, filePath, options = {}) { 68 | const params = Object.assign({ 69 | 'Bucket': this.bucket, 70 | 'Key': filePath, 71 | 'Body': src 72 | }, options); 73 | debug(`[storage-s3:upload] Bucket=${params['Bucket']} Key=${params['Key']}`); 74 | 75 | return this.client.upload(params).promise(); 76 | } 77 | 78 | /** 79 | * Remove the data from storage. 80 | * 81 | * @param {string} filePath - The file path to remove. 82 | * @returns {Promise} 83 | */ 84 | remove(filePath) { 85 | const params = { 86 | 'Bucket': this.bucket, 87 | 'Key': filePath 88 | }; 89 | const request = this.client.deleteObject(params).promise(); 90 | debug(`[storage-s3:remove] Bucket=${params['Bucket']} Key=${params['Key']}`); 91 | return request.then(() => filePath); 92 | } 93 | } 94 | 95 | module.exports = S3Storage; 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

Giga

3 |
4 | 5 |

6 | Storage-agnostic streaming upload/download in Node.js 7 |

8 | 9 |
10 | 11 | CircleCI 12 | 13 | 14 | Coverage Status 15 | 16 | 17 | npm version 18 | 19 | 20 | npm 21 | 22 | 23 | npm 24 | 25 | 26 | MIT Licence 27 | 28 | 29 | Open Source Love 30 | 31 |
32 | 33 |
34 | 35 | **Giga** is an abstract storage class to easily streaming upload and download files to Local File System, AWS S3, and more. 36 | 37 | - It was written for use on [**OMNIOUS**](http://www.omnious.com) which provides fashion A.I API service. 38 | 39 | 40 | ## Installation 41 | 42 | ```bash 43 | # NPM 44 | $ npm install --save giga 45 | # Yarn 46 | $ yarn add giga 47 | ``` 48 | 49 | 50 | ## Usage 51 | 52 | ```node 53 | const fs = require('fs'); 54 | const Giga = require('giga'); 55 | const S3Storage = require('giga/storages/S3Storage'); 56 | const LocalStorage = require('giga/storages/LocalStorage'); 57 | 58 | const storage = new Giga({ 59 | storage: new S3Storage({ 60 | region: 'ap-northeast-2', 61 | bucket: 'test' 62 | }) 63 | }); 64 | 65 | 66 | // Upload file to S3 67 | const { filePath } = await storage.upload(fs.createReadStream('./my-file')); 68 | 69 | // Download file from S3 70 | const { filePath } = await storage.download( 71 | 'hello-world.txt', 72 | fs.createWriteStream('./my-file') 73 | ); 74 | ``` 75 | 76 | 77 | ## Contributing 78 | 79 | This project follows the [**Contributor Covenant**](http://contributor-covenant.org/version/1/4/) Code of Conduct. 80 | 81 | #### Bug Reports & Feature Requests 82 | 83 | Please use the [issue tracker](https://github.com/posquit0/node-giga/issues) to report any bugs or ask feature requests. 84 | 85 | 86 | ## Contact 87 | 88 | If you have any questions, feel free to join me at [`#posquit0` on Freenode](irc://irc.freenode.net/posquit0) and ask away. Click [here](https://kiwiirc.com/client/irc.freenode.net/posquit0) to connect. 89 | 90 | 91 | ## License 92 | 93 | [MIT](https://github.com/posquit0/node-giga/blob/master/LICENSE) © [Byungjin Park](http://www.posquit0.com) 94 | -------------------------------------------------------------------------------- /lib/Giga.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const debug = require('debug')('giga'); 4 | const path = require('path'); 5 | const url = require('url'); 6 | const uuidV4 = require('uuid/v4'); 7 | 8 | 9 | /** 10 | * Giga 11 | */ 12 | class Giga { 13 | /** 14 | * Create a new Giga instance. 15 | * 16 | * @param {Object} options={} - The configurations of Giga. 17 | * @param {Object} options.storage - The storage instance. 18 | */ 19 | constructor(options = {}) { 20 | debug('create an instance'); 21 | this.storage = options.storage; 22 | 23 | if (!this.storage) 24 | throw new Error('Storage must be provided'); 25 | } 26 | 27 | /** 28 | * Download file from the storage. 29 | * 30 | * @param {string} filePath - The file path to download. 31 | * @param {stream.Writable} dst - The destination stream. 32 | * @param {Object} [options={}] - The download options. 33 | * @returns {Promise} 34 | */ 35 | download(filePath, dst, options = {}) { 36 | if (!filePath) 37 | throw new Error('File path must be provided'); 38 | 39 | if (!dst) 40 | throw new TypeError('Destination must be stream'); 41 | 42 | const result = { 43 | filePath, 44 | url: url.resolve(this.storage.baseUrl, filePath) 45 | }; 46 | 47 | debug(`[download] path=${result.filePath} url=${result.url}`); 48 | 49 | return this.storage.download(filePath, options) 50 | .then(src => { 51 | return new Promise((resolve, reject) => { 52 | src.pipe(dst) 53 | .once('error', reject) 54 | .on('finish', () => resolve(result)); 55 | }); 56 | }); 57 | } 58 | 59 | /** 60 | * Upload file to the storage. 61 | * 62 | * @param {stream.Readable} src - The source stream. 63 | * @param {Object} [options={}] - The upload options. 64 | * @param {string} [options.directory] - The directory to upload. 65 | * @param {string} [options.filename] - The file name to upload. 66 | * @returns {Promise} 67 | */ 68 | upload(src, options = {}) { 69 | const directory = options.directory || ''; 70 | const filename = options.filename || uuidV4(); 71 | const filePath = path.posix.join(directory, filename); 72 | const result = { 73 | filePath, 74 | url: url.resolve(this.storage.baseUrl, filePath) 75 | }; 76 | 77 | if (!src) 78 | throw new TypeError('Source must be stream'); 79 | 80 | debug(`[upload] path=${result.filePath} url=${result.url}`); 81 | 82 | return this.storage.upload(src, filePath) 83 | .then(() => result); 84 | } 85 | 86 | /** 87 | * Remove the data from storage. 88 | * 89 | * @param {string} filePath - The file path to remove. 90 | * @returns {Promise} 91 | */ 92 | remove(filePath) { 93 | if (!filePath) 94 | throw new Error('File path must be provided'); 95 | 96 | debug(`[remove] path=${filePath}`); 97 | 98 | return this.storage 99 | .remove(filePath) 100 | .then(() => filePath); 101 | } 102 | } 103 | 104 | module.exports = Giga; 105 | -------------------------------------------------------------------------------- /storages/LocalStorage.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const debug = require('debug')('giga'); 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | const url = require('url'); 7 | 8 | 9 | function mkdirp(dirPath, options = {}) { 10 | const mode = options.mode || 0o777 & (~process.umask()); 11 | 12 | return new Promise((resolve, reject) => { 13 | fs.mkdir(dirPath, mode, (err) => { 14 | if (!err) 15 | return resolve(dirPath); 16 | 17 | if (err.code === 'ENOENT') { 18 | return resolve(mkdirp(path.dirname(dirPath), options) 19 | .then(() => mkdirp(dirPath, options))); 20 | } else { 21 | return fs.stat(dirPath, (_err, stat) => { 22 | return (_err || !stat.isDirectory()) 23 | ? reject(err) 24 | : resolve(dirPath); 25 | }); 26 | } 27 | }); 28 | }); 29 | } 30 | 31 | /** 32 | * Local filesystem storage 33 | */ 34 | class LocalStorage { 35 | /** 36 | * Create a new storage instance. 37 | * 38 | * @param {Object} [options={}] - The configuration of LocalStorage. 39 | */ 40 | constructor(options = {}) { 41 | this.options = Object.assign({ 42 | root: path.join(process.cwd(), '.storage') 43 | }, options); 44 | 45 | this.protocol = 'file'; 46 | this.root = path.normalize(this.options.root); 47 | const baseUrl = url.format({ 48 | protocol: this.protocol, 49 | host: this.root 50 | }); 51 | this.baseUrl = baseUrl.replace(/([^/])$/, '$1/'); 52 | 53 | debug('[storage-local] create an instance'); 54 | } 55 | 56 | /** 57 | * Create a readable stream to download the data from. 58 | * 59 | * @param {string} filePath - The file path to download. 60 | * @param {Object} [options={}] - The download options. 61 | * @returns {Promise} 62 | */ 63 | download(filePath, options = {}) { 64 | const target = path.join(this.root, path.normalize(filePath)); 65 | return new Promise((resolve, reject) => { 66 | try { 67 | const src = fs.createReadStream(target, options); 68 | debug(`[storage-local:download] path=${target}`); 69 | resolve(src); 70 | } catch (err) { 71 | reject(err); 72 | } 73 | }); 74 | } 75 | 76 | /** 77 | * Upload the data as a readable stream to. 78 | * 79 | * @param {stream.Readable} src - The source stream. 80 | * @param {string} filePath - The file path to upload. 81 | * @param {Object} [options={}] - The upload options. 82 | * @returns {Promise} 83 | */ 84 | upload(src, filePath, options = {}) { 85 | const target = path.join(this.root, path.normalize(filePath)); 86 | 87 | // Ensure the path is exists 88 | return mkdirp(path.dirname(target), { mode: 0o755 }) 89 | .then(() => { 90 | const dst = fs.createWriteStream(target, options); 91 | debug(`[storage-local:upload] path=${target}`); 92 | 93 | return new Promise((resolve, reject) => { 94 | src.pipe(dst) 95 | .once('error', reject) 96 | .on('finish', resolve); 97 | }); 98 | }); 99 | } 100 | 101 | /** 102 | * Remove the data from storage. 103 | * 104 | * @param {string} filePath - The file path to remove. 105 | * @returns {Promise} 106 | */ 107 | remove(filePath) { 108 | const target = path.join(this.root, path.normalize(filePath)); 109 | return new Promise((resolve, reject) => { 110 | debug(`[storage-local:remove] path=${target}`); 111 | return fs.unlink(target, err => err ? reject(err) : resolve(target)); 112 | }); 113 | } 114 | } 115 | 116 | module.exports = LocalStorage; 117 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/node,intellij,vim,osx 2 | 3 | .tern* 4 | .storage 5 | 6 | ### Intellij ### 7 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 8 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 9 | 10 | # User-specific stuff: 11 | .idea/**/workspace.xml 12 | .idea/**/tasks.xml 13 | .idea/dictionaries 14 | 15 | # Sensitive or high-churn files: 16 | .idea/**/dataSources/ 17 | .idea/**/dataSources.ids 18 | .idea/**/dataSources.xml 19 | .idea/**/dataSources.local.xml 20 | .idea/**/sqlDataSources.xml 21 | .idea/**/dynamic.xml 22 | .idea/**/uiDesigner.xml 23 | 24 | # Gradle: 25 | .idea/**/gradle.xml 26 | .idea/**/libraries 27 | 28 | # CMake 29 | cmake-build-debug/ 30 | 31 | # Mongo Explorer plugin: 32 | .idea/**/mongoSettings.xml 33 | 34 | ## File-based project format: 35 | *.iws 36 | 37 | ## Plugin-specific files: 38 | 39 | # IntelliJ 40 | /out/ 41 | 42 | # mpeltonen/sbt-idea plugin 43 | .idea_modules/ 44 | 45 | # JIRA plugin 46 | atlassian-ide-plugin.xml 47 | 48 | # Cursive Clojure plugin 49 | .idea/replstate.xml 50 | 51 | # Crashlytics plugin (for Android Studio and IntelliJ) 52 | com_crashlytics_export_strings.xml 53 | crashlytics.properties 54 | crashlytics-build.properties 55 | fabric.properties 56 | 57 | ### Intellij Patch ### 58 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 59 | 60 | # *.iml 61 | # modules.xml 62 | # .idea/misc.xml 63 | # *.ipr 64 | 65 | # Sonarlint plugin 66 | .idea/sonarlint 67 | 68 | ### Node ### 69 | # Logs 70 | logs 71 | *.log 72 | npm-debug.log* 73 | yarn-debug.log* 74 | yarn-error.log* 75 | yarn.lock 76 | 77 | # Runtime data 78 | pids 79 | *.pid 80 | *.seed 81 | *.pid.lock 82 | 83 | # Directory for instrumented libs generated by jscoverage/JSCover 84 | lib-cov 85 | 86 | # Coverage directory used by tools like istanbul 87 | coverage 88 | 89 | # nyc test coverage 90 | .nyc_output 91 | 92 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 93 | .grunt 94 | 95 | # Bower dependency directory (https://bower.io/) 96 | bower_components 97 | 98 | # node-waf configuration 99 | .lock-wscript 100 | 101 | # Compiled binary addons (http://nodejs.org/api/addons.html) 102 | build/Release 103 | 104 | # Dependency directories 105 | node_modules/ 106 | jspm_packages/ 107 | 108 | # Typescript v1 declaration files 109 | typings/ 110 | 111 | # Optional npm cache directory 112 | .npm 113 | 114 | # Optional eslint cache 115 | .eslintcache 116 | 117 | # Optional REPL history 118 | .node_repl_history 119 | 120 | # Output of 'npm pack' 121 | *.tgz 122 | 123 | # Yarn Integrity file 124 | .yarn-integrity 125 | 126 | # dotenv environment variables file 127 | .env 128 | 129 | 130 | ### OSX ### 131 | *.DS_Store 132 | .AppleDouble 133 | .LSOverride 134 | 135 | # Icon must end with two \r 136 | Icon 137 | 138 | # Thumbnails 139 | ._* 140 | 141 | # Files that might appear in the root of a volume 142 | .DocumentRevisions-V100 143 | .fseventsd 144 | .Spotlight-V100 145 | .TemporaryItems 146 | .Trashes 147 | .VolumeIcon.icns 148 | .com.apple.timemachine.donotpresent 149 | 150 | # Directories potentially created on remote AFP share 151 | .AppleDB 152 | .AppleDesktop 153 | Network Trash Folder 154 | Temporary Items 155 | .apdisk 156 | 157 | ### Vim ### 158 | # swap 159 | [._]*.s[a-v][a-z] 160 | [._]*.sw[a-p] 161 | [._]s[a-v][a-z] 162 | [._]sw[a-p] 163 | # session 164 | Session.vim 165 | # temporary 166 | .netrwhist 167 | *~ 168 | # auto-generated tag files 169 | tags 170 | 171 | # End of https://www.gitignore.io/api/node,intellij,vim,osx 172 | --------------------------------------------------------------------------------