@helpers4/node 3.0.5 → 3.0.6
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/README.md +1 -0
- package/lib/index.d.ts +33 -1
- package/lib/index.js +112 -1
- package/lib/index.js.map +1 -1
- package/llms.txt +85 -2
- package/meta/api.json +77 -1
- package/meta/examples.json +25 -0
- package/package.json +3 -2
package/README.md
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -70,4 +70,36 @@ declare function isNodeStream(value: unknown): value is {
|
|
|
70
70
|
*/
|
|
71
71
|
declare function isSharedArrayBuffer(value: unknown): value is SharedArrayBuffer;
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
/**
|
|
74
|
+
* This file is part of helpers4.
|
|
75
|
+
* Copyright (C) 2025 baxyz
|
|
76
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* Reads a file and parses its contents as JSON, returning `null` (or a
|
|
80
|
+
* fallback) on any failure — a missing/unreadable file and invalid content
|
|
81
|
+
* are both treated the same way.
|
|
82
|
+
*
|
|
83
|
+
* Also tolerates JSONC (line/block comments and trailing commas — the
|
|
84
|
+
* dialect used by `tsconfig.json`, VS Code's `settings.json`, etc.): strict
|
|
85
|
+
* `JSON.parse` is tried first, and only on failure is the content re-parsed
|
|
86
|
+
* with comments/trailing commas stripped, so plain JSON pays no extra cost.
|
|
87
|
+
*
|
|
88
|
+
* Unlike `readFileSync` + `JSON.parse`, this never throws.
|
|
89
|
+
*
|
|
90
|
+
* @param filePath - Path to the JSON (or JSONC) file to read.
|
|
91
|
+
* @param fallback - Value returned on failure. Defaults to `null` when omitted.
|
|
92
|
+
* @returns The parsed value typed as `T`, or `fallback` on failure.
|
|
93
|
+
* @example
|
|
94
|
+
* safeReadJsonFile<{ name: string }>('./package.json') // => { name: 'helpers4', ... }
|
|
95
|
+
* safeReadJsonFile('./missing.json') // => null
|
|
96
|
+
* safeReadJsonFile('./missing.json', {}) // => {}
|
|
97
|
+
* @example
|
|
98
|
+
* // tsconfig.json-style JSONC (comments + trailing comma) also parses:
|
|
99
|
+
* safeReadJsonFile('./tsconfig.json') // => { compilerOptions: { strict: true }, ... }
|
|
100
|
+
* @since 3.0.6
|
|
101
|
+
*/
|
|
102
|
+
declare function safeReadJsonFile<T>(filePath: string): T | null;
|
|
103
|
+
declare function safeReadJsonFile<T>(filePath: string, fallback: T): T;
|
|
104
|
+
|
|
105
|
+
export { isBuffer, isNodeStream, isSharedArrayBuffer, safeReadJsonFile };
|
package/lib/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
3
|
+
//#endregion
|
|
1
4
|
//#region helpers/node/isBuffer.ts
|
|
2
5
|
/**
|
|
3
6
|
* This file is part of helpers4.
|
|
@@ -77,6 +80,114 @@ function isSharedArrayBuffer(value) {
|
|
|
77
80
|
return typeof SharedArrayBuffer !== "undefined" && value instanceof SharedArrayBuffer;
|
|
78
81
|
}
|
|
79
82
|
//#endregion
|
|
80
|
-
|
|
83
|
+
//#region helpers/node/_stripJsonComments.ts
|
|
84
|
+
var import___vite_browser_external = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
85
|
+
module.exports = {};
|
|
86
|
+
})))();
|
|
87
|
+
/**
|
|
88
|
+
* This file is part of helpers4.
|
|
89
|
+
* Copyright (C) 2025 baxyz
|
|
90
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
91
|
+
*
|
|
92
|
+
* Internal helper used by safeReadJsonFile.ts to support JSONC (JSON with
|
|
93
|
+
* line and block comments, plus trailing commas) — the dialect used by
|
|
94
|
+
* tsconfig.json, VS Code's settings.json, etc. Not exported from the package
|
|
95
|
+
* barrel — tests live in _stripJsonComments.test.ts.
|
|
96
|
+
*/
|
|
97
|
+
/**
|
|
98
|
+
* Strips line comments (starting with two slashes), block comments (slash-star
|
|
99
|
+
* ... star-slash), and trailing commas (before `}` or `]`) from a JSONC
|
|
100
|
+
* string, so the result can be safely passed to `JSON.parse`. String literals
|
|
101
|
+
* are tracked so a comment-like or comma character occurring *inside* a JSON
|
|
102
|
+
* string (e.g. a URL) is left untouched — this is a string-boundary-aware
|
|
103
|
+
* pass, not a naive regex strip.
|
|
104
|
+
* @ignore
|
|
105
|
+
*/
|
|
106
|
+
function stripJsonComments(input) {
|
|
107
|
+
let output = "";
|
|
108
|
+
let inString = false;
|
|
109
|
+
let pendingComma = "";
|
|
110
|
+
const flushPendingComma = () => {
|
|
111
|
+
if (pendingComma) {
|
|
112
|
+
output += pendingComma;
|
|
113
|
+
pendingComma = "";
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
let i = 0;
|
|
117
|
+
while (i < input.length) {
|
|
118
|
+
const char = input[i];
|
|
119
|
+
if (inString) {
|
|
120
|
+
output += char;
|
|
121
|
+
if (char === "\\") {
|
|
122
|
+
i++;
|
|
123
|
+
if (i < input.length) output += input[i];
|
|
124
|
+
} else if (char === "\"") inString = false;
|
|
125
|
+
i++;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (char === "\"") {
|
|
129
|
+
flushPendingComma();
|
|
130
|
+
inString = true;
|
|
131
|
+
output += char;
|
|
132
|
+
i++;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (char === "/" && input[i + 1] === "/") {
|
|
136
|
+
i += 2;
|
|
137
|
+
while (i < input.length && input[i] !== "\n" && input[i] !== "\r") i++;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (char === "/" && input[i + 1] === "*") {
|
|
141
|
+
i += 2;
|
|
142
|
+
while (i < input.length && !(input[i] === "*" && input[i + 1] === "/")) i++;
|
|
143
|
+
i += 2;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (char === ",") {
|
|
147
|
+
flushPendingComma();
|
|
148
|
+
pendingComma = char;
|
|
149
|
+
i++;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (char === "}" || char === "]") {
|
|
153
|
+
pendingComma = "";
|
|
154
|
+
output += char;
|
|
155
|
+
i++;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (char === " " || char === " " || char === "\n" || char === "\r") {
|
|
159
|
+
if (pendingComma) pendingComma += char;
|
|
160
|
+
else output += char;
|
|
161
|
+
i++;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
flushPendingComma();
|
|
165
|
+
output += char;
|
|
166
|
+
i++;
|
|
167
|
+
}
|
|
168
|
+
flushPendingComma();
|
|
169
|
+
return output;
|
|
170
|
+
}
|
|
171
|
+
//#endregion
|
|
172
|
+
//#region helpers/node/safeReadJsonFile.ts
|
|
173
|
+
/**
|
|
174
|
+
* This file is part of helpers4.
|
|
175
|
+
* Copyright (C) 2025 baxyz
|
|
176
|
+
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
177
|
+
*/
|
|
178
|
+
function safeReadJsonFile(filePath, fallback) {
|
|
179
|
+
try {
|
|
180
|
+
const content = (0, import___vite_browser_external.readFileSync)(filePath, "utf-8");
|
|
181
|
+
try {
|
|
182
|
+
return JSON.parse(content);
|
|
183
|
+
} catch {
|
|
184
|
+
return JSON.parse(stripJsonComments(content));
|
|
185
|
+
}
|
|
186
|
+
} catch {
|
|
187
|
+
return arguments.length < 2 ? null : fallback;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//#endregion
|
|
191
|
+
export { isBuffer, isNodeStream, isSharedArrayBuffer, safeReadJsonFile };
|
|
81
192
|
|
|
82
193
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../helpers/node/isBuffer.ts","../../../helpers/node/isNodeStream.ts","../../../helpers/node/isSharedArrayBuffer.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a Node.js Buffer instance.\n *\n * `Buffer` extends `Uint8Array` and is specific to Node.js, Bun, and Deno.\n * In browser-only environments where `Buffer` is not defined, this function\n * always returns `false`.\n *\n * Useful for filtering or type-narrowing in a functional pipeline:\n * `values.filter(isBuffer)`\n *\n * @param value - The value to check\n * @returns True if value is a Buffer\n * @example\n * isBuffer(Buffer.from('hello')) // => true\n * isBuffer(new Uint8Array(8)) // => false\n * isBuffer('hello') // => false\n * @since 2.0.0\n */\nexport function isBuffer(value: unknown): value is Buffer {\n return typeof Buffer !== 'undefined' && value instanceof Buffer;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a Node.js stream (has a `.pipe()` method).\n *\n * Uses duck-typing: any object with a `pipe` function qualifies, covering\n * `Readable`, `Writable`, `Duplex`, `Transform`, and custom stream-compatible\n * objects without importing from `node:stream`.\n *\n * @param value - The value to check\n * @returns `true` if value is a Node.js stream\n * @example\n * import { Readable } from 'node:stream';\n * isNodeStream(new Readable()) // => true\n * isNodeStream({}) // => false\n * isNodeStream(null) // => false\n * @since 2.0.3\n */\nexport function isNodeStream(value: unknown): value is { pipe: (...args: unknown[]) => unknown } {\n return (\n // Intentionally `object`-only, unlike `isPromiseLike` (see type/isPromiseLike.ts):\n // a callable function exposing `.pipe()` would be an unusual, contrived stream shape.\n value !== null &&\n typeof value === 'object' &&\n typeof (value as Record<string, unknown>)['pipe'] === 'function'\n );\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a `SharedArrayBuffer` instance.\n *\n * `SharedArrayBuffer` enables shared memory between the main thread and worker\n * threads. In browsers without COOP/COEP headers, `SharedArrayBuffer` may be\n * unavailable; this function returns `false` in that case.\n *\n * @param value - The value to check\n * @returns `true` if value is a SharedArrayBuffer\n * @example\n * isSharedArrayBuffer(new SharedArrayBuffer(8)) // => true\n * isSharedArrayBuffer(new ArrayBuffer(8)) // => false\n * isSharedArrayBuffer(null) // => false\n * @since 2.0.3\n */\nexport function isSharedArrayBuffer(value: unknown): value is SharedArrayBuffer {\n return typeof SharedArrayBuffer !== 'undefined' && value instanceof SharedArrayBuffer;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,SAAS,OAAiC;CACxD,OAAO,OAAO,WAAW,eAAe,iBAAiB;AAC3D;;;;;;;;;;;;;;;;;;;;;;;;ACJA,SAAgB,aAAa,OAAoE;CAC/F,OAGE,UAAU,QACV,OAAO,UAAU,YACjB,OAAQ,MAAkC,YAAY;AAE1D;;;;;;;;;;;;;;;;;;;;;;;ACTA,SAAgB,oBAAoB,OAA4C;CAC9E,OAAO,OAAO,sBAAsB,eAAe,iBAAiB;AACtE"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../helpers/node/isBuffer.ts","../../../helpers/node/isNodeStream.ts","../../../helpers/node/isSharedArrayBuffer.ts","../../../__vite-browser-external","../../../helpers/node/_stripJsonComments.ts","../../../helpers/node/safeReadJsonFile.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a Node.js Buffer instance.\n *\n * `Buffer` extends `Uint8Array` and is specific to Node.js, Bun, and Deno.\n * In browser-only environments where `Buffer` is not defined, this function\n * always returns `false`.\n *\n * Useful for filtering or type-narrowing in a functional pipeline:\n * `values.filter(isBuffer)`\n *\n * @param value - The value to check\n * @returns True if value is a Buffer\n * @example\n * isBuffer(Buffer.from('hello')) // => true\n * isBuffer(new Uint8Array(8)) // => false\n * isBuffer('hello') // => false\n * @since 2.0.0\n */\nexport function isBuffer(value: unknown): value is Buffer {\n return typeof Buffer !== 'undefined' && value instanceof Buffer;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a Node.js stream (has a `.pipe()` method).\n *\n * Uses duck-typing: any object with a `pipe` function qualifies, covering\n * `Readable`, `Writable`, `Duplex`, `Transform`, and custom stream-compatible\n * objects without importing from `node:stream`.\n *\n * @param value - The value to check\n * @returns `true` if value is a Node.js stream\n * @example\n * import { Readable } from 'node:stream';\n * isNodeStream(new Readable()) // => true\n * isNodeStream({}) // => false\n * isNodeStream(null) // => false\n * @since 2.0.3\n */\nexport function isNodeStream(value: unknown): value is { pipe: (...args: unknown[]) => unknown } {\n return (\n // Intentionally `object`-only, unlike `isPromiseLike` (see type/isPromiseLike.ts):\n // a callable function exposing `.pipe()` would be an unusual, contrived stream shape.\n value !== null &&\n typeof value === 'object' &&\n typeof (value as Record<string, unknown>)['pipe'] === 'function'\n );\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a `SharedArrayBuffer` instance.\n *\n * `SharedArrayBuffer` enables shared memory between the main thread and worker\n * threads. In browsers without COOP/COEP headers, `SharedArrayBuffer` may be\n * unavailable; this function returns `false` in that case.\n *\n * @param value - The value to check\n * @returns `true` if value is a SharedArrayBuffer\n * @example\n * isSharedArrayBuffer(new SharedArrayBuffer(8)) // => true\n * isSharedArrayBuffer(new ArrayBuffer(8)) // => false\n * isSharedArrayBuffer(null) // => false\n * @since 2.0.3\n */\nexport function isSharedArrayBuffer(value: unknown): value is SharedArrayBuffer {\n return typeof SharedArrayBuffer !== 'undefined' && value instanceof SharedArrayBuffer;\n}\n","module.exports = {}","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n *\n * Internal helper used by safeReadJsonFile.ts to support JSONC (JSON with\n * line and block comments, plus trailing commas) — the dialect used by\n * tsconfig.json, VS Code's settings.json, etc. Not exported from the package\n * barrel — tests live in _stripJsonComments.test.ts.\n */\n\n/**\n * Strips line comments (starting with two slashes), block comments (slash-star\n * ... star-slash), and trailing commas (before `}` or `]`) from a JSONC\n * string, so the result can be safely passed to `JSON.parse`. String literals\n * are tracked so a comment-like or comma character occurring *inside* a JSON\n * string (e.g. a URL) is left untouched — this is a string-boundary-aware\n * pass, not a naive regex strip.\n * @ignore\n */\nexport function stripJsonComments(input: string): string {\n let output = '';\n let inString = false;\n // A comma seen outside a string is held back instead of emitted immediately:\n // if the next significant token turns out to be `}`/`]`, it was a trailing\n // comma and gets dropped; otherwise it (and any whitespace/comments held\n // alongside it) is flushed once a real token confirms it wasn't trailing.\n let pendingComma = '';\n const flushPendingComma = () => {\n if (pendingComma) {\n output += pendingComma;\n pendingComma = '';\n }\n };\n\n let i = 0;\n while (i < input.length) {\n const char = input[i];\n\n if (inString) {\n output += char;\n if (char === '\\\\') {\n // Copy the escaped character as-is (whatever it is) so an escaped\n // quote (`\\\"`) doesn't get mistaken for the string's end.\n i++;\n if (i < input.length) output += input[i];\n } else if (char === '\"') {\n inString = false;\n }\n i++;\n continue;\n }\n\n if (char === '\"') {\n flushPendingComma();\n inString = true;\n output += char;\n i++;\n continue;\n }\n\n if (char === '/' && input[i + 1] === '/') {\n i += 2;\n // Stop at any line-ending character, not just \\n — a bare \\r (classic\n // Mac line endings, or a lone \\r before a later \\n) also ends the line,\n // otherwise everything up to the next \\n (or EOF) gets silently eaten.\n while (i < input.length && input[i] !== '\\n' && input[i] !== '\\r') i++;\n continue;\n }\n\n if (char === '/' && input[i + 1] === '*') {\n i += 2;\n while (i < input.length && !(input[i] === '*' && input[i + 1] === '/')) i++;\n i += 2;\n continue;\n }\n\n if (char === ',') {\n flushPendingComma();\n pendingComma = char;\n i++;\n continue;\n }\n\n if (char === '}' || char === ']') {\n pendingComma = ''; // drop — it was trailing\n output += char;\n i++;\n continue;\n }\n\n if (char === ' ' || char === '\\t' || char === '\\n' || char === '\\r') {\n // Whitespace doesn't resolve a pending comma either way — buffer it\n // alongside so it's dropped too if the comma turns out to be trailing.\n if (pendingComma) {\n pendingComma += char;\n } else {\n output += char;\n }\n i++;\n continue;\n }\n\n flushPendingComma();\n output += char;\n i++;\n }\n\n flushPendingComma();\n return output;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport { readFileSync } from 'node:fs';\nimport { stripJsonComments } from './_stripJsonComments';\n\n/**\n * Reads a file and parses its contents as JSON, returning `null` (or a\n * fallback) on any failure — a missing/unreadable file and invalid content\n * are both treated the same way.\n *\n * Also tolerates JSONC (line/block comments and trailing commas — the\n * dialect used by `tsconfig.json`, VS Code's `settings.json`, etc.): strict\n * `JSON.parse` is tried first, and only on failure is the content re-parsed\n * with comments/trailing commas stripped, so plain JSON pays no extra cost.\n *\n * Unlike `readFileSync` + `JSON.parse`, this never throws.\n *\n * @param filePath - Path to the JSON (or JSONC) file to read.\n * @param fallback - Value returned on failure. Defaults to `null` when omitted.\n * @returns The parsed value typed as `T`, or `fallback` on failure.\n * @example\n * safeReadJsonFile<{ name: string }>('./package.json') // => { name: 'helpers4', ... }\n * safeReadJsonFile('./missing.json') // => null\n * safeReadJsonFile('./missing.json', {}) // => {}\n * @example\n * // tsconfig.json-style JSONC (comments + trailing comma) also parses:\n * safeReadJsonFile('./tsconfig.json') // => { compilerOptions: { strict: true }, ... }\n * @since 3.0.6\n */\nexport function safeReadJsonFile<T>(filePath: string): T | null;\nexport function safeReadJsonFile<T>(filePath: string, fallback: T): T;\nexport function safeReadJsonFile<T>(filePath: string, fallback?: T): T | null {\n try {\n const content = readFileSync(filePath, 'utf-8');\n try {\n return JSON.parse(content) as T;\n } catch {\n // Not strict JSON — retry tolerating JSONC comments/trailing commas\n // before giving up.\n return JSON.parse(stripJsonComments(content)) as T;\n }\n } catch {\n // Distinguish \"no fallback provided\" (→ null) from \"fallback is undefined\"\n // (→ undefined as T) to keep runtime behaviour aligned with the overloads.\n return arguments.length < 2 ? null : (fallback as T);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,SAAS,OAAiC;CACxD,OAAO,OAAO,WAAW,eAAe,iBAAiB;AAC3D;;;;;;;;;;;;;;;;;;;;;;;;ACJA,SAAgB,aAAa,OAAoE;CAC/F,OAGE,UAAU,QACV,OAAO,UAAU,YACjB,OAAQ,MAAkC,YAAY;AAE1D;;;;;;;;;;;;;;;;;;;;;;;ACTA,SAAgB,oBAAoB,OAA4C;CAC9E,OAAO,OAAO,sBAAsB,eAAe,iBAAiB;AACtE;;;;CCvBA,OAAO,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;ACoBlB,SAAgB,kBAAkB,OAAuB;CACvD,IAAI,SAAS;CACb,IAAI,WAAW;CAKf,IAAI,eAAe;CACnB,MAAM,0BAA0B;EAC9B,IAAI,cAAc;GAChB,UAAU;GACV,eAAe;EACjB;CACF;CAEA,IAAI,IAAI;CACR,OAAO,IAAI,MAAM,QAAQ;EACvB,MAAM,OAAO,MAAM;EAEnB,IAAI,UAAU;GACZ,UAAU;GACV,IAAI,SAAS,MAAM;IAGjB;IACA,IAAI,IAAI,MAAM,QAAQ,UAAU,MAAM;GACxC,OAAO,IAAI,SAAS,MAClB,WAAW;GAEb;GACA;EACF;EAEA,IAAI,SAAS,MAAK;GAChB,kBAAkB;GAClB,WAAW;GACX,UAAU;GACV;GACA;EACF;EAEA,IAAI,SAAS,OAAO,MAAM,IAAI,OAAO,KAAK;GACxC,KAAK;GAIL,OAAO,IAAI,MAAM,UAAU,MAAM,OAAO,QAAQ,MAAM,OAAO,MAAM;GACnE;EACF;EAEA,IAAI,SAAS,OAAO,MAAM,IAAI,OAAO,KAAK;GACxC,KAAK;GACL,OAAO,IAAI,MAAM,UAAU,EAAE,MAAM,OAAO,OAAO,MAAM,IAAI,OAAO,MAAM;GACxE,KAAK;GACL;EACF;EAEA,IAAI,SAAS,KAAK;GAChB,kBAAkB;GAClB,eAAe;GACf;GACA;EACF;EAEA,IAAI,SAAS,OAAO,SAAS,KAAK;GAChC,eAAe;GACf,UAAU;GACV;GACA;EACF;EAEA,IAAI,SAAS,OAAO,SAAS,OAAQ,SAAS,QAAQ,SAAS,MAAM;GAGnE,IAAI,cACF,gBAAgB;QAEhB,UAAU;GAEZ;GACA;EACF;EAEA,kBAAkB;EAClB,UAAU;EACV;CACF;CAEA,kBAAkB;CAClB,OAAO;AACT;;;;;;;;AC3EA,SAAgB,iBAAoB,UAAkB,UAAwB;CAC5E,IAAI;EACF,MAAM,WAAA,GAAA,+BAAA,aAAA,CAAuB,UAAU,OAAO;EAC9C,IAAI;GACF,OAAO,KAAK,MAAM,OAAO;EAC3B,QAAQ;GAGN,OAAO,KAAK,MAAM,kBAAkB,OAAO,CAAC;EAC9C;CACF,QAAQ;EAGN,OAAO,UAAU,SAAS,IAAI,OAAQ;CACxC;AACF"}
|
package/llms.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @helpers4/node
|
|
2
2
|
|
|
3
3
|
> Tree-shakable TypeScript utility functions for the `node` domain.
|
|
4
|
-
> Package: `@helpers4/node` — Version: 3.0.
|
|
4
|
+
> Package: `@helpers4/node` — Version: 3.0.6
|
|
5
5
|
> License: LGPL-3.0-or-later
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
@@ -15,7 +15,7 @@ pnpm add @helpers4/node
|
|
|
15
15
|
## Usage
|
|
16
16
|
|
|
17
17
|
```typescript
|
|
18
|
-
import { isBuffer, isNodeStream, isSharedArrayBuffer } from '@helpers4/node';
|
|
18
|
+
import { isBuffer, isNodeStream, isSharedArrayBuffer, ... } from '@helpers4/node';
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Functions
|
|
@@ -25,6 +25,7 @@ import { isBuffer, isNodeStream, isSharedArrayBuffer } from '@helpers4/node';
|
|
|
25
25
|
| `isBuffer` | Checks if a value is a Node.js Buffer instance. `Buffer` extends `Uint8Array` and is specific to No |
|
|
26
26
|
| `isNodeStream` | Checks if a value is a Node.js stream (has a `.pipe()` method). Uses duck-typing: any object with a |
|
|
27
27
|
| `isSharedArrayBuffer` | Checks if a value is a `SharedArrayBuffer` instance. `SharedArrayBuffer` enables shared memory betw |
|
|
28
|
+
| `safeReadJsonFile` | Reads a file and parses its contents as JSON, returning `null` (or a fallback) on any failure — a mi |
|
|
28
29
|
|
|
29
30
|
---
|
|
30
31
|
|
|
@@ -173,3 +174,85 @@ function sendToWorker(buffer: unknown): void {
|
|
|
173
174
|
```
|
|
174
175
|
|
|
175
176
|
---
|
|
177
|
+
|
|
178
|
+
### `safeReadJsonFile`
|
|
179
|
+
|
|
180
|
+
Reads a file and parses its contents as JSON, returning `null` (or a
|
|
181
|
+
fallback) on any failure — a missing/unreadable file and invalid content
|
|
182
|
+
are both treated the same way.
|
|
183
|
+
|
|
184
|
+
Also tolerates JSONC (line/block comments and trailing commas — the
|
|
185
|
+
dialect used by `tsconfig.json`, VS Code's `settings.json`, etc.): strict
|
|
186
|
+
`JSON.parse` is tried first, and only on failure is the content re-parsed
|
|
187
|
+
with comments/trailing commas stripped, so plain JSON pays no extra cost.
|
|
188
|
+
|
|
189
|
+
Unlike `readFileSync` + `JSON.parse`, this never throws.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { safeReadJsonFile } from '@helpers4/node';
|
|
193
|
+
|
|
194
|
+
safeReadJsonFile<T>(filePath: string): T | null
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Parameters:**
|
|
198
|
+
|
|
199
|
+
- `filePath: string` — Path to the JSON (or JSONC) file to read.
|
|
200
|
+
|
|
201
|
+
**Returns:** `T | null` — The parsed value typed as `T`, or `fallback` on failure.
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { safeReadJsonFile } from '@helpers4/node';
|
|
205
|
+
|
|
206
|
+
safeReadJsonFile<T>(filePath: string, fallback: T): T
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Parameters:**
|
|
210
|
+
|
|
211
|
+
- `filePath: string` — Path to the JSON (or JSONC) file to read.
|
|
212
|
+
- `fallback: T` — Value returned on failure. Defaults to `null` when omitted.
|
|
213
|
+
|
|
214
|
+
**Returns:** `T` — The parsed value typed as `T`, or `fallback` on failure.
|
|
215
|
+
|
|
216
|
+
**Examples:**
|
|
217
|
+
|
|
218
|
+
*Read and parse a JSON file*
|
|
219
|
+
|
|
220
|
+
Returns the parsed value when the file exists and contains valid JSON.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
safeReadJsonFile<{ name: string }>('./package.json')
|
|
224
|
+
// => { name: 'my-package', ... }
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
*Return null when the file is missing*
|
|
228
|
+
|
|
229
|
+
Returns null instead of throwing when the file does not exist.
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
safeReadJsonFile('./does-not-exist.json')
|
|
233
|
+
// => null
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
*Use a fallback value*
|
|
237
|
+
|
|
238
|
+
Returns the provided fallback when the file is missing or invalid.
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
safeReadJsonFile('./does-not-exist.json', {})
|
|
242
|
+
// => {}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
*Also reads JSONC (comments + trailing commas)*
|
|
246
|
+
|
|
247
|
+
tsconfig.json/settings.json-style content — line/block comments and a trailing comma — parses too.
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
safeReadJsonFile('./tsconfig.json')
|
|
251
|
+
// {
|
|
252
|
+
// // enable strict type-checking
|
|
253
|
+
// "compilerOptions": { "strict": true },
|
|
254
|
+
// }
|
|
255
|
+
// => { compilerOptions: { strict: true } }
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
---
|
package/meta/api.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"category": "node",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.6",
|
|
4
4
|
"functions": [
|
|
5
5
|
{
|
|
6
6
|
"name": "isBuffer",
|
|
@@ -109,6 +109,82 @@
|
|
|
109
109
|
}
|
|
110
110
|
],
|
|
111
111
|
"sourceFile": "isSharedArrayBuffer.ts"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "safeReadJsonFile",
|
|
115
|
+
"kind": "function",
|
|
116
|
+
"description": "Reads a file and parses its contents as JSON, returning `null` (or a\nfallback) on any failure — a missing/unreadable file and invalid content\nare both treated the same way.\n\nAlso tolerates JSONC (line/block comments and trailing commas — the\ndialect used by `tsconfig.json`, VS Code's `settings.json`, etc.): strict\n`JSON.parse` is tried first, and only on failure is the content re-parsed\nwith comments/trailing commas stripped, so plain JSON pays no extra cost.\n\nUnlike `readFileSync` + `JSON.parse`, this never throws.",
|
|
117
|
+
"since": "3.0.6",
|
|
118
|
+
"signatures": [
|
|
119
|
+
{
|
|
120
|
+
"signature": "safeReadJsonFile<T>(filePath: string): T | null",
|
|
121
|
+
"description": "Reads a file and parses its contents as JSON, returning `null` (or a\nfallback) on any failure — a missing/unreadable file and invalid content\nare both treated the same way.\n\nAlso tolerates JSONC (line/block comments and trailing commas — the\ndialect used by `tsconfig.json`, VS Code's `settings.json`, etc.): strict\n`JSON.parse` is tried first, and only on failure is the content re-parsed\nwith comments/trailing commas stripped, so plain JSON pays no extra cost.\n\nUnlike `readFileSync` + `JSON.parse`, this never throws.",
|
|
122
|
+
"params": [
|
|
123
|
+
{
|
|
124
|
+
"name": "filePath",
|
|
125
|
+
"type": "string",
|
|
126
|
+
"description": "Path to the JSON (or JSONC) file to read."
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
"returns": {
|
|
130
|
+
"type": "T | null",
|
|
131
|
+
"description": "The parsed value typed as `T`, or `fallback` on failure."
|
|
132
|
+
},
|
|
133
|
+
"typeParameters": [
|
|
134
|
+
{
|
|
135
|
+
"name": "T"
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"signature": "safeReadJsonFile<T>(filePath: string, fallback: T): T",
|
|
141
|
+
"description": "Reads a file and parses its contents as JSON, returning `null` (or a\nfallback) on any failure — a missing/unreadable file and invalid content\nare both treated the same way.\n\nAlso tolerates JSONC (line/block comments and trailing commas — the\ndialect used by `tsconfig.json`, VS Code's `settings.json`, etc.): strict\n`JSON.parse` is tried first, and only on failure is the content re-parsed\nwith comments/trailing commas stripped, so plain JSON pays no extra cost.\n\nUnlike `readFileSync` + `JSON.parse`, this never throws.",
|
|
142
|
+
"params": [
|
|
143
|
+
{
|
|
144
|
+
"name": "filePath",
|
|
145
|
+
"type": "string",
|
|
146
|
+
"description": "Path to the JSON (or JSONC) file to read."
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"name": "fallback",
|
|
150
|
+
"type": "T",
|
|
151
|
+
"description": "Value returned on failure. Defaults to `null` when omitted."
|
|
152
|
+
}
|
|
153
|
+
],
|
|
154
|
+
"returns": {
|
|
155
|
+
"type": "T",
|
|
156
|
+
"description": "The parsed value typed as `T`, or `fallback` on failure."
|
|
157
|
+
},
|
|
158
|
+
"typeParameters": [
|
|
159
|
+
{
|
|
160
|
+
"name": "T"
|
|
161
|
+
}
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
],
|
|
165
|
+
"examples": [
|
|
166
|
+
{
|
|
167
|
+
"title": "Read and parse a JSON file",
|
|
168
|
+
"description": "Returns the parsed value when the file exists and contains valid JSON.",
|
|
169
|
+
"code": "safeReadJsonFile<{ name: string }>('./package.json')\n// => { name: 'my-package', ... }"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"title": "Return null when the file is missing",
|
|
173
|
+
"description": "Returns null instead of throwing when the file does not exist.",
|
|
174
|
+
"code": "safeReadJsonFile('./does-not-exist.json')\n// => null"
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"title": "Use a fallback value",
|
|
178
|
+
"description": "Returns the provided fallback when the file is missing or invalid.",
|
|
179
|
+
"code": "safeReadJsonFile('./does-not-exist.json', {})\n// => {}"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"title": "Also reads JSONC (comments + trailing commas)",
|
|
183
|
+
"description": "tsconfig.json/settings.json-style content — line/block comments and a trailing comma — parses too.",
|
|
184
|
+
"code": "safeReadJsonFile('./tsconfig.json')\n// {\n// // enable strict type-checking\n// \"compilerOptions\": { \"strict\": true },\n// }\n// => { compilerOptions: { strict: true } }"
|
|
185
|
+
}
|
|
186
|
+
],
|
|
187
|
+
"sourceFile": "safeReadJsonFile.ts"
|
|
112
188
|
}
|
|
113
189
|
]
|
|
114
190
|
}
|
package/meta/examples.json
CHANGED
|
@@ -45,6 +45,31 @@
|
|
|
45
45
|
"code": "function sendToWorker(buffer: unknown): void {\n if (isSharedArrayBuffer(buffer)) {\n // buffer is SharedArrayBuffer — can be shared directly\n // worker.postMessage({ buffer });\n } else {\n // must transfer or copy\n }\n}"
|
|
46
46
|
}
|
|
47
47
|
]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "safeReadJsonFile",
|
|
51
|
+
"examples": [
|
|
52
|
+
{
|
|
53
|
+
"title": "Read and parse a JSON file",
|
|
54
|
+
"description": "Returns the parsed value when the file exists and contains valid JSON.",
|
|
55
|
+
"code": "safeReadJsonFile<{ name: string }>('./package.json')\n// => { name: 'my-package', ... }"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"title": "Return null when the file is missing",
|
|
59
|
+
"description": "Returns null instead of throwing when the file does not exist.",
|
|
60
|
+
"code": "safeReadJsonFile('./does-not-exist.json')\n// => null"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"title": "Use a fallback value",
|
|
64
|
+
"description": "Returns the provided fallback when the file is missing or invalid.",
|
|
65
|
+
"code": "safeReadJsonFile('./does-not-exist.json', {})\n// => {}"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"title": "Also reads JSONC (comments + trailing commas)",
|
|
69
|
+
"description": "tsconfig.json/settings.json-style content — line/block comments and a trailing comma — parses too.",
|
|
70
|
+
"code": "safeReadJsonFile('./tsconfig.json')\n// {\n// // enable strict type-checking\n// \"compilerOptions\": { \"strict\": true },\n// }\n// => { compilerOptions: { strict: true } }"
|
|
71
|
+
}
|
|
72
|
+
]
|
|
48
73
|
}
|
|
49
74
|
]
|
|
50
75
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helpers4/node",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.6",
|
|
4
4
|
"description": "A set of helpers in TS/JS, compatible with tree-shaking, for node.",
|
|
5
5
|
"author": "baxyz <craft@baxyz.dev>",
|
|
6
6
|
"license": "LGPL-3.0",
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"node",
|
|
30
30
|
"isBuffer",
|
|
31
31
|
"isNodeStream",
|
|
32
|
-
"isSharedArrayBuffer"
|
|
32
|
+
"isSharedArrayBuffer",
|
|
33
|
+
"safeReadJsonFile"
|
|
33
34
|
],
|
|
34
35
|
"files": [
|
|
35
36
|
"lib/index.js",
|