configstore 存储
前言
在我们的项目中,我们经常会用到一些配置,比如:token
、cookie
、用户名
、密码
等等,这些配置我们一般会放在一个文件中,然后在项目中引入,但是这样做有一个问题,就是如果我们的项目是一个开源项目,那么这些配置就会暴露出来,这样就会有安全隐患,所以我们需要一个安全的地方来存储这些配置,这个时候就需要用到configstore
这个包了。
安装
bash
npm install configstore
使用
js
const Configstore = require('configstore')
const pkg = require('./package.json')
// 创建一个configstore实例
const conf = new Configstore(pkg.name)
// 设置配置
conf.set('foo', 'bar')
// 获取配置
console.log(conf.get('foo')) // bar
// 删除配置
conf.delete('foo')
// 获取所有配置
console.log(conf.all) // {}
// 清空配置
conf.clear()
上面简单使用了下这个包,那么去看下这个包的源码,看看它是怎么实现的。
依赖
json
"dependencies": {
"dot-prop": "^6.0.1",
"graceful-fs": "^4.2.6",
"unique-string": "^3.0.0",
"write-file-atomic": "^3.0.3",
"xdg-basedir": "^5.0.1"
},
"devDependencies": {
"ava": "^3.15.0",
"xo": "^0.38.2"
},
看下所依赖的包都有什么作用
dot-prop
:用来操作对象的属性graceful-fs
:用来操作文件unique-string
:生成唯一字符串write-file-atomic
:原子写入文件xdg-basedir
:获取用户目录ava
:测试框架xo
:代码检查
源码
js
import path from 'path'
import os from 'os'
import fs from 'graceful-fs'
import { xdgConfig } from 'xdg-basedir'
import writeFileAtomic from 'write-file-atomic'
import dotProp from 'dot-prop'
import uniqueString from 'unique-string'
// 获取用户目录
const configDirectory = xdgConfig || path.join(os.tmpdir(), uniqueString())
const permissionError = "You don't have access to this file."
const mkdirOptions = { mode: 0o0700, recursive: true }
const writeFileOptions = { mode: 0o0600 }
export default class Configstore {
// 生成用户本地配置文件路径
constructor(id, defaults, options = {}) {
const pathPrefix = options.globalConfigPath
? path.join(id, 'config.json')
: path.join('configstore', `${id}.json`)
this._path = options.configPath || path.join(configDirectory, pathPrefix)
if (defaults) {
this.all = {
...defaults,
...this.all,
}
}
}
// 获取配置文件所有内容
get all() {
try {
return JSON.parse(fs.readFileSync(this._path, 'utf8'))
} catch (error) {
// Create directory if it doesn't exist
if (error.code === 'ENOENT') {
return {}
}
// Improve the message of permission errors
if (error.code === 'EACCES') {
error.message = `${error.message}\n${permissionError}\n`
}
// Empty the file if it encounters invalid JSON
if (error.name === 'SyntaxError') {
writeFileAtomic.sync(this._path, '', writeFileOptions)
return {}
}
throw error
}
}
// 设置配置文件所有内容
set all(value) {
try {
// Make sure the folder exists as it could have been deleted in the meantime
fs.mkdirSync(path.dirname(this._path), mkdirOptions)
writeFileAtomic.sync(this._path, JSON.stringify(value, undefined, '\t'), writeFileOptions)
} catch (error) {
// Improve the message of permission errors
if (error.code === 'EACCES') {
error.message = `${error.message}\n${permissionError}\n`
}
throw error
}
}
// 获取配置文件大小
get size() {
return Object.keys(this.all || {}).length
}
// 获取对应key的配置
get(key) {
return dotProp.get(this.all, key)
}
// 设置key,value
set(key, value) {
const config = this.all
if (arguments.length === 1) {
for (const k of Object.keys(key)) {
dotProp.set(config, k, key[k])
}
} else {
dotProp.set(config, key, value)
}
this.all = config
}
// 判断是否有key
has(key) {
return dotProp.has(this.all, key)
}
// 删除key
delete(key) {
const config = this.all
dotProp.delete(config, key)
this.all = config
}
// 清空配置
clear() {
this.all = {}
}
// 获取配置文件路径
get path() {
return this._path
}
}