From 00afe27ddb90090bb46674b1aee921095c0679c6 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Mon, 6 Oct 2025 20:17:41 -0700 Subject: [PATCH 1/8] fix(tests): update import syntax for Node.js 22 compatibility Updates import syntax in test files to be compatible with the new experimental TypeScript loader enabled by default in Node.js v22.18.0+. Starting in v22.18.0, Node.js enables a "strip-only" mode for TypeScript files by default. This new loader is stricter and does not support certain TypeScript-specific syntax, such as `import = require()` declarations, which were previously handled by a separate transpiler. This change caused `TypeError` and `SyntaxError` exceptions during test runs. This commit replaces the incompatible syntax with standard ES module imports to resolve the test failures. --- mocha/setup.ts | 4 ++-- spec/common/config.spec.ts | 14 +++++++------- spec/v1/config.spec.ts | 14 +++++++------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/mocha/setup.ts b/mocha/setup.ts index ded201904..8f5970cac 100644 --- a/mocha/setup.ts +++ b/mocha/setup.ts @@ -1,6 +1,6 @@ import * as chai from "chai"; -import * as chaiAsPromised from "chai-as-promised"; -import * as nock from "nock"; +import chaiAsPromised from "chai-as-promised"; +import nock from "nock"; chai.use(chaiAsPromised); diff --git a/spec/common/config.spec.ts b/spec/common/config.spec.ts index 0376c8105..e1bb330c6 100644 --- a/spec/common/config.spec.ts +++ b/spec/common/config.spec.ts @@ -23,23 +23,23 @@ import { expect } from "chai"; import * as fs from "fs"; import * as process from "process"; -import Sinon = require("sinon"); +import * as sinon from "sinon"; import { firebaseConfig, resetCache } from "../../src/common/config"; describe("firebaseConfig()", () => { - let readFileSync: Sinon.SinonStub; - let cwdStub: Sinon.SinonStub; + let readFileSync: sinon.SinonStub; + let cwdStub: sinon.SinonStub; before(() => { - readFileSync = Sinon.stub(fs, "readFileSync"); + readFileSync = sinon.stub(fs, "readFileSync"); readFileSync.throws("Unexpected call"); - cwdStub = Sinon.stub(process, "cwd"); + cwdStub = sinon.stub(process, "cwd"); cwdStub.returns("/srv"); }); after(() => { - Sinon.verifyAndRestore(); + sinon.verifyAndRestore(); }); afterEach(() => { @@ -69,4 +69,4 @@ describe("firebaseConfig()", () => { (process as any).env = oldEnv; } }); -}); +}); \ No newline at end of file diff --git a/spec/v1/config.spec.ts b/spec/v1/config.spec.ts index 67bd920db..a78051537 100644 --- a/spec/v1/config.spec.ts +++ b/spec/v1/config.spec.ts @@ -23,23 +23,23 @@ import { expect } from "chai"; import * as fs from "fs"; import * as process from "process"; -import Sinon = require("sinon"); +import * as sinon from "sinon"; import { config, resetCache } from "../../src/v1/config"; describe("config()", () => { - let readFileSync: Sinon.SinonStub; - let cwdStub: Sinon.SinonStub; + let readFileSync: sinon.SinonStub; + let cwdStub: sinon.SinonStub; before(() => { - readFileSync = Sinon.stub(fs, "readFileSync"); + readFileSync = sinon.stub(fs, "readFileSync"); readFileSync.throws("Unexpected call"); - cwdStub = Sinon.stub(process, "cwd"); + cwdStub = sinon.stub(process, "cwd"); cwdStub.returns("/srv"); }); after(() => { - Sinon.verifyAndRestore(); + sinon.verifyAndRestore(); }); afterEach(() => { @@ -70,4 +70,4 @@ describe("config()", () => { expect(loaded).to.not.have.property("firebase"); expect(loaded).to.have.property("foo", "bar"); }); -}); +}); \ No newline at end of file From da6880c1c10275ffd998356ddef51df0bb6847e2 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Mon, 6 Oct 2025 20:31:51 -0700 Subject: [PATCH 2/8] fix(tests): normalize mocha setup imports for node compatibility --- mocha/setup.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/mocha/setup.ts b/mocha/setup.ts index 8f5970cac..ab33f8ffd 100644 --- a/mocha/setup.ts +++ b/mocha/setup.ts @@ -1,6 +1,15 @@ import * as chai from "chai"; -import chaiAsPromised from "chai-as-promised"; -import nock from "nock"; +import * as chaiAsPromisedModule from "chai-as-promised"; +import * as nockModule from "nock"; + +// Normalize CommonJS exports so ts-node (Node.js 20) and Node.js 22's strip-only loader +// both receive callable modules without relying on esModuleInterop. +type ChaiPlugin = Parameters[0]; +type NockModule = typeof nockModule; + +const chaiAsPromised = ((chaiAsPromisedModule as { default?: ChaiPlugin }).default ?? + (chaiAsPromisedModule as unknown as ChaiPlugin)) as ChaiPlugin; +const nock = ((nockModule as NockModule & { default?: NockModule }).default ?? nockModule) as NockModule; chai.use(chaiAsPromised); From 1bfbde5512e07a6bfa3beee66ef3b5c515e901b2 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Mon, 6 Oct 2025 20:34:40 -0700 Subject: [PATCH 3/8] lint: run formatter --- mocha/setup.ts | 7 ++++--- spec/common/config.spec.ts | 2 +- spec/v1/config.spec.ts | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mocha/setup.ts b/mocha/setup.ts index ab33f8ffd..0a6bc5f2a 100644 --- a/mocha/setup.ts +++ b/mocha/setup.ts @@ -7,9 +7,10 @@ import * as nockModule from "nock"; type ChaiPlugin = Parameters[0]; type NockModule = typeof nockModule; -const chaiAsPromised = ((chaiAsPromisedModule as { default?: ChaiPlugin }).default ?? - (chaiAsPromisedModule as unknown as ChaiPlugin)) as ChaiPlugin; -const nock = ((nockModule as NockModule & { default?: NockModule }).default ?? nockModule) as NockModule; +const chaiAsPromised = + (chaiAsPromisedModule as { default?: ChaiPlugin }).default ?? + (chaiAsPromisedModule as unknown as ChaiPlugin); +const nock = (nockModule as NockModule & { default?: NockModule }).default ?? nockModule; chai.use(chaiAsPromised); diff --git a/spec/common/config.spec.ts b/spec/common/config.spec.ts index e1bb330c6..004be249a 100644 --- a/spec/common/config.spec.ts +++ b/spec/common/config.spec.ts @@ -69,4 +69,4 @@ describe("firebaseConfig()", () => { (process as any).env = oldEnv; } }); -}); \ No newline at end of file +}); diff --git a/spec/v1/config.spec.ts b/spec/v1/config.spec.ts index a78051537..97d7b6faa 100644 --- a/spec/v1/config.spec.ts +++ b/spec/v1/config.spec.ts @@ -70,4 +70,4 @@ describe("config()", () => { expect(loaded).to.not.have.property("firebase"); expect(loaded).to.have.property("foo", "bar"); }); -}); \ No newline at end of file +}); From 8ab9ae7c50e3a6c62f44ebefca21a84459cbdbad Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Mon, 6 Oct 2025 21:04:01 -0700 Subject: [PATCH 4/8] fix(tests): normalize bin mocha setup imports --- scripts/bin-test/mocha-setup.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/bin-test/mocha-setup.ts b/scripts/bin-test/mocha-setup.ts index 21b3996d1..6d0d8fa4a 100644 --- a/scripts/bin-test/mocha-setup.ts +++ b/scripts/bin-test/mocha-setup.ts @@ -1,4 +1,11 @@ import * as chai from "chai"; -import * as chaiAsPromised from "chai-as-promised"; +import * as chaiAsPromisedModule from "chai-as-promised"; + +// Match the runtime shim in mocha/setup.ts so bin tests work on Node.js 20 ts-node +// and Node.js 22's strip-only TypeScript loader without enabling esModuleInterop. +type ChaiPlugin = Parameters[0]; + +const chaiAsPromised = ((chaiAsPromisedModule as { default?: ChaiPlugin }).default ?? + (chaiAsPromisedModule as unknown as ChaiPlugin)) as ChaiPlugin; chai.use(chaiAsPromised); From 03e636661650506e11459e763d82f7a6d90576f8 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Mon, 6 Oct 2025 21:07:45 -0700 Subject: [PATCH 5/8] fix(tests): normalize js-yaml import for bin tests --- scripts/bin-test/test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/bin-test/test.ts b/scripts/bin-test/test.ts index 616b50fb5..430bb7598 100644 --- a/scripts/bin-test/test.ts +++ b/scripts/bin-test/test.ts @@ -5,10 +5,15 @@ import * as fs from "fs/promises"; import * as os from "os"; import { expect } from "chai"; -import * as yaml from "js-yaml"; +import * as yamlModule from "js-yaml"; import fetch from "node-fetch"; import * as portfinder from "portfinder"; +type YamlModule = typeof import("js-yaml"); + +// Normalize CommonJS exports (js-yaml) across Node.js 20 ts-node and Node.js 22 strip-only loader. +const yaml = ((yamlModule as { default?: YamlModule }).default ?? (yamlModule as YamlModule)) as YamlModule; + const TIMEOUT_XL = 20_000; const TIMEOUT_L = 10_000; const TIMEOUT_M = 5_000; From 9c24372213bc5e32454646d15f2ef537fb374507 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Mon, 6 Oct 2025 21:30:56 -0700 Subject: [PATCH 6/8] fix(tests): swap bin manifest parser to yaml --- package-lock.json | 15 ++++++++++++++- package.json | 2 +- scripts/bin-test/test.ts | 9 ++------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9c6f62e3e..f865797b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,6 @@ "eslint-plugin-prettier": "^4.0.0", "firebase-admin": "^13.0.0", "genkit": "^1.0.0-rc.4", - "js-yaml": "^3.13.1", "jsdom": "^16.2.1", "jsonwebtoken": "^9.0.0", "jwk-to-pem": "^2.0.5", @@ -60,6 +59,7 @@ "sinon": "^9.2.4", "ts-node": "^10.4.0", "typescript": "^4.3.5", + "yaml": "^2.8.1", "yargs": "^15.3.1" }, "engines": { @@ -8558,6 +8558,19 @@ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", "dev": true }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, "node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", diff --git a/package.json b/package.json index a9ec85b6f..9b1a91b18 100644 --- a/package.json +++ b/package.json @@ -301,7 +301,6 @@ "eslint-plugin-prettier": "^4.0.0", "firebase-admin": "^13.0.0", "genkit": "^1.0.0-rc.4", - "js-yaml": "^3.13.1", "jsdom": "^16.2.1", "jsonwebtoken": "^9.0.0", "jwk-to-pem": "^2.0.5", @@ -317,6 +316,7 @@ "sinon": "^9.2.4", "ts-node": "^10.4.0", "typescript": "^4.3.5", + "yaml": "^2.8.1", "yargs": "^15.3.1" }, "peerDependencies": { diff --git a/scripts/bin-test/test.ts b/scripts/bin-test/test.ts index 430bb7598..cacc0e27c 100644 --- a/scripts/bin-test/test.ts +++ b/scripts/bin-test/test.ts @@ -5,15 +5,10 @@ import * as fs from "fs/promises"; import * as os from "os"; import { expect } from "chai"; -import * as yamlModule from "js-yaml"; +import { parse as parseYaml } from "yaml"; import fetch from "node-fetch"; import * as portfinder from "portfinder"; -type YamlModule = typeof import("js-yaml"); - -// Normalize CommonJS exports (js-yaml) across Node.js 20 ts-node and Node.js 22 strip-only loader. -const yaml = ((yamlModule as { default?: YamlModule }).default ?? (yamlModule as YamlModule)) as YamlModule; - const TIMEOUT_XL = 20_000; const TIMEOUT_L = 10_000; const TIMEOUT_M = 5_000; @@ -182,7 +177,7 @@ async function runHttpDiscovery(modulePath: string): Promise { const body = await res.text(); if (res.status === 200) { - const manifest = yaml.load(body) as Record; + const manifest = parseYaml(body) as Record; return { success: true, manifest }; } else { return { success: false, error: body }; From 7fc46f60a27192a7796cb948b519262ddaefa336 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Mon, 6 Oct 2025 21:39:56 -0700 Subject: [PATCH 7/8] fix linter issue. --- scripts/bin-test/mocha-setup.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/bin-test/mocha-setup.ts b/scripts/bin-test/mocha-setup.ts index 6d0d8fa4a..1fe5d2f95 100644 --- a/scripts/bin-test/mocha-setup.ts +++ b/scripts/bin-test/mocha-setup.ts @@ -5,7 +5,7 @@ import * as chaiAsPromisedModule from "chai-as-promised"; // and Node.js 22's strip-only TypeScript loader without enabling esModuleInterop. type ChaiPlugin = Parameters[0]; -const chaiAsPromised = ((chaiAsPromisedModule as { default?: ChaiPlugin }).default ?? - (chaiAsPromisedModule as unknown as ChaiPlugin)) as ChaiPlugin; +const chaiAsPromisedExport = chaiAsPromisedModule as ChaiPlugin & { default?: ChaiPlugin }; +const chaiAsPromised = chaiAsPromisedExport.default ?? chaiAsPromisedExport; chai.use(chaiAsPromised); From 0242ffdafdc32e3dec10bb267e167f51b33bc8f3 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Mon, 6 Oct 2025 21:53:06 -0700 Subject: [PATCH 8/8] Update mocha/setup.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- mocha/setup.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mocha/setup.ts b/mocha/setup.ts index 0a6bc5f2a..d1d81c5a6 100644 --- a/mocha/setup.ts +++ b/mocha/setup.ts @@ -7,10 +7,10 @@ import * as nockModule from "nock"; type ChaiPlugin = Parameters[0]; type NockModule = typeof nockModule; -const chaiAsPromised = - (chaiAsPromisedModule as { default?: ChaiPlugin }).default ?? - (chaiAsPromisedModule as unknown as ChaiPlugin); -const nock = (nockModule as NockModule & { default?: NockModule }).default ?? nockModule; +const chaiAsPromisedExport = chaiAsPromisedModule as ChaiPlugin & { default?: ChaiPlugin }; +const chaiAsPromised = chaiAsPromisedExport.default ?? chaiAsPromisedExport; +const nockExport = nockModule as NockModule & { default?: NockModule }; +const nock = nockExport.default ?? nockExport; chai.use(chaiAsPromised);