├── .eslintignore ├── .gitignore ├── .eslintrc ├── gulpfile.js ├── src ├── utils.js └── index.js ├── LICENSE ├── CHANGELOG.md ├── package.json ├── tests └── src │ ├── utils.spec.js │ └── index.spec.js └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | fake-appData 4 | .vscode 5 | dist 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb-base", 3 | "env": { 4 | "mocha": "true" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const babel = require('gulp-babel'); 3 | 4 | gulp.task('default', () => 5 | gulp.src('./src/**/*.js') 6 | .pipe(babel({ 7 | presets: ['es2015'], 8 | })) 9 | .pipe(gulp.dest('dist')) 10 | ); 11 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | /* eslint object-shorthand: 0 */ 2 | /* eslint no-param-reassign: 0 */ 3 | /* eslint import/no-unresolved: 0 */ 4 | 5 | const electron = require('electron'); 6 | const app = electron.app || electron.remote.app; 7 | const userData = app.getPath('userData'); 8 | const path = require('path'); 9 | 10 | function getElectronFullPath(filePath) { 11 | return path.join(userData, filePath); 12 | } 13 | 14 | function addDotJsonIfNeeded(filePath) { 15 | if (filePath.substring(filePath.length - 5, filePath.length) === '.json') { 16 | return filePath; 17 | } 18 | 19 | return `${filePath}.json`; 20 | } 21 | 22 | function processPath(filePath) { 23 | return addDotJsonIfNeeded(getElectronFullPath(filePath)); 24 | } 25 | 26 | function processPathNoJson(filePath) { 27 | return getElectronFullPath(filePath); 28 | } 29 | 30 | module.exports = { 31 | processPath, 32 | processPathNoJson, 33 | }; 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ran 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 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/). 6 | ## [Unreleased] 7 | 8 | ### Changed 9 | refactored to use ya-storage module 10 | 11 | ## [1.0.7] 12 | ### Added 13 | - CHANGELOG.md 14 | 15 | ### Changed 16 | - update dependencies (minor versions) 17 | - improve README.md 18 | 19 | ## [1.0.6] 20 | ### Changed 21 | - improve README.md and fix lint problems 22 | 23 | ## [1.0.5] 24 | ### Fixed 25 | - windows compatibility 26 | 27 | ### Added 28 | - human readable message to existing ENOENT error 29 | 30 | ## [1.0.4] 31 | ### Changed 32 | - remove the .json automatic ending from ```remove``` and ```isPathExists``` methods because they also works on directories. 33 | - improve README.md file 34 | 35 | ## [1.0.3] 36 | ### Added 37 | - add .json ending on all methods 38 | 39 | ## [1.0.2] 40 | ### Added 41 | - ```storage.remove``` method 42 | 43 | ## [1.0.1] 44 | ### Added 45 | - tests 46 | - eslint 47 | - build 48 | 49 | ## [1.0.0] 50 | - initial version 51 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-storage", 3 | "version": "1.0.7", 4 | "description": "module for managing storage in electron applications", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "test": "electron-mocha --recursive tests -R spec && electron-mocha --renderer --recursive tests -R spec", 8 | "lint": "eslint ./src/**/*.js; exit 0", 9 | "build": "gulp" 10 | }, 11 | "homepage": "https://github.com/ran-y/electron-storage", 12 | "repository": { 13 | "type": "git", 14 | "url": "git@github.com:ran-y/electron-storage.git" 15 | }, 16 | "keywords": [ 17 | "electron", 18 | "storage", 19 | "json", 20 | "get", 21 | "set", 22 | "isPathExists" 23 | ], 24 | "author": "Ran yitzhaki", 25 | "license": "MIT", 26 | "devDependencies": { 27 | "babel-preset-es2015": "^6.9.0", 28 | "chai": "^3.5.0", 29 | "electron-mocha": "^2.3.1", 30 | "electron-prebuilt": "^1.4.10", 31 | "eslint": "^2.9.1", 32 | "eslint-config-airbnb-base": "^3.0.1", 33 | "eslint-plugin-import": "^1.10.2", 34 | "gulp": "^3.9.1", 35 | "gulp-babel": "^6.1.2", 36 | "proxyquire": "^1.7.10" 37 | }, 38 | "dependencies": { 39 | "ya-storage": "^1.0.3" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/src/utils.spec.js: -------------------------------------------------------------------------------- 1 | const chai = require('chai'); 2 | const { processPath } = require('../../dist/utils'); 3 | const electron = require('electron'); 4 | const app = electron.app || electron.remote.app; 5 | const userData = app.getPath('userData'); 6 | const path = require('path'); 7 | 8 | describe('Electron Storage utils', () => { 9 | describe('utils.processPath', () => { 10 | it('adds .json to the end of a file if needed', (done) => { 11 | const filePath = path.join('a', 'filePath', 'without', 'json'); 12 | const fullPath = processPath(filePath); 13 | chai.expect(fullPath).to.equal(path.join(userData, `${filePath}.json`)); 14 | done(); 15 | }); 16 | 17 | it('does not add .json to the end of a file if not needed', (done) => { 18 | const filePath = path.join('a', 'filePath', 'without', 'json.json'); 19 | const fullPath = processPath(filePath); 20 | chai.expect(fullPath).to.equal(path.join(userData, filePath)); 21 | done(); 22 | }); 23 | 24 | it('adds the electron appDataPath', (done) => { 25 | const filePath = 'data.json'; 26 | const fullPath = processPath(filePath); 27 | chai.expect(fullPath).to.equal(path.join(userData, filePath)); 28 | done(); 29 | }); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-underscore-dangle: 0 */ 2 | 3 | import { 4 | processPath, 5 | processPathNoJson, 6 | } from './utils'; 7 | import ya from 'ya-storage'; 8 | 9 | /** 10 | * get - function the gets filePath and a callback and returns a parse json 11 | * from the file in the specefied path 12 | * 13 | * @param {string} filePath - path to the file relative to the `userData` folder 14 | * @param {undefined | function} cb - an optional callback function 15 | * @return {undefined | Promise} if there is only the first argument, the function 16 | * will return a thenable Promise object 17 | */ 18 | function get(filePath, cb) { 19 | const fullPath = processPath(filePath); 20 | return ya.get(fullPath, cb); 21 | } 22 | 23 | /** 24 | * set - sets a json file into the storage at a path (relative to the `userData` folder) 25 | * also stringify the json if needed and create any folder that is required in the path 26 | * 27 | * @param {string} filePath - path to the file relative to the `userData` folder 28 | * @param {string | object} data - the data to save in the file path, can be parseJson or an object 29 | * @param {undefined | function} cb - an optional callback function 30 | * @return {undefined | Promise} if there are only two first arguments, the function 31 | * will return a thenable Promise object 32 | */ 33 | function set(filePath, data, cb) { 34 | const fullPath = processPath(filePath); 35 | return ya.set(fullPath, data, cb); 36 | } 37 | 38 | /** 39 | * isPathExists - check whether the path inserted is exist in the userData directory 40 | * 41 | * @param {string} fileOrDirPath - a path inside of the userData directory 42 | * @param {undefined|func} cb - an optional callback function 43 | * @return {undefined | Promise} if there are only two first arguments, the function 44 | * will return a thenable Promise object 45 | */ 46 | function isPathExists(fileOrDirPath, cb) { 47 | const fullPath = processPathNoJson(fileOrDirPath); 48 | return ya.isPathExists(fullPath, cb); 49 | } 50 | 51 | 52 | /** 53 | * remove - remove the file/folder from the path inserted 54 | * 55 | * @param {string} fileOrDirPath - a path inside of the userData directory 56 | * @param {undefined|func} cb - an optional callback function 57 | * @return {undefined | Promise} if there are only two first arguments, the function 58 | * will return a thenable Promise object 59 | */ 60 | function remove(fileOrDirPath, cb) { 61 | const fullPath = processPathNoJson(fileOrDirPath); 62 | return ya.remove(fullPath, cb); 63 | } 64 | 65 | module.exports = { 66 | get, 67 | set, 68 | isPathExists, 69 | remove, 70 | }; 71 | -------------------------------------------------------------------------------- /tests/src/index.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint consistent-return: 0 */ 2 | 3 | const chai = require('chai'); 4 | const fs = require('fs'); 5 | const rimraf = require('rimraf'); 6 | const path = require('path'); 7 | const proxyquire = require('proxyquire'); 8 | const fakeAppDataDir = path.join(process.cwd(), 'fake-appData'); 9 | const mockGetElectronFullPath = (filePath) => path.join('fake-appData', filePath); 10 | const storage = proxyquire('../../dist/index', { 11 | './utils': { 12 | processPath: mockGetElectronFullPath, 13 | processPathNoJson: mockGetElectronFullPath, 14 | }, 15 | }); 16 | 17 | describe('Electron Storage', () => { 18 | beforeEach('create the fake-appData folder', () => { 19 | fs.mkdirSync(fakeAppDataDir); 20 | }); 21 | 22 | afterEach('delete the fake-appData folder', () => { 23 | rimraf.sync(fakeAppDataDir); 24 | }); 25 | 26 | describe('storage.get()', () => { 27 | it('receives the data from a json file', (done) => { 28 | const json = JSON.stringify({ awesome: 'data' }); 29 | fs.writeFile(path.join(fakeAppDataDir, 'my-awesome-data.json'), json, (err) => { 30 | if (err) { 31 | throw err; 32 | } 33 | 34 | storage.get('my-awesome-data.json', (error, data) => { 35 | chai.expect(error).to.equal(null); 36 | chai.expect(data).to.deep.equal({ awesome: 'data' }); 37 | done(); 38 | }); 39 | }); 40 | }); 41 | }); 42 | 43 | describe('storage.get()', () => { 44 | it('receives the data from a json file', (done) => { 45 | const json = JSON.stringify({ awesome: 'data' }); 46 | fs.writeFile(path.join(fakeAppDataDir, 'my-awesome-data.json'), json, (err) => { 47 | if (err) { 48 | throw err; 49 | } 50 | 51 | storage.get('my-awesome-data.json').then(data => { 52 | chai.expect(data).to.deep.equal({ awesome: 'data' }); 53 | done(); 54 | }); 55 | }); 56 | }); 57 | }); 58 | 59 | describe('storage.set()', () => { 60 | it('sets a json file that you can later get', (done) => { 61 | storage.set('data.json', { js: 'on' }, (err) => { 62 | chai.expect(err).to.equal(null); 63 | storage.get('data.json', (error, data) => { 64 | chai.expect(data).to.deep.equal({ js: 'on' }); 65 | done(); 66 | }); 67 | }); 68 | }); 69 | 70 | it('creates folders if needed', (done) => { 71 | storage.set(path.join('in', 'some', 'folders', 'data.json'), { js: 'on' }, (err) => { 72 | chai.expect(err).to.equal(null); 73 | storage.get(path.join('in', 'some', 'folders', 'data.json'), (error, data) => { 74 | chai.expect(data).to.deep.equal({ js: 'on' }); 75 | done(); 76 | }); 77 | }); 78 | }); 79 | }); 80 | 81 | describe('storage.isPathExists()', () => { 82 | it('return true if the path exists', (done) => { 83 | storage.set(path.join('in', 'some', 'folders', 'data.json'), { js: 'on' }, (err) => { 84 | chai.expect(err).to.equal(null); 85 | storage.isPathExists(path.join('in', 'some', 'folders', 'data.json'), (data) => { 86 | chai.expect(data).to.equal(true); 87 | done(); 88 | }); 89 | }); 90 | }); 91 | 92 | it('return false if the path doesn\'t exists', (done) => { 93 | storage.set(path.join('in', 'some', 'folders', 'data.json'), { js: 'on' }, (err) => { 94 | chai.expect(err).to.equal(null); 95 | storage.isPathExists(path.join('in', 'some', 'other', 'folders', 'data.json'), (data) => { 96 | chai.expect(data).to.equal(false); 97 | done(); 98 | }); 99 | }); 100 | }); 101 | }); 102 | 103 | describe('storage.remove() - file', () => { 104 | it('removes the file in path', (done) => { 105 | storage.set(path.join('in', 'some', 'folders', 'data.json'), { js: 'on' }, (err) => { 106 | chai.expect(err).to.equal(null); 107 | storage.remove(path.join('in', 'some', 'folders', 'data.json'), error => { 108 | storage.isPathExists(path.join('in', 'some', 'other', 'folders', 'data.json'), (data) => { 109 | chai.expect(data).to.equal(false); 110 | chai.expect(error).to.equal(null); 111 | done(); 112 | }); 113 | }); 114 | }); 115 | }); 116 | }); 117 | 118 | describe('storage.remove() - folder', () => { 119 | it('removes the folder in path', (done) => { 120 | storage.set(path.join('in', 'some', 'folders', 'data.json'), { js: 'on' }, (err) => { 121 | chai.expect(err).to.equal(null); 122 | storage.remove(path.join('in', 'some', 'folders'), error => { 123 | storage.isPathExists(path.join('in', 'some', 'folders'), (data) => { 124 | chai.expect(data).to.equal(false); 125 | chai.expect(error).to.equal(null); 126 | done(); 127 | }); 128 | }); 129 | }); 130 | }); 131 | }); 132 | }); 133 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # electron-storage 2 | 3 | > simple storage managing module for electron 4 | 5 | Electron saves data in app.getPath("userData") folder, which is different in every os. 6 | ```electron-storage``` gives simple methods to get and set json files to this directory. 7 | 8 | * Creates subdirectories if needed - that means you can write ```movies/StarWars.json``` as path, a movies folder will be created and a StarWars.json file inside. 9 | * Supports callbacks and promises. 10 | * The data inserted can be a javascript object, or stringified json. 11 | * You don't have to write ```.json``` in the end of a file path, it will add it for you. 12 | 13 | [![NPM](https://nodei.co/npm/electron-storage.png?downloads=true&downloadRank=true)](https://nodei.co/npm/electron-storage/) 14 | [![Package Quality](http://npm.packagequality.com/badge/electron-storage.png)](http://packagequality.com/#?package=electron- storage) 15 | 16 | [![npm version](https://badge.fury.io/js/electron-storage.svg)](https://badge.fury.io/js/electron-storage) 17 | [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/Cocycles/electron-storage) 18 | [![issues](https://img.shields.io/github/issues/Cocycles/electron-storage.svg)](https://github.com/Cocycles/electron-storage) 19 | [![forks](https://img.shields.io/github/forks/Cocycles/electron-storage.svg)](https://github.com/Cocycles/electron-storage) 20 | [![stars](https://img.shields.io/github/stars/Cocycles/electron-storage.svg)](https://github.com/Cocycles/electron-storage) 21 | [![twitter](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&maxAge=2592000)](https://twitter.com/intent/tweet?text=https://github.com/Cocycles/electron-storage&url=%5Bobject%20Object%5D) 22 | 23 | ## Installation 24 | 25 | ``` 26 | $ npm install --save electron-storage 27 | ``` 28 | ## usage 29 | ```js 30 | 31 | const storage = require('electron-storage'); 32 | ``` 33 | ## API 34 | 35 | ### get 36 | get a json file from storage. 37 | 38 | #### storage.get(filePath, cb) 39 | ```js 40 | storage.get(filePath, (err, data) => { 41 | if (err) { 42 | console.error(err) 43 | } else { 44 | console.log(data); 45 | } 46 | }); 47 | ``` 48 | 49 | #### storage.get(filePath) 50 | ```js 51 | storage.get(filePath) 52 | .then(data => { 53 | console.log(data); 54 | }) 55 | .catch(err => { 56 | console.error(err); 57 | }); 58 | ``` 59 | 60 | ### set 61 | set a json file to storage. 62 | 63 | #### storage.set(filePath, data, cb) 64 | ```js 65 | storage.set(filePath, data, (err) => { 66 | if (err) { 67 | console.error(err) 68 | } 69 | }); 70 | ``` 71 | 72 | #### storage.set(filePath, data) 73 | ```js 74 | storage.set(filePath, data) 75 | .then(() => { 76 | console.log('The file was successfully written to the storage'); 77 | }) 78 | .catch(err => { 79 | console.error(err); 80 | }); 81 | ``` 82 | 83 | ### isPathExists 84 | check if a file or directory exists. 85 | 86 | ```js 87 | // you have to write .json suffix for json files. 88 | // this method works on directories as well, if you don't write `.json` suffix it checks for a directory. 89 | ``` 90 | 91 | #### storage.isPathExists(path, cb) 92 | ```js 93 | storage.isPathExists(path, (itDoes) => { 94 | if (itDoes) { 95 | console.log('pathDoesExists !') 96 | } 97 | }); 98 | ``` 99 | 100 | #### storage.isPathExists(path) 101 | ```js 102 | storage.isPathExists(path) 103 | .then(itDoes => { 104 | if (itDoes) { 105 | console.log('pathDoesExists !') 106 | } 107 | }); 108 | ``` 109 | 110 | ### remove 111 | remove a file or a directory from storage 112 | 113 | #### storage.remove(path, cb) 114 | ```js 115 | storage.remove(path, err => { 116 | if (err) { 117 | console.log(err) 118 | } 119 | }); 120 | ``` 121 | 122 | #### storage.remove(path) 123 | ```js 124 | storage.remove(path) 125 | .then(err => { 126 | if (err) { 127 | console.log(err) 128 | } 129 | }); 130 | ``` 131 | 132 | ## Development 133 | ``` npm run build ``` 134 | for creating es5 files in dist folder 135 | 136 | ## Contribute 137 | Contributions are welcome! please open issues and pull request :) 138 | 139 | ## License 140 | The MIT License (MIT) 141 | Copyright (c) 142 | 143 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 144 | 145 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 146 | 147 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 148 | --------------------------------------------------------------------------------