diff --git a/browser-version/lib/storage.browser.js b/browser-version/lib/storage.browser.js index 885557d..c12abf1 100755 --- a/browser-version/lib/storage.browser.js +++ b/browser-version/lib/storage.browser.js @@ -7,6 +7,7 @@ * This version is the browser version */ const localforage = require('localforage') +const { callbackify } = require('util') // Configure localforage to display NeDB name for now. Would be a good idea to let user use his own app name const store = localforage.createInstance({ @@ -14,73 +15,118 @@ const store = localforage.createInstance({ storeName: 'nedbdata' }) -const exists = (filename, cback) => { - // eslint-disable-next-line node/handle-callback-err - store.getItem(filename, (err, value) => { - if (value !== null) return cback(true) // Even if value is undefined, localforage returns null - else return cback(false) - }) +const existsAsync = async filename => { + try { + const value = await store.getItem(filename) + if (value !== null) return true // Even if value is undefined, localforage returns null + return false + } catch (error) { + return false + } } -const rename = (filename, newFilename, callback) => { - // eslint-disable-next-line node/handle-callback-err - store.getItem(filename, (err, value) => { - if (value === null) store.removeItem(newFilename, () => callback()) +const exists = callbackify(existsAsync) + +const renameAsync = async (filename, newFilename) => { + try { + const value = await store.getItem(filename) + if (value === null) await store.removeItem(newFilename) else { - store.setItem(newFilename, value, () => { - store.removeItem(filename, () => callback()) - }) + await store.setItem(newFilename, value) + await store.removeItem(filename) } - }) + } catch (err) { + console.warn('An error happened while renaming, skip') + } } -const writeFile = (filename, contents, options, callback) => { +const rename = callbackify(renameAsync) + +const writeFileAsync = async (filename, contents, options) => { // Options do not matter in browser setup - if (typeof options === 'function') { callback = options } - store.setItem(filename, contents, () => callback()) + try { + await store.setItem(filename, contents) + } catch (error) { + console.warn('An error happened while writing, skip') + } } -const appendFile = (filename, toAppend, options, callback) => { +const writeFile = callbackify(writeFileAsync) + +const appendFileAsync = async (filename, toAppend, options) => { // Options do not matter in browser setup - if (typeof options === 'function') { callback = options } - - // eslint-disable-next-line node/handle-callback-err - store.getItem(filename, (err, contents) => { - contents = contents || '' - contents += toAppend - store.setItem(filename, contents, () => callback()) - }) + try { + const contents = (await store.getItem(filename)) || '' + await store.setItem(filename, contents + toAppend) + } catch (error) { + console.warn('An error happened appending to file writing, skip') + } } -const readFile = (filename, options, callback) => { - // Options do not matter in browser setup - if (typeof options === 'function') { callback = options } - // eslint-disable-next-line node/handle-callback-err - store.getItem(filename, (err, contents) => callback(null, contents || '')) +const appendFile = callbackify(appendFileAsync) + +const readFileAsync = async (filename, options) => { + try { + return (await store.getItem(filename)) || '' + } catch (error) { + console.warn('An error happened while reading, skip') + return '' + } } -const unlink = (filename, callback) => { - store.removeItem(filename, () => callback()) +const readFile = callbackify(readFileAsync) + +const unlinkAsync = async filename => { + try { + await store.removeItem(filename) + } catch (error) { + console.warn('An error happened while unlinking, skip') + } } +const unlink = callbackify(unlinkAsync) + // Nothing to do, no directories will be used on the browser -const mkdir = (dir, options, callback) => callback() +const mkdirAsync = (dir, options) => Promise.resolve() + +const mkdir = callbackify(mkdirAsync) // Nothing to do, no data corruption possible in the browser -const ensureDatafileIntegrity = (filename, callback) => callback(null) +const ensureDatafileIntegrityAsync = (filename) => Promise.resolve() + +const ensureDatafileIntegrity = callbackify(ensureDatafileIntegrityAsync) -const crashSafeWriteFileLines = (filename, lines, callback) => { +const crashSafeWriteFileLinesAsync = async (filename, lines) => { lines.push('') // Add final new line - writeFile(filename, lines.join('\n'), callback) + await writeFileAsync(filename, lines.join('\n')) } +const crashSafeWriteFileLines = callbackify(crashSafeWriteFileLinesAsync) + // Interface module.exports.exists = exists +module.exports.existsAsync = existsAsync + module.exports.rename = rename +module.exports.renameAsync = renameAsync + module.exports.writeFile = writeFile +module.exports.writeFileAsync = writeFileAsync + module.exports.crashSafeWriteFileLines = crashSafeWriteFileLines +module.exports.crashSafeWriteFileLinesAsync = crashSafeWriteFileLinesAsync + module.exports.appendFile = appendFile +module.exports.appendFileAsync = appendFileAsync + module.exports.readFile = readFile +module.exports.readFileAsync = readFileAsync + module.exports.unlink = unlink +module.exports.unlinkAsync = unlinkAsync + module.exports.mkdir = mkdir +module.exports.mkdirAsync = mkdirAsync + module.exports.ensureDatafileIntegrity = ensureDatafileIntegrity +module.exports.ensureDatafileIntegrityAsync = ensureDatafileIntegrityAsync diff --git a/package-lock.json b/package-lock.json index fe525d6..b530f55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,7 @@ "ts-jest": "^27.0.7", "ts-node": "^10.3.0", "typescript": "^4.4.4", + "util": "^0.12.4", "webpack": "^5.37.0", "webpack-cli": "^4.7.0", "xvfb-maybe": "^0.2.1" @@ -4421,7 +4422,8 @@ "node_modules/async": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true }, "node_modules/async-limiter": { "version": "1.0.1", @@ -4449,6 +4451,18 @@ "node": ">= 4.5.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/babel-core": { "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", @@ -7499,6 +7513,12 @@ "node": ">=0.10.0" } }, + "node_modules/foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "node_modules/form-data": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", @@ -7776,6 +7796,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -8199,6 +8234,22 @@ "node": ">=0.10.0" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -8381,6 +8432,21 @@ "node": ">=6" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -8505,6 +8571,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", + "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", + "foreach": "^2.0.5", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -15795,6 +15880,20 @@ "react": "^16.8.0 || ^17.0.0" } }, + "node_modules/util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -16162,6 +16261,26 @@ "dev": true, "peer": true }, + "node_modules/which-typed-array": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", + "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", + "foreach": "^2.0.5", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -19956,7 +20075,8 @@ "async": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true }, "async-limiter": { "version": "1.0.1", @@ -19978,6 +20098,12 @@ "dev": true, "peer": true }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, "babel-core": { "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", @@ -22395,6 +22521,12 @@ "dev": true, "peer": true }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "form-data": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", @@ -22590,6 +22722,15 @@ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -22927,6 +23068,16 @@ "kind-of": "^6.0.0" } }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -23060,6 +23211,15 @@ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -23139,6 +23299,19 @@ "has-symbols": "^1.0.2" } }, + "is-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", + "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", + "foreach": "^2.0.5", + "has-tostringtag": "^1.0.0" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -29009,6 +29182,20 @@ "object-assign": "^4.1.1" } }, + "util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -29289,6 +29476,20 @@ "dev": true, "peer": true }, + "which-typed-array": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", + "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.5", + "foreach": "^2.0.5", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.7" + } + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", diff --git a/package.json b/package.json index 7820f23..691fd36 100755 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "ts-jest": "^27.0.7", "ts-node": "^10.3.0", "typescript": "^4.4.4", + "util": "^0.12.4", "webpack": "^5.37.0", "webpack-cli": "^4.7.0", "xvfb-maybe": "^0.2.1" diff --git a/webpack.config.js b/webpack.config.js index 8948c34..37a2cb1 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -32,7 +32,8 @@ module.exports = (env, argv) => { process: 'process/browser', Buffer: ['buffer', 'Buffer'], setImmediate: ['timers-browserify', 'setImmediate'], - clearImmediate: ['timers-browserify', 'clearImmediate'] + clearImmediate: ['timers-browserify', 'clearImmediate'], + util: 'util' }) ], entry: {