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 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;
}
}
// 设置all
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;
}
}
// 获取有多少key
get size() {
return Object.keys(this.all || {}).length;
}
// 获取key值,支持dot path的写法 => foo.bar.cc
get(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;
}
// 判断是否有这个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;
}
}
3. 总结
代码比较少只有100多行,主要有两点