configstore 存储 json数据本地化

210 阅读2分钟

本文参加了由公众号@若川视野 发起的每周源码共读活动,       点击了解详情一起参与。

【若川视野 x 源码共读】第10期 | # configstore 存储点击了解本期详情一起参与

configstore 可以实现 json 数据存取,并把数据写入 json 文件,实现数据本地化。那是如何实现的呢,一起看看 configstore 源码。

1. 总览

configstore 有

属性: sizeall

方法: 构造函数, getsetset all属性hasdeleteclear

2. 构造函数

id 就是文件名, defaults 是创建示例时的默认 json 数据,options 未配置选项。

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
  };
 }
}

使用示例看一下结果,configDirectory 为当前电脑用户的目录的 .config 文件夹,pathPrefix 是自己的configstore/${id}.json

let obj = {
 a: 'aaa',
 b: 'bbb'
}
let cs = new Configstore('likeMap', obj)

这里只是展示一下效果,实际上是在 set 函数执行时创建的。 image.png

3.属性

3.1 all

get 相当于定义私有属性,就是读取文件的内容,返回解析完成的 JSON 对象。

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;
 }
}

3.2 size

就是 key 的长度。

get size() {
 return Object.keys(this.all || {}).length;
}

4. 方法

4.1 get

利用 dot-prop 库进行快速取值

import dotProp from 'dot-prop';

get(key) {
 return dotProp.get(this.all, key);
}

4.2 set

也是利用 dot-prop 库进行快速设置值

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;
}

4.3 set 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;
 }
}

4.4 has

利用 dot-prop 库的 has 方法。

has(key) {
 return dotProp.has(this.all, key);
}

4.5 delete

先读取,删除后再存储。

delete(key) {
 const config = this.all;
 dotProp.delete(config, key);
 this.all = config;
}

4.6 clear

直接清空

clear() {
 this.all = {};
}

5. 总结

  1. 利用 ES6 的 get, set 特性定义私有属性。
  2. 把读取值和修改值分别封装为函数,从文件中读取和修改文件中内容实现数据同步。
  3. 扩展文件读取库: graceful-fs,文件写入库: write-file-atomic 。