1. 前言
1.1 环境
- 了解 configstore 作用和使用场景
2. 开始
2.1 index.js中的npm包
write-file-atomicimport path from 'path';import os from 'os';// 更优雅的fs模块,对fs改进import fs from 'graceful-fs';// 获取用户配置路径 ~/.config文件夹import {xdgConfig} from 'xdg-basedir';// 写入文件import writeFileAtomic from 'write-file-atomic';// 通过'foo.bar'的方式来获取删除更新深层的对象,// dotProp.get({foo: {bar: 'unicorn'}}, 'foo.bar'); => 'unicorn'import dotProp from 'dot-prop';// 生成唯一字符串import uniqueString from 'unique-string';
graceful-fs
xdg-basedir
unique-string
dot-prop2.2 index.js 源码
```javascript // config文件夹目录 const configDirectory = xdgConfig || path.join(os.tmpdir(), uniqueString()); // 无权限抛出 const permissionError = ‘You don\’t have access to this file.’; // 文件夹的配置,recursive支持递归, mode: 文件夹权限 const mkdirOptions = {mode: 0o0700, recursive: true}; // 写入权限 const writeFileOptions = {mode: 0o0600};
export default class Configstore {
// id就是文件名,defaults是存入的数据默认值,第三个是配置项
constructor(id, defaults, options = {}) {
// 如果传入了有全局文件路径,直接拼接路径 ${id}/config.json
const pathPrefix = options.globalConfigPath ?
path.join(id, ‘config.json’) :
// 如果没配置,使用默认文件夹 configstore/${id}.json
path.join(‘configstore’, ${id}.json);
// 文件路径,可以直接配置也可以使用拼接默认的this._path = options.configPath || path.join(configDirectory, pathPrefix);// 传入默认值if (defaults) {this.all = {...defaults,...this.all};}}// class语法,get是监听取值,当this.all的时候,会执行里面的代码get all() {try {// 读取配置文件,json解析return JSON.parse(fs.readFileSync(this._path, 'utf8'));} catch (error) {// Create directory if it doesn't existif (error.code === 'ENOENT') {return {};}// Improve the message of permission errorsif (error.code === 'EACCES') {error.message = `${error.message}\n${permissionError}\n`;}// Empty the file if it encounters invalid JSONif (error.name === 'SyntaxError') {writeFileAtomic.sync(this._path, '', writeFileOptions);return {};}throw error;}}// 设置allset 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;}}// 获取有多少keyget size() {return Object.keys(this.all || {}).length;}// 获取key值,支持dot path的写法 => foo.bar.ccget(key) {return dotProp.get(this.all, key);}// 设置key值set(key, value) {const config = this.all;// 如果只有key一个参数,相当于直接更新if (arguments.length === 1) {for (const k of Object.keys(key)) {dotProp.set(config, k, key[k]);}} else {// 有key和value直接设置dotProp.set(config, key, value);}this.all = config;}// 判断是否有这个keyhas(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;}
}
3. 总结
代码比较少只有100多行,主要有两点
