From 7388bc6c41961be45660430e3150b3c39aa8cd50 Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Mon, 15 Jun 2026 16:04:46 -0700 Subject: [PATCH] refactor: replace cjson with internal comment-stripping JSON parser ### Description Removed the external third-party `cjson` dependency and replaced it with a robust custom comment-stripping parser in `src/loadCJSON.ts`. This reduces production dependency weight. ### Scenarios Tested - Added a new `complex.cjson` test fixture with trailing, inline, and string-embedded comments. - Run `npx mocha src/loadCJSON.spec.ts` successfully. ### Sample Commands - `npx mocha src/loadCJSON.spec.ts` --- npm-shrinkwrap.json | 46 ----------------------- package.json | 1 - src/loadCJSON.spec.ts | 13 +++++++ src/loadCJSON.ts | 18 ++++++++- src/test/fixtures/loadCJSON/complex.cjson | 11 ++++++ 5 files changed, 40 insertions(+), 49 deletions(-) create mode 100644 src/test/fixtures/loadCJSON/complex.cjson diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index e48c43b2e05..59b853090d7 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -23,7 +23,6 @@ "async-lock": "1.4.1", "body-parser": "^1.19.0", "chokidar": "^3.6.0", - "cjson": "^0.3.1", "cli-table3": "0.6.5", "colorette": "^2.0.19", "commander": "^5.1.0", @@ -7754,17 +7753,6 @@ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" }, - "node_modules/cjson": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/cjson/-/cjson-0.3.3.tgz", - "integrity": "sha1-qS2ceG5b+bkwgGMp7gXV0yYbSvo=", - "dependencies": { - "json-parse-helpfulerror": "^1.0.3" - }, - "engines": { - "node": ">= 0.3.0" - } - }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -13002,11 +12990,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=" - }, "node_modules/join-path": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/join-path/-/join-path-1.1.1.tgz", @@ -13184,14 +13167,6 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "node_modules/json-parse-helpfulerror": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", - "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", - "dependencies": { - "jju": "^1.1.0" - } - }, "node_modules/json-ptr": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-ptr/-/json-ptr-3.0.1.tgz", @@ -27448,14 +27423,6 @@ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" }, - "cjson": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/cjson/-/cjson-0.3.3.tgz", - "integrity": "sha1-qS2ceG5b+bkwgGMp7gXV0yYbSvo=", - "requires": { - "json-parse-helpfulerror": "^1.0.3" - } - }, "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -31276,11 +31243,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=" - }, "join-path": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/join-path/-/join-path-1.1.1.tgz", @@ -31417,14 +31379,6 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, - "json-parse-helpfulerror": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz", - "integrity": "sha1-E/FM4C7tTpgSl7ZOueO5MuLdE9w=", - "requires": { - "jju": "^1.1.0" - } - }, "json-ptr": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-ptr/-/json-ptr-3.0.1.tgz", diff --git a/package.json b/package.json index 182110a90c2..d3a01e642bc 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,6 @@ "async-lock": "1.4.1", "body-parser": "^1.19.0", "chokidar": "^3.6.0", - "cjson": "^0.3.1", "cli-table3": "0.6.5", "colorette": "^2.0.19", "commander": "^5.1.0", diff --git a/src/loadCJSON.spec.ts b/src/loadCJSON.spec.ts index 4c4f8e1ec54..d9875733110 100644 --- a/src/loadCJSON.spec.ts +++ b/src/loadCJSON.spec.ts @@ -12,6 +12,19 @@ describe("loadCJSON", () => { expect(result).to.deep.equal({ key: "value" }); }); + it("should correctly parse comments inside string values and block comments", () => { + const filePath = path.join(fixturesDir, "complex.cjson"); + const result = loadCJSON(filePath); + expect(result).to.deep.equal({ + url: "https://example.com/foo", + comment_in_string: "this is // not a comment", + block_in_string: "this is /* not a block */ comment", + nested: { + key: "value", + }, + }); + }); + it("should throw FirebaseError on ENOENT", () => { const filePath = path.join(fixturesDir, "nonexistent.cjson"); expect(() => loadCJSON(filePath)).to.throw( diff --git a/src/loadCJSON.ts b/src/loadCJSON.ts index bf419f10d36..60cd76de1e5 100644 --- a/src/loadCJSON.ts +++ b/src/loadCJSON.ts @@ -1,16 +1,30 @@ +import * as fs from "fs"; import { FirebaseError } from "./error"; -import * as cjson from "cjson"; /** * Loads CJSON from given path. */ export function loadCJSON(path: string): any { + let content: string; try { - return cjson.load(path); + content = fs.readFileSync(path, "utf8"); } catch (e: any) { if (e.code === "ENOENT") { throw new FirebaseError(`File ${path} does not exist`); } + throw e; + } + + try { + const stripped = content.replace( + /("([^"\\]|\\.)*")|(\/\*[\s\S]*?\*\/|\/\/.*)/g, + (match, string) => { + if (string) return string; + return ""; + }, + ); + return JSON.parse(stripped); + } catch (e: any) { throw new FirebaseError(`Parse Error in ${path}:\n\n${e.message}`); } } diff --git a/src/test/fixtures/loadCJSON/complex.cjson b/src/test/fixtures/loadCJSON/complex.cjson new file mode 100644 index 00000000000..140483060b9 --- /dev/null +++ b/src/test/fixtures/loadCJSON/complex.cjson @@ -0,0 +1,11 @@ +{ + // Line comment at start + "url": "https://example.com/foo", + "comment_in_string": "this is // not a comment", + "block_in_string": "this is /* not a block */ comment", + /* Multi-line + block comment */ + "nested": { + "key": "value" // trailing line comment + } +}