Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 1 | let _fs |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 2 | try { |
| 3 | _fs = require('graceful-fs') |
| 4 | } catch (_) { |
| 5 | _fs = require('fs') |
| 6 | } |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 7 | const universalify = require('universalify') |
| 8 | const { stringify, stripBom } = require('./utils') |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 9 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 10 | async function _readFile (file, options = {}) { |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 11 | if (typeof options === 'string') { |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 12 | options = { encoding: options } |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 13 | } |
| 14 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 15 | const fs = options.fs || _fs |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 16 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 17 | const shouldThrow = 'throws' in options ? options.throws : true |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 18 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 19 | let data = await universalify.fromCallback(fs.readFile)(file, options) |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 20 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 21 | data = stripBom(data) |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 22 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 23 | let obj |
| 24 | try { |
| 25 | obj = JSON.parse(data, options ? options.reviver : null) |
| 26 | } catch (err) { |
| 27 | if (shouldThrow) { |
| 28 | err.message = `${file}: ${err.message}` |
| 29 | throw err |
| 30 | } else { |
| 31 | return null |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 32 | } |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 33 | } |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 34 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 35 | return obj |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 36 | } |
| 37 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 38 | const readFile = universalify.fromPromise(_readFile) |
| 39 | |
| 40 | function readFileSync (file, options = {}) { |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 41 | if (typeof options === 'string') { |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 42 | options = { encoding: options } |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 43 | } |
| 44 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 45 | const fs = options.fs || _fs |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 46 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 47 | const shouldThrow = 'throws' in options ? options.throws : true |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 48 | |
| 49 | try { |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 50 | let content = fs.readFileSync(file, options) |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 51 | content = stripBom(content) |
| 52 | return JSON.parse(content, options.reviver) |
| 53 | } catch (err) { |
| 54 | if (shouldThrow) { |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 55 | err.message = `${file}: ${err.message}` |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 56 | throw err |
| 57 | } else { |
| 58 | return null |
| 59 | } |
| 60 | } |
| 61 | } |
| 62 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 63 | async function _writeFile (file, obj, options = {}) { |
| 64 | const fs = options.fs || _fs |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 65 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 66 | const str = stringify(obj, options) |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 67 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 68 | await universalify.fromCallback(fs.writeFile)(file, str, options) |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 69 | } |
| 70 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 71 | const writeFile = universalify.fromPromise(_writeFile) |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 72 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 73 | function writeFileSync (file, obj, options = {}) { |
| 74 | const fs = options.fs || _fs |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 75 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 76 | const str = stringify(obj, options) |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 77 | // not sure if fs.writeFileSync returns anything, but just in case |
| 78 | return fs.writeFileSync(file, str, options) |
| 79 | } |
| 80 | |
Brandon Walderman | 110d592 | 2022-04-19 10:35:07 -0700 | [diff] [blame] | 81 | const jsonfile = { |
| 82 | readFile, |
| 83 | readFileSync, |
| 84 | writeFile, |
| 85 | writeFileSync |
Yang Guo | 4fd355c | 2019-09-19 10:59:03 +0200 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | module.exports = jsonfile |