UNPKG

3.34 kBJavaScriptView Raw
1"use strict";
2
3const fs = require("./utils/fs");
4const validate = require("./utils/validate");
5
6const supportedReturnAs = ["utf8", "buffer", "json", "jsonWithDates"];
7
8const validateInput = (methodName, path, returnAs) => {
9 const methodSignature = `${methodName}(path, returnAs)`;
10 validate.argument(methodSignature, "path", path, ["string"]);
11 validate.argument(methodSignature, "returnAs", returnAs, [
12 "string",
13 "undefined"
14 ]);
15
16 if (returnAs && supportedReturnAs.indexOf(returnAs) === -1) {
17 throw new Error(
18 `Argument "returnAs" passed to ${methodSignature} must have one of values: ${supportedReturnAs.join(
19 ", "
20 )}`
21 );
22 }
23};
24
25// Matches strings generated by Date.toJSON()
26// which is called to serialize date to JSON.
27const jsonDateParser = (key, value) => {
28 const reISO = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/;
29 if (typeof value === "string") {
30 if (reISO.exec(value)) {
31 return new Date(value);
32 }
33 }
34 return value;
35};
36
37const makeNicerJsonParsingError = (path, err) => {
38 const nicerError = new Error(
39 `JSON parsing failed while reading ${path} [${err}]`
40 );
41 nicerError.originalError = err;
42 return nicerError;
43};
44
45// ---------------------------------------------------------
46// SYNC
47// ---------------------------------------------------------
48
49const readSync = (path, returnAs) => {
50 const retAs = returnAs || "utf8";
51 let data;
52
53 let encoding = "utf8";
54 if (retAs === "buffer") {
55 encoding = null;
56 }
57
58 try {
59 data = fs.readFileSync(path, { encoding });
60 } catch (err) {
61 if (err.code === "ENOENT") {
62 // If file doesn't exist return undefined instead of throwing.
63 return undefined;
64 }
65 // Otherwise rethrow the error
66 throw err;
67 }
68
69 try {
70 if (retAs === "json") {
71 data = JSON.parse(data);
72 } else if (retAs === "jsonWithDates") {
73 data = JSON.parse(data, jsonDateParser);
74 }
75 } catch (err) {
76 throw makeNicerJsonParsingError(path, err);
77 }
78
79 return data;
80};
81
82// ---------------------------------------------------------
83// ASYNC
84// ---------------------------------------------------------
85
86const readAsync = (path, returnAs) => {
87 return new Promise((resolve, reject) => {
88 const retAs = returnAs || "utf8";
89 let encoding = "utf8";
90 if (retAs === "buffer") {
91 encoding = null;
92 }
93
94 fs.readFile(path, { encoding })
95 .then(data => {
96 // Make final parsing of the data before returning.
97 try {
98 if (retAs === "json") {
99 resolve(JSON.parse(data));
100 } else if (retAs === "jsonWithDates") {
101 resolve(JSON.parse(data, jsonDateParser));
102 } else {
103 resolve(data);
104 }
105 } catch (err) {
106 reject(makeNicerJsonParsingError(path, err));
107 }
108 })
109 .catch(err => {
110 if (err.code === "ENOENT") {
111 // If file doesn't exist return undefined instead of throwing.
112 resolve(undefined);
113 } else {
114 // Otherwise throw
115 reject(err);
116 }
117 });
118 });
119};
120
121// ---------------------------------------------------------
122// API
123// ---------------------------------------------------------
124
125exports.validateInput = validateInput;
126exports.sync = readSync;
127exports.async = readAsync;