From 072d3eada22686e5ce2fa0ab6e93c5ed79184986 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jul 2026 20:50:47 +0000 Subject: [PATCH 01/30] chore(deps): bump the version-minor-and-patch group across 1 directory with 12 updates Bumps the version-minor-and-patch group with 12 updates in the / directory: | Package | From | To | | --- | --- | --- | | [ts-jest](https://github.com/kulshekhar/ts-jest) | `29.4.9` | `29.4.11` | | [@genkit-ai/google-genai](https://github.com/genkit-ai/genkit/tree/HEAD/js/plugins/google-genai) | `1.37.0` | `1.39.0` | | [@types/express-serve-static-core](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/express-serve-static-core) | `4.19.8` | `4.19.9` | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `20.19.39` | `20.19.43` | | [genkit](https://github.com/genkit-ai/genkit/tree/HEAD/js/genkit) | `1.33.0` | `1.39.0` | | [js-yaml](https://github.com/nodeca/js-yaml) | `3.14.2` | `3.15.0` | | [nodemailer](https://github.com/nodemailer/nodemailer) | `9.0.1` | `9.0.3` | | [smtp-server](https://github.com/nodemailer/smtp-server) | `3.19.1` | `3.19.2` | | [@types/node-fetch](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node-fetch) | `2.6.4` | `2.6.13` | | [@genkit-ai/vertexai](https://github.com/genkit-ai/genkit/tree/HEAD/js/plugins/vertexai) | `1.37.0` | `1.39.0` | | [sharp](https://github.com/lovell/sharp) | `0.34.5` | `0.35.3` | | [nanoid](https://github.com/ai/nanoid) | `5.1.9` | `5.1.16` | Updates `ts-jest` from 29.4.9 to 29.4.11 - [Release notes](https://github.com/kulshekhar/ts-jest/releases) - [Changelog](https://github.com/kulshekhar/ts-jest/blob/main/CHANGELOG.md) - [Commits](https://github.com/kulshekhar/ts-jest/compare/v29.4.9...v29.4.11) Updates `@genkit-ai/google-genai` from 1.37.0 to 1.39.0 - [Release notes](https://github.com/genkit-ai/genkit/releases) - [Commits](https://github.com/genkit-ai/genkit/commits/@genkit-ai/google-genai@1.39.0/js/plugins/google-genai) Updates `@types/express-serve-static-core` from 4.19.8 to 4.19.9 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/express-serve-static-core) Updates `@types/node` from 20.19.39 to 20.19.43 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `genkit` from 1.33.0 to 1.39.0 - [Release notes](https://github.com/genkit-ai/genkit/releases) - [Commits](https://github.com/genkit-ai/genkit/commits/genkit@1.39.0/js/genkit) Updates `js-yaml` from 3.14.2 to 3.15.0 - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/3.14.2...3.15.0) Updates `nodemailer` from 9.0.1 to 9.0.3 - [Release notes](https://github.com/nodemailer/nodemailer/releases) - [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodemailer/nodemailer/compare/v9.0.1...v9.0.3) Updates `smtp-server` from 3.19.1 to 3.19.2 - [Release notes](https://github.com/nodemailer/smtp-server/releases) - [Changelog](https://github.com/nodemailer/smtp-server/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodemailer/smtp-server/compare/v3.19.1...v3.19.2) Updates `@types/node-fetch` from 2.6.4 to 2.6.13 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node-fetch) Updates `@genkit-ai/vertexai` from 1.37.0 to 1.39.0 - [Release notes](https://github.com/genkit-ai/genkit/releases) - [Commits](https://github.com/genkit-ai/genkit/commits/@genkit-ai/vertexai@1.39.0/js/plugins/vertexai) Updates `sharp` from 0.34.5 to 0.35.3 - [Release notes](https://github.com/lovell/sharp/releases) - [Commits](https://github.com/lovell/sharp/compare/v0.34.5...v0.35.3) Updates `nanoid` from 5.1.9 to 5.1.16 - [Release notes](https://github.com/ai/nanoid/releases) - [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md) - [Commits](https://github.com/ai/nanoid/compare/5.1.9...5.1.16) --- updated-dependencies: - dependency-name: ts-jest dependency-version: 29.4.11 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-minor-and-patch - dependency-name: "@genkit-ai/google-genai" dependency-version: 1.39.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-minor-and-patch - dependency-name: "@types/express-serve-static-core" dependency-version: 4.19.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-minor-and-patch - dependency-name: "@types/node" dependency-version: 20.19.43 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-minor-and-patch - dependency-name: genkit dependency-version: 1.39.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-minor-and-patch - dependency-name: js-yaml dependency-version: 3.15.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: version-minor-and-patch - dependency-name: nodemailer dependency-version: 9.0.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-minor-and-patch - dependency-name: smtp-server dependency-version: 3.19.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: version-minor-and-patch - dependency-name: "@types/node-fetch" dependency-version: 2.6.13 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-minor-and-patch - dependency-name: "@genkit-ai/vertexai" dependency-version: 1.39.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-minor-and-patch - dependency-name: sharp dependency-version: 0.35.3 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: version-minor-and-patch - dependency-name: nanoid dependency-version: 5.1.16 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: version-minor-and-patch ... Signed-off-by: dependabot[bot] --- delete-user-data/functions/package-lock.json | 104 ++- delete-user-data/functions/package.json | 6 +- .../package-lock.json | 44 +- .../package.json | 4 +- .../functions/package-lock.json | 62 +- .../functions/package.json | 6 +- .../scripts/gen-schema-view/package-lock.json | 683 +++++++------- .../scripts/gen-schema-view/package.json | 4 +- .../scripts/import/package-lock.json | 22 +- .../scripts/import/package.json | 2 +- firestore-counter/functions/package-lock.json | 360 +------- firestore-counter/functions/package.json | 4 +- .../functions/package-lock.json | 44 +- firestore-send-email/functions/package.json | 4 +- .../functions/package-lock.json | 45 +- .../functions/package.json | 4 +- .../functions/package-lock.json | 517 +++++++---- .../functions/package.json | 4 +- package-lock.json | 16 +- package.json | 2 +- .../functions/package-lock.json | 26 +- rtdb-limit-child-nodes/functions/package.json | 2 +- .../functions/package-lock.json | 837 ++++++++++++------ storage-resize-images/functions/package.json | 2 +- 24 files changed, 1439 insertions(+), 1365 deletions(-) diff --git a/delete-user-data/functions/package-lock.json b/delete-user-data/functions/package-lock.json index f8730e43e2..f87735aaa4 100644 --- a/delete-user-data/functions/package-lock.json +++ b/delete-user-data/functions/package-lock.json @@ -8,15 +8,15 @@ "license": "Apache-2.0", "dependencies": { "@google-cloud/pubsub": "^4.3.3", - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "@types/jest": "29.5.0", - "@types/node": "^22.0.0", + "@types/node": "^20.19.43", "concurrently": "^7.2.1", "firebase-admin": "^12.1.0", "firebase-functions": "^4.9.0", "jest": "29.7.0", "lodash.chunk": "^4.2.0", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "typescript": "^4.9.4" }, "devDependencies": { @@ -1281,9 +1281,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -1373,22 +1373,23 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", - "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } }, "node_modules/@types/node-fetch": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", - "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", - "form-data": "^3.0.0" + "form-data": "^4.0.4" } }, "node_modules/@types/qs": { @@ -2743,6 +2744,15 @@ "@google-cloud/storage": "^7.7.0" } }, + "node_modules/firebase-admin/node_modules/@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, "node_modules/firebase-admin/node_modules/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", @@ -2798,9 +2808,9 @@ } }, "node_modules/form-data": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.5.tgz", - "integrity": "sha512-j23EibVLnp4zNXGW7LjryXYa2X6U/M96yoOX+ybZxwkYajdxRNEqYY3zhh7y0i6kfISKS2jr+EJq1YTUDEv5+w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5611,9 +5621,9 @@ "license": "ISC" }, "node_modules/ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "license": "MIT", "dependencies": { "bs-logger": "^0.2.6", @@ -5622,7 +5632,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, @@ -5663,9 +5673,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -7013,9 +7023,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "requires": { "@types/node": "*", "@types/qs": "*", @@ -7101,21 +7111,21 @@ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" }, "@types/node": { - "version": "22.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", - "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "requires": { "undici-types": "~6.21.0" } }, "@types/node-fetch": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", - "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", "dev": true, "requires": { "@types/node": "*", - "form-data": "^3.0.0" + "form-data": "^4.0.4" } }, "@types/qs": { @@ -8082,6 +8092,14 @@ "uuid": "^10.0.0" }, "dependencies": { + "@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "requires": { + "undici-types": "~6.21.0" + } + }, "uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", @@ -8113,9 +8131,9 @@ } }, "form-data": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.5.tgz", - "integrity": "sha512-j23EibVLnp4zNXGW7LjryXYa2X6U/M96yoOX+ybZxwkYajdxRNEqYY3zhh7y0i6kfISKS2jr+EJq1YTUDEv5+w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -10101,9 +10119,9 @@ "dev": true }, "ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "requires": { "bs-logger": "^0.2.6", "fast-json-stable-stringify": "^2.1.0", @@ -10111,15 +10129,15 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, "dependencies": { "semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==" + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==" }, "type-fest": { "version": "4.41.0", diff --git a/delete-user-data/functions/package.json b/delete-user-data/functions/package.json index 3b5f73447b..188ff4eac9 100644 --- a/delete-user-data/functions/package.json +++ b/delete-user-data/functions/package.json @@ -19,8 +19,8 @@ "license": "Apache-2.0", "dependencies": { "@google-cloud/pubsub": "^4.3.3", - "@types/express-serve-static-core": "4.19.8", - "@types/node": "^22.0.0", + "@types/express-serve-static-core": "4.19.9", + "@types/node": "^20.19.43", "concurrently": "^7.2.1", "firebase-admin": "^12.1.0", "firebase-functions": "^4.9.0", @@ -28,7 +28,7 @@ "typescript": "^4.9.4", "@types/jest": "29.5.0", "jest": "29.7.0", - "ts-jest": "29.4.9" + "ts-jest": "29.4.11" }, "engines": { "node": "22" diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json b/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json index 7fbde7fdb9..3b3d9d7ad0 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json @@ -19,7 +19,7 @@ "devDependencies": { "@types/chai": "^4.1.6", "@types/jest": "^29.5.14", - "@types/node": "^22.0.0", + "@types/node": "^20.19.43", "@types/traverse": "^0.6.32", "chai": "^4.2.0", "jest": "29.7.0", @@ -28,7 +28,7 @@ "jest-summarizing-reporter": "^1.1.4", "mocked-env": "^1.3.2", "nyc": "^17.1.0", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "typescript": "^4.9.4", "wait-for-expect": "^3.0.2" } @@ -1464,9 +1464,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", - "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -6754,9 +6754,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -7411,9 +7411,9 @@ } }, "node_modules/ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "dev": true, "license": "MIT", "dependencies": { @@ -7423,7 +7423,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, @@ -9140,9 +9140,9 @@ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" }, "@types/node": { - "version": "22.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", - "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "requires": { "undici-types": "~6.21.0" } @@ -12859,9 +12859,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==" + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==" }, "send": { "version": "0.19.0", @@ -13337,9 +13337,9 @@ } }, "ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "dev": true, "requires": { "bs-logger": "^0.2.6", @@ -13348,7 +13348,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json b/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json index 6061620d15..299638f27c 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json @@ -33,7 +33,7 @@ "devDependencies": { "@types/chai": "^4.1.6", "@types/jest": "^29.5.14", - "@types/node": "^22.0.0", + "@types/node": "^20.19.43", "@types/traverse": "^0.6.32", "chai": "^4.2.0", "jest": "29.7.0", @@ -42,7 +42,7 @@ "jest-summarizing-reporter": "^1.1.4", "mocked-env": "^1.3.2", "nyc": "^17.1.0", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "typescript": "^4.9.4", "wait-for-expect": "^3.0.2" } diff --git a/firestore-bigquery-export/functions/package-lock.json b/firestore-bigquery-export/functions/package-lock.json index 4dc296d4b0..6970d33013 100644 --- a/firestore-bigquery-export/functions/package-lock.json +++ b/firestore-bigquery-export/functions/package-lock.json @@ -9,7 +9,7 @@ "dependencies": { "@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4", "@google-cloud/bigquery": "^7.6.0", - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "firebase-admin": "^13.2.0", "firebase-functions": "^6.3.2", "generate-schema": "^2.6.0", @@ -20,47 +20,17 @@ "devDependencies": { "@types/chai": "^4.1.6", "@types/jest": "29.5.0", - "@types/node": "^22.0.0", + "@types/node": "^20.19.43", "chai": "^4.2.0", "faker": "^5.1.0", "firebase-functions-test": "^3.2.0", "jest": "29.7.0", "mocked-env": "^1.3.2", "nyc": "^18.0.0", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "ts-node": "^9.0.0" } }, - "../firestore-bigquery-change-tracker": { - "name": "@firebaseextensions/firestore-bigquery-change-tracker", - "version": "2.0.4", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@google-cloud/bigquery": "^7.6.0", - "@google-cloud/resource-manager": "^5.1.0", - "firebase-admin": "^13.2.0", - "firebase-functions": "^6.3.2", - "sql-formatter": "^2.3.3", - "traverse": "^0.6.6" - }, - "devDependencies": { - "@types/chai": "^4.1.6", - "@types/jest": "^29.5.14", - "@types/node": "^22.0.0", - "@types/traverse": "^0.6.32", - "chai": "^4.2.0", - "jest": "29.7.0", - "jest-config": "29.7.0", - "jest-environment-node": "29.7.0", - "jest-summarizing-reporter": "^1.1.4", - "mocked-env": "^1.3.2", - "nyc": "^17.1.0", - "ts-jest": "29.4.9", - "typescript": "^4.9.4", - "wait-for-expect": "^3.0.2" - } - }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", @@ -1512,9 +1482,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -1613,9 +1583,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", - "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -8077,9 +8047,9 @@ "license": "ISC" }, "node_modules/ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "dev": true, "license": "MIT", "dependencies": { @@ -8089,7 +8059,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, @@ -8130,9 +8100,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "license": "ISC", "bin": { diff --git a/firestore-bigquery-export/functions/package.json b/firestore-bigquery-export/functions/package.json index 4c8988e446..a006f9f1f0 100644 --- a/firestore-bigquery-export/functions/package.json +++ b/firestore-bigquery-export/functions/package.json @@ -15,7 +15,7 @@ "dependencies": { "@firebaseextensions/firestore-bigquery-change-tracker": "^2.0.4", "@google-cloud/bigquery": "^7.6.0", - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "firebase-admin": "^13.2.0", "firebase-functions": "^6.3.2", "generate-schema": "^2.6.0", @@ -27,14 +27,14 @@ "devDependencies": { "@types/chai": "^4.1.6", "@types/jest": "29.5.0", - "@types/node": "^22.0.0", + "@types/node": "^20.19.43", "chai": "^4.2.0", "faker": "^5.1.0", "firebase-functions-test": "^3.2.0", "jest": "29.7.0", "mocked-env": "^1.3.2", "nyc": "^18.0.0", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "ts-node": "^9.0.0" }, "overrides": { diff --git a/firestore-bigquery-export/scripts/gen-schema-view/package-lock.json b/firestore-bigquery-export/scripts/gen-schema-view/package-lock.json index 5fe0fd2a43..516336268c 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/package-lock.json +++ b/firestore-bigquery-export/scripts/gen-schema-view/package-lock.json @@ -28,7 +28,7 @@ "devDependencies": { "@types/chai": "^4.1.6", "@types/express": "^4.17.14", - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "@types/inquirer": "^9.0.7", "@types/jest": "29.5.0", "chai": "^4.2.0", @@ -38,7 +38,7 @@ "mocked-env": "^1.3.2", "nyc": "^17.1.0", "rimraf": "^2.6.3", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "ts-node": "^7.0.1", "typescript": "^5.0.0" } @@ -909,12 +909,12 @@ } }, "node_modules/@genkit-ai/ai": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/ai/-/ai-1.33.0.tgz", - "integrity": "sha512-d58ByMSIHy8cwKoq6CXdpIk7BMq3VIFi+5lfP4TlZiDxC+HQX1P+jTNjgGdCCjqIwhiF5qjqqX0/PbdX/YP1rg==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/ai/-/ai-1.39.0.tgz", + "integrity": "sha512-e1ZI2ib4Y8ha2Zj/rN7Uioxd16rWMhalPe3krypLw8B4G36X8KZCqj2UhucKbCZJIffU0cxEvag7BP+JVQnsyQ==", "license": "Apache-2.0", "dependencies": { - "@genkit-ai/core": "1.33.0", + "@genkit-ai/core": "1.39.0", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.11.19", "colorette": "^2.0.20", @@ -949,6 +949,7 @@ "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -959,10 +960,65 @@ } }, "node_modules/@genkit-ai/core": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/core/-/core-1.33.0.tgz", - "integrity": "sha512-0adFPBl/nsxuV+B94nyzwRkRHKkW5eCxQbv/80f0OdkcNpQS6CwamAK+kttjplHdUvq9Yu70PzRQz7Sx9tj5NQ==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/core/-/core-1.39.0.tgz", + "integrity": "sha512-MI0cpmwc4K/KPVsXFAcHviOybt3T3IsVSsN37cEcOzo7mmv+s0JSdooxlQgZn68B6e3I8BNLL3Vk1vyc6qIlCw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/api-logs": "^0.52.0", + "@opentelemetry/context-async-hooks": "~1.25.0", + "@opentelemetry/core": "~1.25.0", + "@opentelemetry/sdk-logs": "^0.52.0", + "@opentelemetry/sdk-metrics": "~1.25.0", + "@opentelemetry/sdk-node": "^0.52.0", + "@opentelemetry/sdk-trace-base": "~1.25.0", + "@types/json-schema": "^7.0.15", + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "async-mutex": "^0.5.0", + "cors": "^2.8.5", + "dotprompt": "^1.1.1", + "express": "^4.21.0", + "get-port": "^5.1.0", + "json-schema": "^0.4.0", + "ws": "^8.18.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.22.4" + }, + "optionalDependencies": { + "@cfworker/json-schema": "^4.1.1", + "@genkit-ai/firebase": "^1.16.1" + } + }, + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/ai": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/ai/-/ai-1.40.0.tgz", + "integrity": "sha512-uD+ZLfdCW+0gpMpWiTYGqiQitqlizDN4xPWFAnvTF9YidDhh+fzAMBtnTecp+nhCfOmLu+4PUaJ5hfvi2wy58A==", "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@genkit-ai/core": "1.40.0", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.11.19", + "colorette": "^2.0.20", + "dotprompt": "^1.1.1", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "node-fetch": "^3.3.2", + "partial-json": "^0.1.7", + "uri-templates": "^0.2.0", + "uuid": "^10.0.0" + } + }, + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/core": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/core/-/core-1.40.0.tgz", + "integrity": "sha512-ah42KLZgNO4XjCPaErKIHoF0C4dTiUqGsOHv9E/yNpQdFyUNapCybBVKVc6Pc8iURc8pi4Z2QzARIHIv467k4w==", + "license": "Apache-2.0", + "optional": true, + "peer": true, "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/api-logs": "^0.52.0", @@ -990,20 +1046,20 @@ "@genkit-ai/firebase": "^1.16.1" } }, - "node_modules/@genkit-ai/firebase": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/firebase/-/firebase-1.33.0.tgz", - "integrity": "sha512-bRI6GdyEeZ8koCZ30BxYhB9RKa77/fVnhtc5aetMI1AE63be+SCwpSYanp/9YoUgcjToaRrF7KRnGAiDehcZ9w==", + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/firebase": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/firebase/-/firebase-1.40.0.tgz", + "integrity": "sha512-R4ko8maP+U0Pu5+V7T2ftzRAgiscbo2lr0Vw6pzqvyl1OWrOTuxVt7JE+MLU7DEm3xCTOylDYsaUB1r5T9FK9w==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@genkit-ai/google-cloud": "^1.33.0" + "@genkit-ai/google-cloud": "^1.40.0" }, "peerDependencies": { "@google-cloud/firestore": "^7.11.0", "firebase": ">=11.5.0", "firebase-admin": ">=12.2", - "genkit": "^1.14.1" + "genkit": "^1.40.0" }, "peerDependenciesMeta": { "firebase": { @@ -1011,13 +1067,14 @@ } } }, - "node_modules/@genkit-ai/google-cloud": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/google-cloud/-/google-cloud-1.33.0.tgz", - "integrity": "sha512-dj62UjoY7JpS1lm1GcjxV4/h/BnyL/zEswvvHWqVOY2rRuoCws3aNvJGPoxz67cOH9kDkkLN1BaGz9NbBGhTZg==", + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/google-cloud": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/google-cloud/-/google-cloud-1.40.0.tgz", + "integrity": "sha512-CqHOKNBUUDrAz9rb7waSsUqzn27x1WHMVkgatl+cQ6fGFY68IMxm9yA8R8+P91kN768vbF1oXnaa3dy1vnFDng==", "license": "Apache-2.0", "optional": true, "dependencies": { + "@google-cloud/firestore": "^7.11.0", "@google-cloud/logging-winston": "^6.0.0", "@google-cloud/modelarmor": "^0.4.1", "@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.19.0", @@ -1038,10 +1095,10 @@ "winston": "^3.12.0" }, "peerDependencies": { - "genkit": "^1.14.1" + "genkit": "^1.40.0" } }, - "node_modules/@genkit-ai/google-cloud/node_modules/agent-base": { + "node_modules/@genkit-ai/core/node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", @@ -1051,7 +1108,7 @@ "node": ">= 14" } }, - "node_modules/@genkit-ai/google-cloud/node_modules/debug": { + "node_modules/@genkit-ai/core/node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", @@ -1069,7 +1126,7 @@ } } }, - "node_modules/@genkit-ai/google-cloud/node_modules/gaxios": { + "node_modules/@genkit-ai/core/node_modules/gaxios": { "version": "6.7.1", "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", @@ -1086,7 +1143,7 @@ "node": ">=14" } }, - "node_modules/@genkit-ai/google-cloud/node_modules/gaxios/node_modules/node-fetch": { + "node_modules/@genkit-ai/core/node_modules/gaxios/node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", @@ -1107,7 +1164,22 @@ } } }, - "node_modules/@genkit-ai/google-cloud/node_modules/gcp-metadata": { + "node_modules/@genkit-ai/core/node_modules/gaxios/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@genkit-ai/core/node_modules/gcp-metadata": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", @@ -1122,7 +1194,20 @@ "node": ">=14" } }, - "node_modules/@genkit-ai/google-cloud/node_modules/google-auth-library": { + "node_modules/@genkit-ai/core/node_modules/genkit": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/genkit/-/genkit-1.40.0.tgz", + "integrity": "sha512-OB0duJgIWtAv2Exp1FTc4uh0ZIYg5AUCtQATagU0fXbaEZeSVsn9c2geNR0Btr0tAHVUabpZp19QlSmy9Gpc7Q==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@genkit-ai/ai": "1.40.0", + "@genkit-ai/core": "1.40.0", + "uuid": "^10.0.0" + } + }, + "node_modules/@genkit-ai/core/node_modules/google-auth-library": { "version": "9.15.1", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz", "integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==", @@ -1140,7 +1225,7 @@ "node": ">=14" } }, - "node_modules/@genkit-ai/google-cloud/node_modules/https-proxy-agent": { + "node_modules/@genkit-ai/core/node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", @@ -1154,14 +1239,14 @@ "node": ">= 14" } }, - "node_modules/@genkit-ai/google-cloud/node_modules/ms": { + "node_modules/@genkit-ai/core/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT", "optional": true }, - "node_modules/@genkit-ai/google-cloud/node_modules/node-fetch": { + "node_modules/@genkit-ai/core/node_modules/node-fetch": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", @@ -1180,16 +1265,18 @@ "url": "https://opencollective.com/node-fetch" } }, - "node_modules/@genkit-ai/google-cloud/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "node_modules/@genkit-ai/core/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "optional": true, + "peer": true, "bin": { "uuid": "dist/bin/uuid" } @@ -1421,186 +1508,52 @@ } }, "node_modules/@google-cloud/logging": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-11.2.1.tgz", - "integrity": "sha512-2h9HBJG3OAsvzXmb81qXmaTPfXYU7KJTQUxunoOKFGnY293YQ/eCkW1Y5mHLocwpEqeqQYT/Qvl6Tk+Q7PfStw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-11.3.0.tgz", + "integrity": "sha512-8Y2lFRpPz6rZUQ+J//+toAZ7H0ZT/5KagS0NMhXWdT+sN3pPtNzgm+N0NJ46cf9XX3etj4yfE7HrjX3wMRLBZw==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@google-cloud/common": "^5.0.0", + "@google-cloud/common": "^6.0.0", "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", "@google-cloud/promisify": "4.0.0", + "@grpc/grpc-js": "^1.14.3", "@opentelemetry/api": "^1.7.0", "arrify": "^2.0.1", "dot-prop": "^6.0.0", - "eventid": "^2.0.0", "extend": "^3.0.2", "gcp-metadata": "^6.0.0", - "google-auth-library": "^9.0.0", + "google-auth-library": "^10.6.2", "google-gax": "^4.0.3", + "long": "^5.3.2", "on-finished": "^2.3.0", "pumpify": "^2.0.1", - "stream-events": "^1.0.5", - "uuid": "^9.0.0" + "stream-events": "^1.0.5" }, "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, "node_modules/@google-cloud/logging-winston": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@google-cloud/logging-winston/-/logging-winston-6.0.1.tgz", - "integrity": "sha512-tgA/qe/aGZITMrJ/5Tuykv234pLb/Qo6iDZ8SDkjbsiIy69mLQmbphrUd/IqnE17BSDfrwDUckvWdghiy8b+Qg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/logging-winston/-/logging-winston-6.0.2.tgz", + "integrity": "sha512-rrNs4XXLtk0BAnL6kTjfAH26a/zVGsuZHd6Vve3Ip1fT4/Irz2QJtqI0XiPbT/yfmKqFmYa44GWPXtPPAi56ug==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@google-cloud/logging": "^11.0.0", - "google-auth-library": "^9.0.0", + "@google-cloud/logging": "^11.2.1", + "google-auth-library": "^10.5.0", "lodash.mapvalues": "^4.6.0", - "winston-transport": "^4.3.0" + "winston-transport": "^4.9.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18" }, "peerDependencies": { "winston": ">=3.2.1" } }, - "node_modules/@google-cloud/logging-winston/node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@google-cloud/logging-winston/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "optional": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@google-cloud/logging-winston/node_modules/gaxios": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", - "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.9", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/logging-winston/node_modules/gcp-metadata": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", - "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "gaxios": "^6.1.1", - "google-logging-utils": "^0.0.2", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/logging-winston/node_modules/google-auth-library": { - "version": "9.15.1", - "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", - "optional": true, - "dependencies": { - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "gaxios": "^6.1.1", - "gcp-metadata": "^6.1.0", - "gtoken": "^7.0.0", - "jws": "^4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/logging-winston/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "license": "MIT", - "optional": true, - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@google-cloud/logging-winston/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT", - "optional": true - }, - "node_modules/@google-cloud/logging-winston/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@google-cloud/logging/node_modules/@google-cloud/common": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-5.0.2.tgz", - "integrity": "sha512-V7bmBKYQyu0eVG2BFejuUjlBt+zrya6vtsKdY+JxMM/dNntPF41vZ9+LhOshEUH01zOHEqBSvI7Dad7ZS6aUeA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@google-cloud/projectify": "^4.0.0", - "@google-cloud/promisify": "^4.0.0", - "arrify": "^2.0.1", - "duplexify": "^4.1.1", - "extend": "^3.0.2", - "google-auth-library": "^9.0.0", - "html-entities": "^2.5.2", - "retry-request": "^7.0.0", - "teeny-request": "^9.0.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@google-cloud/logging/node_modules/@google-cloud/paginator": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz", @@ -1670,20 +1623,6 @@ "node": ">=14" } }, - "node_modules/@google-cloud/logging/node_modules/gaxios/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "license": "MIT", - "optional": true, - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/@google-cloud/logging/node_modules/gcp-metadata": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", @@ -1699,22 +1638,18 @@ "node": ">=14" } }, - "node_modules/@google-cloud/logging/node_modules/google-auth-library": { - "version": "9.15.1", - "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", + "node_modules/@google-cloud/logging/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", "optional": true, "dependencies": { - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "gaxios": "^6.1.1", - "gcp-metadata": "^6.1.0", - "gtoken": "^7.0.0", - "jws": "^4.0.0" + "agent-base": "^7.1.2", + "debug": "4" }, "engines": { - "node": ">=14" + "node": ">= 14" } }, "node_modules/@google-cloud/logging/node_modules/ms": { @@ -1724,42 +1659,11 @@ "license": "MIT", "optional": true }, - "node_modules/@google-cloud/logging/node_modules/retry-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", - "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", - "license": "MIT", - "optional": true, - "dependencies": { - "@types/request": "^2.48.8", - "extend": "^3.0.2", - "teeny-request": "^9.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/logging/node_modules/teeny-request": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", - "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.9", - "stream-events": "^1.0.5", - "uuid": "^9.0.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/@google-cloud/logging/node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -1784,15 +1688,15 @@ } }, "node_modules/@google-cloud/modelarmor/node_modules/@grpc/proto-loader": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", - "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.1.tgz", + "integrity": "sha512-wtF6h+DY6M3YaDBPAmvuuA6jV8Sif9MjtOI5euKFWRgCDl5PeDpPsHR9u2l6St5ceY8AZgoNDww5+HvEsXFsGg==", "license": "Apache-2.0", "optional": true, "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", - "protobufjs": "^7.5.3", + "protobufjs": "^7.5.5", "yargs": "^17.7.2" }, "bin": { @@ -1803,9 +1707,9 @@ } }, "node_modules/@google-cloud/modelarmor/node_modules/brace-expansion": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", - "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==", "license": "MIT", "optional": true, "dependencies": { @@ -1834,23 +1738,42 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@google-cloud/modelarmor/node_modules/google-auth-library": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.5.0.tgz", + "integrity": "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.0.0", + "gcp-metadata": "^8.0.0", + "google-logging-utils": "^1.0.0", + "gtoken": "^8.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@google-cloud/modelarmor/node_modules/google-gax": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-5.0.6.tgz", - "integrity": "sha512-1kGbqVQBZPAAu4+/R1XxPQKP0ydbNYoLAr4l0ZO2bMV0kLyLW4I1gAk++qBLWt7DPORTzmWRMsCZe86gDjShJA==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-5.0.7.tgz", + "integrity": "sha512-EhiqaWWJ+9h7sCcKJTsoo6tMcjokVHhWsbSuWCnZJT4vIBP3y4mAoFLnt9SzgkVZeq24ZsFaArr06nnYYku2yA==", "license": "Apache-2.0", "optional": true, "dependencies": { "@grpc/grpc-js": "^1.12.6", "@grpc/proto-loader": "^0.8.0", "duplexify": "^4.1.3", - "google-auth-library": "^10.1.0", - "google-logging-utils": "^1.1.1", + "google-auth-library": "10.5.0", + "google-logging-utils": "1.1.3", "node-fetch": "^3.3.2", "object-hash": "^3.0.0", - "proto3-json-serializer": "^3.0.0", - "protobufjs": "^7.5.3", - "retry-request": "^8.0.0", + "proto3-json-serializer": "3.0.4", + "protobufjs": "^7.5.4", + "retry-request": "^8.0.2", "rimraf": "^5.0.1" }, "engines": { @@ -1867,6 +1790,20 @@ "node": ">=14" } }, + "node_modules/@google-cloud/modelarmor/node_modules/gtoken": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", + "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "license": "MIT", + "optional": true, + "dependencies": { + "gaxios": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@google-cloud/modelarmor/node_modules/minimatch": { "version": "9.0.9", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", @@ -2056,6 +1993,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -2191,6 +2129,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -2303,6 +2242,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -3784,15 +3724,6 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { "version": "0.52.1", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.52.1.tgz", @@ -3869,15 +3800,6 @@ "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/instrumentation": { "version": "0.52.1", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", @@ -4060,9 +3982,9 @@ } }, "node_modules/@opentelemetry/instrumentation-dns/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "optional": true, "bin": { @@ -4174,16 +4096,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/instrumentation-hapi": { "version": "0.40.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.40.0.tgz", @@ -4221,20 +4133,10 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/instrumentation-http/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "optional": true, "bin": { @@ -4633,9 +4535,9 @@ } }, "node_modules/@opentelemetry/instrumentation/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -4703,6 +4605,7 @@ "version": "0.30.16", "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.16.tgz", "integrity": "sha512-ZVQ3Z/PQ+2GQlrBfbMMMT0U7MzvYZLCPP800+ooyaBqm4hMvuQHfP028gB9/db0mwkmyEAMad9houukUVxhwcw==", + "deprecated": "The use of process spans has been removed from Messaging Semantic Conventions. It is now recommended to connect pub/sub spans via Span Links. See https://opentelemetry.io/docs/specs/semconv/messaging/messaging-spans/ for details.", "license": "Apache-2.0", "optional": true, "engines": { @@ -4799,7 +4702,7 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/resource-detector-alibaba-cloud/node_modules/@opentelemetry/semantic-conventions": { + "node_modules/@opentelemetry/resource-detector-alibaba-cloud/node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { "version": "1.28.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", @@ -4809,6 +4712,16 @@ "node": ">=14" } }, + "node_modules/@opentelemetry/resource-detector-alibaba-cloud/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-aws": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.12.0.tgz", @@ -4827,6 +4740,16 @@ "@opentelemetry/api": "^1.0.0" } }, + "node_modules/@opentelemetry/resource-detector-aws/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-azure": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.2.12.tgz", @@ -4845,6 +4768,16 @@ "@opentelemetry/api": "^1.0.0" } }, + "node_modules/@opentelemetry/resource-detector-azure/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-container": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.4.4.tgz", @@ -4879,7 +4812,7 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/resource-detector-container/node_modules/@opentelemetry/semantic-conventions": { + "node_modules/@opentelemetry/resource-detector-container/node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { "version": "1.28.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", @@ -4889,6 +4822,16 @@ "node": ">=14" } }, + "node_modules/@opentelemetry/resource-detector-container/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-gcp": { "version": "0.29.13", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.13.tgz", @@ -4908,6 +4851,16 @@ "@opentelemetry/api": "^1.0.0" } }, + "node_modules/@opentelemetry/resource-detector-gcp/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-gcp/node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -4993,6 +4946,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -5019,15 +4973,6 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/sdk-logs": { "version": "0.52.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.52.1.tgz", @@ -5089,15 +5034,6 @@ "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/sdk-trace-base": { "version": "1.25.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.25.1.tgz", @@ -5115,15 +5051,6 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/sdk-trace-node": { "version": "1.25.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.25.1.tgz", @@ -5145,9 +5072,9 @@ } }, "node_modules/@opentelemetry/sdk-trace-node/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -5157,11 +5084,10 @@ } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.40.0.tgz", - "integrity": "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==", + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", + "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", "license": "Apache-2.0", - "optional": true, "engines": { "node": ">=14" } @@ -5372,9 +5298,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -5626,9 +5552,9 @@ } }, "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -7364,19 +7290,6 @@ "node": ">=6" } }, - "node_modules/eventid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/eventid/-/eventid-2.0.1.tgz", - "integrity": "sha512-sPNTqiMokAvV048P2c9+foqVJzk49o6d4e0D/sq5jog3pw+4kBgyR0gaM1FM7Mx6Kzd9dztesh9oYz1LWWOpzw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "uuid": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/exec": { "version": "0.2.1", "dev": true, @@ -7512,9 +7425,9 @@ } }, "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", "funding": [ { "type": "github", @@ -8048,13 +7961,13 @@ } }, "node_modules/genkit": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/genkit/-/genkit-1.33.0.tgz", - "integrity": "sha512-46cS8uUE+Et/glO0zt4JxR/2RjJ2b9OCOYfIgmJKaOk9vdjLBVBIBcJPNQZ7ToGnr6TJE3ZfM6jyCRfxd7NFQA==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/genkit/-/genkit-1.39.0.tgz", + "integrity": "sha512-Qz9ef/LfAEDMzO1+Nd6l6dMYK/V4ZfWDIp79rz/1V6xDM5VuJMkoqOTCDwXAviuAnjoO2noJug2wIK81ilMhWA==", "license": "Apache-2.0", "dependencies": { - "@genkit-ai/ai": "1.33.0", - "@genkit-ai/core": "1.33.0", + "@genkit-ai/ai": "1.39.0", + "@genkit-ai/core": "1.39.0", "uuid": "^10.0.0" } }, @@ -8542,6 +8455,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -8655,6 +8569,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -11081,7 +10996,9 @@ "optional": true }, "node_modules/long": { - "version": "5.2.3", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "license": "Apache-2.0" }, "node_modules/loupe": { @@ -11914,9 +11831,9 @@ } }, "node_modules/pg-protocol": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.13.0.tgz", - "integrity": "sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.15.0.tgz", + "integrity": "sha512-cq9sECI5s0+uPUXjbz8ioyPJni6RzsRib0US67i5IoTZKw8fNeYlVE7u8F4dG7vEJJtc5wdD1K189lCCUwqWTQ==", "license": "MIT", "optional": true }, @@ -13376,9 +13293,9 @@ } }, "node_modules/ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "dev": true, "license": "MIT", "dependencies": { @@ -13388,7 +13305,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, @@ -13429,9 +13346,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "license": "ISC", "bin": { @@ -14102,9 +14019,9 @@ } }, "node_modules/ws": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", - "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "version": "8.21.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", + "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -14143,9 +14060,9 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", - "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "license": "ISC", "bin": { "yaml": "bin.mjs" diff --git a/firestore-bigquery-export/scripts/gen-schema-view/package.json b/firestore-bigquery-export/scripts/gen-schema-view/package.json index 8981dc3a7e..d9eafd1829 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/package.json +++ b/firestore-bigquery-export/scripts/gen-schema-view/package.json @@ -47,7 +47,7 @@ "devDependencies": { "@types/chai": "^4.1.6", "@types/express": "^4.17.14", - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "@types/inquirer": "^9.0.7", "@types/jest": "29.5.0", "chai": "^4.2.0", @@ -57,7 +57,7 @@ "mocked-env": "^1.3.2", "nyc": "^17.1.0", "rimraf": "^2.6.3", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "ts-node": "^7.0.1", "typescript": "^5.0.0" } diff --git a/firestore-bigquery-export/scripts/import/package-lock.json b/firestore-bigquery-export/scripts/import/package-lock.json index b1eb83b9e6..dbec45d5f8 100644 --- a/firestore-bigquery-export/scripts/import/package-lock.json +++ b/firestore-bigquery-export/scripts/import/package-lock.json @@ -31,7 +31,7 @@ "jest": "29.7.0", "nanoid": "^5.0.9", "rimraf": "^2.6.3", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "typescript": "^5.0.0" } }, @@ -6881,9 +6881,9 @@ } }, "node_modules/nanoid": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.9.tgz", - "integrity": "sha512-ZUvP7KeBLe3OZ1ypw6dI/TzYJuvHP77IM4Ry73waSQTLn8/g8rpdjfyVAh7t1/+FjBtG4lCP42MEbDxOsRpBMw==", + "version": "5.1.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.16.tgz", + "integrity": "sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ==", "dev": true, "funding": [ { @@ -8250,9 +8250,9 @@ } }, "node_modules/ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "dev": true, "license": "MIT", "dependencies": { @@ -8262,7 +8262,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, @@ -8303,9 +8303,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "license": "ISC", "bin": { diff --git a/firestore-bigquery-export/scripts/import/package.json b/firestore-bigquery-export/scripts/import/package.json index e3bc95a71a..bdafc5ef23 100644 --- a/firestore-bigquery-export/scripts/import/package.json +++ b/firestore-bigquery-export/scripts/import/package.json @@ -47,7 +47,7 @@ "jest": "29.7.0", "nanoid": "^5.0.9", "rimraf": "^2.6.3", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "typescript": "^5.0.0" } } diff --git a/firestore-counter/functions/package-lock.json b/firestore-counter/functions/package-lock.json index 386a3f18a9..fee3b49dc9 100644 --- a/firestore-counter/functions/package-lock.json +++ b/firestore-counter/functions/package-lock.json @@ -7,7 +7,7 @@ "name": "firestore-counter-functions", "license": "Apache-2.0", "dependencies": { - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "firebase-admin": "^12.1.0", "firebase-functions": "^4.9.0", "typescript": "^4.9.4" @@ -16,7 +16,7 @@ "@types/jest": "29.5.0", "jest": "29.7.0", "prettier": "1.19.1", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "wait-for-expect": "^3.0.2" } }, @@ -488,32 +488,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, "node_modules/@fastify/busboy": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.2.0.tgz", @@ -1288,38 +1262,6 @@ "node": ">= 10" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", - "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "optional": true, - "peer": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1393,9 +1335,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -1575,34 +1517,6 @@ "node": ">= 0.6" } }, - "node_modules/acorn": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", - "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.5", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", - "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", @@ -1667,14 +1581,6 @@ "node": ">= 8" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -2325,14 +2231,6 @@ } } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2424,17 +2322,6 @@ "node": ">=8" } }, - "node_modules/diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -5190,9 +5077,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -5688,9 +5575,9 @@ "optional": true }, "node_modules/ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "dev": true, "license": "MIT", "dependencies": { @@ -5700,7 +5587,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, @@ -5753,51 +5640,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -5938,14 +5780,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/v8-to-istanbul": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", @@ -6122,17 +5956,6 @@ "node": ">=12" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -6482,31 +6305,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "dependencies": { - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } - } - }, "@fastify/busboy": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.2.0.tgz", @@ -7120,38 +6918,6 @@ "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", "optional": true }, - "@tsconfig/node10": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", - "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", - "dev": true, - "optional": true, - "peer": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "optional": true, - "peer": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "optional": true, - "peer": true - }, - "@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "optional": true, - "peer": true - }, "@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -7225,9 +6991,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "requires": { "@types/node": "*", "@types/qs": "*", @@ -7395,25 +7161,6 @@ "negotiator": "0.6.3" } }, - "acorn": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", - "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", - "dev": true, - "optional": true, - "peer": true - }, - "acorn-walk": { - "version": "8.3.5", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", - "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "acorn": "^8.11.0" - } - }, "agent-base": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", @@ -7457,14 +7204,6 @@ "picomatch": "^2.0.4" } }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "optional": true, - "peer": true - }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -7922,14 +7661,6 @@ } } }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "optional": true, - "peer": true - }, "cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -7984,14 +7715,6 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, - "diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "dev": true, - "optional": true, - "peer": true - }, "diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -9991,9 +9714,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==" + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==" }, "send": { "version": "0.19.2", @@ -10354,9 +10077,9 @@ "optional": true }, "ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "dev": true, "requires": { "bs-logger": "^0.2.6", @@ -10365,7 +10088,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, @@ -10378,29 +10101,6 @@ } } }, - "ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, "tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -10475,14 +10175,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==" }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "optional": true, - "peer": true - }, "v8-to-istanbul": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", @@ -10619,14 +10311,6 @@ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "devOptional": true }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "optional": true, - "peer": true - }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/firestore-counter/functions/package.json b/firestore-counter/functions/package.json index e34f87fa9f..18654af5d1 100644 --- a/firestore-counter/functions/package.json +++ b/firestore-counter/functions/package.json @@ -8,14 +8,14 @@ "firebase-admin": "^12.1.0", "firebase-functions": "^4.9.0", "typescript": "^4.9.4", - "@types/express-serve-static-core": "4.19.8" + "@types/express-serve-static-core": "4.19.9" }, "devDependencies": { "prettier": "1.19.1", "wait-for-expect": "^3.0.2", "@types/jest": "29.5.0", "jest": "29.7.0", - "ts-jest": "29.4.9" + "ts-jest": "29.4.11" }, "scripts": { "prepare": "npm run build", diff --git a/firestore-send-email/functions/package-lock.json b/firestore-send-email/functions/package-lock.json index add8ff27b0..6b9063f9ef 100644 --- a/firestore-send-email/functions/package-lock.json +++ b/firestore-send-email/functions/package-lock.json @@ -8,7 +8,7 @@ "license": "Apache-2.0", "dependencies": { "@sendgrid/mail": "^8.1.4", - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "@types/node": "^20.10.3", "@types/nodemailer": "^8.0.0", "firebase-admin": "^13.2.0", @@ -27,7 +27,7 @@ "firebase-functions-test": "^3.2.0", "jest": "29.7.0", "mocked-env": "^1.3.2", - "ts-jest": "29.4.9" + "ts-jest": "29.4.11" } }, "node_modules/@babel/code-frame": { @@ -1419,9 +1419,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -1510,9 +1510,9 @@ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" }, "node_modules/@types/node": { - "version": "20.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", - "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -4950,9 +4950,9 @@ } }, "node_modules/nodemailer": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-9.0.1.tgz", - "integrity": "sha512-Gwv8SQewT616ZM/URn0H54b8PWo/Wum7md3EW2aWy1lO27+WZCX+Xyak3J+NlmHUjDh5ME+uesJUDRbR3Ye8Bw==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-9.0.3.tgz", + "integrity": "sha512-n+YP+NKwR5zRWa60k3GiQ6Q3B4KXCoAw40dAKeCtYn020iNN74aWK2liXIC3ZEATeGql7we3tE3t8QwhY0eskw==", "license": "MIT-0", "engines": { "node": ">=6.0.0" @@ -5745,13 +5745,13 @@ } }, "node_modules/smtp-server": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/smtp-server/-/smtp-server-3.19.1.tgz", - "integrity": "sha512-2IeTkoLkmRm9LiG3vlws3OddCgp+sDXAVEUXJeBMoW1fpBYUU5iPOxp3hLWGt/D3a+YfT/NrIdRAUjKapy4dhQ==", + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/smtp-server/-/smtp-server-3.19.2.tgz", + "integrity": "sha512-kZVHvcynQ/Nq7EscK02OjbivmdGtlmhGXYgDjZDCTu4RPyuW3OijuGcLuzXbPvGs6drdATWoVhKOIIueLhJ8rQ==", "license": "MIT-0", "dependencies": { "ipv6-normalize": "1.0.1", - "nodemailer": "9.0.1", + "nodemailer": "9.0.3", "punycode.js": "2.3.1" }, "engines": { @@ -6074,9 +6074,9 @@ "license": "ISC" }, "node_modules/ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "dev": true, "license": "MIT", "dependencies": { @@ -6086,7 +6086,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, @@ -6127,9 +6127,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "license": "ISC", "bin": { diff --git a/firestore-send-email/functions/package.json b/firestore-send-email/functions/package.json index 6123962271..58cc69d0fd 100644 --- a/firestore-send-email/functions/package.json +++ b/firestore-send-email/functions/package.json @@ -22,7 +22,7 @@ "license": "Apache-2.0", "dependencies": { "@sendgrid/mail": "^8.1.4", - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "@types/node": "^20.10.3", "@types/nodemailer": "^8.0.0", "firebase-admin": "^13.2.0", @@ -41,7 +41,7 @@ "firebase-functions-test": "^3.2.0", "jest": "29.7.0", "mocked-env": "^1.3.2", - "ts-jest": "29.4.9" + "ts-jest": "29.4.11" }, "private": true } diff --git a/firestore-shorten-urls-bitly/functions/package-lock.json b/firestore-shorten-urls-bitly/functions/package-lock.json index 5163568643..4c593fa59d 100644 --- a/firestore-shorten-urls-bitly/functions/package-lock.json +++ b/firestore-shorten-urls-bitly/functions/package-lock.json @@ -7,8 +7,8 @@ "name": "firestore-shorten-urls-bitly-functions", "license": "Apache-2.0", "dependencies": { - "@types/express-serve-static-core": "4.19.8", - "@types/node": "^22.0.0", + "@types/express-serve-static-core": "4.19.9", + "@types/node": "^20.19.43", "firebase-admin": "^12.1.0", "firebase-functions": "^4.9.0", "typescript": "^4.8.4" @@ -366,9 +366,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -406,9 +406,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", - "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -1123,6 +1123,15 @@ "@google-cloud/storage": "^7.7.0" } }, + "node_modules/firebase-admin/node_modules/@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, "node_modules/firebase-admin/node_modules/uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", @@ -2911,9 +2920,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "requires": { "@types/node": "*", "@types/qs": "*", @@ -2947,9 +2956,9 @@ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" }, "@types/node": { - "version": "22.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", - "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "requires": { "undici-types": "~6.21.0" } @@ -3476,6 +3485,14 @@ "uuid": "^10.0.0" }, "dependencies": { + "@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "requires": { + "undici-types": "~6.21.0" + } + }, "uuid": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", diff --git a/firestore-shorten-urls-bitly/functions/package.json b/firestore-shorten-urls-bitly/functions/package.json index 856cd17d2b..c7ff954118 100644 --- a/firestore-shorten-urls-bitly/functions/package.json +++ b/firestore-shorten-urls-bitly/functions/package.json @@ -13,8 +13,8 @@ "generate-readme": "firebase ext:info .. --markdown > ../README.md" }, "dependencies": { - "@types/express-serve-static-core": "4.19.8", - "@types/node": "^22.0.0", + "@types/express-serve-static-core": "4.19.9", + "@types/node": "^20.19.43", "firebase-admin": "^12.1.0", "firebase-functions": "^4.9.0", "typescript": "^4.8.4" diff --git a/firestore-translate-text/functions/package-lock.json b/firestore-translate-text/functions/package-lock.json index 0ad8db3c31..a7e5568922 100644 --- a/firestore-translate-text/functions/package-lock.json +++ b/firestore-translate-text/functions/package-lock.json @@ -10,7 +10,7 @@ "@genkit-ai/google-genai": "^1.31.0", "@google-cloud/translate": "^8.2.0", "@google-cloud/vertexai": "^1.9.2", - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "@types/node": "^20.10.3", "firebase-admin": "^12.1.0", "firebase-functions": "^4.9.0", @@ -23,7 +23,7 @@ "jest": "29.7.0", "js-yaml": "^3.13.1", "mocked-env": "^1.3.1", - "ts-jest": "29.4.9" + "ts-jest": "29.4.11" } }, "node_modules/@babel/code-frame": { @@ -713,12 +713,12 @@ } }, "node_modules/@genkit-ai/ai": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/ai/-/ai-1.37.0.tgz", - "integrity": "sha512-SQnis1/NJeaGOiFnstmCJ7iGxVj/lwsQpwCXgG+JQrspAvGEIpSHCVBkreUpw6Dy7r0mVCHKup7L1NqBJbvCZg==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/ai/-/ai-1.39.0.tgz", + "integrity": "sha512-e1ZI2ib4Y8ha2Zj/rN7Uioxd16rWMhalPe3krypLw8B4G36X8KZCqj2UhucKbCZJIffU0cxEvag7BP+JVQnsyQ==", "license": "Apache-2.0", "dependencies": { - "@genkit-ai/core": "1.37.0", + "@genkit-ai/core": "1.39.0", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.11.19", "colorette": "^2.0.20", @@ -746,9 +746,9 @@ } }, "node_modules/@genkit-ai/core": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/core/-/core-1.37.0.tgz", - "integrity": "sha512-Bq/HTwRhFoWjn4bbN0gnegsO/0dSYRUtbkWj/xwYfTycSCzVTqQJt3eNJXL6Dd5qSlGa3sWjYTsksiLqfroDzg==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/core/-/core-1.39.0.tgz", + "integrity": "sha512-MI0cpmwc4K/KPVsXFAcHviOybt3T3IsVSsN37cEcOzo7mmv+s0JSdooxlQgZn68B6e3I8BNLL3Vk1vyc6qIlCw==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.9.0", @@ -777,20 +777,75 @@ "@genkit-ai/firebase": "^1.16.1" } }, - "node_modules/@genkit-ai/firebase": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/firebase/-/firebase-1.37.0.tgz", - "integrity": "sha512-yutXazOCGqGeauiShCaPj9fjcS3nn3FUTj7/0nbHXx8mLVhddBEwBIH96MqVGz9pqt3Fl57TCROPguLOmIZaQQ==", + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/ai": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/ai/-/ai-1.40.0.tgz", + "integrity": "sha512-uD+ZLfdCW+0gpMpWiTYGqiQitqlizDN4xPWFAnvTF9YidDhh+fzAMBtnTecp+nhCfOmLu+4PUaJ5hfvi2wy58A==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { - "@genkit-ai/google-cloud": "^1.37.0" + "@genkit-ai/core": "1.40.0", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.11.19", + "colorette": "^2.0.20", + "dotprompt": "^1.1.1", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "node-fetch": "^3.3.2", + "partial-json": "^0.1.7", + "uri-templates": "^0.2.0", + "uuid": "^10.0.0" + } + }, + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/core": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/core/-/core-1.40.0.tgz", + "integrity": "sha512-ah42KLZgNO4XjCPaErKIHoF0C4dTiUqGsOHv9E/yNpQdFyUNapCybBVKVc6Pc8iURc8pi4Z2QzARIHIv467k4w==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/api-logs": "^0.52.0", + "@opentelemetry/context-async-hooks": "~1.25.0", + "@opentelemetry/core": "~1.25.0", + "@opentelemetry/sdk-logs": "^0.52.0", + "@opentelemetry/sdk-metrics": "~1.25.0", + "@opentelemetry/sdk-node": "^0.52.0", + "@opentelemetry/sdk-trace-base": "~1.25.0", + "@types/json-schema": "^7.0.15", + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "async-mutex": "^0.5.0", + "cors": "^2.8.5", + "dotprompt": "^1.1.1", + "express": "^4.21.0", + "get-port": "^5.1.0", + "json-schema": "^0.4.0", + "ws": "^8.18.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.22.4" + }, + "optionalDependencies": { + "@cfworker/json-schema": "^4.1.1", + "@genkit-ai/firebase": "^1.16.1" + } + }, + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/firebase": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/firebase/-/firebase-1.40.0.tgz", + "integrity": "sha512-R4ko8maP+U0Pu5+V7T2ftzRAgiscbo2lr0Vw6pzqvyl1OWrOTuxVt7JE+MLU7DEm3xCTOylDYsaUB1r5T9FK9w==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@genkit-ai/google-cloud": "^1.40.0" }, "peerDependencies": { "@google-cloud/firestore": "^7.11.0", "firebase": ">=11.5.0", "firebase-admin": ">=12.2", - "genkit": "^1.37.0" + "genkit": "^1.40.0" }, "peerDependenciesMeta": { "firebase": { @@ -798,13 +853,14 @@ } } }, - "node_modules/@genkit-ai/google-cloud": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/google-cloud/-/google-cloud-1.37.0.tgz", - "integrity": "sha512-THLcekr0kxzTyZksFVQ/gCIcprlQlenG7aGdGWjAokqWdtX28CU+2pmQF64m++IxOsuuqISIABjpyp0/fSPgjQ==", + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/google-cloud": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/google-cloud/-/google-cloud-1.40.0.tgz", + "integrity": "sha512-CqHOKNBUUDrAz9rb7waSsUqzn27x1WHMVkgatl+cQ6fGFY68IMxm9yA8R8+P91kN768vbF1oXnaa3dy1vnFDng==", "license": "Apache-2.0", "optional": true, "dependencies": { + "@google-cloud/firestore": "^7.11.0", "@google-cloud/logging-winston": "^6.0.0", "@google-cloud/modelarmor": "^0.4.1", "@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.19.0", @@ -825,20 +881,49 @@ "winston": "^3.12.0" }, "peerDependencies": { - "genkit": "^1.37.0" + "genkit": "^1.40.0" + } + }, + "node_modules/@genkit-ai/core/node_modules/genkit": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/genkit/-/genkit-1.40.0.tgz", + "integrity": "sha512-OB0duJgIWtAv2Exp1FTc4uh0ZIYg5AUCtQATagU0fXbaEZeSVsn9c2geNR0Btr0tAHVUabpZp19QlSmy9Gpc7Q==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@genkit-ai/ai": "1.40.0", + "@genkit-ai/core": "1.40.0", + "uuid": "^10.0.0" + } + }, + "node_modules/@genkit-ai/core/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" } }, "node_modules/@genkit-ai/google-genai": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/google-genai/-/google-genai-1.37.0.tgz", - "integrity": "sha512-T22JHU9YuZL7FxxohAYZ4YBWL2M7SKDGW0AoBEciaT59uIIGuWC8bliaAbS9zxj2cQnvEG3hKQRIBOd9wh6z+Q==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/google-genai/-/google-genai-1.39.0.tgz", + "integrity": "sha512-ZP9nA6TlBJ1ZHCmSkz56v0lrRS/Wfh6L09oHgeOIZyD/Pq76uX3W+Uly8dPAbDtNax63l64TsEYZH1HHt8rC8A==", "license": "Apache-2.0", "dependencies": { "google-auth-library": "^9.14.2", "jsonpath-plus": "^10.3.0" }, "peerDependencies": { - "genkit": "^1.37.0" + "genkit": "^1.31.0" } }, "node_modules/@google-cloud/common": { @@ -879,13 +964,13 @@ } }, "node_modules/@google-cloud/logging": { - "version": "11.2.3", - "resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-11.2.3.tgz", - "integrity": "sha512-iUIJ+3Bi6aw9whahT4JmS5Ccd1Eej2Ss9RjOSW2+qcVaWcleepJtFUBuyU2CpewtniVibBUV/731MQw9SWxQ3Q==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-11.3.0.tgz", + "integrity": "sha512-8Y2lFRpPz6rZUQ+J//+toAZ7H0ZT/5KagS0NMhXWdT+sN3pPtNzgm+N0NJ46cf9XX3etj4yfE7HrjX3wMRLBZw==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@google-cloud/common": "^5.0.0", + "@google-cloud/common": "^6.0.0", "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", "@google-cloud/promisify": "4.0.0", @@ -893,10 +978,9 @@ "@opentelemetry/api": "^1.7.0", "arrify": "^2.0.1", "dot-prop": "^6.0.0", - "eventid": "^2.0.0", "extend": "^3.0.2", "gcp-metadata": "^6.0.0", - "google-auth-library": "^9.0.0", + "google-auth-library": "^10.6.2", "google-gax": "^4.0.3", "long": "^5.3.2", "on-finished": "^2.3.0", @@ -904,7 +988,7 @@ "stream-events": "^1.0.5" }, "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, "node_modules/@google-cloud/logging-winston": { @@ -927,9 +1011,9 @@ } }, "node_modules/@google-cloud/logging-winston/node_modules/gaxios": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.5.tgz", - "integrity": "sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.2.0.tgz", + "integrity": "sha512-CUVb4wcYe+771XevyH6HtGmXFAGGKkIC3kswAP8Z1JCe0j80JMaTPZH930DWFrvo0atjh18Arc0pEyUCWa5bfg==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -957,9 +1041,9 @@ } }, "node_modules/@google-cloud/logging-winston/node_modules/google-auth-library": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.7.0.tgz", - "integrity": "sha512-QpTAbNJ36TliZLx3TTtahR8HG0hN9RllL1e3FymOvQSIKK8JmgV58H924ub2wa2DsS3ANjjP1Aw1N+Ramc8hqQ==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.0.tgz", + "integrity": "sha512-xtvUqvINPhTaBm7nXqlYPcrMHJPm1lCNdSovxnKKhTm+4JsvQ+KGVYJViLoH9Yxu8w+T0Qv5HubzYT9BLrppJg==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -984,6 +1068,154 @@ "node": ">=14" } }, + "node_modules/@google-cloud/logging/node_modules/@google-cloud/common": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-6.0.1.tgz", + "integrity": "sha512-1uvKzbmAWUdchIYRsg0f4rUmezOamWuVBSWAPAhnYoUE5OiPEx6v6JOxFIdr3MsrqV+6fyLV3EI1vMPlHoeRvw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "^4.0.0", + "arrify": "^2.0.0", + "duplexify": "^4.1.3", + "extend": "^3.0.2", + "google-auth-library": "^10.0.0-rc.1", + "html-entities": "^2.5.2", + "retry-request": "^8.0.0", + "teeny-request": "^10.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google-cloud/logging/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@google-cloud/logging/node_modules/gaxios": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.2.0.tgz", + "integrity": "sha512-CUVb4wcYe+771XevyH6HtGmXFAGGKkIC3kswAP8Z1JCe0j80JMaTPZH930DWFrvo0atjh18Arc0pEyUCWa5bfg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google-cloud/logging/node_modules/google-auth-library": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.0.tgz", + "integrity": "sha512-xtvUqvINPhTaBm7nXqlYPcrMHJPm1lCNdSovxnKKhTm+4JsvQ+KGVYJViLoH9Yxu8w+T0Qv5HubzYT9BLrppJg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google-cloud/logging/node_modules/google-auth-library/node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google-cloud/logging/node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/logging/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@google-cloud/logging/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, + "node_modules/@google-cloud/logging/node_modules/retry-request": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-8.0.3.tgz", + "integrity": "sha512-qqoc4kkGgP9cmQDWELlOpAmfgJOg0Yi7MT82ZjiPWu451ayju4itwomjM4/dBEliify8C1b3tSaeCOldugtwPQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "teeny-request": "^10.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google-cloud/logging/node_modules/teeny-request": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-10.1.3.tgz", + "integrity": "sha512-5yDliI1uWkYPo7W+Zvrxg6YmoWuj5iC5EydewqrRTvc68nyMTZhlPPlLg6cptUGfbQAb+N9XDPDPzF6N081lug==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "stream-events": "^1.0.5" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@google-cloud/modelarmor": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@google-cloud/modelarmor/-/modelarmor-0.4.1.tgz", @@ -1035,9 +1267,9 @@ } }, "node_modules/@google-cloud/modelarmor/node_modules/gaxios": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.5.tgz", - "integrity": "sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.2.0.tgz", + "integrity": "sha512-CUVb4wcYe+771XevyH6HtGmXFAGGKkIC3kswAP8Z1JCe0j80JMaTPZH930DWFrvo0atjh18Arc0pEyUCWa5bfg==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -2124,15 +2356,6 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { "version": "0.52.1", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.52.1.tgz", @@ -2209,15 +2432,6 @@ "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/instrumentation": { "version": "0.52.1", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", @@ -2511,16 +2725,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/instrumentation-hapi": { "version": "0.40.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.40.0.tgz", @@ -2558,16 +2762,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/instrumentation-ioredis": { "version": "0.42.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.42.0.tgz", @@ -3015,6 +3209,7 @@ "version": "0.30.16", "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.16.tgz", "integrity": "sha512-ZVQ3Z/PQ+2GQlrBfbMMMT0U7MzvYZLCPP800+ooyaBqm4hMvuQHfP028gB9/db0mwkmyEAMad9houukUVxhwcw==", + "deprecated": "The use of process spans has been removed from Messaging Semantic Conventions. It is now recommended to connect pub/sub spans via Span Links. See https://opentelemetry.io/docs/specs/semconv/messaging/messaging-spans/ for details.", "license": "Apache-2.0", "optional": true, "engines": { @@ -3111,7 +3306,7 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/resource-detector-alibaba-cloud/node_modules/@opentelemetry/semantic-conventions": { + "node_modules/@opentelemetry/resource-detector-alibaba-cloud/node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { "version": "1.28.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", @@ -3121,6 +3316,16 @@ "node": ">=14" } }, + "node_modules/@opentelemetry/resource-detector-alibaba-cloud/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-aws": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.12.0.tgz", @@ -3139,6 +3344,16 @@ "@opentelemetry/api": "^1.0.0" } }, + "node_modules/@opentelemetry/resource-detector-aws/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-azure": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.2.12.tgz", @@ -3157,6 +3372,16 @@ "@opentelemetry/api": "^1.0.0" } }, + "node_modules/@opentelemetry/resource-detector-azure/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-container": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.4.4.tgz", @@ -3191,7 +3416,7 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/resource-detector-container/node_modules/@opentelemetry/semantic-conventions": { + "node_modules/@opentelemetry/resource-detector-container/node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { "version": "1.28.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", @@ -3201,6 +3426,16 @@ "node": ">=14" } }, + "node_modules/@opentelemetry/resource-detector-container/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-gcp": { "version": "0.29.13", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.13.tgz", @@ -3220,6 +3455,16 @@ "@opentelemetry/api": "^1.0.0" } }, + "node_modules/@opentelemetry/resource-detector-gcp/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resources": { "version": "1.25.1", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.25.1.tgz", @@ -3236,15 +3481,6 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/sdk-logs": { "version": "0.52.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.52.1.tgz", @@ -3306,15 +3542,6 @@ "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/sdk-trace-base": { "version": "1.25.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.25.1.tgz", @@ -3332,15 +3559,6 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/sdk-trace-node": { "version": "1.25.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.25.1.tgz", @@ -3362,11 +3580,10 @@ } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.41.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.41.1.tgz", - "integrity": "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==", + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", + "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", "license": "Apache-2.0", - "optional": true, "engines": { "node": ">=14" } @@ -3609,9 +3826,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -3736,9 +3953,9 @@ } }, "node_modules/@types/node": { - "version": "20.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", - "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -5098,30 +5315,6 @@ "node": ">=6" } }, - "node_modules/eventid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/eventid/-/eventid-2.0.1.tgz", - "integrity": "sha512-sPNTqiMokAvV048P2c9+foqVJzk49o6d4e0D/sq5jog3pw+4kBgyR0gaM1FM7Mx6Kzd9dztesh9oYz1LWWOpzw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "uuid": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eventid/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", - "license": "MIT", - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -5247,9 +5440,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", "funding": [ { "type": "github", @@ -5661,13 +5854,13 @@ } }, "node_modules/genkit": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/genkit/-/genkit-1.37.0.tgz", - "integrity": "sha512-CkQc8Pf9XYbg13O8RCY6bXxxGypTUNL+A/nm5iLfB/IDni1P5lS8cATFdtvgs0OeCgIr9mD69O5J5EK6Ndiziw==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/genkit/-/genkit-1.39.0.tgz", + "integrity": "sha512-Qz9ef/LfAEDMzO1+Nd6l6dMYK/V4ZfWDIp79rz/1V6xDM5VuJMkoqOTCDwXAviuAnjoO2noJug2wIK81ilMhWA==", "license": "Apache-2.0", "dependencies": { - "@genkit-ai/ai": "1.37.0", - "@genkit-ai/core": "1.37.0", + "@genkit-ai/ai": "1.39.0", + "@genkit-ai/core": "1.39.0", "uuid": "^10.0.0" } }, @@ -7050,9 +7243,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.0.tgz", + "integrity": "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==", "dev": true, "license": "MIT", "dependencies": { @@ -8565,9 +8758,9 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==", "license": "MIT", "optional": true, "dependencies": { @@ -8649,9 +8842,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -9249,9 +9442,9 @@ "license": "ISC" }, "node_modules/ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "dev": true, "license": "MIT", "dependencies": { @@ -9261,7 +9454,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, diff --git a/firestore-translate-text/functions/package.json b/firestore-translate-text/functions/package.json index 24697299e7..904ccd072a 100644 --- a/firestore-translate-text/functions/package.json +++ b/firestore-translate-text/functions/package.json @@ -15,7 +15,7 @@ "@genkit-ai/google-genai": "^1.31.0", "@google-cloud/translate": "^8.2.0", "@google-cloud/vertexai": "^1.9.2", - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "@types/node": "^20.10.3", "firebase-admin": "^12.1.0", "firebase-functions": "^4.9.0", @@ -28,7 +28,7 @@ "jest": "29.7.0", "js-yaml": "^3.13.1", "mocked-env": "^1.3.1", - "ts-jest": "29.4.9" + "ts-jest": "29.4.11" }, "private": true } diff --git a/package-lock.json b/package-lock.json index 87f663a7d2..05d520aba4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "lerna": "^3.4.3", "lint-staged": "^12.4.0", "prettier": "2.7.1", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "typescript": "^5.0.0" } }, @@ -14609,9 +14609,9 @@ } }, "node_modules/ts-jest": { - "version": "29.4.9", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.9.tgz", - "integrity": "sha512-LTb9496gYPMCqjeDLdPrKuXtncudeV1yRZnF4Wo5l3SFi0RYEnYRNgMrFIdg+FHvfzjCyQk1cLncWVqiSX+EvQ==", + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "dev": true, "license": "MIT", "dependencies": { @@ -14621,7 +14621,7 @@ "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.4", + "semver": "^7.8.0", "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, @@ -14662,9 +14662,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index 48d9d6e4fb..c503359601 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "lerna": "^3.4.3", "lint-staged": "^12.4.0", "prettier": "2.7.1", - "ts-jest": "29.4.9", + "ts-jest": "29.4.11", "typescript": "^5.0.0" }, "overrides": { diff --git a/rtdb-limit-child-nodes/functions/package-lock.json b/rtdb-limit-child-nodes/functions/package-lock.json index 5dc2d2b032..73ed90d3d3 100644 --- a/rtdb-limit-child-nodes/functions/package-lock.json +++ b/rtdb-limit-child-nodes/functions/package-lock.json @@ -7,7 +7,7 @@ "name": "rtdb-limit-child-nodes-functions", "license": "Apache-2.0", "dependencies": { - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "@types/node": "^20.10.3", "firebase-admin": "^13.2.0", "firebase-functions": "^6.3.2", @@ -389,9 +389,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -436,9 +436,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", - "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -2983,9 +2983,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "version": "4.19.9", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.9.tgz", + "integrity": "sha512-QP2ESEe/ImWY0HDwNAnK9PvEffUyhLTnWkk7KXzHfyeWAnlrDe1fN77bXl6ia8KT3wPlmA7t9/VPRpnf4Ex9sg==", "requires": { "@types/node": "*", "@types/qs": "*", @@ -3024,9 +3024,9 @@ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" }, "@types/node": { - "version": "20.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", - "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "requires": { "undici-types": "~6.21.0" } diff --git a/rtdb-limit-child-nodes/functions/package.json b/rtdb-limit-child-nodes/functions/package.json index dc499bdf1b..1122081b25 100644 --- a/rtdb-limit-child-nodes/functions/package.json +++ b/rtdb-limit-child-nodes/functions/package.json @@ -12,7 +12,7 @@ }, "license": "Apache-2.0", "dependencies": { - "@types/express-serve-static-core": "4.19.8", + "@types/express-serve-static-core": "4.19.9", "@types/node": "^20.10.3", "firebase-admin": "^13.2.0", "firebase-functions": "^6.3.2", diff --git a/storage-resize-images/functions/package-lock.json b/storage-resize-images/functions/package-lock.json index 8e4fb51e70..946bfbaeca 100644 --- a/storage-resize-images/functions/package-lock.json +++ b/storage-resize-images/functions/package-lock.json @@ -13,7 +13,7 @@ "firebase-functions": "^6.3.1", "genkit": "^1.2.0", "p-queue": "^6.6.2", - "sharp": "^0.34.5", + "sharp": "^0.35.3", "shx": "^0.4.0", "typescript": "^5.7.3" }, @@ -567,9 +567,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", - "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.2.tgz", + "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==", "license": "MIT", "optional": true, "dependencies": { @@ -1225,12 +1225,12 @@ "license": "Apache-2.0" }, "node_modules/@genkit-ai/ai": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/ai/-/ai-1.37.0.tgz", - "integrity": "sha512-SQnis1/NJeaGOiFnstmCJ7iGxVj/lwsQpwCXgG+JQrspAvGEIpSHCVBkreUpw6Dy7r0mVCHKup7L1NqBJbvCZg==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/ai/-/ai-1.39.0.tgz", + "integrity": "sha512-e1ZI2ib4Y8ha2Zj/rN7Uioxd16rWMhalPe3krypLw8B4G36X8KZCqj2UhucKbCZJIffU0cxEvag7BP+JVQnsyQ==", "license": "Apache-2.0", "dependencies": { - "@genkit-ai/core": "1.37.0", + "@genkit-ai/core": "1.39.0", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.11.19", "colorette": "^2.0.20", @@ -1276,9 +1276,9 @@ } }, "node_modules/@genkit-ai/core": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/core/-/core-1.37.0.tgz", - "integrity": "sha512-Bq/HTwRhFoWjn4bbN0gnegsO/0dSYRUtbkWj/xwYfTycSCzVTqQJt3eNJXL6Dd5qSlGa3sWjYTsksiLqfroDzg==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/core/-/core-1.39.0.tgz", + "integrity": "sha512-MI0cpmwc4K/KPVsXFAcHviOybt3T3IsVSsN37cEcOzo7mmv+s0JSdooxlQgZn68B6e3I8BNLL3Vk1vyc6qIlCw==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.9.0", @@ -1307,20 +1307,75 @@ "@genkit-ai/firebase": "^1.16.1" } }, - "node_modules/@genkit-ai/firebase": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/firebase/-/firebase-1.37.0.tgz", - "integrity": "sha512-yutXazOCGqGeauiShCaPj9fjcS3nn3FUTj7/0nbHXx8mLVhddBEwBIH96MqVGz9pqt3Fl57TCROPguLOmIZaQQ==", + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/ai": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/ai/-/ai-1.40.0.tgz", + "integrity": "sha512-uD+ZLfdCW+0gpMpWiTYGqiQitqlizDN4xPWFAnvTF9YidDhh+fzAMBtnTecp+nhCfOmLu+4PUaJ5hfvi2wy58A==", "license": "Apache-2.0", "optional": true, + "peer": true, "dependencies": { - "@genkit-ai/google-cloud": "^1.37.0" + "@genkit-ai/core": "1.40.0", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.11.19", + "colorette": "^2.0.20", + "dotprompt": "^1.1.1", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "node-fetch": "^3.3.2", + "partial-json": "^0.1.7", + "uri-templates": "^0.2.0", + "uuid": "^10.0.0" + } + }, + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/core": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/core/-/core-1.40.0.tgz", + "integrity": "sha512-ah42KLZgNO4XjCPaErKIHoF0C4dTiUqGsOHv9E/yNpQdFyUNapCybBVKVc6Pc8iURc8pi4Z2QzARIHIv467k4w==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/api-logs": "^0.52.0", + "@opentelemetry/context-async-hooks": "~1.25.0", + "@opentelemetry/core": "~1.25.0", + "@opentelemetry/sdk-logs": "^0.52.0", + "@opentelemetry/sdk-metrics": "~1.25.0", + "@opentelemetry/sdk-node": "^0.52.0", + "@opentelemetry/sdk-trace-base": "~1.25.0", + "@types/json-schema": "^7.0.15", + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "async-mutex": "^0.5.0", + "cors": "^2.8.5", + "dotprompt": "^1.1.1", + "express": "^4.21.0", + "get-port": "^5.1.0", + "json-schema": "^0.4.0", + "ws": "^8.18.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.22.4" + }, + "optionalDependencies": { + "@cfworker/json-schema": "^4.1.1", + "@genkit-ai/firebase": "^1.16.1" + } + }, + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/firebase": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/firebase/-/firebase-1.40.0.tgz", + "integrity": "sha512-R4ko8maP+U0Pu5+V7T2ftzRAgiscbo2lr0Vw6pzqvyl1OWrOTuxVt7JE+MLU7DEm3xCTOylDYsaUB1r5T9FK9w==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@genkit-ai/google-cloud": "^1.40.0" }, "peerDependencies": { "@google-cloud/firestore": "^7.11.0", "firebase": ">=11.5.0", "firebase-admin": ">=12.2", - "genkit": "^1.37.0" + "genkit": "^1.40.0" }, "peerDependenciesMeta": { "firebase": { @@ -1328,13 +1383,14 @@ } } }, - "node_modules/@genkit-ai/google-cloud": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/google-cloud/-/google-cloud-1.37.0.tgz", - "integrity": "sha512-THLcekr0kxzTyZksFVQ/gCIcprlQlenG7aGdGWjAokqWdtX28CU+2pmQF64m++IxOsuuqISIABjpyp0/fSPgjQ==", + "node_modules/@genkit-ai/core/node_modules/@genkit-ai/google-cloud": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/google-cloud/-/google-cloud-1.40.0.tgz", + "integrity": "sha512-CqHOKNBUUDrAz9rb7waSsUqzn27x1WHMVkgatl+cQ6fGFY68IMxm9yA8R8+P91kN768vbF1oXnaa3dy1vnFDng==", "license": "Apache-2.0", "optional": true, "dependencies": { + "@google-cloud/firestore": "^7.11.0", "@google-cloud/logging-winston": "^6.0.0", "@google-cloud/modelarmor": "^0.4.1", "@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.19.0", @@ -1355,10 +1411,23 @@ "winston": "^3.12.0" }, "peerDependencies": { - "genkit": "^1.37.0" + "genkit": "^1.40.0" + } + }, + "node_modules/@genkit-ai/core/node_modules/genkit": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/genkit/-/genkit-1.40.0.tgz", + "integrity": "sha512-OB0duJgIWtAv2Exp1FTc4uh0ZIYg5AUCtQATagU0fXbaEZeSVsn9c2geNR0Btr0tAHVUabpZp19QlSmy9Gpc7Q==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@genkit-ai/ai": "1.40.0", + "@genkit-ai/core": "1.40.0", + "uuid": "^10.0.0" } }, - "node_modules/@genkit-ai/google-cloud/node_modules/node-fetch": { + "node_modules/@genkit-ai/core/node_modules/node-fetch": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", @@ -1377,10 +1446,26 @@ "url": "https://opencollective.com/node-fetch" } }, + "node_modules/@genkit-ai/core/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@genkit-ai/vertexai": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/vertexai/-/vertexai-1.37.0.tgz", - "integrity": "sha512-DJ7JktQ6s8VK2EfqG6kT4q7Ltmnr7lfn/GFI+VmuxJuXLzwcf7HfGjGBlpkhtukmJxp96ZdEDBIx7ln7Og42zg==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/vertexai/-/vertexai-1.39.0.tgz", + "integrity": "sha512-7WbgFhJtpuOVNL8HPPgqwImRdEWdrjwvYMZlzZSi5/Oq2op7/8FfI4hV46VXnuQRir5qWPHwV4RZZyC0bnR74Q==", "license": "Apache-2.0", "dependencies": { "@anthropic-ai/sdk": "^0.90.0", @@ -1398,7 +1483,7 @@ "firebase-admin": ">=12.2" }, "peerDependencies": { - "genkit": "^1.37.0" + "genkit": "^1.39.0" } }, "node_modules/@genkit-ai/vertexai/node_modules/node-fetch": { @@ -1501,13 +1586,13 @@ } }, "node_modules/@google-cloud/logging": { - "version": "11.2.3", - "resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-11.2.3.tgz", - "integrity": "sha512-iUIJ+3Bi6aw9whahT4JmS5Ccd1Eej2Ss9RjOSW2+qcVaWcleepJtFUBuyU2CpewtniVibBUV/731MQw9SWxQ3Q==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-11.3.0.tgz", + "integrity": "sha512-8Y2lFRpPz6rZUQ+J//+toAZ7H0ZT/5KagS0NMhXWdT+sN3pPtNzgm+N0NJ46cf9XX3etj4yfE7HrjX3wMRLBZw==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@google-cloud/common": "^5.0.0", + "@google-cloud/common": "^6.0.0", "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", "@google-cloud/promisify": "4.0.0", @@ -1515,10 +1600,9 @@ "@opentelemetry/api": "^1.7.0", "arrify": "^2.0.1", "dot-prop": "^6.0.0", - "eventid": "^2.0.0", "extend": "^3.0.2", "gcp-metadata": "^6.0.0", - "google-auth-library": "^9.0.0", + "google-auth-library": "^10.6.2", "google-gax": "^4.0.3", "long": "^5.3.2", "on-finished": "^2.3.0", @@ -1526,7 +1610,7 @@ "stream-events": "^1.0.5" }, "engines": { - "node": ">=14.0.0" + "node": ">=18" } }, "node_modules/@google-cloud/logging-winston": { @@ -1549,9 +1633,9 @@ } }, "node_modules/@google-cloud/logging-winston/node_modules/gaxios": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.5.tgz", - "integrity": "sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.2.0.tgz", + "integrity": "sha512-CUVb4wcYe+771XevyH6HtGmXFAGGKkIC3kswAP8Z1JCe0j80JMaTPZH930DWFrvo0atjh18Arc0pEyUCWa5bfg==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -1579,9 +1663,9 @@ } }, "node_modules/@google-cloud/logging-winston/node_modules/google-auth-library": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.7.0.tgz", - "integrity": "sha512-QpTAbNJ36TliZLx3TTtahR8HG0hN9RllL1e3FymOvQSIKK8JmgV58H924ub2wa2DsS3ANjjP1Aw1N+Ramc8hqQ==", + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.0.tgz", + "integrity": "sha512-xtvUqvINPhTaBm7nXqlYPcrMHJPm1lCNdSovxnKKhTm+4JsvQ+KGVYJViLoH9Yxu8w+T0Qv5HubzYT9BLrppJg==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -1625,6 +1709,27 @@ "url": "https://opencollective.com/node-fetch" } }, + "node_modules/@google-cloud/logging/node_modules/@google-cloud/common": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-6.0.1.tgz", + "integrity": "sha512-1uvKzbmAWUdchIYRsg0f4rUmezOamWuVBSWAPAhnYoUE5OiPEx6v6JOxFIdr3MsrqV+6fyLV3EI1vMPlHoeRvw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "^4.0.0", + "arrify": "^2.0.0", + "duplexify": "^4.1.3", + "extend": "^3.0.2", + "google-auth-library": "^10.0.0-rc.1", + "html-entities": "^2.5.2", + "retry-request": "^8.0.0", + "teeny-request": "^10.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@google-cloud/logging/node_modules/@google-cloud/promisify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", @@ -1668,6 +1773,127 @@ "node": ">=6" } }, + "node_modules/@google-cloud/logging/node_modules/gaxios": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.2.0.tgz", + "integrity": "sha512-CUVb4wcYe+771XevyH6HtGmXFAGGKkIC3kswAP8Z1JCe0j80JMaTPZH930DWFrvo0atjh18Arc0pEyUCWa5bfg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google-cloud/logging/node_modules/google-auth-library": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.0.tgz", + "integrity": "sha512-xtvUqvINPhTaBm7nXqlYPcrMHJPm1lCNdSovxnKKhTm+4JsvQ+KGVYJViLoH9Yxu8w+T0Qv5HubzYT9BLrppJg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google-cloud/logging/node_modules/google-auth-library/node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google-cloud/logging/node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/logging/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@google-cloud/logging/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "optional": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/@google-cloud/logging/node_modules/retry-request": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-8.0.3.tgz", + "integrity": "sha512-qqoc4kkGgP9cmQDWELlOpAmfgJOg0Yi7MT82ZjiPWu451ayju4itwomjM4/dBEliify8C1b3tSaeCOldugtwPQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "extend": "^3.0.2", + "teeny-request": "^10.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@google-cloud/logging/node_modules/teeny-request": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-10.1.3.tgz", + "integrity": "sha512-5yDliI1uWkYPo7W+Zvrxg6YmoWuj5iC5EydewqrRTvc68nyMTZhlPPlLg6cptUGfbQAb+N9XDPDPzF6N081lug==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "stream-events": "^1.0.5" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@google-cloud/modelarmor": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@google-cloud/modelarmor/-/modelarmor-0.4.1.tgz", @@ -1715,9 +1941,9 @@ } }, "node_modules/@google-cloud/modelarmor/node_modules/gaxios": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.5.tgz", - "integrity": "sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.2.0.tgz", + "integrity": "sha512-CUVb4wcYe+771XevyH6HtGmXFAGGKkIC3kswAP8Z1JCe0j80JMaTPZH930DWFrvo0atjh18Arc0pEyUCWa5bfg==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -2104,9 +2330,9 @@ } }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", - "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.3.tgz", + "integrity": "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg==", "cpu": [ "arm64" ], @@ -2116,19 +2342,19 @@ "darwin" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.4" + "@img/sharp-libvips-darwin-arm64": "1.3.2" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.3.tgz", + "integrity": "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w==", "cpu": [ "x64" ], @@ -2138,19 +2364,38 @@ "darwin" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.4" + "@img/sharp-libvips-darwin-x64": "1.3.2" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.3.tgz", + "integrity": "sha512-lUxcqWIj2wMQ9BrwNjngcr1gWUr5xgaGThBRqPPalIC2n67Cqj1uPh8NnA/ZhAg8hUbKl+kVHKwgUIwe6ZYPrg==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", - "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.2.tgz", + "integrity": "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg==", "cpu": [ "arm64" ], @@ -2164,9 +2409,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.2.tgz", + "integrity": "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw==", "cpu": [ "x64" ], @@ -2180,12 +2425,15 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.2.tgz", + "integrity": "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ==", "cpu": [ "arm" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2196,12 +2444,15 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.2.tgz", + "integrity": "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA==", "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2212,12 +2463,15 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", - "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.2.tgz", + "integrity": "sha512-3z0NHDxD6n5I9gc05U1eW1AyRm+Gznzq3naMrthPNqE6oYykcogW0l/jfpJdjYnuNl8R7yI9pNbE1XiUeyq0Aw==", "cpu": [ "ppc64" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2228,12 +2482,15 @@ } }, "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", - "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.2.tgz", + "integrity": "sha512-bsb4rI+NldGOsXuej2r8OdSS8+zXDVaCWxyWrcv6kneTOlgAHtZABRzBBCwdsPiD90J4myNJuHpg6kA20ImW/w==", "cpu": [ "riscv64" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2244,12 +2501,15 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", - "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.2.tgz", + "integrity": "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ==", "cpu": [ "s390x" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2260,12 +2520,15 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.2.tgz", + "integrity": "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w==", "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2276,12 +2539,15 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.2.tgz", + "integrity": "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw==", "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2292,12 +2558,15 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.2.tgz", + "integrity": "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2308,204 +2577,244 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.3.tgz", + "integrity": "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA==", "cpu": [ "arm" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.4" + "@img/sharp-libvips-linux-arm": "1.3.2" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.3.tgz", + "integrity": "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ==", "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.4" + "@img/sharp-libvips-linux-arm64": "1.3.2" } }, "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", - "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.3.tgz", + "integrity": "sha512-sMd8rDxmpLOwv/7N44klFjOD5DUO7FLdjiXDI0hoxYaf7Ar262dQIEkosE98bps+5HPLtp/EvNqeqQtOycP/IA==", "cpu": [ "ppc64" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.4" + "@img/sharp-libvips-linux-ppc64": "1.3.2" } }, "node_modules/@img/sharp-linux-riscv64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", - "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.3.tgz", + "integrity": "sha512-0Eob78yjlYPfL5vMNWAW55l3R9Y6BQS/gOfe0ZcP9mEz9ohhKSt4im1hayiknXgf8AWrFqMvJcKIdmLmEe7yeQ==", "cpu": [ "riscv64" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.2.4" + "@img/sharp-libvips-linux-riscv64": "1.3.2" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", - "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.3.tgz", + "integrity": "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw==", "cpu": [ "s390x" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.4" + "@img/sharp-libvips-linux-s390x": "1.3.2" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.3.tgz", + "integrity": "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA==", "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.4" + "@img/sharp-libvips-linux-x64": "1.3.2" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.3.tgz", + "integrity": "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w==", "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.3.tgz", + "integrity": "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + "@img/sharp-libvips-linuxmusl-x64": "1.3.2" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", - "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.3.tgz", + "integrity": "sha512-cZ0XkcYGpHZkqW6iCkqTcmUC0CD9DhD5d/qeZlZkfRBn6GnHniZXLUo5+9xw8Iv76YE6LQFN9YNBlKREcCG76w==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.3.tgz", + "integrity": "sha512-2rnq7bX3NzeR2T4YWgz8qiG4h3TSdMe+vN1iQXpJleSJ3SM5zQ8Fy2SyyXAWlbxpEZ2Y+Z4u1BePgJEYbSy80Q==", "cpu": [ "wasm32" ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "license": "Apache-2.0", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.7.0" + "@img/sharp-wasm32": "0.35.3" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.3.tgz", + "integrity": "sha512-4bPwFdMbeC4JQ8L8LOyWp6nsHcboP5fxkp6iPOXz2Vg49R42TuMs2whkJ5OAP4/Ul035qOzy0AecOF9VOscn4w==", "cpu": [ "arm64" ], @@ -2515,16 +2824,16 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", - "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.3.tgz", + "integrity": "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw==", "cpu": [ "ia32" ], @@ -2534,16 +2843,16 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": "^20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.3.tgz", + "integrity": "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA==", "cpu": [ "x64" ], @@ -2553,7 +2862,7 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" @@ -3233,15 +3542,6 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { "version": "0.52.1", "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.52.1.tgz", @@ -3318,15 +3618,6 @@ "@opentelemetry/api": "^1.0.0" } }, - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/instrumentation": { "version": "0.52.1", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", @@ -3620,16 +3911,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/instrumentation-hapi": { "version": "0.40.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.40.0.tgz", @@ -3667,16 +3948,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/instrumentation-ioredis": { "version": "0.42.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.42.0.tgz", @@ -4124,6 +4395,7 @@ "version": "0.30.16", "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.16.tgz", "integrity": "sha512-ZVQ3Z/PQ+2GQlrBfbMMMT0U7MzvYZLCPP800+ooyaBqm4hMvuQHfP028gB9/db0mwkmyEAMad9houukUVxhwcw==", + "deprecated": "The use of process spans has been removed from Messaging Semantic Conventions. It is now recommended to connect pub/sub spans via Span Links. See https://opentelemetry.io/docs/specs/semconv/messaging/messaging-spans/ for details.", "license": "Apache-2.0", "optional": true, "engines": { @@ -4220,7 +4492,7 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/resource-detector-alibaba-cloud/node_modules/@opentelemetry/semantic-conventions": { + "node_modules/@opentelemetry/resource-detector-alibaba-cloud/node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { "version": "1.28.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", @@ -4230,6 +4502,16 @@ "node": ">=14" } }, + "node_modules/@opentelemetry/resource-detector-alibaba-cloud/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-aws": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.12.0.tgz", @@ -4248,6 +4530,16 @@ "@opentelemetry/api": "^1.0.0" } }, + "node_modules/@opentelemetry/resource-detector-aws/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-azure": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.2.12.tgz", @@ -4266,6 +4558,16 @@ "@opentelemetry/api": "^1.0.0" } }, + "node_modules/@opentelemetry/resource-detector-azure/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-container": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.4.4.tgz", @@ -4300,7 +4602,7 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/resource-detector-container/node_modules/@opentelemetry/semantic-conventions": { + "node_modules/@opentelemetry/resource-detector-container/node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { "version": "1.28.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", @@ -4310,6 +4612,16 @@ "node": ">=14" } }, + "node_modules/@opentelemetry/resource-detector-container/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resource-detector-gcp": { "version": "0.29.13", "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.29.13.tgz", @@ -4329,6 +4641,16 @@ "@opentelemetry/api": "^1.0.0" } }, + "node_modules/@opentelemetry/resource-detector-gcp/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@opentelemetry/resources": { "version": "1.25.1", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.25.1.tgz", @@ -4345,15 +4667,6 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/sdk-logs": { "version": "0.52.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.52.1.tgz", @@ -4415,15 +4728,6 @@ "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/sdk-trace-base": { "version": "1.25.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.25.1.tgz", @@ -4441,15 +4745,6 @@ "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, - "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", - "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, "node_modules/@opentelemetry/sdk-trace-node": { "version": "1.25.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.25.1.tgz", @@ -4471,11 +4766,10 @@ } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.41.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.41.1.tgz", - "integrity": "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==", + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz", + "integrity": "sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==", "license": "Apache-2.0", - "optional": true, "engines": { "node": ">=14" } @@ -4818,9 +5112,9 @@ } }, "node_modules/@types/node": { - "version": "20.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", - "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -5413,9 +5707,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==", "license": "MIT", "optional": true, "dependencies": { @@ -6195,30 +6489,6 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, - "node_modules/eventid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/eventid/-/eventid-2.0.1.tgz", - "integrity": "sha512-sPNTqiMokAvV048P2c9+foqVJzk49o6d4e0D/sq5jog3pw+4kBgyR0gaM1FM7Mx6Kzd9dztesh9oYz1LWWOpzw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "uuid": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eventid/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", - "license": "MIT", - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -6366,9 +6636,9 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", + "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", "funding": [ { "type": "github", @@ -6886,13 +7156,13 @@ } }, "node_modules/genkit": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/genkit/-/genkit-1.37.0.tgz", - "integrity": "sha512-CkQc8Pf9XYbg13O8RCY6bXxxGypTUNL+A/nm5iLfB/IDni1P5lS8cATFdtvgs0OeCgIr9mD69O5J5EK6Ndiziw==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/genkit/-/genkit-1.39.0.tgz", + "integrity": "sha512-Qz9ef/LfAEDMzO1+Nd6l6dMYK/V4ZfWDIp79rz/1V6xDM5VuJMkoqOTCDwXAviuAnjoO2noJug2wIK81ilMhWA==", "license": "Apache-2.0", "dependencies": { - "@genkit-ai/ai": "1.37.0", - "@genkit-ai/core": "1.37.0", + "@genkit-ai/ai": "1.39.0", + "@genkit-ai/core": "1.39.0", "uuid": "^10.0.0" } }, @@ -9851,47 +10121,52 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", - "hasInstallScript": true, + "version": "0.35.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.3.tgz", + "integrity": "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q==", "license": "Apache-2.0", "dependencies": { - "@img/colour": "^1.0.0", + "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", - "semver": "^7.7.3" + "semver": "^7.8.5" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" + "@img/sharp-darwin-arm64": "0.35.3", + "@img/sharp-darwin-x64": "0.35.3", + "@img/sharp-freebsd-wasm32": "0.35.3", + "@img/sharp-libvips-darwin-arm64": "1.3.2", + "@img/sharp-libvips-darwin-x64": "1.3.2", + "@img/sharp-libvips-linux-arm": "1.3.2", + "@img/sharp-libvips-linux-arm64": "1.3.2", + "@img/sharp-libvips-linux-ppc64": "1.3.2", + "@img/sharp-libvips-linux-riscv64": "1.3.2", + "@img/sharp-libvips-linux-s390x": "1.3.2", + "@img/sharp-libvips-linux-x64": "1.3.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", + "@img/sharp-libvips-linuxmusl-x64": "1.3.2", + "@img/sharp-linux-arm": "0.35.3", + "@img/sharp-linux-arm64": "0.35.3", + "@img/sharp-linux-ppc64": "0.35.3", + "@img/sharp-linux-riscv64": "0.35.3", + "@img/sharp-linux-s390x": "0.35.3", + "@img/sharp-linux-x64": "0.35.3", + "@img/sharp-linuxmusl-arm64": "0.35.3", + "@img/sharp-linuxmusl-x64": "0.35.3", + "@img/sharp-webcontainers-wasm32": "0.35.3", + "@img/sharp-win32-arm64": "0.35.3", + "@img/sharp-win32-ia32": "0.35.3", + "@img/sharp-win32-x64": "0.35.3" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, "node_modules/shebang-command": { diff --git a/storage-resize-images/functions/package.json b/storage-resize-images/functions/package.json index a141c82b28..5d5ba26de4 100644 --- a/storage-resize-images/functions/package.json +++ b/storage-resize-images/functions/package.json @@ -22,7 +22,7 @@ "firebase-functions": "^6.3.1", "genkit": "^1.2.0", "p-queue": "^6.6.2", - "sharp": "^0.34.5", + "sharp": "^0.35.3", "shx": "^0.4.0", "typescript": "^5.7.3" }, From 7b624a680f9391cf92a41031b51cdd319b0d8182 Mon Sep 17 00:00:00 2001 From: Jacob Cable <32874567+cabljac@users.noreply.github.com> Date: Thu, 30 Jul 2026 10:34:08 +0100 Subject: [PATCH 02/30] chore: enforce Apache license headers with google/addlicense (#2928) * chore: backfill Apache license headers in ts/js files Claude-Session: https://claude.ai/code/session_013dz9GhC3metut6HFswPavu * ci: enforce Apache license headers with addlicense Adds a license job to the Validate workflow that runs google/addlicense in check mode over tracked ts/js files. Run npm run license:fix locally to add missing headers. Claude-Session: https://claude.ai/code/session_013dz9GhC3metut6HFswPavu * ci: pin validate workflow actions to commit SHAs Required by zizmor unpinned-uses mandatory policy. Claude-Session: https://claude.ai/code/session_013dz9GhC3metut6HFswPavu * ci: restrict validate workflow to read-only permissions Resolves zizmor excessive-permissions finding. Claude-Session: https://claude.ai/code/session_013dz9GhC3metut6HFswPavu * chore: harden addlicense script NUL-separated file list for filenames with special characters, and reject unknown modes instead of defaulting to fix. Claude-Session: https://claude.ai/code/session_013dz9GhC3metut6HFswPavu --- .github/workflows/validate.yml | 20 ++++++++++++++-- _emulator/functions/src/index.ts | 16 +++++++++++++ commitlint.config.js | 16 +++++++++++++ .../functions/__tests__/handleDelete.test.ts | 16 +++++++++++++ .../functions/__tests__/helpers.test.ts | 16 +++++++++++++ .../functions/__tests__/helpers/index.ts | 16 +++++++++++++ .../__tests__/helpers/setupEnvironment.ts | 16 +++++++++++++ .../__tests__/recursiveDelete.test.ts | 16 +++++++++++++ .../__tests__/runBatchPubSubDeletions.test.ts | 16 +++++++++++++ .../functions/__tests__/search.test.ts | 16 +++++++++++++ .../__tests__/searchFunction.test.ts | 16 +++++++++++++ .../functions/__tests__/setupTests.ts | 16 +++++++++++++ delete-user-data/functions/jest.config.js | 16 +++++++++++++ .../functions/src/recursiveDelete.ts | 16 +++++++++++++ .../functions/src/runBatchPubSubDeletions.ts | 16 +++++++++++++ .../functions/src/runCustomSearchFunction.ts | 16 +++++++++++++ delete-user-data/functions/src/search.ts | 16 +++++++++++++ delete-user-data/functions/src/types.ts | 16 +++++++++++++ .../jest.config.js | 16 +++++++++++++ .../bigquery/alternativeProject.test.ts | 16 +++++++++++++ .../__tests__/bigquery/checkUpdates.test.ts | 16 +++++++++++++ .../src/__tests__/bigquery/clustering.test.ts | 16 +++++++++++++ .../src/__tests__/bigquery/e2e.test.ts | 16 +++++++++++++ .../bigquery/failedTransaction.test.ts | 16 +++++++++++++ .../initializeLatestMaterializedView.test.ts | 16 +++++++++++++ .../initializeLatestView.test.ts | 16 +++++++++++++ .../materializedViews/integration.test.ts | 16 +++++++++++++ .../shouldRecreateMaterializedView.test.ts | 16 +++++++++++++ .../__tests__/bigquery/partitioning.test.ts | 16 +++++++++++++ .../bigquery/partitioning/config.test.ts | 16 +++++++++++++ .../bigquery/partitioning/converter.test.ts | 16 +++++++++++++ .../src/__tests__/bigquery/stresstest.test.ts | 16 +++++++++++++ .../bigquery/wildcardDocument.test.ts | 16 +++++++++++++ .../src/__tests__/fixtures/changeTracker.ts | 16 +++++++++++++ .../src/__tests__/fixtures/clearTables.ts | 16 +++++++++++++ .../src/__tests__/fixtures/queries.ts | 16 +++++++++++++ .../src/__tests__/logger.test.ts | 16 +++++++++++++ .../src/bigquery/checkUpdates.ts | 16 +++++++++++++ .../src/bigquery/clustering.ts | 16 +++++++++++++ .../src/bigquery/handleFailedTransactions.ts | 16 +++++++++++++ .../initializeLatestMaterializedView.ts | 16 +++++++++++++ .../src/bigquery/initializeLatestView.ts | 16 +++++++++++++ .../src/bigquery/partitioning/config.ts | 16 +++++++++++++ .../src/bigquery/partitioning/converter.ts | 16 +++++++++++++ .../src/bigquery/partitioning/index.ts | 16 +++++++++++++ .../src/bigquery/types.ts | 16 +++++++++++++ .../src/bigquery/utils.test.ts | 16 +++++++++++++ .../src/bigquery/utils.ts | 16 +++++++++++++ .../src/bigquery/validateProject.ts | 16 +++++++++++++ .../src/types.ts | 16 +++++++++++++ .../functions/__tests__/__mocks__/console.ts | 16 +++++++++++++ .../__tests__/__mocks__/firestore.ts | 16 +++++++++++++ .../functions/__tests__/config.test.ts | 16 +++++++++++++ .../functions/__tests__/e2e.test.ts | 16 +++++++++++++ .../__tests__/fixtures/documentData.ts | 16 +++++++++++++ .../functions/__tests__/functions.test.ts | 16 +++++++++++++ .../functions/__tests__/jest.setup.ts | 16 +++++++++++++ .../functions/__tests__/test.types.d.ts | 16 +++++++++++++ .../functions/__tests__/util.test.ts | 16 +++++++++++++ .../big-query-table-test/install-script.js | 16 +++++++++++++ .../functions/jest.config.js | 16 +++++++++++++ .../functions/src/events.ts | 16 +++++++++++++ .../functions/stress_test/count.js | 16 +++++++++++++ .../functions/stress_test/main.js | 16 +++++++++++++ .../functions/stress_test/worker.js | 16 +++++++++++++ .../gen-schema-view/__mocks__/inquirer.js | 16 +++++++++++++ .../scripts/gen-schema-view/jest.config.js | 16 +++++++++++++ .../bigquery/schema/extractors.test.ts | 16 +++++++++++++ .../bigquery/schema/processLeafField.test.ts | 16 +++++++++++++ .../src/__tests__/config/index.test.ts | 16 +++++++++++++ .../src/__tests__/config/interactive.test.ts | 16 +++++++++++++ .../__tests__/config/non-interactive.test.ts | 16 +++++++++++++ .../src/__tests__/e2e/helpers/setup.ts | 16 +++++++++++++ .../src/schema/processLeafField.ts | 16 +++++++++++++ .../scripts/import/__tests__/e2e.test.ts | 16 +++++++++++++ .../import/__tests__/getRowsFromDocs.test.ts | 16 +++++++++++++ .../import/__tests__/helpers/waitFor.ts | 16 +++++++++++++ .../multiThreadCollectionGroupBug.test.ts | 16 +++++++++++++ .../import/__tests__/runMultiThread.test.ts | 16 +++++++++++++ .../__tests__/runMultiThreadMock.test.ts | 16 +++++++++++++ .../scripts/import/__tests__/test.types.d.ts | 16 +++++++++++++ .../scripts/import/jest.config.js | 16 +++++++++++++ .../scripts/import/src/config.ts | 16 +++++++++++++ .../scripts/import/src/helper.ts | 16 +++++++++++++ .../scripts/import/src/logs.ts | 16 +++++++++++++ .../scripts/import/src/program.ts | 16 +++++++++++++ .../scripts/import/src/run-multi-thread.ts | 16 +++++++++++++ .../scripts/import/src/run-single-thread.ts | 16 +++++++++++++ .../scripts/import/src/types.ts | 16 +++++++++++++ .../scripts/import/src/worker.ts | 16 +++++++++++++ .../functions/__tests__/test.types.d.ts | 16 +++++++++++++ firestore-counter/functions/jest.config.js | 16 +++++++++++++ firestore-counter/functions/src/events.ts | 16 +++++++++++++ .../functions/__tests__/config.test.ts | 16 +++++++++++++ .../functions/__tests__/createSMTPServer.ts | 16 +++++++++++++ .../functions/__tests__/e2e.test.ts | 16 +++++++++++++ .../functions/__tests__/e2e/sendgrid.test.ts | 16 +++++++++++++ .../functions/__tests__/functions.test.ts | 16 +++++++++++++ .../functions/__tests__/helpers.test.ts | 16 +++++++++++++ .../functions/__tests__/jest.setup.ts | 16 +++++++++++++ .../nodemailer-sendgrid/index.test.ts | 16 +++++++++++++ .../__tests__/prepare-payload.test.ts | 16 +++++++++++++ .../functions/__tests__/test.types.d.ts | 16 +++++++++++++ .../functions/__tests__/validation.test.ts | 16 +++++++++++++ firestore-send-email/functions/jest.config.js | 16 +++++++++++++ .../functions/jest.teardown.js | 16 +++++++++++++ firestore-send-email/functions/src/events.ts | 16 +++++++++++++ firestore-send-email/functions/src/helpers.ts | 16 +++++++++++++ .../src/nodemailer-sendgrid/index.ts | 16 +++++++++++++ .../src/nodemailer-sendgrid/types.ts | 16 +++++++++++++ .../functions/src/prepare-payload.ts | 16 +++++++++++++ firestore-send-email/functions/src/types.ts | 16 +++++++++++++ .../functions/src/validation.ts | 16 +++++++++++++ .../scripts/oauth2-refresh-token-helper.js | 15 ++++++++++++ .../functions/jest.config.js | 16 +++++++++++++ .../functions/src/events.ts | 16 +++++++++++++ .../functions/__tests__/config.test.ts | 16 +++++++++++++ .../functions/__tests__/functions.test.ts | 16 +++++++++++++ .../functions/__tests__/jest.setup.ts | 16 +++++++++++++ .../functions/__tests__/mocks/firestore.ts | 16 +++++++++++++ .../functions/__tests__/mocks/translate.ts | 16 +++++++++++++ .../functions/__tests__/test.types.d.ts | 16 +++++++++++++ .../unit/translateMultipleBackfill.test.ts | 16 +++++++++++++ .../functions/jest.config.js | 16 +++++++++++++ .../functions/src/events.ts | 16 +++++++++++++ .../functions/src/logs/messages.ts | 16 +++++++++++++ .../functions/src/translate/common.ts | 16 +++++++++++++ .../functions/src/translate/index.ts | 16 +++++++++++++ .../src/translate/translateDocument.ts | 16 +++++++++++++ .../src/translate/translateMultiple.ts | 16 +++++++++++++ .../src/translate/translateSingle.ts | 16 +++++++++++++ jest.config.js | 16 +++++++++++++ license-header.tmpl | 13 +++++++++++ package.json | 2 ++ .../functions/jest.config.js | 16 +++++++++++++ .../functions/index.js | 16 +++++++++++++ .../integration-tests/functions/index.js | 16 +++++++++++++ scripts/addlicense.sh | 23 +++++++++++++++++++ .../__tests__/__mocks__/src/config.ts | 16 +++++++++++++ .../__tests__/__mocks__/src/index.ts | 16 +++++++++++++ .../functions/__tests__/config.test.ts | 16 +++++++++++++ .../__tests__/content-filter.test.ts | 16 +++++++++++++ .../functions/__tests__/convert-image.test.ts | 16 +++++++++++++ .../functions/__tests__/e2e.test.ts | 16 +++++++++++++ .../functions/__tests__/filters.test.ts | 16 +++++++++++++ .../functions/__tests__/function.test.ts | 16 +++++++++++++ .../integration/content-filter.live.test.ts | 16 +++++++++++++ .../functions/__tests__/resize.test.ts | 16 +++++++++++++ .../functions/__tests__/retry-queue.test.ts | 16 +++++++++++++ .../functions/__tests__/test.types.d.ts | 16 +++++++++++++ .../unit/generateResizedImageHandler.test.ts | 16 +++++++++++++ .../__tests__/unit/modifyImage.test.ts | 16 +++++++++++++ .../functions/__tests__/util.test.ts | 16 +++++++++++++ .../functions/__tests__/util.ts | 16 +++++++++++++ .../functions/__tests__/vulnerability.test.ts | 16 +++++++++++++ .../functions/jest.config.js | 16 +++++++++++++ .../functions/src/content-filter.ts | 16 +++++++++++++ storage-resize-images/functions/src/events.ts | 16 +++++++++++++ .../functions/src/file-operations.ts | 16 +++++++++++++ .../functions/src/filters.ts | 16 +++++++++++++ storage-resize-images/functions/src/global.ts | 16 +++++++++++++ .../functions/src/placeholder.ts | 16 +++++++++++++ .../functions/src/resize-image.ts | 16 +++++++++++++ storage-resize-images/functions/src/util.ts | 16 +++++++++++++ 164 files changed, 2615 insertions(+), 2 deletions(-) create mode 100644 license-header.tmpl create mode 100755 scripts/addlicense.sh diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 3e6db004a6..3f7de598d8 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -5,16 +5,32 @@ on: branches: - "**" +permissions: + contents: read + jobs: formatting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: 22 - name: NPM install run: SKIP_POSTINSTALL=yes npm i - name: Prettier Lint Check run: npm run lint + + license: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - name: Setup go + uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 + with: + go-version: stable + - name: Install addlicense + run: go install github.com/google/addlicense@v1.2.0 + - name: Check license headers + run: ./scripts/addlicense.sh check diff --git a/_emulator/functions/src/index.ts b/_emulator/functions/src/index.ts index 65c48daafe..ed8e351c82 100644 --- a/_emulator/functions/src/index.ts +++ b/_emulator/functions/src/index.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as functions from "firebase-functions"; export const findDocumentReferences = functions.https.onRequest( diff --git a/commitlint.config.js b/commitlint.config.js index 5073c20db1..49a815ebbf 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1 +1,17 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + module.exports = { extends: ["@commitlint/config-conventional"] }; diff --git a/delete-user-data/functions/__tests__/handleDelete.test.ts b/delete-user-data/functions/__tests__/handleDelete.test.ts index a2963eb406..f9c7891f90 100644 --- a/delete-user-data/functions/__tests__/handleDelete.test.ts +++ b/delete-user-data/functions/__tests__/handleDelete.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { handleDeletion } from "../src"; import * as admin from "firebase-admin"; // Import Firebase admin to mock Firestore import firebaseFunctionsTest from "firebase-functions-test"; diff --git a/delete-user-data/functions/__tests__/helpers.test.ts b/delete-user-data/functions/__tests__/helpers.test.ts index 659d2ec666..e88d793a75 100644 --- a/delete-user-data/functions/__tests__/helpers.test.ts +++ b/delete-user-data/functions/__tests__/helpers.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { UserRecord } from "firebase-functions/v1/auth"; import setupEnvironment from "./helpers/setupEnvironment"; diff --git a/delete-user-data/functions/__tests__/helpers/index.ts b/delete-user-data/functions/__tests__/helpers/index.ts index 803bd3b892..2afbaff77b 100644 --- a/delete-user-data/functions/__tests__/helpers/index.ts +++ b/delete-user-data/functions/__tests__/helpers/index.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { UserRecord } from "firebase-functions/v1/auth"; import { Query, DocumentData } from "@google-cloud/firestore"; diff --git a/delete-user-data/functions/__tests__/helpers/setupEnvironment.ts b/delete-user-data/functions/__tests__/helpers/setupEnvironment.ts index 9dc56810ab..db9d1ad361 100644 --- a/delete-user-data/functions/__tests__/helpers/setupEnvironment.ts +++ b/delete-user-data/functions/__tests__/helpers/setupEnvironment.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export default () => { process.env.FIRESTORE_EMULATOR_HOST = "127.0.0.1:8080"; process.env.FIREBASE_FIRESTORE_EMULATOR_ADDRESS = "127.0.0.1:8080"; diff --git a/delete-user-data/functions/__tests__/recursiveDelete.test.ts b/delete-user-data/functions/__tests__/recursiveDelete.test.ts index 64a5f71c3d..2977347062 100644 --- a/delete-user-data/functions/__tests__/recursiveDelete.test.ts +++ b/delete-user-data/functions/__tests__/recursiveDelete.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // Import your function and any necessary Firebase modules import { recursiveDelete } from "../src/recursiveDelete"; // Update with your actual file path import * as admin from "firebase-admin"; diff --git a/delete-user-data/functions/__tests__/runBatchPubSubDeletions.test.ts b/delete-user-data/functions/__tests__/runBatchPubSubDeletions.test.ts index 02ff79d7d9..7516a10d30 100644 --- a/delete-user-data/functions/__tests__/runBatchPubSubDeletions.test.ts +++ b/delete-user-data/functions/__tests__/runBatchPubSubDeletions.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { runBatchPubSubDeletions } from "../src/runBatchPubSubDeletions"; import setupEnvironment from "./helpers/setupEnvironment"; diff --git a/delete-user-data/functions/__tests__/search.test.ts b/delete-user-data/functions/__tests__/search.test.ts index 161dd8167a..d0413dd1b1 100644 --- a/delete-user-data/functions/__tests__/search.test.ts +++ b/delete-user-data/functions/__tests__/search.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { UserRecord } from "firebase-admin/lib/auth/user-record"; import { search } from "../src/search"; diff --git a/delete-user-data/functions/__tests__/searchFunction.test.ts b/delete-user-data/functions/__tests__/searchFunction.test.ts index be5b28382a..570085c643 100644 --- a/delete-user-data/functions/__tests__/searchFunction.test.ts +++ b/delete-user-data/functions/__tests__/searchFunction.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { UserRecord } from "firebase-functions/v1/auth"; import { createFirebaseUser, waitForDocumentDeletion } from "./helpers"; diff --git a/delete-user-data/functions/__tests__/setupTests.ts b/delete-user-data/functions/__tests__/setupTests.ts index 45bd417df5..4b104734b9 100644 --- a/delete-user-data/functions/__tests__/setupTests.ts +++ b/delete-user-data/functions/__tests__/setupTests.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import path from "path"; (async function () { diff --git a/delete-user-data/functions/jest.config.js b/delete-user-data/functions/jest.config.js index c506da087d..0dad5ada5a 100644 --- a/delete-user-data/functions/jest.config.js +++ b/delete-user-data/functions/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const packageJson = require("./package.json"); module.exports = { diff --git a/delete-user-data/functions/src/recursiveDelete.ts b/delete-user-data/functions/src/recursiveDelete.ts index 1c4cb41713..ca0d0f6a37 100644 --- a/delete-user-data/functions/src/recursiveDelete.ts +++ b/delete-user-data/functions/src/recursiveDelete.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; const MAX_RETRY_ATTEMPTS = 3; diff --git a/delete-user-data/functions/src/runBatchPubSubDeletions.ts b/delete-user-data/functions/src/runBatchPubSubDeletions.ts index e447b76b05..71d8da664b 100644 --- a/delete-user-data/functions/src/runBatchPubSubDeletions.ts +++ b/delete-user-data/functions/src/runBatchPubSubDeletions.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import chunk from "lodash.chunk"; const { PubSub } = require("@google-cloud/pubsub"); diff --git a/delete-user-data/functions/src/runCustomSearchFunction.ts b/delete-user-data/functions/src/runCustomSearchFunction.ts index 7763824487..2569da16f1 100644 --- a/delete-user-data/functions/src/runCustomSearchFunction.ts +++ b/delete-user-data/functions/src/runCustomSearchFunction.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { runBatchPubSubDeletions } from "./runBatchPubSubDeletions"; import * as logs from "./logs"; import config from "./config"; diff --git a/delete-user-data/functions/src/search.ts b/delete-user-data/functions/src/search.ts index 4f3d663eca..83dc211fb2 100644 --- a/delete-user-data/functions/src/search.ts +++ b/delete-user-data/functions/src/search.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import * as config from "./config"; const { PubSub } = require("@google-cloud/pubsub"); diff --git a/delete-user-data/functions/src/types.ts b/delete-user-data/functions/src/types.ts index 7c28f20186..065090ac09 100644 --- a/delete-user-data/functions/src/types.ts +++ b/delete-user-data/functions/src/types.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export type Paths = { firestorePaths: string[]; }; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/jest.config.js b/firestore-bigquery-export/firestore-bigquery-change-tracker/jest.config.js index 6db0ea596d..7e64dfa96f 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/jest.config.js +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const packageJson = require("./package.json"); module.exports = { diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/alternativeProject.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/alternativeProject.test.ts index 52a5cf9c2f..c930a23e33 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/alternativeProject.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/alternativeProject.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery } from "@google-cloud/bigquery"; import { FirestoreDocumentChangeEvent } from "../.."; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/checkUpdates.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/checkUpdates.test.ts index c9c7ece670..a059746c53 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/checkUpdates.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/checkUpdates.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery } from "@google-cloud/bigquery"; import { FirestoreDocumentChangeEvent } from "../.."; import { changeTracker, changeTrackerEvent } from "../fixtures/changeTracker"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/clustering.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/clustering.test.ts index c505be20ec..c720c158d1 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/clustering.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/clustering.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery, Dataset, Table } from "@google-cloud/bigquery"; import { FirestoreDocumentChangeEvent } from "../.."; import { RawChangelogSchema } from "../../bigquery/schema"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts index a17fa74142..c642de74ca 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery, Dataset, Table } from "@google-cloud/bigquery"; const { logger } = require("firebase-functions"); import waitForExpect from "wait-for-expect"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/failedTransaction.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/failedTransaction.test.ts index c1b7c9e948..0558adc946 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/failedTransaction.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/failedTransaction.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { ChangeTrackerConfig } from "../../bigquery/types"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestMaterializedView.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestMaterializedView.test.ts index 79a753a99a..c26fb4db02 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestMaterializedView.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestMaterializedView.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery, Dataset, diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestView.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestView.test.ts index a73c48389c..ab9d3aa848 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestView.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestView.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { initializeLatestView } from "../../../bigquery/initializeLatestView"; import { initializeLatestMaterializedView } from "../../../bigquery/initializeLatestMaterializedView"; import { ChangeTrackerConfig } from "../../../bigquery/types"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/integration.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/integration.test.ts index e65f3c511e..8b10169d3f 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/integration.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/integration.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery, Dataset, diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/shouldRecreateMaterializedView.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/shouldRecreateMaterializedView.test.ts index 93791bf894..af023dac34 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/shouldRecreateMaterializedView.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/shouldRecreateMaterializedView.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery, Dataset, TableMetadata } from "@google-cloud/bigquery"; import { firestore } from "firebase-admin"; import { RawChangelogViewSchema } from "../../../bigquery/schema"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning.test.ts index 0fb8e975f8..4144cfff43 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { BigQuery, Dataset, Table } from "@google-cloud/bigquery"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/config.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/config.test.ts index ee4428ff9a..5e6512718d 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/config.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/config.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { PartitioningConfig, PartitioningType, diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/converter.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/converter.test.ts index 4a77a537ab..b5cfdee037 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/converter.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/converter.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { PartitionValueConverter } from "../../../bigquery/partitioning/converter"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/stresstest.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/stresstest.test.ts index 8e0a896996..2fbfeb18d0 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/stresstest.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/stresstest.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery, Dataset, Table } from "@google-cloud/bigquery"; import { FirestoreDocumentChangeEvent } from "../.."; import { RawChangelogSchema } from "../../bigquery"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/wildcardDocument.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/wildcardDocument.test.ts index 56b9463307..f264f9eed5 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/wildcardDocument.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/wildcardDocument.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery, Dataset, Table } from "@google-cloud/bigquery"; import { FirestoreDocumentChangeEvent } from "../.."; import { RawChangelogSchema } from "../../bigquery"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/changeTracker.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/changeTracker.ts index dab94e1789..b6465dc60d 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/changeTracker.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/changeTracker.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { firestore } from "firebase-admin"; import { ChangeType, diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/clearTables.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/clearTables.ts index 486e07877f..0022c63c7a 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/clearTables.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/clearTables.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery } from "@google-cloud/bigquery"; export const deleteTable = async ({ diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/queries.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/queries.ts index 89bee61d4a..68752e4a2e 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/queries.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/queries.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery } from "@google-cloud/bigquery"; export const defaultQuery = ( diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/logger.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/logger.test.ts index 8a056d84dc..c00958bafc 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/logger.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/logger.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Logger, LogLevel, logger as defaultLogger } from "../logger"; import { logger as funcsLogger } from "firebase-functions"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/checkUpdates.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/checkUpdates.ts index 6313f32cc5..54685e7591 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/checkUpdates.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/checkUpdates.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Table, TableMetadata } from "@google-cloud/bigquery/build/src/table"; import { Partitioning } from "./partitioning"; import { PartitioningConfig } from "./partitioning/config"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/clustering.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/clustering.ts index 9e518af78d..4e4856c4e8 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/clustering.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/clustering.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { ChangeTrackerConfig } from "."; import * as logs from "../logs"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts index 4addaeec9d..93e10538fc 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { initializeApp } from "firebase-admin/app"; import { getFirestore } from "firebase-admin/firestore"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestMaterializedView.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestMaterializedView.ts index 67cc1db642..8241af8a9f 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestMaterializedView.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestMaterializedView.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery, Table, TableMetadata } from "@google-cloud/bigquery"; import { ChangeTrackerConfig } from "."; import * as logs from "../logs"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestView.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestView.ts index 9f9b59eb1e..b0e7fc9394 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestView.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestView.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery, Dataset, diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/config.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/config.ts index 48165b2fcc..e516c96797 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/config.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/config.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /** Granularity for BigQuery time-based partitioning. */ export type TimePartitioningGranularity = "HOUR" | "DAY" | "MONTH" | "YEAR"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/converter.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/converter.ts index 8d008d635e..1186d450bf 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/converter.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/converter.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as firebase from "firebase-admin"; import { BigQuery } from "@google-cloud/bigquery"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/index.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/index.ts index 038181df74..cd7ee6b251 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/index.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/index.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as bigquery from "@google-cloud/bigquery"; import * as functions from "firebase-functions"; import { TableField } from "@google-cloud/bigquery"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/types.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/types.ts index 0f7087e3da..fed3c92f3b 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/types.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/types.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { PartitioningStrategy } from "./partitioning/config"; /** diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/utils.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/utils.test.ts index f4cf8045f8..e0fc1cee2e 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/utils.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/utils.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { waitForInitialization } from "./utils"; import { Dataset, Table } from "@google-cloud/bigquery"; import * as logs from "../logs"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/utils.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/utils.ts index 0a67d70dbd..3caade8746 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/utils.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/utils.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Dataset, Table } from "@google-cloud/bigquery"; import * as logs from "../logs"; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/validateProject.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/validateProject.ts index 9c84c5a222..329fd383c0 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/validateProject.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/validateProject.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const { ProjectsClient } = require("@google-cloud/resource-manager"); /* TODO: searchProjectsAsync sometimes returns {}. diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/types.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/types.ts index 1c72df715e..de9b53b5df 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/types.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/types.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export enum PartitionFieldType { DATE = "DATE", DATETIME = "DATETIME", diff --git a/firestore-bigquery-export/functions/__tests__/__mocks__/console.ts b/firestore-bigquery-export/functions/__tests__/__mocks__/console.ts index 92fd6eb491..3e2ba68937 100644 --- a/firestore-bigquery-export/functions/__tests__/__mocks__/console.ts +++ b/firestore-bigquery-export/functions/__tests__/__mocks__/console.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { logger } from "firebase-functions"; export const mockConsoleLog = jest.spyOn(logger, "log").mockImplementation(); diff --git a/firestore-bigquery-export/functions/__tests__/__mocks__/firestore.ts b/firestore-bigquery-export/functions/__tests__/__mocks__/firestore.ts index d1603f4a2a..62d2abb243 100644 --- a/firestore-bigquery-export/functions/__tests__/__mocks__/firestore.ts +++ b/firestore-bigquery-export/functions/__tests__/__mocks__/firestore.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as functionsTestInit from "firebase-functions-test"; export const snapshot = ( diff --git a/firestore-bigquery-export/functions/__tests__/config.test.ts b/firestore-bigquery-export/functions/__tests__/config.test.ts index b398c03c37..6970f7cc94 100644 --- a/firestore-bigquery-export/functions/__tests__/config.test.ts +++ b/firestore-bigquery-export/functions/__tests__/config.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { readFileSync } from "fs"; import { resolve as pathResolve } from "path"; diff --git a/firestore-bigquery-export/functions/__tests__/e2e.test.ts b/firestore-bigquery-export/functions/__tests__/e2e.test.ts index 4773a3e25b..d94d0405ab 100644 --- a/firestore-bigquery-export/functions/__tests__/e2e.test.ts +++ b/firestore-bigquery-export/functions/__tests__/e2e.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { BigQuery } from "@google-cloud/bigquery"; diff --git a/firestore-bigquery-export/functions/__tests__/fixtures/documentData.ts b/firestore-bigquery-export/functions/__tests__/fixtures/documentData.ts index 99ecbb7094..49f8d32515 100644 --- a/firestore-bigquery-export/functions/__tests__/fixtures/documentData.ts +++ b/firestore-bigquery-export/functions/__tests__/fixtures/documentData.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; export const documentData = async () => { diff --git a/firestore-bigquery-export/functions/__tests__/functions.test.ts b/firestore-bigquery-export/functions/__tests__/functions.test.ts index d759c377e7..38ec652672 100644 --- a/firestore-bigquery-export/functions/__tests__/functions.test.ts +++ b/firestore-bigquery-export/functions/__tests__/functions.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { logger } from "firebase-functions"; import * as functionsTestInit from "../node_modules/firebase-functions-test"; diff --git a/firestore-bigquery-export/functions/__tests__/jest.setup.ts b/firestore-bigquery-export/functions/__tests__/jest.setup.ts index 3c093138bf..789df7ebe7 100644 --- a/firestore-bigquery-export/functions/__tests__/jest.setup.ts +++ b/firestore-bigquery-export/functions/__tests__/jest.setup.ts @@ -1 +1,17 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + global.config = () => require("../src/config").default; diff --git a/firestore-bigquery-export/functions/__tests__/test.types.d.ts b/firestore-bigquery-export/functions/__tests__/test.types.d.ts index bf5ab464d8..ab2b77c830 100644 --- a/firestore-bigquery-export/functions/__tests__/test.types.d.ts +++ b/firestore-bigquery-export/functions/__tests__/test.types.d.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + declare namespace NodeJS { interface Global { config: () => jest.ModuleMocker; diff --git a/firestore-bigquery-export/functions/__tests__/util.test.ts b/firestore-bigquery-export/functions/__tests__/util.test.ts index 76d54c2bd3..d0bf3cc961 100644 --- a/firestore-bigquery-export/functions/__tests__/util.test.ts +++ b/firestore-bigquery-export/functions/__tests__/util.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { getChangeType } from "../src/util"; import * as functionsTestInit from "firebase-functions-test"; import { ChangeType } from "@firebaseextensions/firestore-bigquery-change-tracker"; diff --git a/firestore-bigquery-export/functions/big-query-table-test/install-script.js b/firestore-bigquery-export/functions/big-query-table-test/install-script.js index 51ee7c2f78..1c668d3917 100644 --- a/firestore-bigquery-export/functions/big-query-table-test/install-script.js +++ b/firestore-bigquery-export/functions/big-query-table-test/install-script.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const admin = require("firebase-admin"); const faker = require("faker"); diff --git a/firestore-bigquery-export/functions/jest.config.js b/firestore-bigquery-export/functions/jest.config.js index 3dbc0c7c13..83bed38c0c 100644 --- a/firestore-bigquery-export/functions/jest.config.js +++ b/firestore-bigquery-export/functions/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /** @type {import('ts-jest').JestConfigWithTsJest} */ const packageJson = require("./package.json"); diff --git a/firestore-bigquery-export/functions/src/events.ts b/firestore-bigquery-export/functions/src/events.ts index 0d6be8a217..a08b20cdb6 100644 --- a/firestore-bigquery-export/functions/src/events.ts +++ b/firestore-bigquery-export/functions/src/events.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as eventArc from "firebase-admin/eventarc"; const { getEventarc } = eventArc; diff --git a/firestore-bigquery-export/functions/stress_test/count.js b/firestore-bigquery-export/functions/stress_test/count.js index 6f9ea64d96..01fc6c2c43 100644 --- a/firestore-bigquery-export/functions/stress_test/count.js +++ b/firestore-bigquery-export/functions/stress_test/count.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const admin = require("firebase-admin"); // Initialize Firebase Admin with your credentials diff --git a/firestore-bigquery-export/functions/stress_test/main.js b/firestore-bigquery-export/functions/stress_test/main.js index cdecdff8e9..f9288af873 100644 --- a/firestore-bigquery-export/functions/stress_test/main.js +++ b/firestore-bigquery-export/functions/stress_test/main.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const { Worker } = require("worker_threads"); const { performance } = require("perf_hooks"); const path = require("path"); diff --git a/firestore-bigquery-export/functions/stress_test/worker.js b/firestore-bigquery-export/functions/stress_test/worker.js index 3f53e985b9..5e1721a330 100644 --- a/firestore-bigquery-export/functions/stress_test/worker.js +++ b/firestore-bigquery-export/functions/stress_test/worker.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const { parentPort, workerData } = require("worker_threads"); const admin = require("firebase-admin"); const { v4: uuidv4 } = require("uuid"); diff --git a/firestore-bigquery-export/scripts/gen-schema-view/__mocks__/inquirer.js b/firestore-bigquery-export/scripts/gen-schema-view/__mocks__/inquirer.js index d8fdfd9906..7cbb0a6e2a 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/__mocks__/inquirer.js +++ b/firestore-bigquery-export/scripts/gen-schema-view/__mocks__/inquirer.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const prompt = jest.fn().mockResolvedValue({}); const createPromptModule = jest.fn().mockReturnValue(prompt); diff --git a/firestore-bigquery-export/scripts/gen-schema-view/jest.config.js b/firestore-bigquery-export/scripts/gen-schema-view/jest.config.js index 5cb8d2e58a..cc42c6dc18 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/jest.config.js +++ b/firestore-bigquery-export/scripts/gen-schema-view/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const packageJson = require("./package.json"); module.exports = { diff --git a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/bigquery/schema/extractors.test.ts b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/bigquery/schema/extractors.test.ts index f73a2501aa..8c5cde36cc 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/bigquery/schema/extractors.test.ts +++ b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/bigquery/schema/extractors.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { jsonExtractScalar, jsonExtract } from "../../../schema/extractors"; import { FirestoreField } from "../../../schema"; diff --git a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/bigquery/schema/processLeafField.test.ts b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/bigquery/schema/processLeafField.test.ts index 8ce2d244d3..c3a604a199 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/bigquery/schema/processLeafField.test.ts +++ b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/bigquery/schema/processLeafField.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { FirestoreField } from "../../../schema"; import { processLeafField } from "../../../schema/processLeafField"; diff --git a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/index.test.ts b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/index.test.ts index e84df471be..8f8a8703e4 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/index.test.ts +++ b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/index.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { parseConfig } from "../../../src/config"; import { promptInquirer } from "../../../src/config/interactive"; import { diff --git a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/interactive.test.ts b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/interactive.test.ts index 3a5b7aba38..938a2318de 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/interactive.test.ts +++ b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/interactive.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { describe, it, diff --git a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/non-interactive.test.ts b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/non-interactive.test.ts index 8764736cfc..ab9581583b 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/non-interactive.test.ts +++ b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/config/non-interactive.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { describe, it, diff --git a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/e2e/helpers/setup.ts b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/e2e/helpers/setup.ts index b1b4fb808b..1becc687cd 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/e2e/helpers/setup.ts +++ b/firestore-bigquery-export/scripts/gen-schema-view/src/__tests__/e2e/helpers/setup.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery, Table } from "@google-cloud/bigquery"; export const setupBQ = async ( diff --git a/firestore-bigquery-export/scripts/gen-schema-view/src/schema/processLeafField.ts b/firestore-bigquery-export/scripts/gen-schema-view/src/schema/processLeafField.ts index 20a954fd08..ae91f794a0 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/src/schema/processLeafField.ts +++ b/firestore-bigquery-export/scripts/gen-schema-view/src/schema/processLeafField.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { FirestoreField, firestoreToBigQueryFieldType, diff --git a/firestore-bigquery-export/scripts/import/__tests__/e2e.test.ts b/firestore-bigquery-export/scripts/import/__tests__/e2e.test.ts index b722af27f7..93eedd3d97 100644 --- a/firestore-bigquery-export/scripts/import/__tests__/e2e.test.ts +++ b/firestore-bigquery-export/scripts/import/__tests__/e2e.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { BigQuery } from "@google-cloud/bigquery"; import * as childProcess from "child_process"; import * as admin from "firebase-admin"; diff --git a/firestore-bigquery-export/scripts/import/__tests__/getRowsFromDocs.test.ts b/firestore-bigquery-export/scripts/import/__tests__/getRowsFromDocs.test.ts index baa6a427e3..16ffec5045 100644 --- a/firestore-bigquery-export/scripts/import/__tests__/getRowsFromDocs.test.ts +++ b/firestore-bigquery-export/scripts/import/__tests__/getRowsFromDocs.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { ChangeType } from "@firebaseextensions/firestore-bigquery-change-tracker"; import { getRowsFromDocs } from "../src/helper"; diff --git a/firestore-bigquery-export/scripts/import/__tests__/helpers/waitFor.ts b/firestore-bigquery-export/scripts/import/__tests__/helpers/waitFor.ts index b0a1584594..9e0198d7a2 100644 --- a/firestore-bigquery-export/scripts/import/__tests__/helpers/waitFor.ts +++ b/firestore-bigquery-export/scripts/import/__tests__/helpers/waitFor.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export async function repeat( fn: { (): Promise; (): any }, until: { ($: any): any; (arg0: any): any }, diff --git a/firestore-bigquery-export/scripts/import/__tests__/multiThreadCollectionGroupBug.test.ts b/firestore-bigquery-export/scripts/import/__tests__/multiThreadCollectionGroupBug.test.ts index d1068ee586..8cfc924d3b 100644 --- a/firestore-bigquery-export/scripts/import/__tests__/multiThreadCollectionGroupBug.test.ts +++ b/firestore-bigquery-export/scripts/import/__tests__/multiThreadCollectionGroupBug.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { runMultiThread } from "../src/run-multi-thread"; import * as admin from "firebase-admin"; import { CliConfig } from "../src/types"; diff --git a/firestore-bigquery-export/scripts/import/__tests__/runMultiThread.test.ts b/firestore-bigquery-export/scripts/import/__tests__/runMultiThread.test.ts index ae681c1e01..413193aeff 100644 --- a/firestore-bigquery-export/scripts/import/__tests__/runMultiThread.test.ts +++ b/firestore-bigquery-export/scripts/import/__tests__/runMultiThread.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { runMultiThread } from "../src/run-multi-thread"; import * as admin from "firebase-admin"; import { CliConfig } from "../src/types"; diff --git a/firestore-bigquery-export/scripts/import/__tests__/runMultiThreadMock.test.ts b/firestore-bigquery-export/scripts/import/__tests__/runMultiThreadMock.test.ts index 22fa36c59d..732cb7e1eb 100644 --- a/firestore-bigquery-export/scripts/import/__tests__/runMultiThreadMock.test.ts +++ b/firestore-bigquery-export/scripts/import/__tests__/runMultiThreadMock.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { runMultiThread } from "../src/run-multi-thread"; import * as workerpool from "workerpool"; import { CliConfig } from "../src/types"; diff --git a/firestore-bigquery-export/scripts/import/__tests__/test.types.d.ts b/firestore-bigquery-export/scripts/import/__tests__/test.types.d.ts index bf5ab464d8..ab2b77c830 100644 --- a/firestore-bigquery-export/scripts/import/__tests__/test.types.d.ts +++ b/firestore-bigquery-export/scripts/import/__tests__/test.types.d.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + declare namespace NodeJS { interface Global { config: () => jest.ModuleMocker; diff --git a/firestore-bigquery-export/scripts/import/jest.config.js b/firestore-bigquery-export/scripts/import/jest.config.js index db5538023e..7c3aea87dc 100644 --- a/firestore-bigquery-export/scripts/import/jest.config.js +++ b/firestore-bigquery-export/scripts/import/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const packageJson = require("./package.json"); module.exports = { diff --git a/firestore-bigquery-export/scripts/import/src/config.ts b/firestore-bigquery-export/scripts/import/src/config.ts index 2c956374f9..95db570113 100644 --- a/firestore-bigquery-export/scripts/import/src/config.ts +++ b/firestore-bigquery-export/scripts/import/src/config.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as program from "commander"; import filenamify from "filenamify"; import inquirer from "inquirer"; diff --git a/firestore-bigquery-export/scripts/import/src/helper.ts b/firestore-bigquery-export/scripts/import/src/helper.ts index 97717763c8..9f61200edb 100644 --- a/firestore-bigquery-export/scripts/import/src/helper.ts +++ b/firestore-bigquery-export/scripts/import/src/helper.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { FirestoreBigQueryEventHistoryTracker } from "@firebaseextensions/firestore-bigquery-change-tracker"; import { BigQuery } from "@google-cloud/bigquery"; diff --git a/firestore-bigquery-export/scripts/import/src/logs.ts b/firestore-bigquery-export/scripts/import/src/logs.ts index f180e15c3c..484e96e476 100644 --- a/firestore-bigquery-export/scripts/import/src/logs.ts +++ b/firestore-bigquery-export/scripts/import/src/logs.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { CliConfig } from "./types"; export const finishedImporting = (rowCount: number) => { diff --git a/firestore-bigquery-export/scripts/import/src/program.ts b/firestore-bigquery-export/scripts/import/src/program.ts index 24f4df2c88..94e10540d0 100644 --- a/firestore-bigquery-export/scripts/import/src/program.ts +++ b/firestore-bigquery-export/scripts/import/src/program.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as program from "commander"; const packageJson = require("../package.json"); diff --git a/firestore-bigquery-export/scripts/import/src/run-multi-thread.ts b/firestore-bigquery-export/scripts/import/src/run-multi-thread.ts index fc7f0a71c4..e0d7199fbc 100644 --- a/firestore-bigquery-export/scripts/import/src/run-multi-thread.ts +++ b/firestore-bigquery-export/scripts/import/src/run-multi-thread.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as firebase from "firebase-admin"; import { getFirestore } from "firebase-admin/firestore"; import { cpus } from "os"; diff --git a/firestore-bigquery-export/scripts/import/src/run-single-thread.ts b/firestore-bigquery-export/scripts/import/src/run-single-thread.ts index 9ed00ae92d..f3bd1bdaa5 100644 --- a/firestore-bigquery-export/scripts/import/src/run-single-thread.ts +++ b/firestore-bigquery-export/scripts/import/src/run-single-thread.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { FirestoreBigQueryEventHistoryTracker, FirestoreDocumentChangeEvent, diff --git a/firestore-bigquery-export/scripts/import/src/types.ts b/firestore-bigquery-export/scripts/import/src/types.ts index 2c384000b1..62cd5719f9 100644 --- a/firestore-bigquery-export/scripts/import/src/types.ts +++ b/firestore-bigquery-export/scripts/import/src/types.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; export interface CliConfig { diff --git a/firestore-bigquery-export/scripts/import/src/worker.ts b/firestore-bigquery-export/scripts/import/src/worker.ts index b1a89b1160..b520e14964 100644 --- a/firestore-bigquery-export/scripts/import/src/worker.ts +++ b/firestore-bigquery-export/scripts/import/src/worker.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { FirestoreBigQueryEventHistoryTracker, FirestoreDocumentChangeEvent, diff --git a/firestore-counter/functions/__tests__/test.types.d.ts b/firestore-counter/functions/__tests__/test.types.d.ts index bf5ab464d8..ab2b77c830 100644 --- a/firestore-counter/functions/__tests__/test.types.d.ts +++ b/firestore-counter/functions/__tests__/test.types.d.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + declare namespace NodeJS { interface Global { config: () => jest.ModuleMocker; diff --git a/firestore-counter/functions/jest.config.js b/firestore-counter/functions/jest.config.js index da7a219816..339c8fcef6 100644 --- a/firestore-counter/functions/jest.config.js +++ b/firestore-counter/functions/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + module.exports = { rootDir: "./", preset: "ts-jest", diff --git a/firestore-counter/functions/src/events.ts b/firestore-counter/functions/src/events.ts index 4fdd5ba553..a59423cf53 100644 --- a/firestore-counter/functions/src/events.ts +++ b/firestore-counter/functions/src/events.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as eventArc from "firebase-admin/eventarc"; const { getEventarc } = eventArc; diff --git a/firestore-send-email/functions/__tests__/config.test.ts b/firestore-send-email/functions/__tests__/config.test.ts index d76b5af634..4c2c389cac 100644 --- a/firestore-send-email/functions/__tests__/config.test.ts +++ b/firestore-send-email/functions/__tests__/config.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as functionsTestInit from "firebase-functions-test"; import mockedEnv from "mocked-env"; import { AuthenticatonType, Config } from "../src/types"; diff --git a/firestore-send-email/functions/__tests__/createSMTPServer.ts b/firestore-send-email/functions/__tests__/createSMTPServer.ts index e3617c6e79..5c95261b42 100644 --- a/firestore-send-email/functions/__tests__/createSMTPServer.ts +++ b/firestore-send-email/functions/__tests__/createSMTPServer.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const SMTPServer = require("smtp-server").SMTPServer; export const smtpServer = () => { diff --git a/firestore-send-email/functions/__tests__/e2e.test.ts b/firestore-send-email/functions/__tests__/e2e.test.ts index 871b24f88b..c327d8fc5c 100644 --- a/firestore-send-email/functions/__tests__/e2e.test.ts +++ b/firestore-send-email/functions/__tests__/e2e.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { smtpServer } from "./createSMTPServer"; diff --git a/firestore-send-email/functions/__tests__/e2e/sendgrid.test.ts b/firestore-send-email/functions/__tests__/e2e/sendgrid.test.ts index c53e296cf3..1ba0680685 100644 --- a/firestore-send-email/functions/__tests__/e2e/sendgrid.test.ts +++ b/firestore-send-email/functions/__tests__/e2e/sendgrid.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // This test suite assumes local emulator is running the extension, with the following config: // AUTH_TYPE=UsernamePassword diff --git a/firestore-send-email/functions/__tests__/functions.test.ts b/firestore-send-email/functions/__tests__/functions.test.ts index b3b30feba4..cad6eaf61e 100644 --- a/firestore-send-email/functions/__tests__/functions.test.ts +++ b/firestore-send-email/functions/__tests__/functions.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const { logger } = require("firebase-functions"); const consoleLogSpy = jest.spyOn(logger, "log").mockImplementation(); diff --git a/firestore-send-email/functions/__tests__/helpers.test.ts b/firestore-send-email/functions/__tests__/helpers.test.ts index 817b5d8978..2248d337b1 100644 --- a/firestore-send-email/functions/__tests__/helpers.test.ts +++ b/firestore-send-email/functions/__tests__/helpers.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import Mail = require("nodemailer/lib/mailer"); const { logger } = require("firebase-functions"); diff --git a/firestore-send-email/functions/__tests__/jest.setup.ts b/firestore-send-email/functions/__tests__/jest.setup.ts index 3c093138bf..789df7ebe7 100644 --- a/firestore-send-email/functions/__tests__/jest.setup.ts +++ b/firestore-send-email/functions/__tests__/jest.setup.ts @@ -1 +1,17 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + global.config = () => require("../src/config").default; diff --git a/firestore-send-email/functions/__tests__/nodemailer-sendgrid/index.test.ts b/firestore-send-email/functions/__tests__/nodemailer-sendgrid/index.test.ts index bab3e3445c..5fd555cdf3 100644 --- a/firestore-send-email/functions/__tests__/nodemailer-sendgrid/index.test.ts +++ b/firestore-send-email/functions/__tests__/nodemailer-sendgrid/index.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as sgMail from "@sendgrid/mail"; import { SendGridTransport } from "../../src/nodemailer-sendgrid"; import { diff --git a/firestore-send-email/functions/__tests__/prepare-payload.test.ts b/firestore-send-email/functions/__tests__/prepare-payload.test.ts index c9a7be394d..13f5e61e6b 100644 --- a/firestore-send-email/functions/__tests__/prepare-payload.test.ts +++ b/firestore-send-email/functions/__tests__/prepare-payload.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { preparePayload, setDependencies } from "../src/prepare-payload"; class MockTemplates { diff --git a/firestore-send-email/functions/__tests__/test.types.d.ts b/firestore-send-email/functions/__tests__/test.types.d.ts index bf5ab464d8..ab2b77c830 100644 --- a/firestore-send-email/functions/__tests__/test.types.d.ts +++ b/firestore-send-email/functions/__tests__/test.types.d.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + declare namespace NodeJS { interface Global { config: () => jest.ModuleMocker; diff --git a/firestore-send-email/functions/__tests__/validation.test.ts b/firestore-send-email/functions/__tests__/validation.test.ts index e54990b3cc..78233d8db6 100644 --- a/firestore-send-email/functions/__tests__/validation.test.ts +++ b/firestore-send-email/functions/__tests__/validation.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { validatePayload, ValidationError } from "../src/validation"; describe("validatePayload", () => { diff --git a/firestore-send-email/functions/jest.config.js b/firestore-send-email/functions/jest.config.js index d9dc123408..26a5af59fb 100644 --- a/firestore-send-email/functions/jest.config.js +++ b/firestore-send-email/functions/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const packageJson = require("./package.json"); module.exports = { diff --git a/firestore-send-email/functions/jest.teardown.js b/firestore-send-email/functions/jest.teardown.js index ff89f0d532..5fb2225bfb 100644 --- a/firestore-send-email/functions/jest.teardown.js +++ b/firestore-send-email/functions/jest.teardown.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + module.exports = async function () { delete process.env.LOCATION; delete process.env.MAIL_COLLECTION; diff --git a/firestore-send-email/functions/src/events.ts b/firestore-send-email/functions/src/events.ts index 38b53c9639..ea7a3817ea 100644 --- a/firestore-send-email/functions/src/events.ts +++ b/firestore-send-email/functions/src/events.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Channel, getEventarc } from "firebase-admin/eventarc"; let eventChannel: Channel | undefined; diff --git a/firestore-send-email/functions/src/helpers.ts b/firestore-send-email/functions/src/helpers.ts index 88e2be15cb..4d5dac74d7 100644 --- a/firestore-send-email/functions/src/helpers.ts +++ b/firestore-send-email/functions/src/helpers.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { createTransport } from "nodemailer"; import { URL } from "url"; import { invalidTlsOptions, invalidURI } from "./logs"; diff --git a/firestore-send-email/functions/src/nodemailer-sendgrid/index.ts b/firestore-send-email/functions/src/nodemailer-sendgrid/index.ts index e02807aa35..fb0a25cbfc 100644 --- a/firestore-send-email/functions/src/nodemailer-sendgrid/index.ts +++ b/firestore-send-email/functions/src/nodemailer-sendgrid/index.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as sgMail from "@sendgrid/mail"; import { SendGridTransportOptions, diff --git a/firestore-send-email/functions/src/nodemailer-sendgrid/types.ts b/firestore-send-email/functions/src/nodemailer-sendgrid/types.ts index 3f7ed10c5c..15e0996043 100644 --- a/firestore-send-email/functions/src/nodemailer-sendgrid/types.ts +++ b/firestore-send-email/functions/src/nodemailer-sendgrid/types.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export interface SendGridTransportOptions { apiKey?: string; [key: string]: unknown; diff --git a/firestore-send-email/functions/src/prepare-payload.ts b/firestore-send-email/functions/src/prepare-payload.ts index 5574c732d0..8bb53f8ccf 100644 --- a/firestore-send-email/functions/src/prepare-payload.ts +++ b/firestore-send-email/functions/src/prepare-payload.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { DocumentData } from "firebase-admin/firestore"; import { validatePayload, diff --git a/firestore-send-email/functions/src/types.ts b/firestore-send-email/functions/src/types.ts index 1b476fb234..463f72ef10 100644 --- a/firestore-send-email/functions/src/types.ts +++ b/firestore-send-email/functions/src/types.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as nodemailer from "nodemailer"; import * as admin from "firebase-admin"; import * as Handlebars from "handlebars"; diff --git a/firestore-send-email/functions/src/validation.ts b/firestore-send-email/functions/src/validation.ts index 98f4e4ca7c..a43f5ea5a7 100644 --- a/firestore-send-email/functions/src/validation.ts +++ b/firestore-send-email/functions/src/validation.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { z } from "zod"; import { logger } from "firebase-functions/v1"; diff --git a/firestore-send-email/scripts/oauth2-refresh-token-helper.js b/firestore-send-email/scripts/oauth2-refresh-token-helper.js index 67fa569008..6ab00b263f 100644 --- a/firestore-send-email/scripts/oauth2-refresh-token-helper.js +++ b/firestore-send-email/scripts/oauth2-refresh-token-helper.js @@ -1,4 +1,19 @@ #!/usr/bin/env node +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /** * Google OAuth Refresh Token Generator diff --git a/firestore-shorten-urls-bitly/functions/jest.config.js b/firestore-shorten-urls-bitly/functions/jest.config.js index d906041181..1e6b64fc48 100644 --- a/firestore-shorten-urls-bitly/functions/jest.config.js +++ b/firestore-shorten-urls-bitly/functions/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const packageJson = require("./package.json"); module.exports = { diff --git a/firestore-shorten-urls-bitly/functions/src/events.ts b/firestore-shorten-urls-bitly/functions/src/events.ts index a39ef6dc50..09136554e8 100644 --- a/firestore-shorten-urls-bitly/functions/src/events.ts +++ b/firestore-shorten-urls-bitly/functions/src/events.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Channel, getEventarc } from "firebase-admin/eventarc"; const EXTENSION_NAME = "firestore-shorten-urls-bitly"; diff --git a/firestore-translate-text/functions/__tests__/config.test.ts b/firestore-translate-text/functions/__tests__/config.test.ts index ea25187373..d702ee1820 100644 --- a/firestore-translate-text/functions/__tests__/config.test.ts +++ b/firestore-translate-text/functions/__tests__/config.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { readFileSync } from "fs"; import { resolve as pathResolve } from "path"; import * as functionsTestInit from "firebase-functions-test"; diff --git a/firestore-translate-text/functions/__tests__/functions.test.ts b/firestore-translate-text/functions/__tests__/functions.test.ts index c4c819dea5..7fd9ff2d94 100644 --- a/firestore-translate-text/functions/__tests__/functions.test.ts +++ b/firestore-translate-text/functions/__tests__/functions.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import mockedEnv from "mocked-env"; import * as functionsTestInit from "firebase-functions-test"; diff --git a/firestore-translate-text/functions/__tests__/jest.setup.ts b/firestore-translate-text/functions/__tests__/jest.setup.ts index 0a4d905beb..6dbe0aa9b3 100644 --- a/firestore-translate-text/functions/__tests__/jest.setup.ts +++ b/firestore-translate-text/functions/__tests__/jest.setup.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { snapshot, mockDocumentSnapshotFactory, diff --git a/firestore-translate-text/functions/__tests__/mocks/firestore.ts b/firestore-translate-text/functions/__tests__/mocks/firestore.ts index d1603f4a2a..62d2abb243 100644 --- a/firestore-translate-text/functions/__tests__/mocks/firestore.ts +++ b/firestore-translate-text/functions/__tests__/mocks/firestore.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as functionsTestInit from "firebase-functions-test"; export const snapshot = ( diff --git a/firestore-translate-text/functions/__tests__/mocks/translate.ts b/firestore-translate-text/functions/__tests__/mocks/translate.ts index 513dd351a7..083b6587e1 100644 --- a/firestore-translate-text/functions/__tests__/mocks/translate.ts +++ b/firestore-translate-text/functions/__tests__/mocks/translate.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as functionsTestInit from "firebase-functions-test"; export const testTranslations = { diff --git a/firestore-translate-text/functions/__tests__/test.types.d.ts b/firestore-translate-text/functions/__tests__/test.types.d.ts index 7df00facb6..578917f955 100644 --- a/firestore-translate-text/functions/__tests__/test.types.d.ts +++ b/firestore-translate-text/functions/__tests__/test.types.d.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + declare namespace NodeJS { interface Global { config: () => jest.ModuleMocker; diff --git a/firestore-translate-text/functions/__tests__/unit/translateMultipleBackfill.test.ts b/firestore-translate-text/functions/__tests__/unit/translateMultipleBackfill.test.ts index 7009061af1..9d3eaa3b99 100644 --- a/firestore-translate-text/functions/__tests__/unit/translateMultipleBackfill.test.ts +++ b/firestore-translate-text/functions/__tests__/unit/translateMultipleBackfill.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import * as fft from "firebase-functions-test"; import { diff --git a/firestore-translate-text/functions/jest.config.js b/firestore-translate-text/functions/jest.config.js index 801e44b58b..16d67cf6dd 100644 --- a/firestore-translate-text/functions/jest.config.js +++ b/firestore-translate-text/functions/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const packageJson = require("./package.json"); module.exports = { diff --git a/firestore-translate-text/functions/src/events.ts b/firestore-translate-text/functions/src/events.ts index 74e2df2aff..cdf1ec8f09 100644 --- a/firestore-translate-text/functions/src/events.ts +++ b/firestore-translate-text/functions/src/events.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as eventArc from "firebase-admin/eventarc"; const { getEventarc } = eventArc; diff --git a/firestore-translate-text/functions/src/logs/messages.ts b/firestore-translate-text/functions/src/logs/messages.ts index 315284ed47..4a1d07210b 100644 --- a/firestore-translate-text/functions/src/logs/messages.ts +++ b/firestore-translate-text/functions/src/logs/messages.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export const messages = { backfillComplete: (successCount: number, errorCount: number) => `Finshed backfilling translations. ${successCount} translations succeeded, ${errorCount} errors.`, diff --git a/firestore-translate-text/functions/src/translate/common.ts b/firestore-translate-text/functions/src/translate/common.ts index ec0db984e1..7b4d867657 100644 --- a/firestore-translate-text/functions/src/translate/common.ts +++ b/firestore-translate-text/functions/src/translate/common.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { v2 } from "@google-cloud/translate"; import * as logs from "../logs"; import * as events from "../events"; diff --git a/firestore-translate-text/functions/src/translate/index.ts b/firestore-translate-text/functions/src/translate/index.ts index 02e49a0f9f..a69ac4ea86 100644 --- a/firestore-translate-text/functions/src/translate/index.ts +++ b/firestore-translate-text/functions/src/translate/index.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + export { translateDocument, translateDocumentBackfill, diff --git a/firestore-translate-text/functions/src/translate/translateDocument.ts b/firestore-translate-text/functions/src/translate/translateDocument.ts index 8e5cb444ce..f271907aef 100644 --- a/firestore-translate-text/functions/src/translate/translateDocument.ts +++ b/firestore-translate-text/functions/src/translate/translateDocument.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as logs from "../logs"; import * as admin from "firebase-admin"; import * as validators from "../validators"; diff --git a/firestore-translate-text/functions/src/translate/translateMultiple.ts b/firestore-translate-text/functions/src/translate/translateMultiple.ts index 1531324b50..92a77fca1e 100644 --- a/firestore-translate-text/functions/src/translate/translateMultiple.ts +++ b/firestore-translate-text/functions/src/translate/translateMultiple.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as logs from "../logs"; import * as admin from "firebase-admin"; import config from "../config"; diff --git a/firestore-translate-text/functions/src/translate/translateSingle.ts b/firestore-translate-text/functions/src/translate/translateSingle.ts index cb85b65adb..707036027c 100644 --- a/firestore-translate-text/functions/src/translate/translateSingle.ts +++ b/firestore-translate-text/functions/src/translate/translateSingle.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as logs from "../logs"; import * as events from "../events"; import * as admin from "firebase-admin"; diff --git a/jest.config.js b/jest.config.js index 6c70e7fe5c..b51ee91d9d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + module.exports = { projects: [ "/*/functions/jest.config.js", diff --git a/license-header.tmpl b/license-header.tmpl new file mode 100644 index 0000000000..34026aee82 --- /dev/null +++ b/license-header.tmpl @@ -0,0 +1,13 @@ +Copyright {{.Year}} Google LLC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/package.json b/package.json index c503359601..d5ca515df1 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,8 @@ "scripts": { "format": "prettier --write \"**/*.{js,md,yml,ts,json,yaml}\"", "lint": "prettier --list-different \"**/*.{js,md,yml,ts,json,yaml}\"", + "license:check": "./scripts/addlicense.sh check", + "license:fix": "./scripts/addlicense.sh fix", "clean": "lerna run --parallel clean && lerna clean", "build": "lerna run --sort build", "local:emulator": "cd _emulator && firebase emulators:start -P demo-test", diff --git a/rtdb-limit-child-nodes/functions/jest.config.js b/rtdb-limit-child-nodes/functions/jest.config.js index d906041181..1e6b64fc48 100644 --- a/rtdb-limit-child-nodes/functions/jest.config.js +++ b/rtdb-limit-child-nodes/functions/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const packageJson = require("./package.json"); module.exports = { diff --git a/samples/rtdb-uppercase-messages/functions/index.js b/samples/rtdb-uppercase-messages/functions/index.js index 96b6c40a70..809d5f8143 100644 --- a/samples/rtdb-uppercase-messages/functions/index.js +++ b/samples/rtdb-uppercase-messages/functions/index.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { database, tasks, logger } from "firebase-functions/v1"; import { initializeApp } from "firebase-admin/app"; diff --git a/samples/rtdb-uppercase-messages/functions/integration-tests/functions/index.js b/samples/rtdb-uppercase-messages/functions/integration-tests/functions/index.js index 89d91d5822..de63abdd73 100644 --- a/samples/rtdb-uppercase-messages/functions/integration-tests/functions/index.js +++ b/samples/rtdb-uppercase-messages/functions/integration-tests/functions/index.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { logger } from "firebase-functions/v1"; import { onCustomEventPublished } from "firebase-functions/v2/eventarc"; diff --git a/scripts/addlicense.sh b/scripts/addlicense.sh new file mode 100755 index 0000000000..5da6ad8623 --- /dev/null +++ b/scripts/addlicense.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Checks (default) or adds Apache license headers on tracked .ts/.js files +# using google/addlicense. Usage: scripts/addlicense.sh [check|fix] +set -euo pipefail +cd "$(dirname "$0")/.." + +if ! command -v addlicense >/dev/null; then + echo "addlicense not found. Install: go install github.com/google/addlicense@v1.2.0" >&2 + exit 1 +fi + +mode="${1:-check}" +flags=(-f license-header.tmpl) +if [ "$mode" = "check" ]; then + flags+=(-check) +elif [ "$mode" != "fix" ]; then + echo "Invalid mode: $mode. Usage: $0 [check|fix]" >&2 + exit 1 +fi + +git ls-files -z -- '*.ts' '*.js' \ + | grep -zvE '(^|/)(node_modules|lib|dist|coverage)/' \ + | xargs -0 addlicense "${flags[@]}" diff --git a/storage-resize-images/functions/__tests__/__mocks__/src/config.ts b/storage-resize-images/functions/__tests__/__mocks__/src/config.ts index c98e07a3c6..3141de1681 100644 --- a/storage-resize-images/functions/__tests__/__mocks__/src/config.ts +++ b/storage-resize-images/functions/__tests__/__mocks__/src/config.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // export enum deleteImage { // always = 0, // never, diff --git a/storage-resize-images/functions/__tests__/__mocks__/src/index.ts b/storage-resize-images/functions/__tests__/__mocks__/src/index.ts index eba67b1632..c40fbe154b 100644 --- a/storage-resize-images/functions/__tests__/__mocks__/src/index.ts +++ b/storage-resize-images/functions/__tests__/__mocks__/src/index.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as functionsTestInit from "firebase-functions-test"; import { generateResizedImage as originalGenerateResizedImage } from "../../../src"; diff --git a/storage-resize-images/functions/__tests__/config.test.ts b/storage-resize-images/functions/__tests__/config.test.ts index 3ff438348b..ff6c819bb8 100644 --- a/storage-resize-images/functions/__tests__/config.test.ts +++ b/storage-resize-images/functions/__tests__/config.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import mockedEnv from "mocked-env"; const environment = { diff --git a/storage-resize-images/functions/__tests__/content-filter.test.ts b/storage-resize-images/functions/__tests__/content-filter.test.ts index 9a0d08779f..92e1b589e8 100644 --- a/storage-resize-images/functions/__tests__/content-filter.test.ts +++ b/storage-resize-images/functions/__tests__/content-filter.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { checkImageContent } from "../src/content-filter"; import * as path from "path"; import { HarmBlockThreshold } from "@google-cloud/vertexai"; diff --git a/storage-resize-images/functions/__tests__/convert-image.test.ts b/storage-resize-images/functions/__tests__/convert-image.test.ts index 08f7cb611d..0259c4faf6 100644 --- a/storage-resize-images/functions/__tests__/convert-image.test.ts +++ b/storage-resize-images/functions/__tests__/convert-image.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import mockedEnv from "mocked-env"; const imageType = require("image-type"); import * as util from "util"; diff --git a/storage-resize-images/functions/__tests__/e2e.test.ts b/storage-resize-images/functions/__tests__/e2e.test.ts index b3be26c8af..2c833288eb 100644 --- a/storage-resize-images/functions/__tests__/e2e.test.ts +++ b/storage-resize-images/functions/__tests__/e2e.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; import { Storage } from "firebase-admin/storage"; import { config } from "dotenv"; diff --git a/storage-resize-images/functions/__tests__/filters.test.ts b/storage-resize-images/functions/__tests__/filters.test.ts index 401a954679..004fe2a023 100644 --- a/storage-resize-images/functions/__tests__/filters.test.ts +++ b/storage-resize-images/functions/__tests__/filters.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as path from "path"; import * as logs from "../src/logs"; import { ObjectMetadata } from "firebase-functions/v1/storage"; diff --git a/storage-resize-images/functions/__tests__/function.test.ts b/storage-resize-images/functions/__tests__/function.test.ts index 8d869c5bd8..3e6dd77cb4 100644 --- a/storage-resize-images/functions/__tests__/function.test.ts +++ b/storage-resize-images/functions/__tests__/function.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { config } from "../src/config"; jest.mock("../src/config"); jest.mock("../src"); diff --git a/storage-resize-images/functions/__tests__/integration/content-filter.live.test.ts b/storage-resize-images/functions/__tests__/integration/content-filter.live.test.ts index 35f698f938..5e62616df2 100644 --- a/storage-resize-images/functions/__tests__/integration/content-filter.live.test.ts +++ b/storage-resize-images/functions/__tests__/integration/content-filter.live.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /** * Live integration tests for checkImageContent — these hit the real * Vertex AI Gemini 2.5 Flash API. They are skipped by default and only diff --git a/storage-resize-images/functions/__tests__/resize.test.ts b/storage-resize-images/functions/__tests__/resize.test.ts index a18d223761..cc6e6d5504 100644 --- a/storage-resize-images/functions/__tests__/resize.test.ts +++ b/storage-resize-images/functions/__tests__/resize.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as fs from "fs"; import mockedEnv from "mocked-env"; diff --git a/storage-resize-images/functions/__tests__/retry-queue.test.ts b/storage-resize-images/functions/__tests__/retry-queue.test.ts index 5296546b89..4bd24263b4 100644 --- a/storage-resize-images/functions/__tests__/retry-queue.test.ts +++ b/storage-resize-images/functions/__tests__/retry-queue.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import PQueue from "p-queue"; describe("RetryQueue", () => { diff --git a/storage-resize-images/functions/__tests__/test.types.d.ts b/storage-resize-images/functions/__tests__/test.types.d.ts index b0b202d31f..48fc67612f 100644 --- a/storage-resize-images/functions/__tests__/test.types.d.ts +++ b/storage-resize-images/functions/__tests__/test.types.d.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + declare namespace NodeJS { interface Global { config: () => jest.ModuleMocker; diff --git a/storage-resize-images/functions/__tests__/unit/generateResizedImageHandler.test.ts b/storage-resize-images/functions/__tests__/unit/generateResizedImageHandler.test.ts index db255d02ff..6f798607bf 100644 --- a/storage-resize-images/functions/__tests__/unit/generateResizedImageHandler.test.ts +++ b/storage-resize-images/functions/__tests__/unit/generateResizedImageHandler.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as path from "path"; import * as fs from "fs"; import { config as loadEnv } from "dotenv"; diff --git a/storage-resize-images/functions/__tests__/unit/modifyImage.test.ts b/storage-resize-images/functions/__tests__/unit/modifyImage.test.ts index c62b3aa9a4..e07d7b6c74 100644 --- a/storage-resize-images/functions/__tests__/unit/modifyImage.test.ts +++ b/storage-resize-images/functions/__tests__/unit/modifyImage.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as path from "path"; import { config } from "dotenv"; diff --git a/storage-resize-images/functions/__tests__/util.test.ts b/storage-resize-images/functions/__tests__/util.test.ts index ff25b85ff2..a450ee48e5 100644 --- a/storage-resize-images/functions/__tests__/util.test.ts +++ b/storage-resize-images/functions/__tests__/util.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { startsWithArray, convertPathToPosix } from "../src/util"; const imagePath = ["/test/picture"]; diff --git a/storage-resize-images/functions/__tests__/util.ts b/storage-resize-images/functions/__tests__/util.ts index 392be51060..1caa6c454a 100644 --- a/storage-resize-images/functions/__tests__/util.ts +++ b/storage-resize-images/functions/__tests__/util.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as admin from "firebase-admin"; export const waitForFile = async ( diff --git a/storage-resize-images/functions/__tests__/vulnerability.test.ts b/storage-resize-images/functions/__tests__/vulnerability.test.ts index 6f410c8147..055ea7adce 100644 --- a/storage-resize-images/functions/__tests__/vulnerability.test.ts +++ b/storage-resize-images/functions/__tests__/vulnerability.test.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const firebase = require("firebase/app"); const firebaseAuth = require("firebase/auth"); const firebaseStorage = require("firebase/storage"); diff --git a/storage-resize-images/functions/jest.config.js b/storage-resize-images/functions/jest.config.js index 822dce175a..81de4c2e3c 100644 --- a/storage-resize-images/functions/jest.config.js +++ b/storage-resize-images/functions/jest.config.js @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + const packageJson = require("./package.json"); module.exports = { diff --git a/storage-resize-images/functions/src/content-filter.ts b/storage-resize-images/functions/src/content-filter.ts index e5bf484829..751f22f0d8 100644 --- a/storage-resize-images/functions/src/content-filter.ts +++ b/storage-resize-images/functions/src/content-filter.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import vertexAI, { gemini } from "@genkit-ai/vertexai"; import { genkit, z } from "genkit"; import type { SafetyThreshold } from "./config"; diff --git a/storage-resize-images/functions/src/events.ts b/storage-resize-images/functions/src/events.ts index 6b548d7665..9bf68a0fd9 100644 --- a/storage-resize-images/functions/src/events.ts +++ b/storage-resize-images/functions/src/events.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as eventArc from "firebase-admin/eventarc"; const { getEventarc } = eventArc; diff --git a/storage-resize-images/functions/src/file-operations.ts b/storage-resize-images/functions/src/file-operations.ts index 7ae0e566df..5b5909d417 100644 --- a/storage-resize-images/functions/src/file-operations.ts +++ b/storage-resize-images/functions/src/file-operations.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as path from "path"; import { ObjectMetadata } from "firebase-functions/v1/storage"; import { Bucket, File } from "@google-cloud/storage"; diff --git a/storage-resize-images/functions/src/filters.ts b/storage-resize-images/functions/src/filters.ts index 0f1487f4e3..8156f4a0dd 100644 --- a/storage-resize-images/functions/src/filters.ts +++ b/storage-resize-images/functions/src/filters.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as path from "path"; import * as logs from "./logs"; diff --git a/storage-resize-images/functions/src/global.ts b/storage-resize-images/functions/src/global.ts index 52f0777244..06c628e4d4 100644 --- a/storage-resize-images/functions/src/global.ts +++ b/storage-resize-images/functions/src/global.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import PQueue from "p-queue"; /** diff --git a/storage-resize-images/functions/src/placeholder.ts b/storage-resize-images/functions/src/placeholder.ts index 9e298b0093..43f2986e0f 100644 --- a/storage-resize-images/functions/src/placeholder.ts +++ b/storage-resize-images/functions/src/placeholder.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { Bucket } from "@google-cloud/storage"; import * as log from "./logs"; diff --git a/storage-resize-images/functions/src/resize-image.ts b/storage-resize-images/functions/src/resize-image.ts index 41b7eddb14..2372158118 100644 --- a/storage-resize-images/functions/src/resize-image.ts +++ b/storage-resize-images/functions/src/resize-image.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as os from "os"; import sharp from "sharp"; import * as path from "path"; diff --git a/storage-resize-images/functions/src/util.ts b/storage-resize-images/functions/src/util.ts index 017739b0d1..82f185bacb 100644 --- a/storage-resize-images/functions/src/util.ts +++ b/storage-resize-images/functions/src/util.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import * as path from "path"; import { FileMetadata } from "@google-cloud/storage"; From 71a28eadfdcb20f80c1f55c0d11bc99d36f06b3b Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Wed, 12 Aug 2026 14:51:50 -0700 Subject: [PATCH 03/30] Add release workflow --- .github/workflows/release-kit.yaml | 250 +++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 .github/workflows/release-kit.yaml diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml new file mode 100644 index 0000000000..b76bc303ee --- /dev/null +++ b/.github/workflows/release-kit.yaml @@ -0,0 +1,250 @@ +name: Release Kit + +on: + workflow_dispatch: + inputs: + target_kit: + description: "Kit / Package to publish" + required: true + type: choice + options: + - "kits/bigquery-firestore-export" + - "kits/delete-user-data" + - "kits/firestore-bigquery-export" + - "kits/firestore-bundle-builder" + - "kits/firestore-counter" + - "kits/firestore-genai-chatbot" + - "kits/firestore-incremental-capture" + - "kits/firestore-send-email" + - "kits/firestore-translate-text" + - "kits/firestore-vector-search" + - "kits/rtdb-limit-child-nodes" + - "kits/speech-to-text" + - "kits/storage-resize-images" + bump_level: + description: "Version Bump Level" + required: true + default: "patch" + type: choice + options: + - "patch" + - "minor" + - "major" + is_prerelease: + description: "Publish as Release Candidate (RC)" + required: true + default: true + type: boolean + dry_run: + description: "Dry run (validate without pushing/publishing)" + required: true + default: true + type: boolean + +jobs: + # ========================================================= + # 1. TEST JOB (Low Permissions: Read-Only) + # ========================================================= + test: + name: Run Tests + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "24" + + - name: Install Dependencies + run: npm ci + + - name: Run Workspace Tests + run: npm test --workspace=${{ inputs.target_kit }} + + # ========================================================= + # 2. RELEASE JOB (Elevated Permissions: Write) + # ========================================================= + release: + name: Version, Publish & Tag Release + needs: test + runs-on: ubuntu-latest + permissions: + contents: write # Needed to push version commit, git tag & create GitHub Release + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: kits + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "24" + registry-url: "https://wombat-dressing-room.appspot.com" + + - name: Configure Git User + if: ${{ !inputs.dry_run }} + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Read & Validate CHANGELOG.md + id: changelog + working-directory: ${{ inputs.target_kit }} + run: | + CHANGELOG_FILE="CHANGELOG.md" + + if [ ! -f "$CHANGELOG_FILE" ]; then + echo "::error file=${{ inputs.target_kit }}/CHANGELOG.md::CHANGELOG.md is missing! Releasing requires a CHANGELOG.md file." + exit 1 + fi + + NOTES=$(cat "$CHANGELOG_FILE") + + if [ -z "$(echo "$NOTES" | tr -d '[:space:]')" ]; then + echo "::error file=${{ inputs.target_kit }}/CHANGELOG.md::CHANGELOG.md is empty! Please populate it with release notes before publishing." + exit 1 + fi + + # Output notes via multiline heredoc + EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) + echo "notes<<$EOF" >> $GITHUB_OUTPUT + echo "$NOTES" >> $GITHUB_OUTPUT + echo "$EOF" >> $GITHUB_OUTPUT + + - name: Determine Version Bump Type + id: config + working-directory: ${{ inputs.target_kit }} + run: | + CURRENT_VER=$(node -p "require('./package.json').version") + BUMP="${{ inputs.bump_level }}" + IS_PRERELEASE="${{ inputs.is_prerelease }}" + + if [ "$IS_PRERELEASE" = "true" ]; then + if [[ "$CURRENT_VER" =~ -rc\.[0-9]+$ ]]; then + BUMP_TYPE="prerelease" + else + BUMP_TYPE="pre${BUMP}" + fi + TARGET_TAG="next" + else + BUMP_TYPE="$BUMP" + TARGET_TAG="latest (and next)" + fi + + echo "current_ver=$CURRENT_VER" >> $GITHUB_OUTPUT + echo "bump_type=$BUMP_TYPE" >> $GITHUB_OUTPUT + echo "target_tag=$TARGET_TAG" >> $GITHUB_OUTPUT + + - name: Install Dependencies & Build + run: | + npm ci + npm run build --workspace=${{ inputs.target_kit }} + + - name: Bump Version (Clear CHANGELOG on Stable Release Only) + id: versioning + working-directory: ${{ inputs.target_kit }} + run: | + BUMP_TYPE="${{ steps.config.outputs.bump_type }}" + IS_PRERELEASE="${{ inputs.is_prerelease }}" + DRY_RUN="${{ inputs.dry_run }}" + + if [ "$DRY_RUN" = "true" ]; then + npm version $BUMP_TYPE --preid=rc --no-git-tag-version + else + # Only truncate CHANGELOG.md if this is a STABLE release (not a prerelease) + if [ "$IS_PRERELEASE" != "true" ]; then + echo "Stable release detected: clearing CHANGELOG.md..." + > CHANGELOG.md + git add CHANGELOG.md + else + echo "Prerelease detected: preserving CHANGELOG.md content." + fi + + # Create version bump commit and git tag + if [[ "$BUMP_TYPE" == pre* ]] || [[ "$BUMP_TYPE" == "prerelease" ]]; then + npm version $BUMP_TYPE --preid=rc -m "chore(release): %s [skip ci]" + else + npm version $BUMP_TYPE -m "chore(release): %s [skip ci]" + fi + fi + + NEW_VER=$(node -p "require('./package.json').version") + PKG_NAME=$(node -p "require('./package.json').name") + + echo "version=$NEW_VER" >> $GITHUB_OUTPUT + echo "pkg_name=$PKG_NAME" >> $GITHUB_OUTPUT + echo "tag_name=${PKG_NAME}@${NEW_VER}" >> $GITHUB_OUTPUT + + - name: Dry Run Summary + if: ${{ inputs.dry_run }} + run: | + echo "==========================================================" + echo " DRY RUN SUMMARY " + echo "==========================================================" + echo " Package Name: ${{ steps.versioning.outputs.pkg_name }}" + echo " Target Directory: ${{ inputs.target_kit }}" + echo " Current Version: ${{ steps.config.outputs.current_ver }}" + echo " Target Version: ${{ steps.versioning.outputs.version }}" + echo " Version Bump: ${{ steps.config.outputs.bump_type }}" + echo " NPM Dist-Tag: ${{ steps.config.outputs.target_tag }}" + echo " Release Type: $( [ "${{ inputs.is_prerelease }}" = "true" ] && echo "Release Candidate (RC)" || echo "Stable Release" )" + echo " Git Tag Name: ${{ steps.versioning.outputs.tag_name }}" + echo " CHANGELOG State: $( [ "${{ inputs.is_prerelease }}" = "true" ] && echo "Preserved" || echo "Will be cleared on publish" )" + echo "----------------------------------------------------------" + echo " Release Notes from CHANGELOG.md:" + echo "${{ steps.changelog.outputs.notes }}" + echo "==========================================================" + + - name: Push Version Commit & Tags to Branch + if: ${{ !inputs.dry_run }} + run: git push origin kits --follow-tags + + - name: Publish to NPM + working-directory: ${{ inputs.target_kit }} + run: | + IS_PRERELEASE="${{ inputs.is_prerelease }}" + DRY_RUN="${{ inputs.dry_run }}" + PKG_NAME="${{ steps.versioning.outputs.pkg_name }}" + VERSION="${{ steps.versioning.outputs.version }}" + + DRY_RUN_FLAG="" + if [ "$DRY_RUN" = "true" ]; then + DRY_RUN_FLAG="--dry-run" + echo "Executing npm publish with --dry-run..." + fi + + if [ "$IS_PRERELEASE" = "true" ]; then + npm publish --tag next --access public $DRY_RUN_FLAG + else + npm publish --tag latest --access public $DRY_RUN_FLAG + if [ "$DRY_RUN" != "true" ]; then + npm dist-tag add ${PKG_NAME}@${VERSION} next + fi + fi + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Create GitHub Release via GitHub CLI + if: ${{ !inputs.dry_run }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG_NAME="${{ steps.versioning.outputs.tag_name }}" + PKG_NAME="${{ steps.versioning.outputs.pkg_name }}" + VERSION="${{ steps.versioning.outputs.version }}" + IS_PRERELEASE="${{ inputs.is_prerelease }}" + + PRERELEASE_FLAG="" + if [ "$IS_PRERELEASE" = "true" ]; then + PRERELEASE_FLAG="--prerelease" + fi + + gh release create "$TAG_NAME" \ + --title "$PKG_NAME v$VERSION" \ + --notes "${{ steps.changelog.outputs.notes }}" \ + --target kits \ + $PRERELEASE_FLAG From cd30b83dd923fa9b15839172f177cae2b84c6160 Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Thu, 13 Aug 2026 08:34:16 -0700 Subject: [PATCH 04/30] Fix zizmore findings in new file only (existing errors still present) --- .github/workflows/release-kit.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index b76bc303ee..5b20229c47 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -51,10 +51,10 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c448218163 with: node-version: "24" @@ -75,12 +75,12 @@ jobs: contents: write # Needed to push version commit, git tag & create GitHub Release steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] with: ref: kits - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c448218163 with: node-version: "24" registry-url: "https://wombat-dressing-room.appspot.com" From 0384dc392399bc7dc4a37dca46c348ab46fd535f Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Thu, 13 Aug 2026 08:48:00 -0700 Subject: [PATCH 05/30] Another attempt to fix zizmor --- .github/workflows/release-kit.yaml | 73 ++++++++++++++++++------------ 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index 5b20229c47..c00f2b285f 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -118,10 +118,12 @@ jobs: - name: Determine Version Bump Type id: config working-directory: ${{ inputs.target_kit }} + env: + BUMP_LEVEL: ${{ inputs.bump_level }} + IS_PRERELEASE: ${{ inputs.is_prerelease }} run: | CURRENT_VER=$(node -p "require('./package.json').version") - BUMP="${{ inputs.bump_level }}" - IS_PRERELEASE="${{ inputs.is_prerelease }}" + BUMP="$BUMP_LEVEL" if [ "$IS_PRERELEASE" = "true" ]; then if [[ "$CURRENT_VER" =~ -rc\.[0-9]+$ ]]; then @@ -140,18 +142,20 @@ jobs: echo "target_tag=$TARGET_TAG" >> $GITHUB_OUTPUT - name: Install Dependencies & Build + env: + TARGET_KIT: ${{ inputs.target_kit }} run: | npm ci - npm run build --workspace=${{ inputs.target_kit }} + npm run build --workspace=$TARGET_KIT - name: Bump Version (Clear CHANGELOG on Stable Release Only) id: versioning working-directory: ${{ inputs.target_kit }} + env: + BUMP_TYPE: ${{ steps.config.outputs.bump_type }} + IS_PRERELEASE: ${{ inputs.is_prerelease }} + DRY_RUN: ${{ inputs.dry_run }} run: | - BUMP_TYPE="${{ steps.config.outputs.bump_type }}" - IS_PRERELEASE="${{ inputs.is_prerelease }}" - DRY_RUN="${{ inputs.dry_run }}" - if [ "$DRY_RUN" = "true" ]; then npm version $BUMP_TYPE --preid=rc --no-git-tag-version else @@ -181,22 +185,32 @@ jobs: - name: Dry Run Summary if: ${{ inputs.dry_run }} + env: + PKG_NAME: ${{ steps.versioning.outputs.pkg_name }} + TARGET_KIT: ${{ inputs.target_kit }} + CURRENT_VER: ${{ steps.config.outputs.current_ver }} + VERSION: ${{ steps.versioning.outputs.version }} + BUMP_TYPE: ${{ steps.config.outputs.bump_type }} + TARGET_TAG: ${{ steps.config.outputs.target_tag }} + IS_PRERELEASE: ${{ inputs.is_prerelease }} + TAG_NAME: ${{ steps.versioning.outputs.tag_name }} + NOTES: ${{ steps.changelog.outputs.notes }} run: | echo "==========================================================" echo " DRY RUN SUMMARY " echo "==========================================================" - echo " Package Name: ${{ steps.versioning.outputs.pkg_name }}" - echo " Target Directory: ${{ inputs.target_kit }}" - echo " Current Version: ${{ steps.config.outputs.current_ver }}" - echo " Target Version: ${{ steps.versioning.outputs.version }}" - echo " Version Bump: ${{ steps.config.outputs.bump_type }}" - echo " NPM Dist-Tag: ${{ steps.config.outputs.target_tag }}" - echo " Release Type: $( [ "${{ inputs.is_prerelease }}" = "true" ] && echo "Release Candidate (RC)" || echo "Stable Release" )" - echo " Git Tag Name: ${{ steps.versioning.outputs.tag_name }}" - echo " CHANGELOG State: $( [ "${{ inputs.is_prerelease }}" = "true" ] && echo "Preserved" || echo "Will be cleared on publish" )" + echo " Package Name: $PKG_NAME" + echo " Target Directory: $TARGET_KIT" + echo " Current Version: $CURRENT_VER" + echo " Target Version: $VERSION" + echo " Version Bump: $BUMP_TYPE" + echo " NPM Dist-Tag: $TARGET_TAG" + echo " Release Type: $( [ "$IS_PRERELEASE" = "true" ] && echo "Release Candidate (RC)" || echo "Stable Release" )" + echo " Git Tag Name: $TAG_NAME" + echo " CHANGELOG State: $( [ "$IS_PRERELEASE" = "true" ] && echo "Preserved" || echo "Will be cleared on publish" )" echo "----------------------------------------------------------" echo " Release Notes from CHANGELOG.md:" - echo "${{ steps.changelog.outputs.notes }}" + echo "$NOTES" echo "==========================================================" - name: Push Version Commit & Tags to Branch @@ -205,12 +219,13 @@ jobs: - name: Publish to NPM working-directory: ${{ inputs.target_kit }} + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + IS_PRERELEASE: ${{ inputs.is_prerelease }} + DRY_RUN: ${{ inputs.dry_run }} + PKG_NAME: ${{ steps.versioning.outputs.pkg_name }} + VERSION: ${{ steps.versioning.outputs.version }} run: | - IS_PRERELEASE="${{ inputs.is_prerelease }}" - DRY_RUN="${{ inputs.dry_run }}" - PKG_NAME="${{ steps.versioning.outputs.pkg_name }}" - VERSION="${{ steps.versioning.outputs.version }}" - DRY_RUN_FLAG="" if [ "$DRY_RUN" = "true" ]; then DRY_RUN_FLAG="--dry-run" @@ -225,19 +240,17 @@ jobs: npm dist-tag add ${PKG_NAME}@${VERSION} next fi fi - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Create GitHub Release via GitHub CLI if: ${{ !inputs.dry_run }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG_NAME: ${{ steps.versioning.outputs.tag_name }} + PKG_NAME: ${{ steps.versioning.outputs.pkg_name }} + VERSION: ${{ steps.versioning.outputs.version }} + IS_PRERELEASE: ${{ inputs.is_prerelease }} + NOTES: ${{ steps.changelog.outputs.notes }} run: | - TAG_NAME="${{ steps.versioning.outputs.tag_name }}" - PKG_NAME="${{ steps.versioning.outputs.pkg_name }}" - VERSION="${{ steps.versioning.outputs.version }}" - IS_PRERELEASE="${{ inputs.is_prerelease }}" - PRERELEASE_FLAG="" if [ "$IS_PRERELEASE" = "true" ]; then PRERELEASE_FLAG="--prerelease" @@ -245,6 +258,6 @@ jobs: gh release create "$TAG_NAME" \ --title "$PKG_NAME v$VERSION" \ - --notes "${{ steps.changelog.outputs.notes }}" \ + --notes "$NOTES" \ --target kits \ $PRERELEASE_FLAG From b2e181ce09bd021beda55d6df4f6abbd769e736e Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Thu, 13 Aug 2026 09:04:49 -0700 Subject: [PATCH 06/30] More zizmor fixes. Trusted publishing seems incompatible with Google --- .github/workflows/release-kit.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index c00f2b285f..0fd7be35ec 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -54,7 +54,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] - name: Setup Node.js - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c448218163 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "24" @@ -80,7 +80,7 @@ jobs: ref: kits - name: Setup Node.js - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c448218163 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "24" registry-url: "https://wombat-dressing-room.appspot.com" @@ -218,6 +218,7 @@ jobs: run: git push origin kits --follow-tags - name: Publish to NPM + # zizmor: ignore[use-trusted-publishing] working-directory: ${{ inputs.target_kit }} env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} From 95834dca42d2b6db2bdbab3749272f7cc019c83a Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Thu, 13 Aug 2026 09:12:57 -0700 Subject: [PATCH 07/30] Apparently I have to fix ALL zizmore issues if I touch any action --- .github/workflows/npm_publish_bq_scripts.yml | 6 ++++-- .github/workflows/readmes-updated.yml | 13 +++++++++---- .github/workflows/release.yml | 6 +++++- .github/workflows/test.yml | 10 +++++++--- .github/workflows/validate.yml | 8 ++++++-- 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/.github/workflows/npm_publish_bq_scripts.yml b/.github/workflows/npm_publish_bq_scripts.yml index 2958e80572..54d378d8e0 100644 --- a/.github/workflows/npm_publish_bq_scripts.yml +++ b/.github/workflows/npm_publish_bq_scripts.yml @@ -14,9 +14,11 @@ jobs: runs-on: ubuntu-latest name: publish_if_newer_version steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + persist-credentials: false - name: Setup node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 20 - name: NPM install diff --git a/.github/workflows/readmes-updated.yml b/.github/workflows/readmes-updated.yml index 6bd0b17030..5147ca6bce 100644 --- a/.github/workflows/readmes-updated.yml +++ b/.github/workflows/readmes-updated.yml @@ -20,17 +20,20 @@ env: jobs: build: runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 with: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} ref: ${{ github.event.pull_request.head.ref }} repository: ${{ github.event.pull_request.head.repo.full_name }} + persist-credentials: false - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 with: node-version: 22 cache: "npm" @@ -44,7 +47,7 @@ jobs: echo "::set-output name=dir::$(npm config get prefix)" - name: Cache global dependencies - uses: actions/cache@v4 + uses: actions/cache@6849a62b9183863484f7a264a7806655c65f9038 with: path: ${{ steps.global-deps-setup.outputs.dir }} key: @@ -54,8 +57,10 @@ jobs: ${{ runner.os }}-npm-global-deps-v1- - name: Install Firebase and Lerna + env: + GLOBAL_DEPS_DIR: ${{ steps.global-deps-setup.outputs.dir }} run: | - echo "${{ steps.global-deps-setup.outputs.dir }}/bin" >> $GITHUB_PATH + echo "$GLOBAL_DEPS_DIR/bin" >> $GITHUB_PATH npm install -g firebase-tools lerna - name: Install local dependencies diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e7735bc6d7..0921767e41 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,8 +9,12 @@ jobs: release: name: "Create Releases" runs-on: ubuntu-latest + permissions: + contents: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + with: + persist-credentials: false - name: Release Script env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 59a6807011..40bcc64efa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,14 +9,18 @@ on: jobs: nodejs: runs-on: ubuntu-latest + permissions: + contents: read strategy: matrix: node: ["20"] name: node.js_${{ matrix.node }}_test steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + with: + persist-credentials: false - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 with: node-version: ${{ matrix.node }} cache: "npm" @@ -26,7 +30,7 @@ jobs: - name: Build emulator functions run: cd _emulator/functions && npm i && npm run build & cd ../.. - name: Install Firebase CLI - uses: nick-invision/retry@v1 + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 with: timeout_minutes: 10 retry_wait_seconds: 60 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 96504aeb37..a674466a27 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -8,10 +8,14 @@ on: jobs: formatting: runs-on: ubuntu-latest + permissions: + contents: read steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + with: + persist-credentials: false - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 with: node-version: 20 - name: NPM install From 8a6bb32fc434fdc5a14a128827426fb99ea80e97 Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Thu, 13 Aug 2026 09:48:26 -0700 Subject: [PATCH 08/30] Fix credential persistence finding in validate.yml license job --- .github/workflows/validate.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 85f32e473f..e341b962d0 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -30,6 +30,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + with: + persist-credentials: false - name: Setup go uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 with: From 69233e0eb2a8dac69339fb7cf72c322e9fc1342a Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Thu, 13 Aug 2026 10:07:13 -0700 Subject: [PATCH 09/30] Fix incorrect actions/cache commit hash in readmes-updated.yml --- .github/workflows/readmes-updated.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/readmes-updated.yml b/.github/workflows/readmes-updated.yml index 5147ca6bce..4895e611e7 100644 --- a/.github/workflows/readmes-updated.yml +++ b/.github/workflows/readmes-updated.yml @@ -47,7 +47,7 @@ jobs: echo "::set-output name=dir::$(npm config get prefix)" - name: Cache global dependencies - uses: actions/cache@6849a62b9183863484f7a264a7806655c65f9038 + uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 with: path: ${{ steps.global-deps-setup.outputs.dir }} key: From f97c164fea5f645620e2cd13bed9bd5f1245376b Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Thu, 13 Aug 2026 12:00:59 -0700 Subject: [PATCH 10/30] fix(ci): remove workspace flags and support target_branch parameter --- .github/workflows/release-kit.yaml | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index 0fd7be35ec..84f06c7387 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -21,6 +21,11 @@ on: - "kits/rtdb-limit-child-nodes" - "kits/speech-to-text" - "kits/storage-resize-images" + target_branch: + description: "Branch to release from" + required: true + default: "kits" + type: string bump_level: description: "Version Bump Level" required: true @@ -52,17 +57,19 @@ jobs: contents: read steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] + with: + ref: ${{ inputs.target_branch }} - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "24" - - name: Install Dependencies - run: npm ci - - - name: Run Workspace Tests - run: npm test --workspace=${{ inputs.target_kit }} + - name: Install Dependencies & Run Tests + working-directory: ${{ inputs.target_kit }} + run: | + npm ci + npm test # ========================================================= # 2. RELEASE JOB (Elevated Permissions: Write) @@ -77,7 +84,7 @@ jobs: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] with: - ref: kits + ref: ${{ inputs.target_branch }} - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -142,11 +149,10 @@ jobs: echo "target_tag=$TARGET_TAG" >> $GITHUB_OUTPUT - name: Install Dependencies & Build - env: - TARGET_KIT: ${{ inputs.target_kit }} + working-directory: ${{ inputs.target_kit }} run: | npm ci - npm run build --workspace=$TARGET_KIT + npm run build - name: Bump Version (Clear CHANGELOG on Stable Release Only) id: versioning @@ -215,7 +221,7 @@ jobs: - name: Push Version Commit & Tags to Branch if: ${{ !inputs.dry_run }} - run: git push origin kits --follow-tags + run: git push origin ${{ inputs.target_branch }} --follow-tags - name: Publish to NPM # zizmor: ignore[use-trusted-publishing] @@ -260,5 +266,5 @@ jobs: gh release create "$TAG_NAME" \ --title "$PKG_NAME v$VERSION" \ --notes "$NOTES" \ - --target kits \ + --target "${{ inputs.target_branch }}" \ $PRERELEASE_FLAG From b1c5c1953c969cae9580494e560f81fb509b82de Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Thu, 13 Aug 2026 13:25:59 -0700 Subject: [PATCH 11/30] fix(ci): use public registry for npm ci during build step --- .github/workflows/release-kit.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index 84f06c7387..d955ff62f4 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -91,6 +91,7 @@ jobs: with: node-version: "24" registry-url: "https://wombat-dressing-room.appspot.com" + always-auth: false - name: Configure Git User if: ${{ !inputs.dry_run }} @@ -151,7 +152,7 @@ jobs: - name: Install Dependencies & Build working-directory: ${{ inputs.target_kit }} run: | - npm ci + npm ci --registry=https://registry.npmjs.org npm run build - name: Bump Version (Clear CHANGELOG on Stable Release Only) From 6fcc767af6e6fea459f4b361ab9be780501ad41a Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Thu, 13 Aug 2026 16:52:15 -0700 Subject: [PATCH 12/30] fix(ci): pass target_branch via env to resolve zizmor template-injection --- .github/workflows/release-kit.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index d955ff62f4..dfc380f212 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -222,7 +222,9 @@ jobs: - name: Push Version Commit & Tags to Branch if: ${{ !inputs.dry_run }} - run: git push origin ${{ inputs.target_branch }} --follow-tags + env: + TARGET_BRANCH: ${{ inputs.target_branch }} + run: git push origin "$TARGET_BRANCH" --follow-tags - name: Publish to NPM # zizmor: ignore[use-trusted-publishing] @@ -258,6 +260,7 @@ jobs: VERSION: ${{ steps.versioning.outputs.version }} IS_PRERELEASE: ${{ inputs.is_prerelease }} NOTES: ${{ steps.changelog.outputs.notes }} + TARGET_BRANCH: ${{ inputs.target_branch }} run: | PRERELEASE_FLAG="" if [ "$IS_PRERELEASE" = "true" ]; then @@ -267,5 +270,5 @@ jobs: gh release create "$TAG_NAME" \ --title "$PKG_NAME v$VERSION" \ --notes "$NOTES" \ - --target "${{ inputs.target_branch }}" \ + --target "$TARGET_BRANCH" \ $PRERELEASE_FLAG From 587c3a0dd71a883e1e2b5e910cf385729c313de8 Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Thu, 13 Aug 2026 17:46:15 -0700 Subject: [PATCH 13/30] chore(ci): remove target_branch parameter in favor of github.ref_name --- .github/workflows/release-kit.yaml | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index dfc380f212..2ea8f03885 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -21,11 +21,6 @@ on: - "kits/rtdb-limit-child-nodes" - "kits/speech-to-text" - "kits/storage-resize-images" - target_branch: - description: "Branch to release from" - required: true - default: "kits" - type: string bump_level: description: "Version Bump Level" required: true @@ -57,8 +52,6 @@ jobs: contents: read steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] - with: - ref: ${{ inputs.target_branch }} - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -83,8 +76,6 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] - with: - ref: ${{ inputs.target_branch }} - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -223,8 +214,8 @@ jobs: - name: Push Version Commit & Tags to Branch if: ${{ !inputs.dry_run }} env: - TARGET_BRANCH: ${{ inputs.target_branch }} - run: git push origin "$TARGET_BRANCH" --follow-tags + REF_NAME: ${{ github.ref_name }} + run: git push origin "$REF_NAME" --follow-tags - name: Publish to NPM # zizmor: ignore[use-trusted-publishing] @@ -260,7 +251,7 @@ jobs: VERSION: ${{ steps.versioning.outputs.version }} IS_PRERELEASE: ${{ inputs.is_prerelease }} NOTES: ${{ steps.changelog.outputs.notes }} - TARGET_BRANCH: ${{ inputs.target_branch }} + REF_NAME: ${{ github.ref_name }} run: | PRERELEASE_FLAG="" if [ "$IS_PRERELEASE" = "true" ]; then @@ -270,5 +261,5 @@ jobs: gh release create "$TAG_NAME" \ --title "$PKG_NAME v$VERSION" \ --notes "$NOTES" \ - --target "$TARGET_BRANCH" \ + --target "$REF_NAME" \ $PRERELEASE_FLAG From 6ed7c12fb18174e74126a2352aa5f61993eaa931 Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Tue, 18 Aug 2026 09:59:34 -0700 Subject: [PATCH 14/30] Kits should be published from the kits branch --- .github/workflows/release-kit.yaml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index 2ea8f03885..616609f26c 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -52,6 +52,8 @@ jobs: contents: read steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] + with: + ref: "kits" - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -76,6 +78,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] + with: + ref: "kits" - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -214,8 +218,8 @@ jobs: - name: Push Version Commit & Tags to Branch if: ${{ !inputs.dry_run }} env: - REF_NAME: ${{ github.ref_name }} - run: git push origin "$REF_NAME" --follow-tags + TARGET_BRANCH: "kits" + run: git push origin "$TARGET_BRANCH" --follow-tags - name: Publish to NPM # zizmor: ignore[use-trusted-publishing] @@ -251,7 +255,7 @@ jobs: VERSION: ${{ steps.versioning.outputs.version }} IS_PRERELEASE: ${{ inputs.is_prerelease }} NOTES: ${{ steps.changelog.outputs.notes }} - REF_NAME: ${{ github.ref_name }} + TARGET_BRANCH: "kits" run: | PRERELEASE_FLAG="" if [ "$IS_PRERELEASE" = "true" ]; then @@ -261,5 +265,5 @@ jobs: gh release create "$TAG_NAME" \ --title "$PKG_NAME v$VERSION" \ --notes "$NOTES" \ - --target "$REF_NAME" \ + --target "$TARGET_BRANCH" \ $PRERELEASE_FLAG From bcc9445f64c753d5bc0dcf308387c64d023775bd Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Tue, 18 Aug 2026 17:08:26 -0700 Subject: [PATCH 15/30] Trying out trusted publishing --- .github/workflows/release-kit.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index 616609f26c..c5d8eee232 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -85,7 +85,6 @@ jobs: uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "24" - registry-url: "https://wombat-dressing-room.appspot.com" always-auth: false - name: Configure Git User @@ -224,6 +223,9 @@ jobs: - name: Publish to NPM # zizmor: ignore[use-trusted-publishing] working-directory: ${{ inputs.target_kit }} + permissions: + contents: read + id-token: write env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} IS_PRERELEASE: ${{ inputs.is_prerelease }} @@ -238,9 +240,9 @@ jobs: fi if [ "$IS_PRERELEASE" = "true" ]; then - npm publish --tag next --access public $DRY_RUN_FLAG + npm publish --tag next --provenance --access public $DRY_RUN_FLAG else - npm publish --tag latest --access public $DRY_RUN_FLAG + npm publish --tag latest --provenance --access public $DRY_RUN_FLAG if [ "$DRY_RUN" != "true" ]; then npm dist-tag add ${PKG_NAME}@${VERSION} next fi From c0d6361e4f48422267691f31ed956cda4565b594 Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Tue, 18 Aug 2026 17:09:54 -0700 Subject: [PATCH 16/30] Fix YAML --- .github/workflows/release-kit.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index c5d8eee232..0d18f03231 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -75,6 +75,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: write # Needed to push version commit, git tag & create GitHub Release + id-token: write # Needed to publish to npm steps: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] @@ -223,9 +224,6 @@ jobs: - name: Publish to NPM # zizmor: ignore[use-trusted-publishing] working-directory: ${{ inputs.target_kit }} - permissions: - contents: read - id-token: write env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} IS_PRERELEASE: ${{ inputs.is_prerelease }} From 6615b4113afbb4fedc8ffe3c475fb5bb3b7c2d4d Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Wed, 19 Aug 2026 12:54:17 -0700 Subject: [PATCH 17/30] chore(ci): clean up setup-node in release-kit workflow --- .github/workflows/release-kit.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index 0d18f03231..37ff2e1f46 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -86,7 +86,6 @@ jobs: uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "24" - always-auth: false - name: Configure Git User if: ${{ !inputs.dry_run }} From c2b80862c39797cd55d781089433f6819d7f9110 Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Wed, 19 Aug 2026 18:15:08 -0700 Subject: [PATCH 18/30] Remove node token --- .github/workflows/release-kit.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index 37ff2e1f46..7b942c569d 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -224,7 +224,6 @@ jobs: # zizmor: ignore[use-trusted-publishing] working-directory: ${{ inputs.target_kit }} env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} IS_PRERELEASE: ${{ inputs.is_prerelease }} DRY_RUN: ${{ inputs.dry_run }} PKG_NAME: ${{ steps.versioning.outputs.pkg_name }} From 391178243a2890b9c681549f206d42e7d81ec620 Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Thu, 20 Aug 2026 11:19:16 -0700 Subject: [PATCH 19/30] Print inputs as the first step of release-kits This helps debug action failures when several releases are happening at once and they fail early --- .github/workflows/release-kit.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index 616609f26c..674262b7dc 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -51,6 +51,12 @@ jobs: permissions: contents: read steps: + - name: Print inputs + env: + INPUTS: ${{ toJSON(inputs) }} + run: | + echo "$INPUTS" + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] with: ref: "kits" From 8ed32d3a45e2299ed950aa817f26fe2c12b5380f Mon Sep 17 00:00:00 2001 From: Corie Watson Date: Mon, 24 Aug 2026 11:15:21 +0100 Subject: [PATCH 20/30] fix(bq-scripts): use full git URL in repository.url (#2967) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary `npm publish --provenance` requires `repository.url` to resolve to the GitHub repo that built the package. Two BigQuery script packages declared a bare `github.com/firebase/extensions.git` — no scheme, so npm can't normalise it and provenance fails. Prefixed both with `git+https://`, matching `firestore-bigquery-change-tracker`, which already publishes fine: - `@firebaseextensions/fs-bq-schema-views` - `@firebaseextensions/fs-bq-import-collection` Broken since `--provenance` was added in March 2026. No other `package.json` on `next` is affected. --- firestore-bigquery-export/scripts/gen-schema-view/package.json | 2 +- firestore-bigquery-export/scripts/import/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firestore-bigquery-export/scripts/gen-schema-view/package.json b/firestore-bigquery-export/scripts/gen-schema-view/package.json index d9eafd1829..f4f3ac7009 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/package.json +++ b/firestore-bigquery-export/scripts/gen-schema-view/package.json @@ -5,7 +5,7 @@ "main": "./lib/index.js", "repository": { "type": "git", - "url": "github.com/firebase/extensions.git", + "url": "git+https://github.com/firebase/extensions.git", "directory": "firestore-bigquery-export/scripts/gen-schema-view" }, "scripts": { diff --git a/firestore-bigquery-export/scripts/import/package.json b/firestore-bigquery-export/scripts/import/package.json index bdafc5ef23..bbf874c472 100644 --- a/firestore-bigquery-export/scripts/import/package.json +++ b/firestore-bigquery-export/scripts/import/package.json @@ -5,7 +5,7 @@ "main": "./lib/index.js", "repository": { "type": "git", - "url": "github.com/firebase/extensions.git", + "url": "git+https://github.com/firebase/extensions.git", "directory": "firestore-bigquery-export/scripts/import" }, "scripts": { From 6495e5c2c2f5e941af35b14e23aefbb740bfe915 Mon Sep 17 00:00:00 2001 From: Jacob Cable <32874567+cabljac@users.noreply.github.com> Date: Thu, 27 Aug 2026 17:25:42 +0100 Subject: [PATCH 21/30] chore(ci): sync release-kit workflow from kits (#2992) Syncs release-kit.yaml byte-for-byte with the version that landed on kits in #2990. This copy never executes (Release Kit is always dispatched from kits; next has no kits/ directories); it only lists the workflow in the Actions UI, and it had drifted to show the old broken versioning logic. No behavior change. Will need re-syncing if #2991 lands on kits. --- .github/workflows/release-kit.yaml | 205 ++++++++++++++++++++--------- 1 file changed, 140 insertions(+), 65 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index 5a2384475a..e9f6b13adf 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -41,6 +41,15 @@ on: default: true type: boolean +# All releases push to the same branch; a concurrent run would fail its push +# after already publishing to npm, leaving a version with no commit or tag. +# GitHub keeps at most ONE pending run per group: with a run in progress and +# one queued, a third dispatch cancels the queued one. Dispatch kits one at a +# time and check for a "Canceled" run before assuming a release happened. +concurrency: + group: release-kit + cancel-in-progress: false + jobs: # ========================================================= # 1. TEST JOB (Low Permissions: Read-Only) @@ -51,15 +60,7 @@ jobs: permissions: contents: read steps: - - name: Print inputs - env: - INPUTS: ${{ toJSON(inputs) }} - run: | - echo "$INPUTS" - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] - with: - ref: "kits" - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -81,17 +82,16 @@ jobs: runs-on: ubuntu-latest permissions: contents: write # Needed to push version commit, git tag & create GitHub Release - id-token: write # Needed to publish to npm steps: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] - with: - ref: "kits" - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "24" + registry-url: "https://wombat-dressing-room.appspot.com" + always-auth: false - name: Configure Git User if: ${{ !inputs.dry_run }} @@ -123,31 +123,91 @@ jobs: echo "$NOTES" >> $GITHUB_OUTPUT echo "$EOF" >> $GITHUB_OUTPUT - - name: Determine Version Bump Type + - name: Determine Next Version id: config working-directory: ${{ inputs.target_kit }} env: BUMP_LEVEL: ${{ inputs.bump_level }} IS_PRERELEASE: ${{ inputs.is_prerelease }} + # The registry is the source of truth for versions: npm reserves every + # version ever published (even after unpublish), and package.json on the + # branch can lag behind what was actually released. + NPM_CONFIG_REGISTRY: https://registry.npmjs.org run: | - CURRENT_VER=$(node -p "require('./package.json').version") - BUMP="$BUMP_LEVEL" + set -o pipefail + + # The push at the end of the job would create a stray branch named + # after the ref if this were dispatched from a tag. + if [ "$GITHUB_REF_TYPE" != "branch" ]; then + echo "::error::Release Kit must be dispatched from a branch, got $GITHUB_REF_TYPE '$GITHUB_REF_NAME'." + exit 1 + fi + + PKG_NAME=$(node -p "require('./package.json').name") + LOCAL_VER=$(node -p "require('./package.json').version") + # The packument is fetched directly rather than via `npm view`: npm + # hides a fully unpublished package behind E404 (dropping its reserved + # versions in time.unpublished) and its --json output shape changes + # across npm majors. The registry itself 404s only for never-published + # names. time keys include per-version-unpublished versions. + PACKUMENT="$RUNNER_TEMP/packument.json" + HTTP_STATUS=$(curl -sS --retry 3 -o "$PACKUMENT" -w '%{http_code}' "$NPM_CONFIG_REGISTRY/$PKG_NAME") + if [ "$HTTP_STATUS" = "404" ]; then + TAKEN="" + elif [ "$HTTP_STATUS" != "200" ]; then + echo "::error::Registry returned HTTP $HTTP_STATUS for $PKG_NAME; cannot trust the version computation." + exit 1 + else + TAKEN=$(node -e ' + const data = JSON.parse(require("fs").readFileSync(0, "utf8")); + const time = data.time || {}; + const meta = ["created", "modified", "unpublished"]; + const keys = Object.keys(time).filter(v => !meta.includes(v)); + const unpub = (time.unpublished && time.unpublished.versions) || []; + const unpubList = Array.isArray(unpub) ? unpub : Object.keys(unpub); + console.log(keys.concat(unpubList).join(" ")); + ' < "$PACKUMENT") + fi + + HIGHEST=$(npx --yes semver@7.8.5 $LOCAL_VER $TAKEN | tail -n 1) + # 0.0.0 seed keeps grep from emptying the pipe when no stable exists yet. + HIGHEST_STABLE=$(npx --yes semver@7.8.5 0.0.0 $LOCAL_VER $TAKEN | grep -v -- - | tail -n 1) + + # The bump level is applied to the highest stable version; an existing + # rc line continues unless the requested level opens a higher line. if [ "$IS_PRERELEASE" = "true" ]; then - if [[ "$CURRENT_VER" =~ -rc\.[0-9]+$ ]]; then - BUMP_TYPE="prerelease" - else - BUMP_TYPE="pre${BUMP}" + NEW_VER=$(npx --yes semver@7.8.5 -i "pre${BUMP_LEVEL}" --preid rc "$HIGHEST_STABLE") + BUMP_TYPE="pre${BUMP_LEVEL}" + if [[ "$HIGHEST" == *-rc.* ]]; then + CONTINUED=$(npx --yes semver@7.8.5 -i prerelease --preid rc "$HIGHEST") + if [ "$(npx --yes semver@7.8.5 "$NEW_VER" "$CONTINUED" | tail -n 1)" = "$CONTINUED" ]; then + NEW_VER="$CONTINUED" + BUMP_TYPE="prerelease" + fi fi TARGET_TAG="next" else - BUMP_TYPE="$BUMP" + NEW_VER=$(npx --yes semver@7.8.5 -i "$BUMP_LEVEL" "$HIGHEST_STABLE") + BUMP_TYPE="$BUMP_LEVEL" TARGET_TAG="latest (and next)" fi - echo "current_ver=$CURRENT_VER" >> $GITHUB_OUTPUT + for v in $TAKEN; do + if [ "$v" = "$NEW_VER" ]; then + echo "::error::Computed version $NEW_VER already exists on the registry." + exit 1 + fi + done + + echo "current_ver=$LOCAL_VER" >> $GITHUB_OUTPUT + echo "highest_ver=$HIGHEST" >> $GITHUB_OUTPUT + echo "highest_stable=$HIGHEST_STABLE" >> $GITHUB_OUTPUT echo "bump_type=$BUMP_TYPE" >> $GITHUB_OUTPUT echo "target_tag=$TARGET_TAG" >> $GITHUB_OUTPUT + echo "version=$NEW_VER" >> $GITHUB_OUTPUT + echo "pkg_name=$PKG_NAME" >> $GITHUB_OUTPUT + echo "tag_name=${PKG_NAME}@${NEW_VER}" >> $GITHUB_OUTPUT - name: Install Dependencies & Build working-directory: ${{ inputs.target_kit }} @@ -155,52 +215,52 @@ jobs: npm ci --registry=https://registry.npmjs.org npm run build - - name: Bump Version (Clear CHANGELOG on Stable Release Only) - id: versioning + - name: Apply Version Bump (Clear CHANGELOG on Stable Release Only) working-directory: ${{ inputs.target_kit }} env: - BUMP_TYPE: ${{ steps.config.outputs.bump_type }} + NEW_VER: ${{ steps.config.outputs.version }} IS_PRERELEASE: ${{ inputs.is_prerelease }} DRY_RUN: ${{ inputs.dry_run }} run: | - if [ "$DRY_RUN" = "true" ]; then - npm version $BUMP_TYPE --preid=rc --no-git-tag-version - else - # Only truncate CHANGELOG.md if this is a STABLE release (not a prerelease) - if [ "$IS_PRERELEASE" != "true" ]; then - echo "Stable release detected: clearing CHANGELOG.md..." - > CHANGELOG.md - git add CHANGELOG.md - else - echo "Prerelease detected: preserving CHANGELOG.md content." - fi + # npm version only performs git operations when .git sits next to + # package.json; kits live in kits// with .git at the repo root, + # so git commit/tag are done explicitly in the next step. + npm version "$NEW_VER" --no-git-tag-version - # Create version bump commit and git tag - if [[ "$BUMP_TYPE" == pre* ]] || [[ "$BUMP_TYPE" == "prerelease" ]]; then - npm version $BUMP_TYPE --preid=rc -m "chore(release): %s [skip ci]" - else - npm version $BUMP_TYPE -m "chore(release): %s [skip ci]" - fi + if [ "$DRY_RUN" != "true" ] && [ "$IS_PRERELEASE" != "true" ]; then + echo "Stable release detected: clearing CHANGELOG.md..." + > CHANGELOG.md fi - NEW_VER=$(node -p "require('./package.json').version") - PKG_NAME=$(node -p "require('./package.json').name") - - echo "version=$NEW_VER" >> $GITHUB_OUTPUT - echo "pkg_name=$PKG_NAME" >> $GITHUB_OUTPUT - echo "tag_name=${PKG_NAME}@${NEW_VER}" >> $GITHUB_OUTPUT + - name: Commit & Tag Release + if: ${{ !inputs.dry_run }} + env: + TARGET_KIT: ${{ inputs.target_kit }} + TAG_NAME: ${{ steps.config.outputs.tag_name }} + run: | + git add "$TARGET_KIT/package.json" + # npm version also bumps the lockfile; kits currently ship npm-shrinkwrap.json. + [ -f "$TARGET_KIT/npm-shrinkwrap.json" ] && git add "$TARGET_KIT/npm-shrinkwrap.json" + [ -f "$TARGET_KIT/package-lock.json" ] && git add "$TARGET_KIT/package-lock.json" + [ -f "$TARGET_KIT/CHANGELOG.md" ] && git add "$TARGET_KIT/CHANGELOG.md" + # git commit exits non-zero if the bump staged no changes, so a broken + # bump fails the release instead of publishing without a release commit. + git commit -m "chore(release): $TAG_NAME [skip ci]" + git tag -a "$TAG_NAME" -m "$TAG_NAME" - name: Dry Run Summary if: ${{ inputs.dry_run }} env: - PKG_NAME: ${{ steps.versioning.outputs.pkg_name }} + PKG_NAME: ${{ steps.config.outputs.pkg_name }} TARGET_KIT: ${{ inputs.target_kit }} CURRENT_VER: ${{ steps.config.outputs.current_ver }} - VERSION: ${{ steps.versioning.outputs.version }} + HIGHEST_VER: ${{ steps.config.outputs.highest_ver }} + HIGHEST_STABLE: ${{ steps.config.outputs.highest_stable }} + VERSION: ${{ steps.config.outputs.version }} BUMP_TYPE: ${{ steps.config.outputs.bump_type }} TARGET_TAG: ${{ steps.config.outputs.target_tag }} IS_PRERELEASE: ${{ inputs.is_prerelease }} - TAG_NAME: ${{ steps.versioning.outputs.tag_name }} + TAG_NAME: ${{ steps.config.outputs.tag_name }} NOTES: ${{ steps.changelog.outputs.notes }} run: | echo "==========================================================" @@ -208,7 +268,9 @@ jobs: echo "==========================================================" echo " Package Name: $PKG_NAME" echo " Target Directory: $TARGET_KIT" - echo " Current Version: $CURRENT_VER" + echo " package.json Ver: $CURRENT_VER" + echo " Highest Known: $HIGHEST_VER" + echo " Highest Stable: $HIGHEST_STABLE" echo " Target Version: $VERSION" echo " Version Bump: $BUMP_TYPE" echo " NPM Dist-Tag: $TARGET_TAG" @@ -220,20 +282,15 @@ jobs: echo "$NOTES" echo "==========================================================" - - name: Push Version Commit & Tags to Branch - if: ${{ !inputs.dry_run }} - env: - TARGET_BRANCH: "kits" - run: git push origin "$TARGET_BRANCH" --follow-tags - - name: Publish to NPM # zizmor: ignore[use-trusted-publishing] working-directory: ${{ inputs.target_kit }} env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} IS_PRERELEASE: ${{ inputs.is_prerelease }} DRY_RUN: ${{ inputs.dry_run }} - PKG_NAME: ${{ steps.versioning.outputs.pkg_name }} - VERSION: ${{ steps.versioning.outputs.version }} + PKG_NAME: ${{ steps.config.outputs.pkg_name }} + VERSION: ${{ steps.config.outputs.version }} run: | DRY_RUN_FLAG="" if [ "$DRY_RUN" = "true" ]; then @@ -242,32 +299,50 @@ jobs: fi if [ "$IS_PRERELEASE" = "true" ]; then - npm publish --tag next --provenance --access public $DRY_RUN_FLAG + npm publish --tag next --access public $DRY_RUN_FLAG else - npm publish --tag latest --provenance --access public $DRY_RUN_FLAG + npm publish --tag latest --access public $DRY_RUN_FLAG if [ "$DRY_RUN" != "true" ]; then npm dist-tag add ${PKG_NAME}@${VERSION} next fi fi + # Pushed only after a successful publish: a failed publish leaves the + # branch untouched, and the next run recomputes the version from the + # registry either way. + - name: Push Version Commit & Tag to Branch + if: ${{ !inputs.dry_run }} + env: + REF_NAME: ${{ github.ref_name }} + TAG_NAME: ${{ steps.config.outputs.tag_name }} + run: | + git push --atomic origin "HEAD:refs/heads/$REF_NAME" "refs/tags/$TAG_NAME" + - name: Create GitHub Release via GitHub CLI if: ${{ !inputs.dry_run }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAG_NAME: ${{ steps.versioning.outputs.tag_name }} - PKG_NAME: ${{ steps.versioning.outputs.pkg_name }} - VERSION: ${{ steps.versioning.outputs.version }} + TAG_NAME: ${{ steps.config.outputs.tag_name }} + PKG_NAME: ${{ steps.config.outputs.pkg_name }} + VERSION: ${{ steps.config.outputs.version }} IS_PRERELEASE: ${{ inputs.is_prerelease }} NOTES: ${{ steps.changelog.outputs.notes }} - TARGET_BRANCH: "kits" + REF_NAME: ${{ github.ref_name }} run: | PRERELEASE_FLAG="" if [ "$IS_PRERELEASE" = "true" ]; then PRERELEASE_FLAG="--prerelease" fi + # A re-run after a transient gh failure must not mint a new version + # just to get a release page, so creation is skipped if it exists. + if gh release view "$TAG_NAME" > /dev/null 2>&1; then + echo "Release $TAG_NAME already exists; skipping creation." + exit 0 + fi + gh release create "$TAG_NAME" \ --title "$PKG_NAME v$VERSION" \ --notes "$NOTES" \ - --target "$TARGET_BRANCH" \ + --target "$REF_NAME" \ $PRERELEASE_FLAG From 3ee422d5a332d852752cc2e63b62d3a9378b31a6 Mon Sep 17 00:00:00 2001 From: Jacob Cable <32874567+cabljac@users.noreply.github.com> Date: Thu, 27 Aug 2026 18:07:58 +0100 Subject: [PATCH 22/30] chore(ci): sync release-kit workflow from kits (#2993) (#2994) Syncs release-kit.yaml byte-for-byte with the #2993 version on kits (trusted publishing, checkout/push/release pinned to kits). The #2992 copy on next authenticated via the removed NPM_TOKEN and checked out the dispatched ref, so dispatching from next failed at the test job. The #2993 file is dispatch-ref-agnostic, making the two copies safely identical. No behavior change beyond fixing dispatch-from-next. --- .github/workflows/release-kit.yaml | 31 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index e9f6b13adf..f4cc9a3f88 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -60,7 +60,12 @@ jobs: permissions: contents: read steps: + # Kits live only on the kits branch; the ref is pinned so dispatching + # from any branch (including next, which lists the workflow in the UI) + # releases the same content. - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] + with: + ref: "kits" - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 @@ -82,16 +87,17 @@ jobs: runs-on: ubuntu-latest permissions: contents: write # Needed to push version commit, git tag & create GitHub Release + id-token: write # Needed to publish to npm via trusted publishing steps: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # zizmor: ignore[artipacked] + with: + ref: "kits" - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "24" - registry-url: "https://wombat-dressing-room.appspot.com" - always-auth: false - name: Configure Git User if: ${{ !inputs.dry_run }} @@ -136,13 +142,6 @@ jobs: run: | set -o pipefail - # The push at the end of the job would create a stray branch named - # after the ref if this were dispatched from a tag. - if [ "$GITHUB_REF_TYPE" != "branch" ]; then - echo "::error::Release Kit must be dispatched from a branch, got $GITHUB_REF_TYPE '$GITHUB_REF_NAME'." - exit 1 - fi - PKG_NAME=$(node -p "require('./package.json').name") LOCAL_VER=$(node -p "require('./package.json').version") @@ -283,10 +282,8 @@ jobs: echo "==========================================================" - name: Publish to NPM - # zizmor: ignore[use-trusted-publishing] working-directory: ${{ inputs.target_kit }} env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} IS_PRERELEASE: ${{ inputs.is_prerelease }} DRY_RUN: ${{ inputs.dry_run }} PKG_NAME: ${{ steps.config.outputs.pkg_name }} @@ -299,9 +296,9 @@ jobs: fi if [ "$IS_PRERELEASE" = "true" ]; then - npm publish --tag next --access public $DRY_RUN_FLAG + npm publish --tag next --provenance --access public $DRY_RUN_FLAG else - npm publish --tag latest --access public $DRY_RUN_FLAG + npm publish --tag latest --provenance --access public $DRY_RUN_FLAG if [ "$DRY_RUN" != "true" ]; then npm dist-tag add ${PKG_NAME}@${VERSION} next fi @@ -313,10 +310,10 @@ jobs: - name: Push Version Commit & Tag to Branch if: ${{ !inputs.dry_run }} env: - REF_NAME: ${{ github.ref_name }} + TARGET_BRANCH: "kits" TAG_NAME: ${{ steps.config.outputs.tag_name }} run: | - git push --atomic origin "HEAD:refs/heads/$REF_NAME" "refs/tags/$TAG_NAME" + git push --atomic origin "HEAD:refs/heads/$TARGET_BRANCH" "refs/tags/$TAG_NAME" - name: Create GitHub Release via GitHub CLI if: ${{ !inputs.dry_run }} @@ -327,7 +324,7 @@ jobs: VERSION: ${{ steps.config.outputs.version }} IS_PRERELEASE: ${{ inputs.is_prerelease }} NOTES: ${{ steps.changelog.outputs.notes }} - REF_NAME: ${{ github.ref_name }} + TARGET_BRANCH: "kits" run: | PRERELEASE_FLAG="" if [ "$IS_PRERELEASE" = "true" ]; then @@ -344,5 +341,5 @@ jobs: gh release create "$TAG_NAME" \ --title "$PKG_NAME v$VERSION" \ --notes "$NOTES" \ - --target "$REF_NAME" \ + --target "$TARGET_BRANCH" \ $PRERELEASE_FLAG From a9191dc8247f46045efd822eb5ddb1d65984bceb Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Mon, 31 Aug 2026 14:00:24 -0700 Subject: [PATCH 23/30] chore(ci): print inputs at start of release-kit workflow --- .github/workflows/release-kit.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index f4cc9a3f88..ee566d988a 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -60,6 +60,12 @@ jobs: permissions: contents: read steps: + - name: Print inputs + env: + INPUTS: ${{ toJSON(inputs) }} + run: | + echo "$INPUTS" + # Kits live only on the kits branch; the ref is pinned so dispatching # from any branch (including next, which lists the workflow in the UI) # releases the same content. From 5c80474690cadb4574a909cf5369d88877c4b80a Mon Sep 17 00:00:00 2001 From: Izaak Gough Date: Tue, 1 Sep 2026 19:52:05 +0100 Subject: [PATCH 24/30] fix(firestore-bigquery-export): scope insert retry to schema lag (#2937) ## The bug The retry guard was an `async` function called without `await`, so it was always truthy and every insert failure retried with `ignoreUnknownValues: true`. Unknown fields were dropped and the write reported success. Since 2020 (`2de70201`), untested. ## The fix The retry now removes only the columns BigQuery named, and only the ones we add to existing tables (`document_id`, `old_data`, and `path_params` with `wildcardIds`). Anything else fails the insert and backs up the full row. Two adjacent bugs go with it: `settings()` was called on every failure though it may only be called once, so every backup after the first threw; and `error_details` was always empty. ## Testing 52 new offline tests, `tsc --noEmit` clean, plus verified against a live BigQuery instance. ## To decide Allowlisting `document_id` costs a duplicate row in the legacy `_latest` view, taken because those tables already duplicate every pre-upgrade row. Needs a CHANGELOG note and a tracker version bump. --------- Co-authored-by: Jacob Cable --- .../CHANGELOG.md | 12 + .../package-lock.json | 4 +- .../package.json | 2 +- .../__tests__/bigquery/backupSettings.test.ts | 258 +++++ .../src/__tests__/bigquery/e2e.test.ts | 11 +- .../__tests__/bigquery/insertRetry.test.ts | 887 ++++++++++++++++++ .../src/bigquery/handleFailedTransactions.ts | 121 ++- .../src/bigquery/index.ts | 230 ++++- .../src/logs.ts | 39 +- 9 files changed, 1506 insertions(+), 58 deletions(-) create mode 100644 firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md create mode 100644 firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/backupSettings.test.ts create mode 100644 firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/insertRetry.test.ts diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md b/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md new file mode 100644 index 0000000000..74027d7b69 --- /dev/null +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +## 2.1.0 + +Insert-failure semantics changed. Since 2020, the retry guard in `insertData` was broken (an un-awaited async check that was always truthy), so every failed insert was retried with `ignoreUnknownValues: true` and reported success while silently dropping any field BigQuery did not recognise. + +- Failed inserts are now retried once for schema lag on the columns this package itself adds (`document_id`, `old_data`, and - when wildcard ids are enabled - `path_params`), stripping exactly those columns for the retry, and once for transient failures: per-row reasons `backendError`, `internalError`, `rateLimitExceeded`, `timeout`, `stopped`, plus any error carrying no per-row detail at all (network failures, request-level errors), which also gets one full retry. +- Every other failure is terminal: the original, unmodified rows are written to the configured backup collection (`backupTableId`, keyed by `insertId`) and the insert error is rethrown to the caller. +- Fixed the backup path calling `db.settings()` more than once per Firestore instance, which made every backup after the first throw and replaced the insert error. A failed backup write is now logged and the original insert error is still the one thrown. +- Backup documents now populate `error_details` (the field previously existed but was always empty). + +Operators consuming this via the firestore-bigquery-export extension or kit will see failures that previously passed as success: new error logs, retries from their own queue or trigger policy, and rows in `BACKUP_COLLECTION` where fields were previously dropped silently. During a schema-lag window the stripped columns are written as null; the affected column names are logged at warn level. A row written with a null `document_id` during such a window is permanently duplicated in the legacy `_latest` view (it groups by `document_name, document_id`); installs using the standard latest query are unaffected. diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json b/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json index 3b3d9d7ad0..0c294b8b6b 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json @@ -1,12 +1,12 @@ { "name": "@firebaseextensions/firestore-bigquery-change-tracker", - "version": "2.0.4", + "version": "2.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@firebaseextensions/firestore-bigquery-change-tracker", - "version": "2.0.4", + "version": "2.1.0", "license": "Apache-2.0", "dependencies": { "@google-cloud/bigquery": "^7.6.0", diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json b/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json index 299638f27c..3466e92321 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json @@ -5,7 +5,7 @@ "url": "git+https://github.com/firebase/extensions.git", "directory": "firestore-bigquery-export/firestore-bigquery-change-tracker" }, - "version": "2.0.4", + "version": "2.1.0", "description": "Core change-tracker library for Cloud Firestore Collection BigQuery Exports", "main": "./lib/index.js", "scripts": { diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/backupSettings.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/backupSettings.test.ts new file mode 100644 index 0000000000..562b84f525 --- /dev/null +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/backupSettings.test.ts @@ -0,0 +1,258 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChangeTrackerConfig } from "../../bigquery/types"; + +const commit = jest.fn(); +const set = jest.fn(); +const settings = jest.fn(); + +const batch = jest.fn(() => ({ set, commit })); +const collection = jest.fn(() => ({ doc: (id: string) => ({ id }) })); + +jest.mock("firebase-admin", () => ({ apps: [{}] })); +jest.mock("firebase-admin/app", () => ({ initializeApp: jest.fn() })); +jest.mock("firebase-admin/firestore", () => ({ + // A fresh object per call, deliberately: the guard must key on the database id + // rather than on instance identity. + getFirestore: jest.fn(() => ({ settings, batch, collection })), +})); + +const config = { + backupTableId: "bq_failures", + firestoreInstanceId: "(default)", +} as ChangeTrackerConfig; + +const ROWS = [{ insertId: "e1", json: { event_id: "e1" } }]; + +/** Fresh module, so the module-level "already configured" set starts empty. */ +const loadHandler = () => { + let handler: any; + jest.isolateModules(() => { + handler = require("../../bigquery/handleFailedTransactions").default; + }); + return handler; +}; + +describe("handleFailedTransactions Firestore settings", () => { + beforeEach(() => { + jest.clearAllMocks(); + commit.mockResolvedValue(undefined); + settings.mockImplementation(() => undefined); + }); + + it("applies settings once across repeated failures", async () => { + const handler = loadHandler(); + + await handler(ROWS, config, new Error("insert failed")); + await handler(ROWS, config, new Error("insert failed")); + + expect(settings).toHaveBeenCalledTimes(1); + expect(commit).toHaveBeenCalledTimes(2); + }); + + it("still writes the backup when settings cannot be applied", async () => { + settings.mockImplementation(() => { + throw new Error("Firestore has already been initialized"); + }); + + const handler = loadHandler(); + + await expect( + handler(ROWS, config, new Error("insert failed")) + ).resolves.toBeUndefined(); + + expect(commit).toHaveBeenCalledTimes(1); + }); + + it("still writes the backup when the thrown value is not an Error", async () => { + // `insertData` reports whatever it caught, so a non-Error reaches here. + const handler = loadHandler(); + + await expect( + handler(ROWS, config, undefined as any) + ).resolves.toBeUndefined(); + + expect(commit).toHaveBeenCalledTimes(1); + expect(typeof set.mock.calls[0][1].error_details).toBe("string"); + }); + + it("writes one document per row, keyed by insertId", async () => { + const handler = loadHandler(); + + await handler( + [{ insertId: "a" }, { insertId: "b" }], + config, + new Error("boom") + ); + + expect(collection).toHaveBeenCalledWith("bq_failures"); + expect(set).toHaveBeenCalledTimes(2); + expect(set.mock.calls[0][0]).toMatchObject({ id: "a" }); + expect(set.mock.calls[0][1]).toMatchObject({ error_details: "boom" }); + }); +}); + +/** + * A stand-in for `PartialFailureError`: one entry per failed row nesting the + * per-field errors, and the empty message `@google-cloud/common` builds from them. + */ +const partialFailure = (groups: any[]) => + Object.assign(new Error(""), { name: "PartialFailureError", errors: groups }); + +describe("handleFailedTransactions error details", () => { + beforeEach(() => { + jest.clearAllMocks(); + commit.mockResolvedValue(undefined); + settings.mockImplementation(() => undefined); + }); + + const detailsFor = async (e: any) => { + // Cleared per call, so a test may describe more than one failure shape. + set.mockClear(); + + await loadHandler()(ROWS, config, e); + + return set.mock.calls[0][1].error_details; + }; + + it("records the nested per-field messages when the top-level message is empty", async () => { + // The shape a real rejected insert arrives in. + const details = await detailsFor( + partialFailure([ + { + errors: [ + { message: "no such field: document_id.", reason: "invalid" }, + ], + row: { insertId: "e1" }, + }, + ]) + ); + + expect(details).toBe("no such field: document_id."); + }); + + it("deduplicates messages shared across failed rows", async () => { + const details = await detailsFor( + partialFailure([ + { errors: [{ message: "no such field: document_id." }] }, + { errors: [{ message: "no such field: document_id." }] }, + { errors: [{ message: "no such field: old_data." }] }, + ]) + ); + + expect(details).toBe( + "no such field: document_id.; no such field: old_data." + ); + }); + + it("caps the number of messages and the total length", async () => { + const details = await detailsFor( + partialFailure( + Array.from({ length: 9 }, (_, i) => ({ + errors: [{ message: `${"x".repeat(400)} ${i}` }], + })) + ) + ); + + // The count must survive the truncation rather than be cut off by it. + expect(details.length).toBeLessThanOrEqual(1000); + expect(details.endsWith(" (+4 more)")).toBe(true); + expect(details).toContain("..."); + + const short = await detailsFor( + partialFailure( + Array.from({ length: 8 }, (_, i) => ({ + errors: [{ message: `field ${i}` }], + })) + ) + ); + + expect(short).toBe("field 0; field 1; field 2; field 3; field 4 (+3 more)"); + }); + + it("falls back to the reason when an entry carries no message", async () => { + // A `stopped` entry, the row BigQuery did not attempt, arrives with an empty + // message and location, so the reason is all there is. + const details = await detailsFor( + partialFailure([ + { errors: [{ message: "", location: "", reason: "stopped" }] }, + { errors: [{ message: "", location: "", reason: "stopped" }] }, + ]) + ); + + expect(details).toBe("stopped"); + }); + + it("prefers an entry's message over its reason", async () => { + const details = await detailsFor( + partialFailure([ + { + errors: [ + { message: "no such field: document_id.", reason: "invalid" }, + ], + }, + ]) + ); + + expect(details).toBe("no such field: document_id."); + }); + + it("survives an error whose message getter throws", async () => { + const hostile = { + get message(): string { + throw new Error("hostile getter"); + }, + }; + + await expect(detailsFor(hostile)).resolves.toBe("Unknown error"); + }); + + it("prefers a populated top-level message over the nested ones", async () => { + const details = await detailsFor( + Object.assign(new Error("quota exceeded"), { + errors: [{ errors: [{ message: "no such field: document_id." }] }], + }) + ); + + expect(details).toBe("quota exceeded"); + }); + + it("still writes a string for every malformed shape of `errors`", async () => { + // The handler runs inside the caller's catch block, so a throw loses the row. + const shapes: any[] = [ + partialFailure([]), + Object.assign(new Error(""), { errors: "not an array" }), + Object.assign(new Error(""), { errors: [null, undefined] }), + Object.assign(new Error(""), { errors: [{ errors: null }] }), + Object.assign(new Error(""), { errors: [{ errors: [null] }] }), + Object.assign(new Error(""), { errors: [{ errors: [{}] }] }), + Object.assign(new Error(""), { errors: [{ errors: [{ message: 42 }] }] }), + "a plain string", + 42, + null, + Object.create(null), + ]; + + for (const shape of shapes) { + jest.clearAllMocks(); + + await expect(loadHandler()(ROWS, config, shape)).resolves.toBeUndefined(); + + expect(typeof set.mock.calls[0][1].error_details).toBe("string"); + } + }); +}); diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts index c642de74ca..6c1642411a 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts @@ -814,8 +814,15 @@ describe("e2e", () => { test("successfully adds old data field if it does not yet exist", async () => { const event: FirestoreDocumentChangeEvent = changeTrackerEvent({}); - /** Create a table without an old_data column */ - let schema = [{ name: "Name", type: "STRING" }]; + /** + * A valid changelog in every respect except that it predates `old_data`, + * which is the case this test is about. The base columns are never added + * to a table that already exists, so a table missing those as well would + * fail the insert outright rather than exercise the lag retry. + */ + let schema = RawChangelogSchema.fields.filter( + (field) => field.name !== "old_data" + ); let [originalRawTable] = await dataset.createTable(table_raw_changelog, { schema, diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/insertRetry.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/insertRetry.test.ts new file mode 100644 index 0000000000..6a34d486d5 --- /dev/null +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/insertRetry.test.ts @@ -0,0 +1,887 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FirestoreBigQueryEventHistoryTracker } from "../../bigquery"; +import { ChangeTrackerConfig } from "../../bigquery/types"; +import handleFailedTransactions from "../../bigquery/handleFailedTransactions"; +import { logger } from "../../logger"; + +jest.mock("../../bigquery/handleFailedTransactions", () => ({ + __esModule: true, + default: jest.fn().mockResolvedValue(undefined), +})); + +const handleFailedTransactionsMock = handleFailedTransactions as jest.Mock; + +process.env.PROJECT_ID = "test-project"; + +const config = ( + overrides: Partial = {} +): ChangeTrackerConfig => + ({ + datasetId: "dataset", + tableId: "table", + datasetLocation: "us", + backupTableId: "backup", + transformFunction: "", + partitioning: { granularity: "NONE" }, + clustering: [], + bqProjectId: "test-project", + ...overrides, + } as ChangeTrackerConfig); + +/** + * The error shape `@google-cloud/bigquery` actually throws: `response` is the raw + * `insertAll` body, where `insertErrors` is an array, and the error's own + * `errors` is the remapped copy that drops `location`. + */ +function partialFailure( + fieldErrors: Array<{ message: string; location?: string; reason?: string }> +) { + // BigQuery always sets a reason on these entries, and classification reads it. + const entries = fieldErrors.map((fieldError) => ({ + reason: "invalid", + ...fieldError, + })); + + const e: any = new Error("insert failed"); + e.name = "PartialFailureError"; + e.errors = [ + { + row: {}, + errors: entries.map(({ message, reason }) => ({ message, reason })), + }, + ]; + e.response = { + kind: "bigquery#tableDataInsertAllResponse", + insertErrors: [{ index: 0, errors: entries }], + }; + return e; +} + +/** An error with no partial-failure body, e.g. a network or quota failure. */ +function transportFailure() { + const e: any = new Error("ECONNRESET"); + e.code = "ECONNRESET"; + return e; +} + +/** + * Carries every column the allowlist can name, so that asserting one was removed + * cannot pass because the key was never there. + */ +const ROWS = [ + { + insertId: "e1", + json: { + event_id: "e1", + data: "{}", + document_id: "d1", + old_data: null, + path_params: "{}", + created_at: "2026-01-01 00:00:00", + }, + }, +]; + +/** The row payload of the nth `insert` call, 0-indexed. */ +const payloadOf = (insert: jest.Mock, call: number) => + insert.mock.calls[call][0][0].json; + +/** A tracker whose inserts are served by `insert`, so no client is needed. */ +function trackerWith( + insert: jest.Mock, + overrides?: Partial +) { + const tracker = new FirestoreBigQueryEventHistoryTracker(config(overrides)); + + jest.spyOn(tracker as any, "bigqueryDataset").mockReturnValue({ + table: () => ({ insert }), + }); + + return tracker; +} + +/** Invokes the private insert path directly. */ +const insertData = (tracker: FirestoreBigQueryEventHistoryTracker) => + (tracker as any).insertData(ROWS); + +describe("insertData retry behaviour", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe("a column we just added is not streamable yet", () => { + it("retries once without the rejected column, and succeeds", async () => { + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([ + { message: "no such field.", location: "document_id" }, + ]) + ) + .mockResolvedValueOnce(undefined); + + await expect(insertData(trackerWith(insert))).resolves.toBeUndefined(); + + expect(insert).toHaveBeenCalledTimes(2); + expect(payloadOf(insert, 0)).toHaveProperty("document_id"); + expect(payloadOf(insert, 1)).not.toHaveProperty("document_id"); + expect(payloadOf(insert, 1)).toMatchObject({ + event_id: "e1", + data: "{}", + }); + expect(insert.mock.calls[1][1]).toMatchObject({ + ignoreUnknownValues: false, + }); + expect(handleFailedTransactionsMock).not.toHaveBeenCalled(); + }); + + it("matches the inlined message form that omits location", async () => { + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([{ message: "no such field: path_params." }]) + ) + .mockResolvedValueOnce(undefined); + + await expect( + insertData(trackerWith(insert, { wildcardIds: true })) + ).resolves.toBeUndefined(); + + expect(insert).toHaveBeenCalledTimes(2); + expect(payloadOf(insert, 1)).not.toHaveProperty("path_params"); + }); + + it("does not ignore an unknown field BigQuery did not name", async () => { + // BigQuery names one unknown field per row, so a stray key alongside a + // lagging column only surfaces on the retry. + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([ + { message: "no such field.", location: "document_id" }, + ]) + ) + .mockRejectedValueOnce( + partialFailure([{ message: "no such field.", location: "injected" }]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(insert).toHaveBeenCalledTimes(2); + expect(payloadOf(insert, 1)).not.toHaveProperty("document_id"); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + + it("strips one column per retry when BigQuery names them one at a time", async () => { + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([{ message: "no such field.", location: "old_data" }]) + ) + .mockRejectedValueOnce( + partialFailure([ + { message: "no such field.", location: "document_id" }, + ]) + ) + .mockResolvedValueOnce(undefined); + + await expect(insertData(trackerWith(insert))).resolves.toBeUndefined(); + + expect(insert).toHaveBeenCalledTimes(3); + expect(payloadOf(insert, 1)).not.toHaveProperty("old_data"); + expect(payloadOf(insert, 2)).not.toHaveProperty("old_data"); + expect(payloadOf(insert, 2)).not.toHaveProperty("document_id"); + expect(handleFailedTransactionsMock).not.toHaveBeenCalled(); + }); + + it("ignores stopped rows when recognising the lag", async () => { + // With `skipInvalidRows` false BigQuery marks the rows it did not attempt + // as `stopped`, with the empty message and location a live instance sends. + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([ + { message: "", location: "", reason: "stopped" }, + { message: "no such field.", location: "document_id" }, + ]) + ) + .mockResolvedValueOnce(undefined); + + await expect(insertData(trackerWith(insert))).resolves.toBeUndefined(); + + expect(insert).toHaveBeenCalledTimes(2); + expect(payloadOf(insert, 1)).not.toHaveProperty("document_id"); + expect(handleFailedTransactionsMock).not.toHaveBeenCalled(); + }); + + it("names a column once however many rows rejected it", async () => { + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([ + { message: "no such field.", location: "document_id" }, + { message: "no such field.", location: "document_id" }, + ]) + ) + .mockResolvedValueOnce(undefined); + + const warn = jest + .spyOn(logger, "warn") + .mockImplementation(() => undefined); + + await expect(insertData(trackerWith(insert))).resolves.toBeUndefined(); + + const messages = warn.mock.calls.map(([message]) => String(message)); + warn.mockRestore(); + + expect( + messages.some((m) => m.includes("without document_id, document_id")) + ).toBe(false); + expect(messages.some((m) => m.includes("without document_id"))).toBe( + true + ); + }); + + it("gives up when a retry makes no progress", async () => { + // Bounds the recursion: the same column twice means removing it did not help. + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([ + { message: "no such field.", location: "document_id" }, + ]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(insert).toHaveBeenCalledTimes(2); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + + it("backs up and throws when the retry also fails", async () => { + const error = partialFailure([ + { message: "no such field.", location: "path_params" }, + ]); + const insert = jest.fn().mockRejectedValue(error); + const tracker = trackerWith(insert, { wildcardIds: true }); + + // Must start true, or asserting false below passes against an + // implementation that never clears the flag. + tracker._initialized = true; + + await expect(insertData(tracker)).rejects.toThrow("insert failed"); + + expect(insert).toHaveBeenCalledTimes(2); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + expect(tracker._initialized).toBe(false); + }); + + it("backs up the row the caller gave us, not the one the retry reduced", async () => { + // A strip followed by a terminal rejection for a different column is the + // ordinary case, and the backup is the only record of the row that is left. + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([{ message: "no such field: document_id." }]) + ) + .mockRejectedValueOnce( + partialFailure([{ message: "no such field: injected_col." }]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + // Without this, the assertion below passes even if nothing was stripped. + expect(payloadOf(insert, 1)).not.toHaveProperty("document_id"); + expect(handleFailedTransactionsMock).toHaveBeenCalledWith( + ROWS, + expect.anything(), + expect.anything() + ); + }); + + it("clears initialization so a column that is really gone comes back", async () => { + // Nothing here can tell a lagging column from one that was actually + // dropped, so a warm instance must not strip it for its whole life. + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([{ message: "no such field: old_data." }]) + ) + .mockResolvedValueOnce(undefined); + + const tracker = trackerWith(insert); + tracker._initialized = true; + + await expect(insertData(tracker)).resolves.toBeUndefined(); + + expect(insert).toHaveBeenCalledTimes(2); + expect(tracker._initialized).toBe(false); + }); + + it("does not match a column that merely contains an allowlisted name", async () => { + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([{ message: "no such field: document_id_v2." }]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(insert).toHaveBeenCalledTimes(1); + }); + + // `path_params` needs its own config: the column is only added, and the key + // only emitted, when wildcard ids are enabled. + const addedColumns: Array<[string, Partial]> = [ + ["document_id", {}], + ["old_data", {}], + ["path_params", { wildcardIds: true }], + ]; + + it.each(addedColumns)( + "covers %s, every column added to an existing table", + async (column, overrides) => { + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([{ message: "no such field.", location: column }]) + ) + .mockResolvedValueOnce(undefined); + + await expect( + insertData(trackerWith(insert, overrides)) + ).resolves.toBeUndefined(); + + expect(insert).toHaveBeenCalledTimes(2); + expect(payloadOf(insert, 1)).not.toHaveProperty(column); + } + ); + + it("does not allowlist path_params when wildcard ids are disabled", async () => { + // The column is never created here, but a transform function can still + // inject the key, since `transformRows` uses its response verbatim. + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([ + { message: "no such field.", location: "path_params" }, + ]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(insert).toHaveBeenCalledTimes(1); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + }); + + describe("schema drift we did not add", () => { + it("does not retry, and does not silently drop the field", async () => { + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([{ message: "no such field.", location: "user_age" }]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(insert).toHaveBeenCalledTimes(1); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + + it("does not retry when only some rejected fields are ours", async () => { + const insert = jest.fn().mockRejectedValue( + partialFailure([ + { message: "no such field.", location: "document_id" }, + { message: "no such field.", location: "user_age" }, + ]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(insert).toHaveBeenCalledTimes(1); + }); + + it("does not retry a rejection that is not an unknown field", async () => { + const insert = jest.fn().mockRejectedValue( + partialFailure([ + { + message: "Cannot convert value to timestamp.", + location: "timestamp", + }, + ]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(insert).toHaveBeenCalledTimes(1); + }); + }); + + describe("the user-configured partition column", () => { + const partitioned = { + partitioning: { + granularity: "HOUR", + bigqueryColumnName: "created_at", + bigqueryColumnType: "TIMESTAMP", + firestoreFieldName: "createdAt", + }, + } as Partial; + + it("is not allowlisted, even under the strategy that adds it", async () => { + // `tableRequiresUpdate` is false for a table that is already + // time-partitioned, so on exactly that table the column is never added. + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([ + { message: "no such field.", location: "created_at" }, + ]) + ); + + await expect( + insertData(trackerWith(insert, partitioned)) + ).rejects.toThrow("insert failed"); + + expect(insert).toHaveBeenCalledTimes(1); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + + it("is not allowlisted when no partitioning is configured", async () => { + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([ + { message: "no such field.", location: "created_at" }, + ]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(insert).toHaveBeenCalledTimes(1); + }); + + it("is not allowlisted under the Firestore timestamp strategy", async () => { + // Excluded deliberately, not for want of a code path: `timestamp` keys the + // partition, so a null misfiles the row rather than costing an event. + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([{ message: "no such field.", location: "timestamp" }]) + ); + + await expect( + insertData( + trackerWith(insert, { + partitioning: { + granularity: "DAY", + bigqueryColumnName: "timestamp", + }, + } as Partial) + ) + ).rejects.toThrow("insert failed"); + + expect(insert).toHaveBeenCalledTimes(1); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + + it("is not allowlisted when field partitioning names a base column", async () => { + // Keyed on the collision, not on `timestamp`, so any base-column name hits it. + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([{ message: "no such field.", location: "data" }]) + ); + + await expect( + insertData( + trackerWith(insert, { + partitioning: { + granularity: "DAY", + bigqueryColumnName: "data", + bigqueryColumnType: "TIMESTAMP", + firestoreFieldName: "someField", + }, + } as Partial) + ) + ).rejects.toThrow("insert failed"); + + expect(insert).toHaveBeenCalledTimes(1); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + }); + + describe("a transient blip followed by a schema lag", () => { + it("can still retry the schema lag", async () => { + const insert = jest + .fn() + .mockRejectedValueOnce(transportFailure()) + .mockRejectedValueOnce( + partialFailure([ + { message: "no such field.", location: "document_id" }, + ]) + ) + .mockResolvedValueOnce(undefined); + + await expect(insertData(trackerWith(insert))).resolves.toBeUndefined(); + + expect(insert).toHaveBeenCalledTimes(3); + expect(payloadOf(insert, 1)).toHaveProperty("document_id"); + expect(payloadOf(insert, 2)).not.toHaveProperty("document_id"); + expect(handleFailedTransactionsMock).not.toHaveBeenCalled(); + }); + + it("spends the transient retry at most once", async () => { + const insert = jest + .fn() + .mockRejectedValueOnce(transportFailure()) + .mockRejectedValueOnce( + partialFailure([ + { message: "no such field.", location: "document_id" }, + ]) + ) + .mockRejectedValue(transportFailure()); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "ECONNRESET" + ); + + expect(insert).toHaveBeenCalledTimes(3); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + }); + + describe("a schema lag followed by a transient blip", () => { + it("can still retry the blip, and keeps the column stripped", async () => { + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([ + { message: "no such field.", location: "document_id" }, + ]) + ) + .mockRejectedValueOnce(transportFailure()) + .mockResolvedValueOnce(undefined); + + await expect(insertData(trackerWith(insert))).resolves.toBeUndefined(); + + expect(insert).toHaveBeenCalledTimes(3); + expect(payloadOf(insert, 0)).toHaveProperty("document_id"); + expect(payloadOf(insert, 1)).not.toHaveProperty("document_id"); + expect(payloadOf(insert, 2)).not.toHaveProperty("document_id"); + expect(handleFailedTransactionsMock).not.toHaveBeenCalled(); + }); + }); + + describe("malformed failures", () => { + it("survives a null entry in the errors array", async () => { + // Not producible by the current library, but classifying runs inside the + // catch block, where a throw loses the real error and skips the backup. + const insert = jest.fn().mockRejectedValue({ + message: "insert failed", + response: { insertErrors: [{ index: 0, errors: [null] }] }, + }); + + await expect(insertData(trackerWith(insert))).rejects.toMatchObject({ + message: "insert failed", + }); + + expect(insert).toHaveBeenCalledTimes(1); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + + it("survives a non-object thrown value", async () => { + const insert = jest.fn().mockRejectedValue(undefined); + + await expect(insertData(trackerWith(insert))).rejects.toBeUndefined(); + + // Only shows the backup was reached, since the module is mocked here. That + // it writes a row for a non-Error is pinned in backupSettings.test.ts. + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + + it("still reports the insert error when error logging hits a bad entry", async () => { + // `e.errors` is the remapped copy logged on the terminal path. + const error: any = new Error("insert failed"); + error.errors = [null]; + error.response = { + insertErrors: [ + { index: 0, errors: [{ message: "no such field.", location: "x" }] }, + ], + }; + + const insert = jest.fn().mockRejectedValue(error); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + + it("still reports the insert error when errors is not an array", async () => { + const error: any = new Error("insert failed"); + error.errors = { nested: "not an array" }; + + const insert = jest.fn().mockRejectedValue(error); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + }); + }); + + describe("transient failures", () => { + it("retries a partial failure whose reasons are all retryable", async () => { + // A rate limit or backend error arrives as a partial failure, not as a + // bare transport error. + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([ + { message: "Backend error.", reason: "backendError" }, + { message: "Row skipped.", reason: "stopped" }, + ]) + ) + .mockResolvedValueOnce(undefined); + + await expect(insertData(trackerWith(insert))).resolves.toBeUndefined(); + + expect(insert).toHaveBeenCalledTimes(2); + expect(insert.mock.calls[1][1]).toMatchObject({ + ignoreUnknownValues: false, + }); + expect(handleFailedTransactionsMock).not.toHaveBeenCalled(); + }); + + it("does not retry when any reason is not retryable", async () => { + const insert = jest.fn().mockRejectedValue( + partialFailure([ + { message: "Backend error.", reason: "backendError" }, + { message: "Cannot convert value.", reason: "invalid" }, + ]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(insert).toHaveBeenCalledTimes(1); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + + it("does not retry a partial failure with no reason to judge", async () => { + // Fails closed: an entry we cannot classify is not evidence of a blip. + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([{ message: "", reason: undefined }]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(insert).toHaveBeenCalledTimes(1); + }); + + it("retries once with options unchanged", async () => { + const insert = jest + .fn() + .mockRejectedValueOnce(transportFailure()) + .mockResolvedValueOnce(undefined); + + await expect(insertData(trackerWith(insert))).resolves.toBeUndefined(); + + expect(insert).toHaveBeenCalledTimes(2); + expect(insert.mock.calls[1][1]).toMatchObject({ + ignoreUnknownValues: false, + }); + expect(handleFailedTransactionsMock).not.toHaveBeenCalled(); + }); + + it("backs up and throws when the retry also fails", async () => { + const insert = jest.fn().mockRejectedValue(transportFailure()); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "ECONNRESET" + ); + + expect(insert).toHaveBeenCalledTimes(2); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + }); + + describe("backup collection", () => { + it("is skipped when no backupTableId is configured", async () => { + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([{ message: "no such field.", location: "user_age" }]) + ); + + await expect( + insertData(trackerWith(insert, { backupTableId: undefined })) + ).rejects.toThrow("insert failed"); + + expect(handleFailedTransactionsMock).not.toHaveBeenCalled(); + }); + + it("does not let its own failure mask the insert error", async () => { + handleFailedTransactionsMock.mockRejectedValueOnce( + new Error("firestore batch failed") + ); + + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([{ message: "no such field.", location: "user_age" }]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + }); + + it("is used for a terminal failure on the first attempt", async () => { + const insert = jest + .fn() + .mockRejectedValue( + partialFailure([{ message: "no such field.", location: "user_age" }]) + ); + + await expect(insertData(trackerWith(insert))).rejects.toThrow( + "insert failed" + ); + + // This failure never reaches a second attempt, so a backup condition keyed + // on "this is the second attempt" would skip it. + expect(insert).toHaveBeenCalledTimes(1); + expect(handleFailedTransactionsMock).toHaveBeenCalledTimes(1); + expect(handleFailedTransactionsMock).toHaveBeenCalledWith( + ROWS, + expect.objectContaining({ backupTableId: "backup" }), + expect.any(Error) + ); + }); + }); + + describe("retry logging", () => { + let debug: jest.SpyInstance; + let warn: jest.SpyInstance; + + beforeEach(() => { + debug = jest.spyOn(logger, "debug").mockImplementation(() => undefined); + warn = jest.spyOn(logger, "warn").mockImplementation(() => undefined); + }); + + afterEach(() => { + debug.mockRestore(); + warn.mockRestore(); + }); + + it("warns rather than debugs when a retry drops columns", async () => { + // Debug is suppressed at the default log level. + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([ + { message: "no such field.", location: "document_id" }, + ]) + ) + .mockResolvedValueOnce(undefined); + + await expect(insertData(trackerWith(insert))).resolves.toBeUndefined(); + + expect( + warn.mock.calls.filter(([message]) => + String(message).includes("without document_id") + ) + ).toHaveLength(1); + expect( + debug.mock.calls.filter(([message]) => + String(message).includes("without document_id") + ) + ).toHaveLength(0); + }); + + it("names the columns it dropped", async () => { + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([{ message: "no such field.", location: "old_data" }]) + ) + .mockResolvedValueOnce(undefined); + + await expect(insertData(trackerWith(insert))).resolves.toBeUndefined(); + + const messages = warn.mock.calls.map(([message]) => String(message)); + + expect(messages.some((m) => m.includes("without old_data"))).toBe(true); + }); + + it("distinguishes the retry that drops columns from the one that does not", async () => { + // Only one of the two retries drops columns, and the logs are all an + // operator has to tell them apart. + const insert = jest + .fn() + .mockRejectedValueOnce( + partialFailure([ + { message: "no such field.", location: "document_id" }, + ]) + ) + .mockRejectedValueOnce(transportFailure()) + .mockResolvedValueOnce(undefined); + + await expect(insertData(trackerWith(insert))).resolves.toBeUndefined(); + + const messages = [...debug.mock.calls, ...warn.mock.calls].map( + ([message]) => String(message) + ); + const dropped = messages.filter((message) => + message.includes("without document_id") + ); + + expect(dropped).toHaveLength(1); + expect(dropped[0]).toContain(`${ROWS.length} row(s)`); + expect( + messages.filter((message) => message.includes("transient")) + ).toHaveLength(1); + }); + }); +}); diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts index 93e10538fc..2ad56c6a91 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts @@ -23,15 +23,126 @@ if (!admin.apps.length) { initializeApp(); } +/** `settings()` may only be called once per instance, and before it is used. */ +const settingsApplied = new Set(); + +function backupFirestore(instanceId: string) { + const db = getFirestore(instanceId); + + if (!settingsApplied.has(instanceId)) { + settingsApplied.add(instanceId); + + try { + db.settings({ ignoreUndefinedProperties: true }); + } catch (settingsError) { + // Something else reached this instance first. The backup still goes + // ahead, without `ignoreUndefinedProperties`. + } + } + + return db; +} + +/** Distinct messages recorded before the rest are counted instead. */ +const MAX_ERROR_MESSAGES = 5; + +/** Cap, so one bad insert cannot write an unbounded Firestore field. */ +const MAX_ERROR_DETAILS_LENGTH = 1000; + +function truncate( + value: string, + limit: number = MAX_ERROR_DETAILS_LENGTH +): string { + return value.length > limit ? `${value.slice(0, limit - 3)}...` : value; +} + +/** + * The per-field messages a `PartialFailureError` nests under + * `errors[].errors[].message`, deduplicated because a batch usually fails the + * same way for every row. + */ +function nestedErrorMessages(e: unknown): string { + const groups = (e as any)?.errors; + + if (!Array.isArray(groups)) return ""; + + const messages = new Set(); + + for (const group of groups) { + const inner = (group as any)?.errors; + const entries = Array.isArray(inner) ? inner : [group]; + + for (const entry of entries) { + const message = (entry as any)?.message; + + if (typeof message === "string" && message.length > 0) { + messages.add(message); + continue; + } + + // A `stopped` entry, the row BigQuery did not attempt, arrives with an + // empty `message` and `location`, so `reason` is all there is. + const reason = (entry as any)?.reason; + + if (typeof reason === "string" && reason.length > 0) { + messages.add(reason); + } + } + } + + if (messages.size === 0) return ""; + + const all = Array.from(messages); + const shown = all.slice(0, MAX_ERROR_MESSAGES); + const remaining = all.length - shown.length; + const suffix = remaining > 0 ? ` (+${remaining} more)` : ""; + + // Truncating the messages rather than the finished string, so the count is + // not the part that gets cut off. + return `${truncate( + shown.join("; "), + MAX_ERROR_DETAILS_LENGTH - suffix.length + )}${suffix}`; +} + +/** + * `insertData` reports whatever it caught, so this is not always an Error, and on + * the common failure its `message` is empty: `@google-cloud/common` builds a + * `PartialFailureError`'s message from entries that carry none, so the real + * reason sits one level down. + */ +function describeError(e: unknown): string { + // Runs inside the caller's catch block, where a throw is reported as a failed + // backup, so the whole body is guarded rather than just `String(e)`. + try { + const message = (e as any)?.message; + + if (typeof message === "string" && message.length > 0) { + return truncate(message); + } + + // Already capped, so it is not truncated a second time here. + const nested = nestedErrorMessages(e); + + if (nested.length > 0) return nested; + + return truncate(String(e)); + } catch (describeFailure) { + // A value whose `toString` or `message` throws, or an object with a null + // prototype. + return "Unknown error"; + } +} + export default async ( rows: any[], config: ChangeTrackerConfig, e: Error ): Promise => { - const db = getFirestore(config.firestoreInstanceId!); - db.settings({ - ignoreUndefinedProperties: true, - }); + const db = backupFirestore(config.firestoreInstanceId!); + + const errorDetails = describeError(e); + const batchArray = [db.batch()]; let operationCounter = 0; @@ -42,7 +153,7 @@ export default async ( batchArray[batchIndex].set(ref, { ...row, - error_details: e.message, + error_details: errorDetails, }); operationCounter++; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/index.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/index.ts index edc7052ba2..6858823cb3 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/index.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/index.ts @@ -47,6 +47,81 @@ import type { ChangeTrackerConfig } from "./types"; import { PartitioningConfig } from "./partitioning/config"; export type { ChangeTrackerConfig } from "./types"; +interface InsertAllError { + message?: string; + location?: string; + reason?: string; +} + +/** + * The `insertAll` error reasons BigQuery documents as worth retrying. `stopped` + * marks a row BigQuery did not attempt, and never appears without one of the + * others alongside it. + */ +const RETRYABLE_INSERT_REASONS = [ + "backendError", + "internalError", + "rateLimitExceeded", + "timeout", + "stopped", +]; + +/** + * Read from `response.insertErrors` rather than the error's own `errors`, which + * is a remapped copy that drops `location` and so cannot identify the column. + */ +function extractInsertErrors(e: any): InsertAllError[] { + const insertErrors = e?.response?.insertErrors; + + if (!Array.isArray(insertErrors)) return []; + + return insertErrors.flatMap((insertError) => + Array.isArray(insertError?.errors) ? insertError.errors : [] + ); +} + +/** + * Null for anything it cannot attribute, so an unrecognised entry fails the + * insert rather than dropping data. Two response forms exist: the bare + * `"no such field."` naming the column in `location`, and an inlined + * `"no such field: document_id."`. + */ +function unknownFieldColumn( + error: InsertAllError, + columns: string[] +): string | null { + // Runs inside a catch block, so a malformed entry must not throw. + const message = error?.message ?? ""; + + if (!/^no such field/i.test(message)) return null; + + if (error.location) { + return columns.includes(error.location) ? error.location : null; + } + + // Whole name, not a substring: `document_id_v2` must not match `document_id`. + const named = message.match(/^no such field:\s*(.+?)\.?$/i); + + return named && columns.includes(named[1]) ? named[1] : null; +} + +/** Rows are inserted with `raw: true`, so the payload is under `json`. */ +function withoutColumns( + rows: bigquery.RowMetadata[], + columns: string[] +): bigquery.RowMetadata[] { + if (!columns.length) return rows; + + return rows.map((row) => { + if (!row?.json) return row; + + const json = { ...row.json }; + columns.forEach((column) => delete json[column]); + + return { ...row, json }; + }); +} + /** * An FirestoreEventHistoryTracker that exports data to BigQuery. * @@ -154,39 +229,79 @@ export class FirestoreBigQueryEventHistoryTracker } /** - * Check whether a failed operation is retryable or not. - * Reasons for retrying: - * 1) We added a new column to our schema. Sometimes BQ is not ready to stream insertion records immediately - * after adding a new column to an existing table (https://issuetracker.google.com/35905247) + * The rejected columns when an insert failure is the one case it is safe to + * retry: a column added to an existing table that BigQuery is not ready to + * stream into yet (https://issuetracker.google.com/35905247). Any other unknown + * field is real drift, and dropping it would lose the user's data. + * + * Not `async`: the result is used in a guard, where a promise is always truthy. */ - private async isRetryableInsertionError(e) { - let isRetryable = true; - const expectedErrors = [ - { message: "no such field.", location: documentIdField.name }, - { message: "no such field.", location: documentPathParams.name }, - ]; - if ( - e.response && - e.response.insertErrors && - e.response.insertErrors.errors - ) { - const errors = e.response.insertErrors.errors; - errors?.forEach((error) => { - let isExpected = false; - expectedErrors?.forEach((expectedError) => { - if ( - error.message === expectedError.message && - error.location === expectedError.location - ) { - isExpected = true; - } - }); - if (!isExpected) { - isRetryable = false; - } - }); + private schemaLagColumns(e: any): string[] { + const errors = extractInsertErrors(e); + + // Without per-field detail we cannot show the retry is safe. + if (!errors.length) return []; + + const addedColumns = this.columnsAddedToExistingTables(); + const rejected: string[] = []; + + for (const error of errors) { + // A row BigQuery did not attempt because another in the request failed. + // Skipping it is what lets a multi-row batch be recognised as lag at all. + if (error?.reason === "stopped") continue; + + const column = unknownFieldColumn(error, addedColumns); + + if (!column) return []; + + rejected.push(column); } - return isRetryable; + + // One entry per row, so the same column appears once per rejected row. + return [...new Set(rejected)]; + } + + /** + * The only columns a lag retry may drop. Exact in both directions: one missing + * costs the event once the caller's retries run out, and one listed that is + * never actually added is stripped from every insert for the table's life. + * + * A null in a column the latest view groups on duplicates the document in + * `_latest` permanently. Accepted for these, whose tables already hold + * pre-upgrade rows with the same nulls; not for `timestamp`, where a null + * misfiles the row instead. + */ + private columnsAddedToExistingTables(): string[] { + const columns = [documentIdField.name, oldDataField.name]; + + // Only added, and only emitted, when wildcard ids are on. A transform + // function can inject the key regardless: `transformRows` uses its response + // verbatim. + if (this.config.wildcardIds) { + columns.push(documentPathParams.name); + } + + // The custom partition column is deliberately not allowlisted. Initialize + // can still add it to an existing table (the clustering comparison in + // `tableRequiresUpdate` returns true for default installs), so it can lag; + // when it does, the insert fails terminally and the row is backed up + // intact rather than stripped and retried. Safe in the lossy direction. + return columns; + } + + /** + * Qualifies only when every entry names a reason BigQuery documents as + * retryable; anything else is a rejection of the data, which a retry cannot + * fix. A failure with no partial-failure body says nothing about the schema. + */ + private isTransientInsertionError(e: any): boolean { + const errors = extractInsertErrors(e); + + if (!errors.length) return true; + + return errors.every((error) => + RETRYABLE_INSERT_REASONS.includes(error?.reason) + ); } /** @@ -213,11 +328,18 @@ export class FirestoreBigQueryEventHistoryTracker /** * Inserts rows of data into the BigQuery raw change log table. + * + * Columns are removed at the `insert` call rather than from `rows`, so the + * backup on the terminal path still holds every column. */ private async insertData( rows: bigquery.RowMetadata[], overrideOptions: InsertRowsOptions = {}, - retry: boolean = true + // Columns a schema-lag retry has already removed from the payload. Each + // retry must remove one not removed before, which bounds the recursion. + strippedColumns: string[] = [], + // Tracked separately, so a blip cannot consume the retry a later lag needs. + allowTransientRetry: boolean = true ) { const options = { skipInvalidRows: false, @@ -230,27 +352,51 @@ export class FirestoreBigQueryEventHistoryTracker const table = dataset.table(this.rawChangeLogTableName()); logs.dataInserting(rows.length); - await table.insert(rows, options); + await table.insert(withoutColumns(rows, strippedColumns), options); logs.dataInserted(rows.length); } catch (e) { - if (retry && this.isRetryableInsertionError(e)) { - retry = false; - logs.dataInsertRetried(rows.length); + // A column we just added may not be streamable yet, so remove the ones + // BigQuery named and retry. + // + // Not `ignoreUnknownValues`: BigQuery reports one unknown field per row, so + // that would also discard fields it never mentioned. + const lagColumns = this.schemaLagColumns(e).filter( + (column) => !strippedColumns.includes(column) + ); + + if (lagColumns.length) { + logs.dataInsertRetriedWithoutColumns(rows.length, lagColumns); + + // If the column is genuinely gone rather than lagging, this makes the + // next batch re-run `initialize` and add it back. + this._initialized = false; + return this.insertData( rows, - { ...overrideOptions, ignoreUnknownValues: true }, - retry + overrideOptions, + [...strippedColumns, ...lagColumns], + allowTransientRetry ); } - // Exceeded number of retries, save in failed collection - if (!retry && this.config.backupTableId) { - await handleFailedTransactions(rows, this.config, e); + if (allowTransientRetry && this.isTransientInsertionError(e)) { + logs.dataInsertRetriedAfterTransientError(rows.length); + return this.insertData(rows, overrideOptions, strippedColumns, false); + } + + // Terminal: no further attempt will be made for these rows. + if (this.config.backupTableId) { + try { + await handleFailedTransactions(rows, this.config, e); + } catch (backupError) { + // A failed backup must not replace the insert error the caller needs. + logs.failedBackupWrite(backupError); + } } // Reinitializing in case the destintation table is modified. this._initialized = false; - logs.bigQueryTableInsertErrors(e.errors); + logs.bigQueryTableInsertErrors(e?.errors); throw e; } } diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/logs.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/logs.ts index 9b1b2f6582..1930bdc7db 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/logs.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/logs.ts @@ -137,9 +137,24 @@ export const dataInserted = (rowCount: number) => { logger.debug(`Inserted ${rowCount} row(s) of data into BigQuery`); }; -export const dataInsertRetried = (rowCount: number) => { +/** + * Warn rather than debug, and name the columns: this is the one retry path that + * leaves a column permanently null, and debug is off at the default log level. + */ +export const dataInsertRetriedWithoutColumns = ( + rowCount: number, + columns: string[] +) => { + logger.warn( + `Retrying insert of ${rowCount} row(s) of data into BigQuery without ${columns.join( + ", " + )}. BigQuery does not have those columns yet, so they will be null for these rows.` + ); +}; + +export const dataInsertRetriedAfterTransientError = (rowCount: number) => { logger.debug( - `Retried to insert ${rowCount} row(s) of data into BigQuery (ignoring unknown columns)` + `Retrying insert of ${rowCount} row(s) of data into BigQuery after a transient failure, with options unchanged` ); }; @@ -217,16 +232,28 @@ export const bigQueryTableInsertErrors = ( ) => { logger.warn(`Error when inserting data to table.`); - insertErrors?.forEach((error) => { + // Runs on the terminal path of a failed insert, so a throw here would replace + // the insert error the caller needs. + if (!Array.isArray(insertErrors)) return; + + insertErrors.forEach((error) => { logger.warn("ROW DATA JSON:"); - logger.warn(error.row); + logger.warn(error?.row); + + if (!Array.isArray(error?.errors)) return; - error.errors?.forEach((error) => - logger.warn(`ROW ERROR MESSAGE: ${error.message}`) + error.errors.forEach((error) => + logger.warn(`ROW ERROR MESSAGE: ${error?.message}`) ); }); }; +export const failedBackupWrite = (error: unknown) => { + logger.warn( + `Could not write failed rows to the backup collection. The original insert error is still thrown. Backup error: ${error}` + ); +}; + export const updatedClustering = (fields: string) => { logger.info(`Clustering updated with new settings fields: ${fields}`); }; From 11b340630a36834f677cd5e6eaf21d402d826ba4 Mon Sep 17 00:00:00 2001 From: Jacob Cable <32874567+cabljac@users.noreply.github.com> Date: Tue, 1 Sep 2026 22:28:25 +0100 Subject: [PATCH 25/30] fix(firestore-bigquery-change-tracker): fix the table update check and clustering sync (#2817) Fixes #2194. (#2801, the `db.settings()` guard, was originally part of this branch but landed on next with #2937; this PR no longer touches that file.) #2194: `tableRequiresUpdate` always returned true, via two accidental triggers: `JSON.stringify(config.clustering)` gives `"null"` vs the table's `"[]"`, and `fields.find(...)` fed `undefined` into a boolean comparison. Fixed with `config.clustering || []` and `fields.some(...)`. The `find` -> `some` change is behavioral, not cosmetic: clustering sync on existing tables depended on the always-true trigger, because `updateClustering` mutated the shared metadata before `tableRequiresUpdate` compared it (desired vs desired). A third commit moves `updateClustering` after the check, inside `shouldUpdate`. The `some` fix has no behavioral regression guard (offline tests pass booleans directly, and the live suites assert final table state, which the spurious update also produced), so `fields` is now typed `TableField[]` and a revert to `find` fails compilation. Rebased onto next after #2937 merged. The behavior change disclosed earlier is now narrower: `tableRequiresUpdate` gained a trigger that fires when the configured custom partition column is missing from the table's schema, so the column is added by a real metadata update on the next initialize instead of by the old spurious path, and the trigger stops firing once the column lands. What remains: an insert racing the column's schema propagation fails terminally with its rows backed up intact, since the column is deliberately not stripped for a lag retry (a null there misfiles the row into the wrong partition permanently). Verified against live BigQuery: clustering, insertRetry, backupSettings, and checkUpdates suites all pass; clustering, checkUpdates, and partitioning (with `RUN_BIGQUERY_INTEGRATION_TESTS=true`) re-run after the review follow-up. --- .../CHANGELOG.md | 3 + .../bigquery/checkUpdatesUnit.test.ts | 183 ++++++++++++++++++ .../src/bigquery/checkUpdates.ts | 10 +- .../src/bigquery/index.ts | 32 +-- .../src/bigquery/partitioning/index.ts | 22 ++- 5 files changed, 229 insertions(+), 21 deletions(-) create mode 100644 firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/checkUpdatesUnit.test.ts diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md b/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md index 74027d7b69..563eb324b5 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md @@ -8,5 +8,8 @@ Insert-failure semantics changed. Since 2020, the retry guard in `insertData` wa - Every other failure is terminal: the original, unmodified rows are written to the configured backup collection (`backupTableId`, keyed by `insertId`) and the insert error is rethrown to the caller. - Fixed the backup path calling `db.settings()` more than once per Firestore instance, which made every backup after the first throw and replaced the insert error. A failed backup write is now logged and the original insert error is still the one thrown. - Backup documents now populate `error_details` (the field previously existed but was always empty). +- Stopped the spurious table update on every cold start: a broken comparison made `tableRequiresUpdate` return true for default installs (null clustering compared against `[]`, and a truthiness bug in the wildcard-column check), so `setMetadata` ran on every initialize. Both comparisons are fixed; this reduces, not eliminates, repeat updates. Pre-existing configurations that still re-fire the update on every cold start: wildcards toggled off with `path_params` still present; partitioning configured against a pre-existing unpartitioned table (the update never applies the partitioning to the table itself, so the check keeps firing); and an invalid clustering config, including `CLUSTERING=a, b`, where the untrimmed ` b` is never applied and the mismatch persists. +- Restored clustering synchronisation on existing tables: the desired clustering was applied to the in-memory metadata before the update check read it, so adding, changing, reordering, or removing clustering on an existing table never reached BigQuery except via the (now removed) spurious update. Clustering changes now apply exactly when the config and table disagree. +- A custom partition column absent from an existing table's schema now fires its own `tableRequiresUpdate` trigger and is added by a real metadata update; previously it was only ever added as a side effect of the spurious update. Inserts that race the column's propagation fail terminally (the column is deliberately not stripped for a lag retry, since a null there misfiles the row into the wrong partition permanently) and the rows are written to the backup collection intact. Operators consuming this via the firestore-bigquery-export extension or kit will see failures that previously passed as success: new error logs, retries from their own queue or trigger policy, and rows in `BACKUP_COLLECTION` where fields were previously dropped silently. During a schema-lag window the stripped columns are written as null; the affected column names are logged at warn level. A row written with a null `document_id` during such a window is permanently duplicated in the legacy `_latest` view (it groups by `document_name, document_id`); installs using the standard latest query are unaffected. diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/checkUpdatesUnit.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/checkUpdatesUnit.test.ts new file mode 100644 index 0000000000..d26f235aac --- /dev/null +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/checkUpdatesUnit.test.ts @@ -0,0 +1,183 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Table } from "@google-cloud/bigquery/build/src/table"; +import { tableRequiresUpdate } from "../../bigquery/checkUpdates"; +import { ChangeTrackerConfig } from "../../bigquery"; +import { PartitioningStrategy } from "../../bigquery/partitioning/config"; + +interface StubTableOptions { + clusteringFields?: string[]; + schemaFieldNames?: string[]; + timePartitioning?: { type: string; field?: string }; +} + +// Offline: the stub's `getMetadata` stands in for the only network call +// `tableRequiresUpdate` can reach (`isTablePartitioned`); every other check +// reads the metadata object directly. +function stubTable({ + clusteringFields, + schemaFieldNames = [], + timePartitioning, +}: StubTableOptions = {}): Table { + const metadata = { + clustering: clusteringFields ? { fields: clusteringFields } : undefined, + schema: { fields: schemaFieldNames.map((name) => ({ name })) }, + timePartitioning, + }; + return { + metadata, + getMetadata: async () => [metadata], + } as unknown as Table; +} + +function baseConfig(overrides: Partial) { + return { + datasetId: "d", + tableId: "t", + datasetLocation: "us", + wildcardIds: false, + clustering: null, + ...overrides, + } as ChangeTrackerConfig; +} + +const customFieldPartitioning: PartitioningStrategy = { + granularity: "DAY", + bigqueryColumnName: "created_at", + bigqueryColumnType: "TIMESTAMP", + firestoreFieldName: "created_at", +}; + +const columnsForNonWildcardTable = { + documentIdColExists: true, + pathParamsColExists: false, + oldDataColExists: true, +}; + +describe("tableRequiresUpdate (offline)", () => { + test("null clustering config against an unclustered table is a no-op", async () => { + const result = await tableRequiresUpdate({ + table: stubTable(), + config: baseConfig({ clustering: null }), + ...columnsForNonWildcardTable, + }); + expect(result).toBe(false); + }); + + test("null clustering config against a clustered table fires an update", async () => { + const result = await tableRequiresUpdate({ + table: stubTable({ clusteringFields: ["timestamp"] }), + config: baseConfig({ clustering: null }), + ...columnsForNonWildcardTable, + }); + expect(result).toBe(true); + }); + + test("clustering config against an unclustered table fires an update", async () => { + const result = await tableRequiresUpdate({ + table: stubTable(), + config: baseConfig({ clustering: ["timestamp"] }), + ...columnsForNonWildcardTable, + }); + expect(result).toBe(true); + }); + + test("matching clustering is a no-op", async () => { + const result = await tableRequiresUpdate({ + table: stubTable({ clusteringFields: ["timestamp", "data"] }), + config: baseConfig({ clustering: ["timestamp", "data"] }), + ...columnsForNonWildcardTable, + }); + expect(result).toBe(false); + }); + + test("reordered clustering fires an update", async () => { + const result = await tableRequiresUpdate({ + table: stubTable({ clusteringFields: ["data", "timestamp"] }), + config: baseConfig({ clustering: ["timestamp", "data"] }), + ...columnsForNonWildcardTable, + }); + expect(result).toBe(true); + }); + + test("wildcards on with no path_params column fires an update", async () => { + const result = await tableRequiresUpdate({ + table: stubTable(), + config: baseConfig({ clustering: null, wildcardIds: true }), + ...columnsForNonWildcardTable, + }); + expect(result).toBe(true); + }); + + test("wildcards on with a path_params column is a no-op", async () => { + const result = await tableRequiresUpdate({ + table: stubTable(), + config: baseConfig({ clustering: null, wildcardIds: true }), + ...columnsForNonWildcardTable, + pathParamsColExists: true, + }); + expect(result).toBe(false); + }); + + test("wildcards off with a path_params column still present fires an update", async () => { + const result = await tableRequiresUpdate({ + table: stubTable(), + config: baseConfig({ clustering: null, wildcardIds: false }), + ...columnsForNonWildcardTable, + pathParamsColExists: true, + }); + expect(result).toBe(true); + }); + + test("custom partition column missing from a partitioned table fires an update", async () => { + const result = await tableRequiresUpdate({ + table: stubTable({ + schemaFieldNames: ["timestamp", "data"], + timePartitioning: { type: "DAY", field: "created_at" }, + }), + config: baseConfig({ partitioning: customFieldPartitioning }), + ...columnsForNonWildcardTable, + }); + expect(result).toBe(true); + }); + + test("custom partition column present on a partitioned table is a no-op", async () => { + const result = await tableRequiresUpdate({ + table: stubTable({ + schemaFieldNames: ["timestamp", "data", "created_at"], + timePartitioning: { type: "DAY", field: "created_at" }, + }), + config: baseConfig({ partitioning: customFieldPartitioning }), + ...columnsForNonWildcardTable, + }); + expect(result).toBe(false); + }); + + test("timestamp partitioning with the built-in timestamp column is a no-op", async () => { + const result = await tableRequiresUpdate({ + table: stubTable({ + schemaFieldNames: ["timestamp", "data"], + timePartitioning: { type: "DAY", field: "timestamp" }, + }), + config: baseConfig({ + partitioning: { granularity: "DAY", bigqueryColumnName: "timestamp" }, + }), + ...columnsForNonWildcardTable, + }); + expect(result).toBe(false); + }); +}); diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/checkUpdates.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/checkUpdates.ts index 54685e7591..5782f30a09 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/checkUpdates.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/checkUpdates.ts @@ -39,7 +39,7 @@ export async function tableRequiresUpdate({ const { metadata } = table; /** Check clustering */ - const configCluster = JSON.stringify(config.clustering); + const configCluster = JSON.stringify(config.clustering || []); const tableCluster = JSON.stringify(metadata.clustering?.fields || []); if (configCluster !== tableCluster) return true; @@ -55,6 +55,14 @@ export async function tableRequiresUpdate({ /** Check partitioning */ const partitioningConfig = new PartitioningConfig(config.partitioning); const partitioning = new Partitioning(partitioningConfig, table); + + /** Check the configured partition column exists in the schema */ + const partitionFieldMissing = + partitioning.customPartitionFieldMissingFromSchema( + metadata.schema?.fields || [] + ); + if (partitionFieldMissing) return true; + const isValidPartition = await partitioning.isValidPartitionForExistingTable(); if (isValidPartition) return true; diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/index.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/index.ts index 6858823cb3..12a8127c2e 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/index.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/index.ts @@ -32,6 +32,7 @@ import { import * as logs from "../logs"; import { InsertRowsOptions, + TableField, TableMetadata, } from "@google-cloud/bigquery/build/src/table"; @@ -281,11 +282,10 @@ export class FirestoreBigQueryEventHistoryTracker columns.push(documentPathParams.name); } - // The custom partition column is deliberately not allowlisted. Initialize - // can still add it to an existing table (the clustering comparison in - // `tableRequiresUpdate` returns true for default installs), so it can lag; - // when it does, the insert fails terminally and the row is backed up - // intact rather than stripped and retried. Safe in the lossy direction. + // The custom partition column is deliberately not allowlisted: stripping + // it for a lag retry writes a null that misfiles the row into the wrong + // partition permanently. An insert racing the column's propagation fails + // terminally instead, with the rows backed up intact. return columns; } @@ -482,18 +482,21 @@ export class FirestoreBigQueryEventHistoryTracker logs.bigQueryTableAlreadyExists(table.id, dataset.id); const [metadata] = await table.getMetadata(); - const fields = metadata.schema ? metadata.schema.fields : []; - - await clustering.updateClustering(metadata); - - const documentIdColExists = fields.find( + // The annotation is load-bearing: it keeps the column checks below + // boolean, so a non-boolean (e.g. a `find` result) cannot reach + // `tableRequiresUpdate` and re-fire the update on every initialize. + const fields: TableField[] = metadata.schema + ? metadata.schema.fields + : []; + + const documentIdColExists = fields.some( (column) => column.name === "document_id" ); - const pathParamsColExists = fields.find( + const pathParamsColExists = fields.some( (column) => column.name === "path_params" ); - const oldDataColExists = fields.find( + const oldDataColExists = fields.some( (column) => column.name === "old_data" ); @@ -524,6 +527,11 @@ export class FirestoreBigQueryEventHistoryTracker }); if (shouldUpdate) { + // Must run after `tableRequiresUpdate`: it rewrites `metadata.clustering` + // to the desired state, and the update check compares that same object + // against the config. + await clustering.updateClustering(metadata); + /** set partitioning */ await partitioning.addPartitioningToSchema(metadata.schema.fields); diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/index.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/index.ts index cd7ee6b251..748522d573 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/index.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/index.ts @@ -67,6 +67,19 @@ export class Partitioning { }; } + /** + * True when the configured partition column belongs in the schema but the + * given fields do not contain it. Pure: reads only the config and the + * fields passed in, so update checks can call it without a network round + * trip. `addPartitioningToSchema` adds exactly this column, which is what + * lets a metadata update gated on this check converge. + */ + customPartitionFieldMissingFromSchema(fields: TableField[]): boolean { + const partitionField = this.getNewPartitionField(); + if (!partitionField) return false; + return !fields.some((field) => field.name === partitionField.name); + } + getPartitionValue( event: FirestoreDocumentChangeEvent ): Record { @@ -162,20 +175,13 @@ export class Partitioning { } async addPartitioningToSchema(fields: TableField[]): Promise { - if ( - !this.config.isFirestoreFieldPartitioning() && - !this.config.isFirestoreTimestampPartitioning() - ) { - return; - } - const newField = this.getNewPartitionField(); if (!newField) { return; } - if (fields.some((field) => field.name === newField.name)) { + if (!this.customPartitionFieldMissingFromSchema(fields)) { return; } From 7a1de866f431d18bcb6535dd1c125bb25578bc0e Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Tue, 1 Sep 2026 11:56:00 -0700 Subject: [PATCH 26/30] feat(release-kit): add use firebase-functions RC checkbox and validation --- .github/workflows/release-kit.yaml | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index ee566d988a..7c05aa7e57 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -35,6 +35,11 @@ on: required: true default: true type: boolean + use_firebase_functions_rc: + description: "Use firebase-functions RC" + required: true + default: false + type: boolean dry_run: description: "Dry run (validate without pushing/publishing)" required: true @@ -78,10 +83,25 @@ jobs: with: node-version: "24" + - name: Validate Inputs + env: + IS_PRERELEASE: ${{ inputs.is_prerelease }} + USE_FIREBASE_FUNCTIONS_RC: ${{ inputs.use_firebase_functions_rc }} + run: | + if [ "$USE_FIREBASE_FUNCTIONS_RC" = "true" ] && [ "$IS_PRERELEASE" != "true" ]; then + echo "::error::'Use firebase-functions RC' can only be checked when creating a kit RC (Publish as Release Candidate must be true)." + exit 1 + fi + - name: Install Dependencies & Run Tests working-directory: ${{ inputs.target_kit }} + env: + USE_FIREBASE_FUNCTIONS_RC: ${{ inputs.use_firebase_functions_rc }} run: | npm ci + if [ "$USE_FIREBASE_FUNCTIONS_RC" = "true" ]; then + npm install --save firebase-functions@next + fi npm test # ========================================================= @@ -105,6 +125,16 @@ jobs: with: node-version: "24" + - name: Validate Inputs + env: + IS_PRERELEASE: ${{ inputs.is_prerelease }} + USE_FIREBASE_FUNCTIONS_RC: ${{ inputs.use_firebase_functions_rc }} + run: | + if [ "$USE_FIREBASE_FUNCTIONS_RC" = "true" ] && [ "$IS_PRERELEASE" != "true" ]; then + echo "::error::'Use firebase-functions RC' can only be checked when creating a kit RC (Publish as Release Candidate must be true)." + exit 1 + fi + - name: Configure Git User if: ${{ !inputs.dry_run }} run: | @@ -216,8 +246,13 @@ jobs: - name: Install Dependencies & Build working-directory: ${{ inputs.target_kit }} + env: + USE_FIREBASE_FUNCTIONS_RC: ${{ inputs.use_firebase_functions_rc }} run: | npm ci --registry=https://registry.npmjs.org + if [ "$USE_FIREBASE_FUNCTIONS_RC" = "true" ]; then + npm install --save firebase-functions@next + fi npm run build - name: Apply Version Bump (Clear CHANGELOG on Stable Release Only) @@ -265,6 +300,7 @@ jobs: BUMP_TYPE: ${{ steps.config.outputs.bump_type }} TARGET_TAG: ${{ steps.config.outputs.target_tag }} IS_PRERELEASE: ${{ inputs.is_prerelease }} + USE_FIREBASE_FUNCTIONS_RC: ${{ inputs.use_firebase_functions_rc }} TAG_NAME: ${{ steps.config.outputs.tag_name }} NOTES: ${{ steps.changelog.outputs.notes }} run: | @@ -280,6 +316,7 @@ jobs: echo " Version Bump: $BUMP_TYPE" echo " NPM Dist-Tag: $TARGET_TAG" echo " Release Type: $( [ "$IS_PRERELEASE" = "true" ] && echo "Release Candidate (RC)" || echo "Stable Release" )" + echo " Functions RC: $( [ "$USE_FIREBASE_FUNCTIONS_RC" = "true" ] && echo "Yes (firebase-functions@next)" || echo "No" )" echo " Git Tag Name: $TAG_NAME" echo " CHANGELOG State: $( [ "$IS_PRERELEASE" = "true" ] && echo "Preserved" || echo "Will be cleared on publish" )" echo "----------------------------------------------------------" From aafba2c7e735fa474f3ae532478c7a491f0ce01f Mon Sep 17 00:00:00 2001 From: Andy Perelson Date: Thu, 3 Sep 2026 19:02:26 +0000 Subject: [PATCH 27/30] Specify registry for firebase-functions RC install. --- .github/workflows/release-kit.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-kit.yaml b/.github/workflows/release-kit.yaml index 7c05aa7e57..6cec4f96e3 100644 --- a/.github/workflows/release-kit.yaml +++ b/.github/workflows/release-kit.yaml @@ -100,7 +100,7 @@ jobs: run: | npm ci if [ "$USE_FIREBASE_FUNCTIONS_RC" = "true" ]; then - npm install --save firebase-functions@next + npm install --save --registry=https://registry.npmjs.org firebase-functions@next fi npm test @@ -251,7 +251,7 @@ jobs: run: | npm ci --registry=https://registry.npmjs.org if [ "$USE_FIREBASE_FUNCTIONS_RC" = "true" ]; then - npm install --save firebase-functions@next + npm install --save --registry=https://registry.npmjs.org firebase-functions@next fi npm run build From c3522bf41e71afe5b7809a6c848c2e84cd5ac984 Mon Sep 17 00:00:00 2001 From: Jacob Cable <32874567+cabljac@users.noreply.github.com> Date: Mon, 7 Sep 2026 15:49:58 +0100 Subject: [PATCH 28/30] chore(firestore-bigquery-change-tracker): release 2.1.1, accept firebase-admin 14 (#3133) The change tracker pins `firebase-admin` to `^13.2.0`. A consumer on firebase-admin 14 therefore installs a second copy of the SDK nested under the tracker, and that copy has its own app registry: the consumer's `initializeApp()` never reaches it. Every call the tracker makes through its own copy, which today is the backup write in `handleFailedTransactions`, fails with "The default Firebase app does not exist", the failure is logged as `failedBackupWrite`, and the rows meant for `backupTableId` are lost. Verified by loading both copies in one process against the published 2.1.0. The range was already widened to `^13.2.0 || ^14.0.0` on the `kits` branch (cc86630a) but that landed at 2.0.4 and was never published; 2.1.0 was cut from `next` without it. This cherry-picks that commit onto `next` and releases it as 2.1.1 with a changelog entry. No source changes: the tracker only uses `getFirestore`, `firebase-admin/app` and `Timestamp`, all unchanged between 13 and 14, and the firebase-functions 6 it depends on already accepts admin 14. `npm ci` and `npm run build` pass. The jest suite needs live BigQuery and was not run. Unblocks the kit bump in #3127. --------- Co-authored-by: Izaak Gough --- .../firestore-bigquery-change-tracker/CHANGELOG.md | 4 ++++ .../firestore-bigquery-change-tracker/package-lock.json | 6 +++--- .../firestore-bigquery-change-tracker/package.json | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md b/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md index 563eb324b5..f9e5809490 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 2.1.1 + +- `firebase-admin` 14 is accepted alongside 13. With the previous `^13.2.0` range a consumer on 14 installed a second copy of the SDK under this package, and that copy never sees the consumer's `initializeApp()`, so every backup write to `backupTableId` failed with "The default Firebase app does not exist" and the rows were lost. + ## 2.1.0 Insert-failure semantics changed. Since 2020, the retry guard in `insertData` was broken (an un-awaited async check that was always truthy), so every failed insert was retried with `ignoreUnknownValues: true` and reported success while silently dropping any field BigQuery did not recognise. diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json b/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json index 0c294b8b6b..b52fb114e5 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json @@ -1,17 +1,17 @@ { "name": "@firebaseextensions/firestore-bigquery-change-tracker", - "version": "2.1.0", + "version": "2.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@firebaseextensions/firestore-bigquery-change-tracker", - "version": "2.1.0", + "version": "2.1.1", "license": "Apache-2.0", "dependencies": { "@google-cloud/bigquery": "^7.6.0", "@google-cloud/resource-manager": "^5.1.0", - "firebase-admin": "^13.2.0", + "firebase-admin": "^13.2.0 || ^14.0.0", "firebase-functions": "^6.3.2", "sql-formatter": "^2.3.3", "traverse": "^0.6.6" diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json b/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json index 3466e92321..4758ea657e 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json @@ -5,7 +5,7 @@ "url": "git+https://github.com/firebase/extensions.git", "directory": "firestore-bigquery-export/firestore-bigquery-change-tracker" }, - "version": "2.1.0", + "version": "2.1.1", "description": "Core change-tracker library for Cloud Firestore Collection BigQuery Exports", "main": "./lib/index.js", "scripts": { @@ -25,7 +25,7 @@ "dependencies": { "@google-cloud/bigquery": "^7.6.0", "@google-cloud/resource-manager": "^5.1.0", - "firebase-admin": "^13.2.0", + "firebase-admin": "^13.2.0 || ^14.0.0", "firebase-functions": "^6.3.2", "sql-formatter": "^2.3.3", "traverse": "^0.6.6" From 0f857caa1ab0dfd4dac6584b129fe843e03deeed Mon Sep 17 00:00:00 2001 From: Jacob Cable <32874567+cabljac@users.noreply.github.com> Date: Mon, 7 Sep 2026 17:36:43 +0100 Subject: [PATCH 29/30] chore(firestore-bigquery-change-tracker): release 2.2.0, run on firebase-admin 14 (#3134) Follow-up to #3133. 2.1.1 widened the firebase-admin range to `^13.2.0 || ^14.0.0` but two things stopped it working on 14. First, firebase-admin 14 removes the namespaced API. The package still read `admin.apps` at import in `handleFailedTransactions` and `admin.firestore.Timestamp` in the partition converter, so wherever it resolved against admin 14 it threw `Cannot read properties of undefined (reading 'length')` at import. Every namespaced use, in shipped code, the test fixture and the tests, is now the modular API from `firebase-admin/app` and `firebase-admin/firestore`, which is identical on 13 and 14. Second, the package depends on firebase-functions `^6.3.2`, whose peer range for firebase-admin stops at `^13.0.0`. On a consumer running admin 14 npm therefore kept a nested admin 13 under the tracker regardless of the tracker's own range, and that nested copy has no default app. Under npm that nesting is also why 2.1.1 did not crash: `admin.apps` resolved on the nested 13. The range now accepts firebase-functions 7 as well; the package only uses its `logger`. Verified: build and the test tsconfig compile against admin 14.3.0 and functions 7.3.2; `converter.test.ts` passes (48) on that tree; the packed tarball installed into the firestore-bigquery-export kit on admin 14, followed by `npm dedupe`, collapses to a single admin copy, the tracker resolves the kit's app, and all 62 kit tests pass. An existing consumer shrinkwrap does not dedupe on its own, since the nested 13 still satisfies the new ranges, so the kit bump must dedupe explicitly. The kit pins firebase-functions `^7.3.3-rc.0`, which no stable range matches, so a nested firebase-functions 7.3.2 remains under the tracker until the kit moves to a stable 7.x; that only affects trace correlation on tracker log lines, not the admin app. The lockfile stays on admin 13 and functions 6 because under admin 14 the jest config cannot load the ESM-only `jose` that firebase-functions v2 pulls in via admin auth; that is a jest `transformIgnorePatterns` gap for a separate change. The live BigQuery suites were not run. Unblocks the kit bump in #3127. --- .../firestore-bigquery-change-tracker/CHANGELOG.md | 7 +++++++ .../package-lock.json | 6 +++--- .../firestore-bigquery-change-tracker/package.json | 7 +++++-- .../src/__tests__/bigquery/backupSettings.test.ts | 6 ++++-- .../src/__tests__/bigquery/e2e.test.ts | 14 +++++++------- .../__tests__/bigquery/failedTransaction.test.ts | 9 ++++++--- .../initializeLatestMaterializedView.test.ts | 6 +++--- .../bigquery/materializedViews/integration.test.ts | 10 +++++----- .../shouldRecreateMaterializedView.test.ts | 10 +++++----- .../src/__tests__/bigquery/partitioning.test.ts | 14 ++++++-------- .../bigquery/partitioning/converter.test.ts | 14 ++++---------- .../src/__tests__/fixtures/changeTracker.ts | 4 ++-- .../src/bigquery/handleFailedTransactions.ts | 5 ++--- .../src/bigquery/partitioning/converter.ts | 9 +++------ .../firestore-bigquery-change-tracker/src/logs.ts | 4 ++-- 15 files changed, 64 insertions(+), 61 deletions(-) diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md b/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md index f9e5809490..a4c97b0bc8 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 2.2.0 + +- Works on `firebase-admin` 14. 2.1.1 widened the range but the package still used the namespaced API (`admin.apps`, `admin.firestore.Timestamp`), which firebase-admin 14 removes, so it threw at import wherever it was resolved against admin 14. Every use is now the modular API from `firebase-admin/app` and `firebase-admin/firestore`, which works on 13 and 14 alike. +- `firebase-functions` 7.3 and later is accepted alongside 6. This package only uses its `logger`, but the firebase-functions 6 peer range for `firebase-admin` stops at 13, as does the range of firebase-functions 7.0 through 7.2, so on a consumer running firebase-admin 14 npm nested a second admin copy under this package however wide this package's own range was, and that nested copy has no default app. +- Declares `engines.node >=18`, the floor firebase-admin 13 already imposed, so an unsupported Node is reported at install rather than at runtime. +- Consumers that pin neither `firebase-admin` nor `firebase-functions` themselves and resolve fresh now get firebase-admin 14 and firebase-functions 7, which need Node 22 and Node 18 respectively. Pin firebase-admin `^13` to stay on Node 18 or 20. + ## 2.1.1 - `firebase-admin` 14 is accepted alongside 13. With the previous `^13.2.0` range a consumer on 14 installed a second copy of the SDK under this package, and that copy never sees the consumer's `initializeApp()`, so every backup write to `backupTableId` failed with "The default Firebase app does not exist" and the rows were lost. diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json b/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json index b52fb114e5..999ee96349 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json @@ -1,18 +1,18 @@ { "name": "@firebaseextensions/firestore-bigquery-change-tracker", - "version": "2.1.1", + "version": "2.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@firebaseextensions/firestore-bigquery-change-tracker", - "version": "2.1.1", + "version": "2.2.0", "license": "Apache-2.0", "dependencies": { "@google-cloud/bigquery": "^7.6.0", "@google-cloud/resource-manager": "^5.1.0", "firebase-admin": "^13.2.0 || ^14.0.0", - "firebase-functions": "^6.3.2", + "firebase-functions": "^6.3.2 || ^7.3.0", "sql-formatter": "^2.3.3", "traverse": "^0.6.6" }, diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json b/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json index 4758ea657e..0ebc3ea45b 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json @@ -5,7 +5,10 @@ "url": "git+https://github.com/firebase/extensions.git", "directory": "firestore-bigquery-export/firestore-bigquery-change-tracker" }, - "version": "2.1.1", + "version": "2.2.0", + "engines": { + "node": ">=18" + }, "description": "Core change-tracker library for Cloud Firestore Collection BigQuery Exports", "main": "./lib/index.js", "scripts": { @@ -26,7 +29,7 @@ "@google-cloud/bigquery": "^7.6.0", "@google-cloud/resource-manager": "^5.1.0", "firebase-admin": "^13.2.0 || ^14.0.0", - "firebase-functions": "^6.3.2", + "firebase-functions": "^6.3.2 || ^7.3.0", "sql-formatter": "^2.3.3", "traverse": "^0.6.6" }, diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/backupSettings.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/backupSettings.test.ts index 562b84f525..f2057ae822 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/backupSettings.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/backupSettings.test.ts @@ -23,8 +23,10 @@ const settings = jest.fn(); const batch = jest.fn(() => ({ set, commit })); const collection = jest.fn(() => ({ doc: (id: string) => ({ id }) })); -jest.mock("firebase-admin", () => ({ apps: [{}] })); -jest.mock("firebase-admin/app", () => ({ initializeApp: jest.fn() })); +jest.mock("firebase-admin/app", () => ({ + getApps: jest.fn(() => [{}]), + initializeApp: jest.fn(), +})); jest.mock("firebase-admin/firestore", () => ({ // A fresh object per call, deliberately: the guard must key on the database id // rather than on instance identity. diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts index 6c1642411a..d3ca740ffa 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/e2e.test.ts @@ -28,7 +28,7 @@ import { latestConsistentSnapshotView } from "../../bigquery/snapshot"; import { deleteTable } from "../fixtures/clearTables"; import { changeTracker, changeTrackerEvent } from "../fixtures/changeTracker"; import { getBigQueryTableData } from "../fixtures/queries"; -import { firestore } from "firebase-admin"; +import { Timestamp } from "firebase-admin/firestore"; process.env.PROJECT_ID = "dev-extensions-testing"; @@ -167,7 +167,7 @@ describe("e2e", () => { }); test("successfully partitions with a valid DateTime Timestamp", async () => { - const created = firestore.Timestamp.now(); + const created = Timestamp.now(); const event: FirestoreDocumentChangeEvent = changeTrackerEvent({ data: { created }, @@ -206,7 +206,7 @@ describe("e2e", () => { }); test("successfully partitions with a valid DateTime Timestamp Date", async () => { - const created = firestore.Timestamp.now().toDate(); + const created = Timestamp.now().toDate(); const event: FirestoreDocumentChangeEvent = changeTrackerEvent({ data: { created }, @@ -243,7 +243,7 @@ describe("e2e", () => { }); test("successfully partitions with a valid Firebase Timestamp value with a Timestamp partitioning type", async () => { - const created = firestore.Timestamp.now(); + const created = Timestamp.now(); const event: FirestoreDocumentChangeEvent = changeTrackerEvent({ data: { created }, @@ -280,7 +280,7 @@ describe("e2e", () => { }); test("successfully partitions with a valid Firebase Timestamp value with a Date partitioning type", async () => { - const created = firestore.Timestamp.now(); + const created = Timestamp.now(); const expectedDate = created.toDate().toISOString().substring(0, 10); const event: FirestoreDocumentChangeEvent = changeTrackerEvent({ @@ -316,7 +316,7 @@ describe("e2e", () => { }); test("successfully partitions with a valid Firebase Timestamp value with a DateTime partitioning type", async () => { - const created = firestore.Timestamp.now(); + const created = Timestamp.now(); const expectedDate = created.toDate().toISOString().substring(0, 22); const event: FirestoreDocumentChangeEvent = changeTrackerEvent({ @@ -354,7 +354,7 @@ describe("e2e", () => { }); test("successfully partitions with a valid Firebase Timestamp value with `timestamp` as field name and Timestamp type", async () => { - const created = firestore.Timestamp.now(); + const created = Timestamp.now(); const expectedDate = created.toDate().toISOString().substring(0, 22); const event: FirestoreDocumentChangeEvent = changeTrackerEvent({ diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/failedTransaction.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/failedTransaction.test.ts index 0558adc946..3998e444e6 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/failedTransaction.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/failedTransaction.test.ts @@ -14,15 +14,18 @@ * limitations under the License. */ -import * as admin from "firebase-admin"; +import { Firestore, getFirestore } from "firebase-admin/firestore"; import { ChangeTrackerConfig } from "../../bigquery/types"; import handleFailedTransactions from "../../bigquery/handleFailedTransactions"; -// admin.initializeApp(); -const db = admin.firestore(); +let db: Firestore; describe("handleFailedTransactions", () => { + beforeAll(() => { + db = getFirestore(); + }); + it("should be defined", () => { expect(handleFailedTransactions).toBeDefined(); }); diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestMaterializedView.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestMaterializedView.test.ts index c26fb4db02..26f473d630 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestMaterializedView.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestMaterializedView.test.ts @@ -20,7 +20,7 @@ import { TableMetadata, Table, } from "@google-cloud/bigquery"; -import { firestore } from "firebase-admin"; +import { Timestamp } from "firebase-admin/firestore"; import { RawChangelogViewSchema } from "../../../bigquery/schema"; import { initializeLatestMaterializedView } from "../../../bigquery/initializeLatestMaterializedView"; import { @@ -143,7 +143,7 @@ describe("initializeLatestMaterializedView", () => { test("does not recreate view if configuration matches", async () => { const event = changeTrackerEvent({ - data: { end_date: firestore.Timestamp.now() }, + data: { end_date: Timestamp.now() }, eventId: "testing2", }); @@ -185,7 +185,7 @@ describe("initializeLatestMaterializedView", () => { test("recreates view when switching from incremental to non-incremental", async () => { const event = changeTrackerEvent({ - data: { end_date: firestore.Timestamp.now() }, + data: { end_date: Timestamp.now() }, eventId: "testing3", }); diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/integration.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/integration.test.ts index 8b10169d3f..6c7bd7625c 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/integration.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/integration.test.ts @@ -34,7 +34,7 @@ import { changeTrackerEvent, } from "../../fixtures/changeTracker"; import { getBigQueryTableData } from "../../fixtures/queries"; -import { firestore } from "firebase-admin"; +import { Timestamp } from "firebase-admin/firestore"; process.env.PROJECT_ID = "dev-extensions-testing"; @@ -45,7 +45,7 @@ process.env.PROJECT_ID = "dev-extensions-testing"; // eventId = "testing", // documentId = "testing", // pathParams = { documentId: "12345" }, -// data = { end_date: firestore.Timestamp.now() }, +// data = { end_date: Timestamp.now() }, // oldData = null, // useNewSnapshotQuerySyntax = false, // }: any): FirestoreDocumentChangeEvent => { @@ -65,7 +65,7 @@ process.env.PROJECT_ID = "dev-extensions-testing"; const bq: BigQuery = new BigQuery({ projectId: process.env.PROJECT_ID }); const event: FirestoreDocumentChangeEvent = changeTrackerEvent({}); const event2: FirestoreDocumentChangeEvent = changeTrackerEvent({ - data: { end_date: firestore.Timestamp.now() }, + data: { end_date: Timestamp.now() }, eventId: "testing2", }); let randomID: string; @@ -329,7 +329,7 @@ describe("integration", () => { eventId: "testing3", documentId: "doc3", pathParams: { documentId: "doc3" }, - data: { end_date: firestore.Timestamp.now(), status: "completed" }, + data: { end_date: Timestamp.now(), status: "completed" }, oldData: null, }); @@ -340,7 +340,7 @@ describe("integration", () => { eventId: "testing4", documentId: "doc4", pathParams: { documentId: "doc4" }, - data: { end_date: firestore.Timestamp.now(), status: "pending" }, + data: { end_date: Timestamp.now(), status: "pending" }, oldData: null, }); diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/shouldRecreateMaterializedView.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/shouldRecreateMaterializedView.test.ts index af023dac34..ff9cd96a5a 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/shouldRecreateMaterializedView.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/shouldRecreateMaterializedView.test.ts @@ -15,7 +15,7 @@ */ import { BigQuery, Dataset, TableMetadata } from "@google-cloud/bigquery"; -import { firestore } from "firebase-admin"; +import { Timestamp } from "firebase-admin/firestore"; import { RawChangelogViewSchema } from "../../../bigquery/schema"; import { buildMaterializedViewQuery, @@ -102,7 +102,7 @@ describe("Materialized View Recreation", () => { test("should not recreate incremental materialized view when unchanged", async () => { // Create initial event const event = changeTrackerEvent({ - data: { end_date: firestore.Timestamp.now() }, + data: { end_date: Timestamp.now() }, eventId: "testing2", }); @@ -162,7 +162,7 @@ describe("Materialized View Recreation", () => { test("should not recreate non-incremental materialized view when unchanged", async () => { // Create initial event const event = changeTrackerEvent({ - data: { end_date: firestore.Timestamp.now() }, + data: { end_date: Timestamp.now() }, eventId: "testing2", }); @@ -224,7 +224,7 @@ describe("Materialized View Recreation", () => { test("should recreate materialized view when inc -> non-inc ", async () => { // Create initial event const event = changeTrackerEvent({ - data: { end_date: firestore.Timestamp.now() }, + data: { end_date: Timestamp.now() }, eventId: "testing2", }); @@ -285,7 +285,7 @@ describe("Materialized View Recreation", () => { test("should recreate materialized view when non-inc -> inc ", async () => { // Create initial event const event = changeTrackerEvent({ - data: { end_date: firestore.Timestamp.now() }, + data: { end_date: Timestamp.now() }, eventId: "testing2", }); diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning.test.ts index 4144cfff43..9d6d81bbe7 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import * as admin from "firebase-admin"; +import { Timestamp } from "firebase-admin/firestore"; import { BigQuery, Dataset, Table } from "@google-cloud/bigquery"; import { ChangeType, FirestoreDocumentChangeEvent } from "../.."; @@ -236,7 +236,7 @@ describeIfBigQueryIntegration("processing partitions on a new table", () => { bqProjectId: undefined, }; - const end_date = admin.firestore.Timestamp.now(); + const end_date = Timestamp.now(); const event: FirestoreDocumentChangeEvent = { timestamp: "", @@ -382,7 +382,7 @@ describeIfBigQueryIntegration("processing partitions on a new table", () => { bqProjectId: undefined, }; - const end_date = admin.firestore.Timestamp.now(); + const end_date = Timestamp.now(); const event: FirestoreDocumentChangeEvent = { timestamp: "", @@ -415,7 +415,7 @@ describeIfBigQueryIntegration("processing partitions on a new table", () => { bqProjectId: undefined, }; - const end_date = admin.firestore.Timestamp.now(); + const end_date = Timestamp.now(); const event: FirestoreDocumentChangeEvent = { timestamp: "", @@ -449,7 +449,7 @@ describeIfBigQueryIntegration("processing partitions on a new table", () => { bqProjectId: undefined, }; - const end_date = admin.firestore.Timestamp.now(); + const end_date = Timestamp.now(); const event: FirestoreDocumentChangeEvent = { timestamp: "", @@ -777,9 +777,7 @@ describeIfBigQueryIntegration( firestoreFieldName: "endDate", }); - const oldDate = admin.firestore.Timestamp.fromDate( - new Date("2024-01-15T10:00:00Z") - ); + const oldDate = Timestamp.fromDate(new Date("2024-01-15T10:00:00Z")); const event: FirestoreDocumentChangeEvent = { timestamp: "", diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/converter.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/converter.test.ts index b5cfdee037..54c679d9da 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/converter.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/partitioning/converter.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import * as admin from "firebase-admin"; +import { Timestamp } from "firebase-admin/firestore"; import { PartitionValueConverter } from "../../../bigquery/partitioning/converter"; describe("PartitionValueConverter", () => { @@ -22,9 +22,7 @@ describe("PartitionValueConverter", () => { const converter = new PartitionValueConverter("TIMESTAMP"); test("converts Firebase Timestamp to BigQuery timestamp string", () => { - const timestamp = admin.firestore.Timestamp.fromDate( - new Date("2024-01-15T10:30:00Z") - ); + const timestamp = Timestamp.fromDate(new Date("2024-01-15T10:30:00Z")); const result = converter.convert(timestamp); expect(result).toBeDefined(); expect(typeof result).toBe("string"); @@ -195,9 +193,7 @@ describe("PartitionValueConverter", () => { const converter = new PartitionValueConverter("DATE"); test("converts Firebase Timestamp to BigQuery date string", () => { - const timestamp = admin.firestore.Timestamp.fromDate( - new Date("2024-01-15T10:30:00Z") - ); + const timestamp = Timestamp.fromDate(new Date("2024-01-15T10:30:00Z")); const result = converter.convert(timestamp); expect(result).toBe("2024-01-15"); }); @@ -248,9 +244,7 @@ describe("PartitionValueConverter", () => { const converter = new PartitionValueConverter("DATETIME"); test("converts Firebase Timestamp to BigQuery datetime string", () => { - const timestamp = admin.firestore.Timestamp.fromDate( - new Date("2024-01-15T10:30:00Z") - ); + const timestamp = Timestamp.fromDate(new Date("2024-01-15T10:30:00Z")); const result = converter.convert(timestamp); expect(result).toBeDefined(); expect(result).toContain("2024-01-15"); diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/changeTracker.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/changeTracker.ts index b6465dc60d..e362c4d3cc 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/changeTracker.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/fixtures/changeTracker.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { firestore } from "firebase-admin"; +import { Timestamp } from "firebase-admin/firestore"; import { ChangeType, FirestoreBigQueryEventHistoryTracker, @@ -66,7 +66,7 @@ export const changeTrackerEvent = ({ eventId = "testing", documentId = "testing", pathParams = { documentId: "12345" }, - data = { end_date: firestore.Timestamp.now() }, + data = { end_date: Timestamp.now() }, oldData = null, useNewSnapshotQuerySyntax = false, }: any): FirestoreDocumentChangeEvent => { diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts index 2ad56c6a91..51e7172c35 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/handleFailedTransactions.ts @@ -14,12 +14,11 @@ * limitations under the License. */ -import * as admin from "firebase-admin"; -import { initializeApp } from "firebase-admin/app"; +import { getApps, initializeApp } from "firebase-admin/app"; import { getFirestore } from "firebase-admin/firestore"; import { ChangeTrackerConfig } from "."; -if (!admin.apps.length) { +if (!getApps().length) { initializeApp(); } diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/converter.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/converter.ts index 1186d450bf..3e6862f567 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/converter.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/partitioning/converter.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import * as firebase from "firebase-admin"; +import { Timestamp } from "firebase-admin/firestore"; import { BigQuery } from "@google-cloud/bigquery"; export class PartitionValueConverter { @@ -34,13 +34,10 @@ export class PartitionValueConverter { convert(value: unknown): string | null { let date: Date; - if (value instanceof firebase.firestore.Timestamp) { + if (value instanceof Timestamp) { date = value.toDate(); } else if (this.isTimestampLike(value)) { - date = new firebase.firestore.Timestamp( - value._seconds, - value._nanoseconds - ).toDate(); + date = new Timestamp(value._seconds, value._nanoseconds).toDate(); } else if (value instanceof Date && !isNaN(value.getTime())) { date = value; } else if (typeof value === "string") { diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/logs.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/logs.ts index 1930bdc7db..fc8213218d 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/logs.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/logs.ts @@ -15,7 +15,7 @@ */ import { Table } from "@google-cloud/bigquery"; -import { firestore } from "firebase-admin"; +import type { Timestamp } from "firebase-admin/firestore"; import { logger } from "./logger"; export const arrayFieldInvalid = (fieldName: string) => { @@ -207,7 +207,7 @@ export const firestoreTimePartitioningParametersWarning = ( fieldName: string | undefined, fieldType: string | undefined, firestoreFieldName: string | undefined, - dataFirestoreField: firestore.Timestamp | string | undefined + dataFirestoreField: Timestamp | string | undefined ) => { logger.warn( "All TimePartitioning option parameters need to be available to create new custom schema field" From 0a7d599a2286201b22cad0fa0443899f4f12c3bc Mon Sep 17 00:00:00 2001 From: Jacob Cable <32874567+cabljac@users.noreply.github.com> Date: Mon, 7 Sep 2026 18:17:03 +0100 Subject: [PATCH 30/30] fix(firestore-bigquery-change-tracker): preserve BigQuery project on view updates, release 2.2.1 (#3137) Cherry-pick of da219826 from #3121 (Corie's fix, approved by Izaak) onto `next`, plus the 2.2.1 version bump and changelog entry. #3121 targets `kits`, but the tracker is published from `next`, so the fix never reached npm from there. The bug: `initializeLatestView` builds the snapshot query for an existing `_raw_latest` view without `bqProjectId`, so `buildLatestSnapshotViewQuery` falls back to `process.env.PROJECT_ID`. That variable is only set for extensions. On a kit the view query became `undefined..` and the `initBigQuerySync` task failed in `afterFirstDeploy`. The create path already passed the project. The fix passes `bq.projectId` on the update path too, matching the create path. Tests: the materializedViews suites pass locally (20 tests), including the new one that sets `process.env.PROJECT_ID` to a decoy and asserts the query uses the BigQuery project. Not verified against a live redeploy. After merge, dispatch `npm_publish_bq_scripts.yml` for 2.2.1, then regenerate the kit shrinkwrap in the stack so the rc pins it. Fixes #3120 --------- Co-authored-by: Corie Watson --- .../CHANGELOG.md | 4 ++ .../package-lock.json | 4 +- .../package.json | 2 +- .../initializeLatestView.test.ts | 39 +++++++++++++++++++ .../src/bigquery/initializeLatestView.ts | 1 + 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md b/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md index a4c97b0bc8..2d74076c8b 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 2.2.1 + +- Updating an existing `_raw_latest` view now builds the snapshot query with the configured BigQuery project. That path dropped `bqProjectId`, so the query fell back to `process.env.PROJECT_ID`, which is only set for extensions. On a kit, or any caller that passes `bqProjectId` but does not set `PROJECT_ID`, the query referenced `undefined..
` and BigQuery rejected the update. For an extension whose `BIGQUERY_PROJECT_ID` differs from `PROJECT_ID`, the update previously built the view against the functions project instead of the BigQuery project. + ## 2.2.0 - Works on `firebase-admin` 14. 2.1.1 widened the range but the package still used the namespaced API (`admin.apps`, `admin.firestore.Timestamp`), which firebase-admin 14 removes, so it threw at import wherever it was resolved against admin 14. Every use is now the modular API from `firebase-admin/app` and `firebase-admin/firestore`, which works on 13 and 14 alike. diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json b/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json index 999ee96349..c48b68c381 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/package-lock.json @@ -1,12 +1,12 @@ { "name": "@firebaseextensions/firestore-bigquery-change-tracker", - "version": "2.2.0", + "version": "2.2.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@firebaseextensions/firestore-bigquery-change-tracker", - "version": "2.2.0", + "version": "2.2.1", "license": "Apache-2.0", "dependencies": { "@google-cloud/bigquery": "^7.6.0", diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json b/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json index 0ebc3ea45b..ae4300fe2e 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/package.json @@ -5,7 +5,7 @@ "url": "git+https://github.com/firebase/extensions.git", "directory": "firestore-bigquery-export/firestore-bigquery-change-tracker" }, - "version": "2.2.0", + "version": "2.2.1", "engines": { "node": ">=18" }, diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestView.test.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestView.test.ts index ab9d3aa848..27303d5e9b 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestView.test.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/__tests__/bigquery/materializedViews/initializeLatestView.test.ts @@ -80,5 +80,44 @@ describe("initializeLatestView", () => { expect(initializeLatestMaterializedView).not.toHaveBeenCalled(); }); + + it("uses the BigQuery project when updating an existing view", async () => { + const originalProjectId = process.env.PROJECT_ID; + process.env.PROJECT_ID = "function-project"; + const metadata = { + schema: { + fields: [{ name: "document_id" }, { name: "old_data" }], + }, + view: { query: "SELECT FIRST_VALUE(data)" }, + }; + mockView.getMetadata.mockResolvedValueOnce([metadata]); + + try { + await initializeLatestView({ + bq: { projectId: "bigquery-project" } as any, + dataset: { id: "test_dataset" } as any, + view: mockView as any, + viewExists: true, + rawChangeLogTableName: "test_raw_table", + rawLatestViewName: "test_raw_view", + changeTrackerConfig: { + ...mockConfig, + useNewSnapshotQuerySyntax: true, + }, + }); + + expect(mockView.setMetadata).toHaveBeenCalledWith(metadata); + expect(metadata.view.query).toContain( + "`bigquery-project.test_dataset.test_raw_table`" + ); + expect(metadata.view.query).not.toContain("function-project"); + } finally { + if (originalProjectId === undefined) { + delete process.env.PROJECT_ID; + } else { + process.env.PROJECT_ID = originalProjectId; + } + } + }); }); }); diff --git a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestView.ts b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestView.ts index b0e7fc9394..fe8ee95717 100644 --- a/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestView.ts +++ b/firestore-bigquery-export/firestore-bigquery-change-tracker/src/bigquery/initializeLatestView.ts @@ -104,6 +104,7 @@ export async function initializeLatestView({ datasetId: config.datasetId, tableName: rawChangeLogTableName, schema, + bqProjectId: bq.projectId, useLegacyQuery: !config.useNewSnapshotQuerySyntax, });