From 3d497949ee815900d4e3713adde3343b8eadca40 Mon Sep 17 00:00:00 2001 From: Armando Navarro Date: Fri, 10 Jul 2026 15:43:53 -0700 Subject: [PATCH 1/7] fix(schematics): only emit FirebaseOptions keys in the generated app config (#3707) The Firebase CLI's apps.sdkconfig response includes management-API fields (projectNumber, version, locationId) alongside the web app config. The schematic only deleted locationId and inlined the rest into initializeApp(), so the generated app failed to compile with TS2769: 'projectNumber' does not exist in type 'FirebaseOptions'. Keep only the keys FirebaseOptions accepts, so future additions to the CLI response cannot break the generated config again. --- src/schematics/setup/index.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/schematics/setup/index.ts b/src/schematics/setup/index.ts index 06e29f789..3d40ed132 100644 --- a/src/schematics/setup/index.ts +++ b/src/schematics/setup/index.ts @@ -18,6 +18,12 @@ import { } from '../utils'; import { appPrompt, featuresPrompt, projectPrompt, userPrompt } from './prompts'; +// FirebaseOptions keys — apps.sdkconfig responses include management-API extras that initializeApp() rejects. +const firebaseOptionsKeys = [ + 'apiKey', 'authDomain', 'databaseURL', 'projectId', 'storageBucket', + 'messagingSenderId', 'appId', 'measurementId', 'recaptchaSiteKey', +]; + export interface SetupConfig extends DeployOptions { firebaseProject: FirebaseProject, firebaseApp?: FirebaseApp, @@ -92,8 +98,11 @@ export const ngAddSetupProject = ( firebaseApp = await appPrompt(firebaseProject, undefined, { projectRoot }); const result = await firebaseTools.apps.sdkconfig('web', firebaseApp.appId, { nonInteractive: true, projectRoot }); - sdkConfig = result.sdkConfig; - delete sdkConfig.locationId; + sdkConfig = Object.fromEntries( + firebaseOptionsKeys + .filter(key => result.sdkConfig[key] !== undefined) + .map(key => [key, result.sdkConfig[key]]) + ); setupConfig.sdkConfig = sdkConfig; setupConfig.firebaseApp = firebaseApp; // set up data connect locally if data connect hasn't already been initialized. From 97a7a746fe11b5ec67ddac68a8aac40f1631e022 Mon Sep 17 00:00:00 2001 From: Armando Navarro Date: Tue, 4 Aug 2026 17:34:14 -0700 Subject: [PATCH 2/7] fix(schematics): use the exported logger/compat subpath in generated functions (#3730) The SSR Cloud Function generated by `ng deploy` crashed at cold start: Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './lib/logger/compat' is not defined by "exports" in node_modules/firebase-functions/package.json Both generated templates required `firebase-functions/lib/logger/compat`. firebase-functions declares an exports map, and the internal `lib/` path is not in it. The exported subpath is `firebase-functions/logger/compat`, which maps to the same file. Verified by generating the function source and loading it against a real firebase-functions install: the shipped path throws, the exported path loads and emits structured Cloud Logging JSON, which is what the compat logger is there to do. This affects the deployed function rather than the build, so it fails at runtime in Cloud Functions rather than during `ng deploy`, and it is present in both the 20.x and 21.x lines. (cherry picked from commit a99f09b72aa941946d1412149c6c8b4e9dc51783) --- src/schematics/deploy/functions-templates.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/schematics/deploy/functions-templates.ts b/src/schematics/deploy/functions-templates.ts index 4005675c9..13cd9ab14 100644 --- a/src/schematics/deploy/functions-templates.ts +++ b/src/schematics/deploy/functions-templates.ts @@ -37,7 +37,7 @@ export const defaultFunction = ( ) => `const functions = require('firebase-functions'); // Increase readability in Cloud Logging -require("firebase-functions/lib/logger/compat"); +require("firebase-functions/logger/compat"); const expressApp = require('./${path}/main').app(); @@ -55,7 +55,7 @@ export const functionGen2 = ( ) => `const { onRequest } = require('firebase-functions/v2/https'); // Increase readability in Cloud Logging -require("firebase-functions/lib/logger/compat"); +require("firebase-functions/logger/compat"); const expressApp = require('./${path}/main').app(); From 560d76a052a8766da212f8f25808a1acf4cb990d Mon Sep 17 00:00:00 2001 From: Armando Navarro Date: Mon, 20 Jul 2026 16:56:23 -0700 Subject: [PATCH 3/7] fix(core): drop vestigial @angular/platform-browser-dynamic peer (#3718) Every platform-browser-dynamic 20.x/21.x patch release requires the exact @angular/core and @angular/common version matching its own patch. Declaring pbd as a required peer therefore makes npm pull in a pbd version whose required core/common usually differs from the app's installed core/common, failing `ng add @angular/fire` with ERESOLVE on Angular >= 20.1 apps. Nothing in the published package imports platform-browser-dynamic; the only usage in the repo is the Karma test bootstrap (src/test.ts), which is supplied by the root package.json and is unaffected. Removing a peer nothing imports is non-breaking for consumers. Considered marking the peer optional via peerDependenciesMeta instead (the manifest already uses that pattern for firebase-tools and platform-server); it would also avoid the ERESOLVE on npm, but it keeps advertising a dependency relationship that does not exist and relies on npm-specific resolver behavior. Deletion fixes every package manager. Refs #3667 (cherry picked from commit 8dfcc2c8b5c117d0a35d60bd3fb2cf55c5a84eb4) --- src/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/package.json b/src/package.json index 4f0bc9082..71657cddd 100644 --- a/src/package.json +++ b/src/package.json @@ -26,7 +26,6 @@ "@angular/common": "^20.0.0", "@angular/core": "^20.0.0", "@angular/platform-browser": "^20.0.0", - "@angular/platform-browser-dynamic": "^20.0.0", "@angular/platform-server": "^20.0.0", "rxjs": "~7.8.0", "firebase-tools": "^14.0.0" From 1c0059abb7446ffa7e17f7e728ba27698948176a Mon Sep 17 00:00:00 2001 From: Munir I Said Date: Wed, 8 Jul 2026 00:14:29 +0300 Subject: [PATCH 4/7] Update firebaseTools schematics to reflect v14.0.0 firebase-tools requirement (#3662) (cherry picked from commit 8bf386e5587b65dfbe3aefeacb2514bcdee8044f) --- src/schematics/firebaseTools.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/schematics/firebaseTools.ts b/src/schematics/firebaseTools.ts index 2d8c394b1..3d8136763 100644 --- a/src/schematics/firebaseTools.ts +++ b/src/schematics/firebaseTools.ts @@ -45,7 +45,7 @@ export const getFirebaseTools = () => globalThis.firebaseTools ? const version = firebaseTools.cli.version(); console.log(`Using firebase-tools version ${version}`); if (semverCompare(version, '14.0.0') === -1) { - console.error('firebase-tools version 13.0.0+ is required, please upgrade and run again'); + console.error('firebase-tools version 14.0.0+ is required, please upgrade and run again'); return Promise.reject(); } return firebaseTools; From 0ba7057355a5b10b40e3802929502fc417fb6896 Mon Sep 17 00:00:00 2001 From: Armando Navarro Date: Wed, 8 Jul 2026 14:18:22 -0700 Subject: [PATCH 5/7] fix(schematics): accept firebase-tools 15 in the peer range (#3702) The optional firebase-tools peerDependency was capped at ^14.0.0, which excludes the current major (15.x). The ng add version check already accepts anything >= 14.0.0 and the schematic runs fine on 15.x, so the narrow range only produces spurious peer-dependency warnings for users on the current CLI. (cherry picked from commit 45f138df324dc0c86c0e052115b532300ccf00bb) --- src/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package.json b/src/package.json index 71657cddd..1cce5ce94 100644 --- a/src/package.json +++ b/src/package.json @@ -28,7 +28,7 @@ "@angular/platform-browser": "^20.0.0", "@angular/platform-server": "^20.0.0", "rxjs": "~7.8.0", - "firebase-tools": "^14.0.0" + "firebase-tools": "^14.0.0 || ^15.0.0" }, "peerDependenciesMeta": { "firebase-tools": { "optional": true }, From 926258ebd0147de23dbe24d1db0162c20b4215cc Mon Sep 17 00:00:00 2001 From: Armando Navarro Date: Tue, 11 Aug 2026 10:21:23 -0700 Subject: [PATCH 6/7] fix(schematics): make the generated Cloud Functions manifest installable ng deploy with SSR to Cloud Functions generated a package.json that could not install and, once installable, could not run. Three defects, each hidden behind the previous one. The manifest pinned both dependencies to 0.0.0, which npm rejects with ETARGET. deploy/actions.ts statically imports ../versions.json, so esbuild inlines the placeholder values into the emitted bundle, while replaceSchematicVersions only rewrote the copied dist versions.json that the v20 runtime never reads. The build now rewrites the placeholders in the emitted bundles as well, using a distinctive per-package token. A blind replace of "0.0.0" was not an option: it appears eleven more times per bundle as sentinels inside the bundled semver library. firebase-admin joins the root package.json so the existing resolution finds a version for it. It is not a phantom dependency, as an earlier analysis of this bug claimed. firebase-functions declares it a required, non-optional peer and loads it eagerly, so omitting it produces a function that installs cleanly and then throws "Cannot find module 'firebase-admin/app-check'" on its first request. The firebase-functions floor moves to ^6.1.1 because 6.0.0 through 6.1.0 declare a peer range that excludes firebase-admin 13, which would ERESOLVE. DEFAULT_NODE_VERSION moves from 14 to 22. Cloud Functions decommissioned nodejs14 in early 2025, so the deploy failed at the runtime check even with correct dependency versions. 22 is the only value that Cloud Functions still accepts, satisfies the engines of both @angular/core and firebase-admin, and is not already past end of life. The generated first-generation template now requires firebase-functions/v1 rather than the package root, where .region() stopped living as of firebase-functions 6. The old form resolved fine and threw only once the deployed function served a request. Considered and rejected: porting v21's runtime read of versions.json, which changes module loading in a patch release and is the class of change that broke 21.0.0-rc.0. Also rejected was defaulting CF3v2 to true, which would fix the first-generation crash by moving every user to 2nd gen, a swap Google refuses in place for an existing function of the same name. Verified against a real Angular 20.3.27 application: published 20.0.1 fails with ERESOLVE and this build installs cleanly. The generated manifest installs and both templates load, including under --legacy-peer-deps. Both new build checks were mutation-tested. Also raises the version to 20.0.2 and corrects a docs example that told users to select the decommissioned nodejs12 runtime. --- docs/deploy/getting-started.md | 2 +- package-lock.json | 137 ++++--------------- package.json | 5 +- src/schematics/deploy/functions-templates.ts | 9 +- src/schematics/versions.json | 4 +- tools/build.ts | 92 ++++++++++++- 6 files changed, 127 insertions(+), 122 deletions(-) diff --git a/docs/deploy/getting-started.md b/docs/deploy/getting-started.md index 5e3cf180d..1c701adc0 100644 --- a/docs/deploy/getting-started.md +++ b/docs/deploy/getting-started.md @@ -97,7 +97,7 @@ Setting `functionsNodeVersion` and `functionsRuntimeOptions` in your `angular.js "deploy": { "builder": "@angular/fire:deploy", "options": { - "functionsNodeVersion": 12, + "functionsNodeVersion": 22, "functionsRuntimeOptions": { "memory": "2GB", "timeoutSeconds": 10, diff --git a/package-lock.json b/package-lock.json index 45a587ed3..149335d97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@angular/fire", - "version": "20.0.0", + "version": "20.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@angular/fire", - "version": "20.0.0", + "version": "20.0.2", "license": "MIT", "dependencies": { "@angular-devkit/architect": "~0.2000.0", @@ -21,7 +21,8 @@ "@schematics/angular": "^20.0.0", "esbuild": "^0.24.0", "firebase": "^11.8.0", - "firebase-functions": "^6.1.0", + "firebase-admin": "^13.0.0", + "firebase-functions": "^6.1.1", "fs-extra": "^8.0.1", "fuzzy": "^0.1.3", "husky": "^4.2.5", @@ -4775,8 +4776,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.1.1.tgz", "integrity": "sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@firebase/ai": { "version": "1.3.0", @@ -5392,7 +5392,6 @@ "integrity": "sha512-ZxOdH8Wr01hBDvKCQfMWqwUcfNcN3JY19k1LtS1fTFhEyorYPLsbWN+VxIRL46pOYGHTPkU3Or5HbT/SLQM5nA==", "license": "Apache-2.0", "optional": true, - "peer": true, "dependencies": { "@opentelemetry/api": "^1.3.0", "fast-deep-equal": "^3.1.1", @@ -5410,7 +5409,6 @@ "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==", "license": "Apache-2.0", "optional": true, - "peer": true, "dependencies": { "arrify": "^2.0.0", "extend": "^3.0.2" @@ -5425,7 +5423,6 @@ "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", "license": "Apache-2.0", "optional": true, - "peer": true, "engines": { "node": ">=14.0.0" } @@ -5436,7 +5433,6 @@ "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", "license": "Apache-2.0", "optional": true, - "peer": true, "engines": { "node": ">=14" } @@ -5447,7 +5443,6 @@ "integrity": "sha512-7/5LRgykyOfQENcm6hDKP8SX/u9XxE5YOiWOkgkwcoO+cG8xT/cyOvp9wwN3IxfdYgpHs8CE7Nq2PKX2lNaEXw==", "license": "Apache-2.0", "optional": true, - "peer": true, "dependencies": { "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", @@ -5475,7 +5470,6 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "license": "MIT", "optional": true, - "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -5791,7 +5785,6 @@ "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", "license": "MIT", "optional": true, - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/js-sdsl" @@ -6658,7 +6651,6 @@ "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "license": "Apache-2.0", "optional": true, - "peer": true, "engines": { "node": ">=8.0.0" } @@ -7508,7 +7500,6 @@ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">= 10" } @@ -7562,8 +7553,7 @@ "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/@types/connect": { "version": "3.4.38", @@ -7731,7 +7721,6 @@ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.9.tgz", "integrity": "sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/ms": "*", "@types/node": "*" @@ -7759,8 +7748,7 @@ "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/@types/mime": { "version": "1.3.5", @@ -7772,8 +7760,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/node": { "version": "12.12.41", @@ -8036,8 +8023,7 @@ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/@types/triple-beam": { "version": "1.3.5", @@ -8505,7 +8491,6 @@ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "event-target-shim": "^5.0.0" }, @@ -8897,7 +8882,6 @@ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=8" } @@ -8924,7 +8908,6 @@ "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "retry": "0.13.1" } @@ -8934,8 +8917,7 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/autoprefixer": { "version": "10.4.21", @@ -9139,7 +9121,6 @@ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.0.tgz", "integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==", "license": "MIT", - "peer": true, "engines": { "node": "*" } @@ -9309,8 +9290,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/buffer-from": { "version": "1.1.2", @@ -9855,7 +9835,6 @@ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -10772,7 +10751,6 @@ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=0.4.0" } @@ -10969,7 +10947,6 @@ "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", @@ -10989,7 +10966,6 @@ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "safe-buffer": "^5.0.1" } @@ -11067,7 +11043,6 @@ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "once": "^1.4.0" } @@ -11867,7 +11842,6 @@ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=6" } @@ -11982,7 +11956,6 @@ "resolved": "https://registry.npmjs.org/farmhash-modern/-/farmhash-modern-1.1.0.tgz", "integrity": "sha512-6ypT4XfgqJk/F3Yuv4SX26I3doUjt0GTG4a+JgWxXQpxXzTBq8fPUeGHfcYMMDPHJHm3yPOSjaeBwBGAHWXCdA==", "license": "MIT", - "peer": true, "engines": { "node": ">=18.0.0" } @@ -12065,7 +12038,6 @@ ], "license": "MIT", "optional": true, - "peer": true, "dependencies": { "strnum": "^1.1.1" }, @@ -12317,7 +12289,6 @@ "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.4.0.tgz", "integrity": "sha512-Y8DcyKK+4pl4B93ooiy1G8qvdyRMkcNFfBSh+8rbVcw4cW8dgG0VXCCTp5NUwub8sn9vSPsOwpb9tE2OuFmcfQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@fastify/busboy": "^3.0.0", "@firebase/database-compat": "^2.0.0", @@ -12343,7 +12314,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.24.tgz", "integrity": "sha512-w9CZGm9RDjzTh/D+hFwlBJ3ziUaVw7oufKA3vOFSOZlzmW9AkZnfjPb+DLnrV6qtgL/LNmP0/2zBNCFHL3F0ng==", "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -12467,7 +12437,6 @@ "integrity": "sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -12595,8 +12564,7 @@ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/functions-have-names": { "version": "1.2.3", @@ -12621,7 +12589,6 @@ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", @@ -12642,7 +12609,6 @@ "https://github.com/sponsors/ctavan" ], "license": "MIT", - "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -12652,7 +12618,6 @@ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", "license": "Apache-2.0", - "peer": true, "dependencies": { "gaxios": "^6.1.1", "google-logging-utils": "^0.0.2", @@ -13086,7 +13051,6 @@ "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz", "integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==", "license": "Apache-2.0", - "peer": true, "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", @@ -13105,7 +13069,6 @@ "integrity": "sha512-V6eky/xz2mcKfAd1Ioxyd6nmA61gao3n01C+YeuIwu3vzM9EDR6wcVzMSIbLMDXWeoi9SHYctXuKYC5uJUT3eQ==", "license": "Apache-2.0", "optional": true, - "peer": true, "dependencies": { "@grpc/grpc-js": "^1.10.9", "@grpc/proto-loader": "^0.7.13", @@ -13130,7 +13093,6 @@ "integrity": "sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg==", "license": "Apache-2.0", "optional": true, - "peer": true, "dependencies": { "@grpc/proto-loader": "^0.7.13", "@js-sdsl/ordered-map": "^4.4.2" @@ -13149,7 +13111,6 @@ ], "license": "MIT", "optional": true, - "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -13159,7 +13120,6 @@ "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=14" } @@ -13194,7 +13154,6 @@ "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", "license": "MIT", - "peer": true, "dependencies": { "gaxios": "^6.0.0", "jws": "^4.0.0" @@ -13424,8 +13383,7 @@ } ], "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/html-escaper": { "version": "2.0.2", @@ -14746,7 +14704,6 @@ "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/panva" } @@ -14795,7 +14752,6 @@ "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", "license": "MIT", - "peer": true, "dependencies": { "bignumber.js": "^9.0.0" } @@ -14904,7 +14860,6 @@ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "license": "MIT", - "peer": true, "dependencies": { "jws": "^3.2.2", "lodash.includes": "^4.3.0", @@ -14927,7 +14882,6 @@ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", "license": "MIT", - "peer": true, "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", @@ -14939,7 +14893,6 @@ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", "license": "MIT", - "peer": true, "dependencies": { "jwa": "^1.4.1", "safe-buffer": "^5.0.1" @@ -14950,7 +14903,6 @@ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", "license": "MIT", - "peer": true, "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", @@ -14962,7 +14914,6 @@ "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.2.0.tgz", "integrity": "sha512-PwchfHcQK/5PSydeKCs1ylNym0w/SSv8a62DgHJ//7x2ZclCoinlsjAfDxAAbpoTPybOum/Jgy+vkvMmKz89Ww==", "license": "MIT", - "peer": true, "dependencies": { "@types/express": "^4.17.20", "@types/jsonwebtoken": "^9.0.4", @@ -14980,7 +14931,6 @@ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", "license": "MIT", - "peer": true, "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" @@ -15578,8 +15528,7 @@ "node_modules/limiter": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", - "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==", - "peer": true + "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" }, "node_modules/lines-and-columns": { "version": "1.2.4", @@ -15821,8 +15770,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.debounce": { "version": "4.0.8", @@ -15835,43 +15783,37 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.isnumber": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -15884,8 +15826,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.template": { "version": "4.5.0", @@ -16213,7 +16154,6 @@ "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.3.0.tgz", "integrity": "sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==", "license": "MIT", - "peer": true, "dependencies": { "lodash.clonedeep": "^4.5.0", "lru-cache": "6.0.0" @@ -16224,7 +16164,6 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "license": "ISC", - "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -16236,8 +16175,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/magic-string": { "version": "0.30.17", @@ -16589,7 +16527,6 @@ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", "license": "MIT", "optional": true, - "peer": true, "bin": { "mime": "cli.js" }, @@ -17763,7 +17700,6 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "license": "MIT", - "peer": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -18145,7 +18081,6 @@ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">= 6" } @@ -19056,7 +18991,6 @@ "integrity": "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==", "license": "Apache-2.0", "optional": true, - "peer": true, "dependencies": { "protobufjs": "^7.2.5" }, @@ -19840,7 +19774,6 @@ "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@types/request": "^2.48.8", "extend": "^3.0.2", @@ -19856,7 +19789,6 @@ "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@types/caseless": "*", "@types/node": "*", @@ -21217,7 +21149,6 @@ "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "stubs": "^3.0.0" } @@ -21227,8 +21158,7 @@ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/streamroller": { "version": "3.1.5", @@ -21435,16 +21365,14 @@ } ], "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/supports-color": { "version": "7.2.0", @@ -21588,7 +21516,6 @@ "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", "license": "Apache-2.0", "optional": true, - "peer": true, "dependencies": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", @@ -21606,7 +21533,6 @@ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "debug": "4" }, @@ -21620,7 +21546,6 @@ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -21636,7 +21561,6 @@ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", "optional": true, - "peer": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -21655,7 +21579,6 @@ ], "license": "MIT", "optional": true, - "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -21891,8 +21814,7 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tree-dump": { "version": "1.0.3", @@ -22647,7 +22569,6 @@ "https://github.com/sponsors/ctavan" ], "license": "MIT", - "peer": true, "bin": { "uuid": "dist/esm/bin/uuid" } @@ -22743,8 +22664,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause", - "peer": true + "license": "BSD-2-Clause" }, "node_modules/webpack": { "version": "5.99.8", @@ -23170,7 +23090,6 @@ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "license": "MIT", - "peer": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" diff --git a/package.json b/package.json index dbfd2b852..b57ae332f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@angular/fire", - "version": "20.0.0", + "version": "20.0.2", "description": "Angular + Firebase = ❤️", "private": true, "scripts": { @@ -58,7 +58,8 @@ "@schematics/angular": "^20.0.0", "esbuild": "^0.24.0", "firebase": "^11.8.0", - "firebase-functions": "^6.1.0", + "firebase-admin": "^13.0.0", + "firebase-functions": "^6.1.1", "fs-extra": "^8.0.1", "fuzzy": "^0.1.3", "husky": "^4.2.5", diff --git a/src/schematics/deploy/functions-templates.ts b/src/schematics/deploy/functions-templates.ts index 13cd9ab14..772491049 100644 --- a/src/schematics/deploy/functions-templates.ts +++ b/src/schematics/deploy/functions-templates.ts @@ -1,6 +1,9 @@ import { DeployBuilderOptions } from './actions'; -export const DEFAULT_NODE_VERSION = 14; +// Must be a runtime Cloud Functions still accepts, and must satisfy the engines of @angular/core +// (the function runs the Angular server) and of firebase-admin. The `dockerfile` template below +// also drops it into `FROM node:-slim`, so it picks the base image on the Cloud Run path. +export const DEFAULT_NODE_VERSION = 22; export const DEFAULT_FUNCTION_NAME = 'ssr'; const DEFAULT_FUNCTION_REGION = 'us-central1'; @@ -34,7 +37,9 @@ export const defaultFunction = ( path: string, options: DeployBuilderOptions, functionName: string|undefined, -) => `const functions = require('firebase-functions'); +// `.region()` lives on the /v1 subpath since firebase-functions 6. Requiring the package root +// instead still resolves, and fails only when the deployed function serves its first request. +) => `const functions = require('firebase-functions/v1'); // Increase readability in Cloud Logging require("firebase-functions/logger/compat"); diff --git a/src/schematics/versions.json b/src/schematics/versions.json index 9477d49a4..176a5b8ea 100644 --- a/src/schematics/versions.json +++ b/src/schematics/versions.json @@ -2,7 +2,7 @@ "peerDependencies": { }, "firebaseFunctionsDependencies": { - "firebase-admin": { "dev": false, "version": "0.0.0" }, - "firebase-functions": { "dev": false, "version": "0.0.0" } + "firebase-admin": { "dev": false, "version": "FIREBASE_ADMIN_VERSION" }, + "firebase-functions": { "dev": false, "version": "FIREBASE_FUNCTIONS_VERSION" } } } diff --git a/tools/build.ts b/tools/build.ts index c947ad765..1082ca24c 100644 --- a/tools/build.ts +++ b/tools/build.ts @@ -1,6 +1,7 @@ import { spawn } from 'cross-spawn'; +import { readFileSync, readdirSync } from 'fs'; import { copy, writeFile } from 'fs-extra'; -import { join } from 'path'; +import { join, sep } from 'path'; import { keys as tsKeys } from 'ts-transformer-keys'; import * as esbuild from "esbuild"; @@ -274,16 +275,95 @@ async function replacePackageCoreVersion() { }); } +/** The placeholder a package's version is written as in src/schematics/versions.json, e.g. + * firebase-admin becomes FIREBASE_ADMIN_VERSION. That file is hand-written, so a placeholder + * spelled any other way is not a compile error: it only fails the build in the checks below. */ +const versionPlaceholder = (name: string) => `${name.toUpperCase().replace(/[^A-Z0-9]+/g, '_')}_VERSION`; + +/** Every compiled schematic bundle, as a glob for replace-in-file. */ +const compiledSchematicsGlob = () => `${dest('schematics').split(sep).join('/')}/**/*.js`; + +/** Every compiled schematic bundle, as absolute paths. */ +const compiledSchematicFiles = (directory: string): string[] => + readdirSync(directory, { withFileTypes: true }).flatMap(entry => { + const entryPath = join(directory, entry.name); + if (entry.isDirectory()) { return compiledSchematicFiles(entryPath); } + return entryPath.endsWith('.js') ? [entryPath] : []; + }); + +/** The schematics ship as esbuild bundles, so `import { firebaseFunctionsDependencies } from + * '../versions.json'` is inlined at compile time and the copied versions.json is never read at + * runtime. Rewriting only that copy leaves the placeholder baked into the emitted JavaScript. */ +async function writeSchematicVersionsIntoBundles(versions: Record) { + // eslint-disable-next-line @typescript-eslint/no-require-imports + const replace = require('replace-in-file'); + for (const [name, version] of Object.entries(versions)) { + if (!version) { + throw new Error(`No version resolved for ${name}, so the generated Cloud Functions manifest would not install. Add it to the root package.json.`); + } + const placeholder = versionPlaceholder(name); + const replacements = await replace({ + // Glob patterns need forward slashes even on Windows. + files: compiledSchematicsGlob(), + // (?![A-Z0-9_]) stops FIREBASE_ADMIN_VERSION from also matching the start of a misspelled + // FIREBASE_ADMIN_VERSIONS, which would replace part of it and leave "^13.0.0S" behind. + from: new RegExp(`${placeholder}(?![A-Z0-9_])`, 'g'), + to: version, + // When the glob matches no files at all, return an empty result instead of rejecting, so the + // failure comes out of the check below with a message that says where we looked. + allowEmptyPaths: true, + }); + if (!replacements.some(replacement => replacement.hasChanged)) { + throw new Error(`No ${placeholder} placeholder found in the compiled schematics. Check that src/schematics/versions.json spells it exactly that way, and that the build is reading ${compiledSchematicsGlob()}.`); + } + } +} + +/** A compiled bundle that still contains one or more of our placeholders. */ +interface BundleWithPlaceholders { + file: string; + placeholders: string[]; +} + +/** Fails the build if any of our version placeholders is still present in a compiled bundle. + * Checks only the placeholders named in `packageNames`, because a blanket search for anything + * ending in _VERSION also hits SEMVER_SPEC_VERSION and TERM_PROGRAM_VERSION from bundled + * libraries, which are not ours and are supposed to be there. */ +function assertNoVersionPlaceholdersRemain(packageNames: string[]) { + const files = compiledSchematicFiles(dest('schematics')); + if (files.length === 0) { + throw new Error(`No compiled schematics found under ${dest('schematics')}, so no version placeholder could have been replaced.`); + } + const ourPlaceholders = packageNames.map(versionPlaceholder); + const bundlesWithPlaceholders: BundleWithPlaceholders[] = files + .map(file => { + const contents = readFileSync(file, 'utf8'); + return { file, placeholders: ourPlaceholders.filter(placeholder => contents.includes(placeholder)) }; + }) + .filter(bundle => bundle.placeholders.length > 0); + if (bundlesWithPlaceholders.length > 0) { + const offendingBundles = bundlesWithPlaceholders + .map(bundle => ` ${bundle.file}: ${bundle.placeholders.join(', ')}`) + .join('\n'); + throw new Error(`Unreplaced version placeholders in the compiled schematics:\n${offendingBundles}\nThe generated manifests would ship a placeholder instead of a version.`); + } +} + +/** Resolves the versions src/schematics/versions.json asks for from the root package.json, then + * writes them both into the copied versions.json and into the compiled bundles that inlined them. */ async function replaceSchematicVersions() { const root = await rootPackage; const packagesPath = dest('schematics', 'versions.json'); const dependencies = await import(packagesPath); - Object.keys(dependencies.peerDependencies).forEach(name => { - dependencies.peerDependencies[name].version = root.dependencies[name] || root.devDependencies[name]; - }); - Object.keys(dependencies.firebaseFunctionsDependencies).forEach(name => { - dependencies.firebaseFunctionsDependencies[name].version = root.dependencies[name] || root.devDependencies[name]; + const resolved: Record = {}; + [dependencies.peerDependencies, dependencies.firebaseFunctionsDependencies].forEach(block => { + Object.keys(block).forEach(name => { + block[name].version = root.dependencies[name] || root.devDependencies[name]; + resolved[name] = block[name].version; + }); }); + await writeSchematicVersionsIntoBundles(resolved); + assertNoVersionPlaceholdersRemain(Object.keys(resolved)); return writeFile(packagesPath, JSON.stringify(dependencies, null, 2)); } From f0853d148dc553ba623bff9381176356c179f214 Mon Sep 17 00:00:00 2001 From: Maxim Wilman Date: Mon, 12 Jan 2026 20:53:53 +0100 Subject: [PATCH 7/7] Upgrade Java version from 11 to 21 in workflow (cherry picked from commit 7576b5fb5c3baf58bceb6b190653437403e0d747) --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ebb9d9b3e..6786c6311 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -115,7 +115,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '11' + java-version: '21' - name: node_modules cache id: node_modules_cache uses: actions/cache@v3 @@ -183,7 +183,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '11' + java-version: '21' - name: Test headless run: npm run test:chrome-headless # Tests are flaky on Windows