1. 前言
-
本文参加了由 公众号@若川视野 发起的每周源码共读活动, 点击了解详情一起参与。
-
这是源码共读的第10期,链接:configstore 存储
2. configstore是什么
configstore是一个简单的配置存储库,用于在Node.js应用程序中保存数据。它提供了一种简单的方式来读取、写入和管理配置数据,这些数据以JSON格式存储在磁盘上的文件中。
使用configstore有以下几个好处:
-
简化配置数据管理:使用configstore可以将配置数据以键值对的形式存储,以便更轻松地读取和修改配置。
-
方便的配置文件操作:configstore自动管理配置文件的存储路径,并提供了保存和读取配置文件的功能。
-
默认值和数据验证:configstore允许设置配置项的默认值,并在读取配置数据时使用该默认值。这是很有用的,当某个配置项的值尚未设置时,configstore可以提供一个合理的默认值,避免了因为配置数据缺失而导致的错误。
-
数据持久化:configstore将配置数据以JSON格式存储在磁盘上的文件中,从而确保数据的持久化。
-
轻量且易于使用:configstore是一个轻量级的模块,易于安装和使用。它具有简单的API,不需要额外的库或依赖项。
3. 源码解析
js
import path from 'path'; // path 主要用处处理文件路径
import os from 'os'; // os 模块提供了一些基本的系统操作函数
import fs from 'graceful-fs'; // 文件系统模块 graceful-fs 是fs的替代品,进行了各种改进
import {xdgConfig} from 'xdg-basedir';// 跨平台的方法来获取常用的配置目录路径,如用户的配置目录和缓存目录。
import writeFileAtomic from 'write-file-atomic';// fs.writeFile的扩展,使其操作原子化,并允许您设置所有权。
import dotProp from 'dot-prop'; // dot-prop 用于获取对象的属性
import uniqueString from 'unique-string';// 生成一个唯一的随机字符串
const configDirectory = xdgConfig || path.join(os.tmpdir(), uniqueString()); // xdgConfig 获取配置文件夹路径,如果没有则使用临时文件夹路径 "C:\\Users\\admin\\.config"
const permissionError = 'You don\'t have access to this file.';
const mkdirOptions = {mode: 0o0700, recursive: true}; // 递归创建文件夹 0o0700 代表文件夹所有者可读可写可执行,其他人不可读不可写不可执行
const writeFileOptions = {mode: 0o0600}; // 创建文件 0o0600 代表文件所有者可读可写,其他人不可读不可写
/**
* @param {string} id - The project ID.
* @param {object} defaults - Default config.
* @param {object} options - Options.
* @param {boolean} options.globalConfigPath - Use a path within the user home directory.
* @param {string} options.configPath - Use a custom path for the config file.
*/
export default class Configstore {
constructor(id, defaults, options = {}) {
// pathPrefix是一个路径前缀,如果options.globalConfigPath为true,则为id/config.json,否则为configstore/id.json
const pathPrefix = options.globalConfigPath ?
path.join(id, 'config.json') :
path.join('configstore', `${id}.json`);
// this._path是配置文件的路径 如果未指定options.configPath,则为configDirectory/pathPrefix
// 例如:"C:\\Users\\admin\\.config\\" + "configstore\\configstore-test.json"
this._path = options.configPath || path.join(configDirectory, pathPrefix);
console.log('打印***this._path',this._path)
// 如果defaults存在,则将defaults和this.all合并
if (defaults) {
this.all = {
...defaults,
...this.all
};
}
}
// all是一个getter/setter,用于获取/设置配置文件的内容
get all() {
try {
return JSON.parse(fs.readFileSync(this._path, 'utf8'));
} catch (error) {
console.log('打印***err',error)
// 如果文件夹不存在,则创建文件夹
if (error.code === 'ENOENT') {
return {};
}
// 提高权限错误的消息
if (error.code === 'EACCES') {
error.message = `${error.message}\n${permissionError}\n`;
}
// 如果遇到无效的JSON,则清空文件
if (error.name === 'SyntaxError') {
writeFileAtomic.sync(this._path, '', writeFileOptions);
return {};
}
throw error;
}
}
// all是一个getter/setter,用于获取/设置配置文件的内容
set all(value) {
try {
// 确保文件夹存在,因为它可能已经被删除了
fs.mkdirSync(path.dirname(this._path), mkdirOptions);
// 写入文件
writeFileAtomic.sync(this._path, JSON.stringify(value, undefined, '\t'), writeFileOptions);
} catch (error) {
// 提高权限错误的消息
if (error.code === 'EACCES') {
error.message = `${error.message}\n${permissionError}\n`;
}
throw error;
}
}
// size是一个getter,用于获取配置文件的大小
get size() {
return Object.keys(this.all || {}).length;
}
// get是一个getter,用于获取配置文件的内容
get(key) {
return dotProp.get(this.all, key);
}
// set是一个setter,用于设置配置文件的内容
set(key, value) {
// 获取配置文件的内容
const config = this.all;
// 如果key是一个对象,则将key的所有属性设置到config中
if (arguments.length === 1) {
for (const k of Object.keys(key)) {
dotProp.set(config, k, key[k]);
}
} else {
// 否则将key和value设置到config中
dotProp.set(config, key, value);
}
// 将config设置到配置文件中
this.all = config;
}
// has是一个getter,用于判断配置文件是否存在key
has(key) {
return dotProp.has(this.all, key);
}
// delete是一个setter,用于删除配置文件的key
delete(key) {
const config = this.all;
dotProp.delete(config, key);
this.all = config;
}
// clear是一个setter,用于清空配置文件
clear() {
this.all = {};
}
// path是一个getter,用于获取配置文件的路径
get path() {
return this._path;
}
}
整体流程如下:
-
首先,创建一个configstore实例,可以通过指定配置文件名和默认配置来初始化。
-
在应用程序中,可以使用configstore的API来读取、写入和修改配置数据。API包括读取配置项、写入配置项、删除配置项等。
-
在读取配置数据时,configstore会首先查找指定的配置项。如果不存在,则返回默认值(如果设置了)。如果没有设置默认值,则返回undefined。
-
在写入和修改配置数据时,configstore会将新的配置数据写入内部的配置对象中,并自动将数据保存到配置文件中。
-
配置文件存储在磁盘上的文件中,以JSON格式保存。在保存配置数据时,configstore将配置对象转换为JSON字符串,并将其写入文件中。
-
配置文件的存储路径由configstore自动管理,通常位于用户的home目录下的.config文件夹中。
流程图如下:
4. 总结
最后总结一下:
- 学习了一些包工具如
xdg-basedir
、dot-prop
、write-file-atomic
,参考常用npm包使用 - 存储的路径的学习
- 使用getter、setter进行属性读写
每天一小点,加油 O^O!