storage.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. const fs = require('fs')
  2. const path = require('path')
  3. const { remote } = require('electron')
  4. const { app } = remote
  5. const getChromeStoragePath = (storageType, extensionId) => {
  6. return path.join(
  7. app.getPath('userData'), `/Chrome Storage/${extensionId}-${storageType}.json`)
  8. }
  9. const mkdirp = (dir, callback) => {
  10. fs.mkdir(dir, (error) => {
  11. if (error && error.code === 'ENOENT') {
  12. mkdirp(path.dirname(dir), (error) => {
  13. if (!error) {
  14. mkdirp(dir, callback)
  15. }
  16. })
  17. } else if (error && error.code === 'EEXIST') {
  18. callback(null)
  19. } else {
  20. callback(error)
  21. }
  22. })
  23. }
  24. const readChromeStorageFile = (storageType, extensionId, cb) => {
  25. const filePath = getChromeStoragePath(storageType, extensionId)
  26. fs.readFile(filePath, 'utf8', (err, data) => {
  27. if (err && err.code === 'ENOENT') {
  28. return cb(null, null)
  29. }
  30. cb(err, data)
  31. })
  32. }
  33. const writeChromeStorageFile = (storageType, extensionId, data, cb) => {
  34. const filePath = getChromeStoragePath(storageType, extensionId)
  35. mkdirp(path.dirname(filePath), err => {
  36. if (err) { /* we just ignore the errors of mkdir or mkdirp */ }
  37. fs.writeFile(filePath, data, cb)
  38. })
  39. }
  40. const getStorage = (storageType, extensionId, cb) => {
  41. readChromeStorageFile(storageType, extensionId, (err, data) => {
  42. if (err) throw err
  43. if (!cb) throw new TypeError('No callback provided')
  44. if (data !== null) {
  45. cb(JSON.parse(data))
  46. } else {
  47. // Disabled due to false positive in StandardJS
  48. // eslint-disable-next-line standard/no-callback-literal
  49. cb({})
  50. }
  51. })
  52. }
  53. const setStorage = (storageType, extensionId, storage, cb) => {
  54. const json = JSON.stringify(storage)
  55. writeChromeStorageFile(storageType, extensionId, json, err => {
  56. if (err) throw err
  57. if (cb) cb()
  58. })
  59. }
  60. const getStorageManager = (storageType, extensionId) => {
  61. return {
  62. get (keys, callback) {
  63. getStorage(storageType, extensionId, storage => {
  64. if (keys == null) return callback(storage)
  65. let defaults = {}
  66. switch (typeof keys) {
  67. case 'string':
  68. keys = [keys]
  69. break
  70. case 'object':
  71. if (!Array.isArray(keys)) {
  72. defaults = keys
  73. keys = Object.keys(keys)
  74. }
  75. break
  76. }
  77. // Disabled due to false positive in StandardJS
  78. // eslint-disable-next-line standard/no-callback-literal
  79. if (keys.length === 0) return callback({})
  80. let items = {}
  81. keys.forEach(function (key) {
  82. var value = storage[key]
  83. if (value == null) value = defaults[key]
  84. items[key] = value
  85. })
  86. callback(items)
  87. })
  88. },
  89. set (items, callback) {
  90. getStorage(storageType, extensionId, storage => {
  91. Object.keys(items).forEach(function (name) {
  92. storage[name] = items[name]
  93. })
  94. setStorage(storageType, extensionId, storage, callback)
  95. })
  96. },
  97. remove (keys, callback) {
  98. getStorage(storageType, extensionId, storage => {
  99. if (!Array.isArray(keys)) {
  100. keys = [keys]
  101. }
  102. keys.forEach(function (key) {
  103. delete storage[key]
  104. })
  105. setStorage(storageType, extensionId, storage, callback)
  106. })
  107. },
  108. clear (callback) {
  109. setStorage(storageType, extensionId, {}, callback)
  110. }
  111. }
  112. }
  113. module.exports = {
  114. setup: extensionId => ({
  115. sync: getStorageManager('sync', extensionId),
  116. local: getStorageManager('local', extensionId)
  117. })
  118. }