@ms-cloudpack/json-utilities 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/readJson.d.ts CHANGED
@@ -13,16 +13,23 @@ export interface ReadJsonOptions {
13
13
  /**
14
14
  * If true, log a warning if the file can't be parsed (or exists but can't be read).
15
15
  * This does NOT log a message if the file doesn't exist.
16
+ * (Ignored if `throwOnError` is true.)
16
17
  */
17
18
  verbose?: boolean;
19
+ /**
20
+ * If true, throw on a parse error. Otherwise (default), return undefined.
21
+ * If the file doesn't exist, that is NOT an error.
22
+ */
23
+ throwOnError?: boolean;
18
24
  }
19
25
  /**
20
- * Reads JSON from a path and returns the object, or undefined if it does not exist or is unparsable.
26
+ * Reads JSON from a path and returns the object, or undefined if it does not exist.
27
+ * If the file exists but is unparsable, behavior depends on options (return undefined by default).
21
28
  */
22
29
  export declare function readJson<TData>(path: string, options?: ReadJsonOptions): Promise<TData | undefined>;
23
30
  /**
24
- * Synchronously reads JSON from a path and returns the object, or undefined if it does not exist
25
- * or is unparsable.
31
+ * Synchronously reads JSON from a path and returns the object, or undefined if it does not exist.
32
+ * If the file exists but is unparsable, behavior depends on options (return undefined by default).
26
33
  */
27
34
  export declare function readJsonSync<TData>(path: string, options?: ReadJsonOptions): TData | undefined;
28
35
  //# sourceMappingURL=readJson.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"readJson.d.ts","sourceRoot":"","sources":["../src/readJson.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC/B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAe7G;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,KAAK,GAAG,SAAS,CAelG"}
1
+ {"version":3,"file":"readJson.d.ts","sourceRoot":"","sources":["../src/readJson.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC/B;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAmB7G;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,KAAK,GAAG,SAAS,CAmBlG"}
package/lib/readJson.js CHANGED
@@ -3,44 +3,55 @@ import fs from 'fs';
3
3
  import fsPromises from 'fs/promises';
4
4
  import jju from 'jju';
5
5
  /**
6
- * Reads JSON from a path and returns the object, or undefined if it does not exist or is unparsable.
6
+ * Reads JSON from a path and returns the object, or undefined if it does not exist.
7
+ * If the file exists but is unparsable, behavior depends on options (return undefined by default).
7
8
  */
8
9
  export async function readJson(path, options = {}) {
9
10
  if (!fs.existsSync(path)) {
10
11
  return undefined;
11
12
  }
13
+ let contents;
12
14
  try {
13
- const contents = await fsPromises.readFile(path, 'utf8');
14
- return parseJson({ contents, path, ...options });
15
+ contents = await fsPromises.readFile(path, 'utf8');
15
16
  }
16
17
  catch (err) {
17
- if (options.verbose) {
18
- console.warn(`Error reading ${path}: ${err.message || err}`);
18
+ const message = `Error reading ${path}: ${err.message || err}`;
19
+ if (options.throwOnError) {
20
+ throw new Error(message);
19
21
  }
22
+ else if (options.verbose) {
23
+ console.warn(message);
24
+ }
25
+ return undefined;
20
26
  }
21
- return undefined;
27
+ return parseJson({ contents, path, ...options });
22
28
  }
23
29
  /**
24
- * Synchronously reads JSON from a path and returns the object, or undefined if it does not exist
25
- * or is unparsable.
30
+ * Synchronously reads JSON from a path and returns the object, or undefined if it does not exist.
31
+ * If the file exists but is unparsable, behavior depends on options (return undefined by default).
26
32
  */
27
33
  export function readJsonSync(path, options = {}) {
28
34
  if (!fs.existsSync(path)) {
29
35
  return undefined;
30
36
  }
37
+ let contents;
31
38
  try {
32
- const contents = fs.readFileSync(path, 'utf8');
33
- return parseJson({ contents, path, ...options });
39
+ contents = fs.readFileSync(path, 'utf8');
34
40
  }
35
41
  catch (err) {
36
- if (options.verbose) {
37
- console.warn(`Error reading ${path}: ${err.message || err}`);
42
+ const message = `Error reading ${path}: ${err.message || err}`;
43
+ if (options.throwOnError) {
44
+ throw new Error(message);
45
+ }
46
+ else if (options.verbose) {
47
+ console.warn(message);
38
48
  }
49
+ return undefined;
39
50
  }
40
- return undefined;
51
+ return parseJson({ contents, path, ...options });
41
52
  }
42
53
  function parseJson(params) {
43
- const { contents, path, mode, verbose } = params;
54
+ const { contents, path, mode, verbose, throwOnError } = params;
44
55
  try {
45
56
  if (mode === 'permissive') {
46
57
  return jju.parse(contents);
@@ -48,8 +59,12 @@ function parseJson(params) {
48
59
  return JSON.parse(contents);
49
60
  }
50
61
  catch (err) {
51
- if (verbose) {
52
- console.warn(`Error parsing JSON from ${path}: ${err.message || err}`);
62
+ const message = `Error parsing JSON from ${path}: ${err.message || err}`;
63
+ if (throwOnError) {
64
+ throw new Error(message);
65
+ }
66
+ else if (verbose) {
67
+ console.warn(message);
53
68
  }
54
69
  }
55
70
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"readJson.js","sourceRoot":"","sources":["../src/readJson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,sGAAsG;AACtG,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,GAAG,MAAM,KAAK,CAAC;AAqBtB;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAQ,IAAY,EAAE,UAA2B,EAAE;IAC/E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzD,OAAO,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,iBAAiB,IAAI,KAAM,GAAa,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAQ,IAAY,EAAE,UAA2B,EAAE;IAC7E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/C,OAAO,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,iBAAiB,IAAI,KAAM,GAAa,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,SAAS,CAAQ,MAA4D;IACpF,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IACjD,IAAI,CAAC;QACH,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1B,OAAO,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAU,CAAC;QACtC,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAU,CAAC;IACvC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,2BAA2B,IAAI,KAAM,GAAa,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import fs from 'fs';\n// NOTE: Importing the whole module (not named exports) is required to make Jest mocks work elsewhere.\nimport fsPromises from 'fs/promises';\nimport jju from 'jju';\n\n/**\n * Options for `readJson` and `readJsonSync`.\n */\nexport interface ReadJsonOptions {\n /**\n * How to read the JSON file:\n * - `strict`: Use `JSON.parse` (fastest, but does not give informative error messages)\n * - `permissive`: Use `jju.parse` (slower, but allows comments and trailing commas, and gives\n * informative error messages if `verbose` is true)\n * @default 'strict'\n */\n mode?: 'strict' | 'permissive';\n /**\n * If true, log a warning if the file can't be parsed (or exists but can't be read).\n * This does NOT log a message if the file doesn't exist.\n */\n verbose?: boolean;\n}\n\n/**\n * Reads JSON from a path and returns the object, or undefined if it does not exist or is unparsable.\n */\nexport async function readJson<TData>(path: string, options: ReadJsonOptions = {}): Promise<TData | undefined> {\n if (!fs.existsSync(path)) {\n return undefined;\n }\n\n try {\n const contents = await fsPromises.readFile(path, 'utf8');\n return parseJson({ contents, path, ...options });\n } catch (err) {\n if (options.verbose) {\n console.warn(`Error reading ${path}: ${(err as Error).message || err}`);\n }\n }\n\n return undefined;\n}\n\n/**\n * Synchronously reads JSON from a path and returns the object, or undefined if it does not exist\n * or is unparsable.\n */\nexport function readJsonSync<TData>(path: string, options: ReadJsonOptions = {}): TData | undefined {\n if (!fs.existsSync(path)) {\n return undefined;\n }\n\n try {\n const contents = fs.readFileSync(path, 'utf8');\n return parseJson({ contents, path, ...options });\n } catch (err) {\n if (options.verbose) {\n console.warn(`Error reading ${path}: ${(err as Error).message || err}`);\n }\n }\n\n return undefined;\n}\n\nfunction parseJson<TData>(params: { contents: string; path: string } & ReadJsonOptions): TData | undefined {\n const { contents, path, mode, verbose } = params;\n try {\n if (mode === 'permissive') {\n return jju.parse(contents) as TData;\n }\n return JSON.parse(contents) as TData;\n } catch (err) {\n if (verbose) {\n console.warn(`Error parsing JSON from ${path}: ${(err as Error).message || err}`);\n }\n }\n return undefined;\n}\n"]}
1
+ {"version":3,"file":"readJson.js","sourceRoot":"","sources":["../src/readJson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,sGAAsG;AACtG,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,GAAG,MAAM,KAAK,CAAC;AA2BtB;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAQ,IAAY,EAAE,UAA2B,EAAE;IAC/E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,iBAAiB,IAAI,KAAM,GAAa,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC;QAC1E,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AACnD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAQ,IAAY,EAAE,UAA2B,EAAE;IAC7E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,iBAAiB,IAAI,KAAM,GAAa,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC;QAC1E,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,SAAS,CAAQ,MAA4D;IACpF,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IAC/D,IAAI,CAAC;QACH,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1B,OAAO,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAU,CAAC;QACtC,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAU,CAAC;IACvC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,2BAA2B,IAAI,KAAM,GAAa,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC;QACpF,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import fs from 'fs';\n// NOTE: Importing the whole module (not named exports) is required to make Jest mocks work elsewhere.\nimport fsPromises from 'fs/promises';\nimport jju from 'jju';\n\n/**\n * Options for `readJson` and `readJsonSync`.\n */\nexport interface ReadJsonOptions {\n /**\n * How to read the JSON file:\n * - `strict`: Use `JSON.parse` (fastest, but does not give informative error messages)\n * - `permissive`: Use `jju.parse` (slower, but allows comments and trailing commas, and gives\n * informative error messages if `verbose` is true)\n * @default 'strict'\n */\n mode?: 'strict' | 'permissive';\n /**\n * If true, log a warning if the file can't be parsed (or exists but can't be read).\n * This does NOT log a message if the file doesn't exist.\n * (Ignored if `throwOnError` is true.)\n */\n verbose?: boolean;\n /**\n * If true, throw on a parse error. Otherwise (default), return undefined.\n * If the file doesn't exist, that is NOT an error.\n */\n throwOnError?: boolean;\n}\n\n/**\n * Reads JSON from a path and returns the object, or undefined if it does not exist.\n * If the file exists but is unparsable, behavior depends on options (return undefined by default).\n */\nexport async function readJson<TData>(path: string, options: ReadJsonOptions = {}): Promise<TData | undefined> {\n if (!fs.existsSync(path)) {\n return undefined;\n }\n\n let contents: string;\n try {\n contents = await fsPromises.readFile(path, 'utf8');\n } catch (err) {\n const message = `Error reading ${path}: ${(err as Error).message || err}`;\n if (options.throwOnError) {\n throw new Error(message);\n } else if (options.verbose) {\n console.warn(message);\n }\n return undefined;\n }\n\n return parseJson({ contents, path, ...options });\n}\n\n/**\n * Synchronously reads JSON from a path and returns the object, or undefined if it does not exist.\n * If the file exists but is unparsable, behavior depends on options (return undefined by default).\n */\nexport function readJsonSync<TData>(path: string, options: ReadJsonOptions = {}): TData | undefined {\n if (!fs.existsSync(path)) {\n return undefined;\n }\n\n let contents: string;\n try {\n contents = fs.readFileSync(path, 'utf8');\n } catch (err) {\n const message = `Error reading ${path}: ${(err as Error).message || err}`;\n if (options.throwOnError) {\n throw new Error(message);\n } else if (options.verbose) {\n console.warn(message);\n }\n return undefined;\n }\n\n return parseJson({ contents, path, ...options });\n}\n\nfunction parseJson<TData>(params: { contents: string; path: string } & ReadJsonOptions): TData | undefined {\n const { contents, path, mode, verbose, throwOnError } = params;\n try {\n if (mode === 'permissive') {\n return jju.parse(contents) as TData;\n }\n return JSON.parse(contents) as TData;\n } catch (err) {\n const message = `Error parsing JSON from ${path}: ${(err as Error).message || err}`;\n if (throwOnError) {\n throw new Error(message);\n } else if (verbose) {\n console.warn(message);\n }\n }\n return undefined;\n}\n"]}
@@ -5,6 +5,7 @@ export interface WriteJsonOptions extends Pick<ReadJsonOptions, 'mode'> {
5
5
  * (For files with comments, `mode: 'permissive'` must also be set.)
6
6
  */
7
7
  update?: boolean;
8
+ fileHeaderComment?: string;
8
9
  }
9
10
  /**
10
11
  * Writes json to a path. Ensures the path exists.
@@ -1 +1 @@
1
- {"version":3,"file":"writeJson.d.ts","sourceRoot":"","sources":["../src/writeJson.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC;IACrE;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB9G;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,IAAI,CAMnG"}
1
+ {"version":3,"file":"writeJson.d.ts","sourceRoot":"","sources":["../src/writeJson.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC;IACrE;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB9G;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,gBAAqB,GAAG,IAAI,CAMnG"}
package/lib/writeJson.js CHANGED
@@ -16,7 +16,7 @@ export async function writeJson(filePath, data, options = {}) {
16
16
  await fsExtra.ensureDir(folderPath);
17
17
  let contents;
18
18
  try {
19
- contents = stringify(filePath, data, options);
19
+ contents = (options.fileHeaderComment ?? '') + stringify(filePath, data, options);
20
20
  await fsPromises.writeFile(filePath, contents, 'utf8');
21
21
  }
22
22
  catch (err) {
@@ -35,7 +35,7 @@ export async function writeJson(filePath, data, options = {}) {
35
35
  export function writeJsonSync(filePath, data, options = {}) {
36
36
  const folderPath = path.dirname(filePath);
37
37
  fsExtra.ensureDirSync(folderPath);
38
- const contents = stringify(filePath, data, options);
38
+ const contents = (options.fileHeaderComment ?? '') + stringify(filePath, data, options);
39
39
  fs.writeFileSync(filePath, contents, 'utf8');
40
40
  }
41
41
  function stringify(filePath, data, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"writeJson.js","sourceRoot":"","sources":["../src/writeJson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,OAAO,MAAM,UAAU,CAAC;AAC/B,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAW3C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB,EAAE,IAAa,EAAE,UAA4B,EAAE;IAC7F,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAEpC,IAAI,QAA4B,CAAC;IACjC,IAAI,CAAC;QACH,QAAQ,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,UAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,QAAQ,IAAI,GAAG,YAAY,UAAU,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC9D,uCAAuC;YACvC,MAAM,QAAQ,CACZ,IAAI,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,CAAC,EACjD,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CACrD,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,IAAa,EAAE,UAA4B,EAAE;IAC3F,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAElC,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACpD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,SAAS,CAAC,QAAgB,EAAE,IAAa,EAAE,OAAyB;IAC3E,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAEjC,IAAI,MAAM,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtC,MAAM,eAAe,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC1D,OAAO,GAAG,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,EAAE;YACvC,IAAI,EAAE,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;YAC9C,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,GAAG;YACV,UAAU,EAAE,IAAI;YAChB,iBAAiB,EAAE,IAAI;SACxB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAC9C,CAAC","sourcesContent":["import fs from 'fs';\nimport fsExtra from 'fs-extra';\nimport fsPromises from 'fs/promises';\nimport jju from 'jju';\nimport { JsonStreamStringify } from 'json-stream-stringify';\nimport path from 'path';\nimport { pipeline } from 'stream/promises';\nimport type { ReadJsonOptions } from './readJson.js';\n\nexport interface WriteJsonOptions extends Pick<ReadJsonOptions, 'mode'> {\n /**\n * If true, read the file (if it exists) and preserve as much of the original formatting as possible.\n * (For files with comments, `mode: 'permissive'` must also be set.)\n */\n update?: boolean;\n}\n\n/**\n * Writes json to a path. Ensures the path exists.\n *\n * If the JSON is very large (causing a RangeError \"Invalid string length\"), it will fall back to\n * stringifying and writing the object using a stream, provided that `update` is false/unset.\n */\nexport async function writeJson(filePath: string, data: unknown, options: WriteJsonOptions = {}): Promise<void> {\n const folderPath = path.dirname(filePath);\n await fsExtra.ensureDir(folderPath);\n\n let contents: string | undefined;\n try {\n contents = stringify(filePath, data, options);\n await fsPromises.writeFile(filePath, contents, 'utf8');\n } catch (err) {\n if (!contents && err instanceof RangeError && !options.update) {\n // It's a giant object, so try a stream\n await pipeline(\n new JsonStreamStringify(data, undefined, 2, true),\n fs.createWriteStream(filePath, { encoding: 'utf8' }),\n );\n } else {\n throw err;\n }\n }\n}\n\n/**\n * Synchronously writes json to a path. Ensures the path exists.\n */\nexport function writeJsonSync(filePath: string, data: unknown, options: WriteJsonOptions = {}): void {\n const folderPath = path.dirname(filePath);\n fsExtra.ensureDirSync(folderPath);\n\n const contents = stringify(filePath, data, options);\n fs.writeFileSync(filePath, contents, 'utf8');\n}\n\nfunction stringify(filePath: string, data: unknown, options: WriteJsonOptions): string {\n const { update, mode } = options;\n\n if (update && fs.existsSync(filePath)) {\n const originalContent = fs.readFileSync(filePath, 'utf8');\n return jju.update(originalContent, data, {\n mode: mode === 'permissive' ? 'json5' : 'json',\n indent: 2,\n quote: '\"',\n quote_keys: true,\n no_trailing_comma: true,\n });\n }\n\n return JSON.stringify(data, null, 2) + '\\n';\n}\n"]}
1
+ {"version":3,"file":"writeJson.js","sourceRoot":"","sources":["../src/writeJson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,OAAO,MAAM,UAAU,CAAC;AAC/B,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAY3C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB,EAAE,IAAa,EAAE,UAA4B,EAAE;IAC7F,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAEpC,IAAI,QAA4B,CAAC;IACjC,IAAI,CAAC;QACH,QAAQ,GAAG,CAAC,OAAO,CAAC,iBAAiB,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAClF,MAAM,UAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,QAAQ,IAAI,GAAG,YAAY,UAAU,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC9D,uCAAuC;YACvC,MAAM,QAAQ,CACZ,IAAI,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,CAAC,EACjD,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CACrD,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,IAAa,EAAE,UAA4B,EAAE;IAC3F,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1C,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAElC,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,iBAAiB,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACxF,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,SAAS,CAAC,QAAgB,EAAE,IAAa,EAAE,OAAyB;IAC3E,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAEjC,IAAI,MAAM,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtC,MAAM,eAAe,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC1D,OAAO,GAAG,CAAC,MAAM,CAAC,eAAe,EAAE,IAAI,EAAE;YACvC,IAAI,EAAE,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;YAC9C,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,GAAG;YACV,UAAU,EAAE,IAAI;YAChB,iBAAiB,EAAE,IAAI;SACxB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AAC9C,CAAC","sourcesContent":["import fs from 'fs';\nimport fsExtra from 'fs-extra';\nimport fsPromises from 'fs/promises';\nimport jju from 'jju';\nimport { JsonStreamStringify } from 'json-stream-stringify';\nimport path from 'path';\nimport { pipeline } from 'stream/promises';\nimport type { ReadJsonOptions } from './readJson.js';\n\nexport interface WriteJsonOptions extends Pick<ReadJsonOptions, 'mode'> {\n /**\n * If true, read the file (if it exists) and preserve as much of the original formatting as possible.\n * (For files with comments, `mode: 'permissive'` must also be set.)\n */\n update?: boolean;\n fileHeaderComment?: string;\n}\n\n/**\n * Writes json to a path. Ensures the path exists.\n *\n * If the JSON is very large (causing a RangeError \"Invalid string length\"), it will fall back to\n * stringifying and writing the object using a stream, provided that `update` is false/unset.\n */\nexport async function writeJson(filePath: string, data: unknown, options: WriteJsonOptions = {}): Promise<void> {\n const folderPath = path.dirname(filePath);\n await fsExtra.ensureDir(folderPath);\n\n let contents: string | undefined;\n try {\n contents = (options.fileHeaderComment ?? '') + stringify(filePath, data, options);\n await fsPromises.writeFile(filePath, contents, 'utf8');\n } catch (err) {\n if (!contents && err instanceof RangeError && !options.update) {\n // It's a giant object, so try a stream\n await pipeline(\n new JsonStreamStringify(data, undefined, 2, true),\n fs.createWriteStream(filePath, { encoding: 'utf8' }),\n );\n } else {\n throw err;\n }\n }\n}\n\n/**\n * Synchronously writes json to a path. Ensures the path exists.\n */\nexport function writeJsonSync(filePath: string, data: unknown, options: WriteJsonOptions = {}): void {\n const folderPath = path.dirname(filePath);\n fsExtra.ensureDirSync(folderPath);\n\n const contents = (options.fileHeaderComment ?? '') + stringify(filePath, data, options);\n fs.writeFileSync(filePath, contents, 'utf8');\n}\n\nfunction stringify(filePath: string, data: unknown, options: WriteJsonOptions): string {\n const { update, mode } = options;\n\n if (update && fs.existsSync(filePath)) {\n const originalContent = fs.readFileSync(filePath, 'utf8');\n return jju.update(originalContent, data, {\n mode: mode === 'permissive' ? 'json5' : 'json',\n indent: 2,\n quote: '\"',\n quote_keys: true,\n no_trailing_comma: true,\n });\n }\n\n return JSON.stringify(data, null, 2) + '\\n';\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ms-cloudpack/json-utilities",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Helpers for reading/writing json files.",
5
5
  "license": "MIT",
6
6
  "type": "module",