From 488f41b9ac33d0a6466762e8edb861b4775d171c Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 15 Jan 2025 16:42:06 -0800 Subject: [PATCH 01/10] Added tsup configuration --- packages/angular/package-lock.json | 1589 ++++++++++++++++++++ packages/angular/package.json | 24 + packages/angular/src/data-connect/index.ts | 65 + packages/angular/src/index.ts | 1 + packages/angular/tsup.config.ts | 14 + 5 files changed, 1693 insertions(+) create mode 100644 packages/angular/package-lock.json create mode 100644 packages/angular/package.json create mode 100644 packages/angular/src/data-connect/index.ts create mode 100644 packages/angular/src/index.ts create mode 100644 packages/angular/tsup.config.ts diff --git a/packages/angular/package-lock.json b/packages/angular/package-lock.json new file mode 100644 index 00000000..6f645100 --- /dev/null +++ b/packages/angular/package-lock.json @@ -0,0 +1,1589 @@ +{ + "name": "@tanstack-query-firebase/angular", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@tanstack-query-firebase/angular", + "version": "0.0.1", + "license": "ISC", + "dependencies": { + "@angular/core": "^19.1.0", + "@angular/fire": "^19.0.0-rc.5", + "@tanstack/angular-query-experimental": "^5.64.1", + "firebase": "^11.1.0" + } + }, + "node_modules/@angular-devkit/core": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.0.tgz", + "integrity": "sha512-DAHd1TX4aiWTqW0eUDIXuntE/nd//SGnjJzIaqKGtj1/bngoY76S/DS7uStgxcZRD4VmprM0cJ0w68w3CMtzrA==", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.1.0.tgz", + "integrity": "sha512-S+MUDHiK+51I9KdYcNbeSfChmPXnLaQWy9lCjxYktzj0dP6Jvcp9vvdmgc83kVaPBcHepBCZhqqaPVvUzoBihQ==", + "dependencies": { + "@angular-devkit/core": "19.1.0", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.17", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/common": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.1.0.tgz", + "integrity": "sha512-At7Rj/RbXBcXBPYfBkgnBKyUDgZBiq7NNSnBbFnbIOkP6lY8JT8Y2fN0JX7Q+Hrmw4U2ysjM3A7cHiwdGLd8Nw==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/core": "19.1.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/compiler": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.1.0.tgz", + "integrity": "sha512-kqmTuUZlTMGeR0iXFjCDQYOYUR6N6hCHDyzgmGUH0cm+gRg2RJCrhEk7D3lttlVDo4ZvIyJ/4vkah0K623U7yA==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/core": "19.1.0" + }, + "peerDependenciesMeta": { + "@angular/core": { + "optional": true + } + } + }, + "node_modules/@angular/core": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.1.0.tgz", + "integrity": "sha512-mbqBkq4Fz61pfmmZDHcH64BzXw8jRUGAdaCOykZO11BuTLPHVZMGWepWtQScuYTZCCj8BR+rfrCULe5TGEQcCA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.15.0" + } + }, + "node_modules/@angular/fire": { + "version": "19.0.0-rc.5", + "resolved": "https://registry.npmjs.org/@angular/fire/-/fire-19.0.0-rc.5.tgz", + "integrity": "sha512-432Um0KvqOa8B9OG3z8aKeY5b97Od+WXtQxUrj3ADugpw564oTNLRTO45l2TW1se52GvoWKz8oXjdv80hMY8Mw==", + "dependencies": { + "@angular-devkit/schematics": "^19.0.0", + "@schematics/angular": "^19.0.0", + "firebase": "^11.0.2", + "rxfire": "^6.1.0", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/platform-browser": "^19.0.0", + "@angular/platform-browser-dynamic": "^19.0.0", + "@angular/platform-server": "^19.0.0", + "firebase-tools": "^13.0.0", + "rxjs": "~7.8.0" + }, + "peerDependenciesMeta": { + "@angular/platform-server": { + "optional": true + }, + "firebase-tools": { + "optional": true + } + } + }, + "node_modules/@angular/platform-browser": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.1.0.tgz", + "integrity": "sha512-nDSHx1WJZbrVjXNKG1qYgmS1fojKbxdWPye1teH0qHjBcZBYa5i9na2HHooBBPBLLVkgst8+ewuVb4cZHaEESg==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/animations": "19.1.0", + "@angular/common": "19.1.0", + "@angular/core": "19.1.0" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } + } + }, + "node_modules/@angular/platform-browser-dynamic": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.1.0.tgz", + "integrity": "sha512-ZN2BR3uhtAJZggOfpdAuQy2QtO0w46ofG3boFfsW8HQP7ed3GzItEfMLLTcX9ypIu+YVygRwZRLuf0KUsYSJIA==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/common": "19.1.0", + "@angular/compiler": "19.1.0", + "@angular/core": "19.1.0", + "@angular/platform-browser": "19.1.0" + } + }, + "node_modules/@firebase/analytics": { + "version": "0.10.10", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.10.tgz", + "integrity": "sha512-Psdo7c9g2SLAYh6u1XRA+RZ7ab2JfBVuAt/kLzXkhKZL/gS2cQUCMsOW5p0RIlDPRKqpdNSmvujd2TeRWLKOkQ==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/installations": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/analytics-compat": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.16.tgz", + "integrity": "sha512-Q/s+u/TEMSb2EDJFQMGsOzpSosybBl8HuoSEMyGZ99+0Pu7SIR9MPDGUjc8PKiCFQWDJ3QXxgqh1d/rujyAMbA==", + "dependencies": { + "@firebase/analytics": "0.10.10", + "@firebase/analytics-types": "0.8.3", + "@firebase/component": "0.6.11", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/analytics-types": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz", + "integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==" + }, + "node_modules/@firebase/app": { + "version": "0.10.17", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.17.tgz", + "integrity": "sha512-53sIYyAnYEPIZdaxuyq5OST7j4KBc2pqmktz+tEb1BIUSbXh8Gp4k/o6qzLelLpm4ngrBz7SRN0PZJqNRAyPog==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/app-check": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.10.tgz", + "integrity": "sha512-DWFfxxif/t+Ow4MmRUevDX+A3hVxm1rUf6y5ZP4sIomfnVCO1NNahqtsv9rb1/tKGkTeoVT40weiTS/WjQG1mA==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/app-check-compat": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.17.tgz", + "integrity": "sha512-a/eadrGsY0MVCBPhrNbKUhoYpms4UKTYLKO7nswwSFVsm3Rw6NslQQCNLfvljcDqP4E7alQDRGJXjkxd/5gJ+Q==", + "dependencies": { + "@firebase/app-check": "0.8.10", + "@firebase/app-check-types": "0.5.3", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/app-check-interop-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", + "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==" + }, + "node_modules/@firebase/app-check-types": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz", + "integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==" + }, + "node_modules/@firebase/app-compat": { + "version": "0.2.47", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.47.tgz", + "integrity": "sha512-TdEWGDp6kSwuO1mxiM2Fe39eLWygfyzqTZcoU3aPV0viqqphPCbBBnVjPbFJErZ4+yaS7uCWXEbFEP9m5/COKA==", + "dependencies": { + "@firebase/app": "0.10.17", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/app-types": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", + "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==" + }, + "node_modules/@firebase/auth": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.8.1.tgz", + "integrity": "sha512-LX9N/Cf5Z35r5yqm2+5M3+2bRRe/+RFaa/+u4HDni7TA27C/Xm4XHLKcWcLg1BzjrS4zngSaBEOSODvp6RFOqQ==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@react-native-async-storage/async-storage": "^1.18.1" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@firebase/auth-compat": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.16.tgz", + "integrity": "sha512-YlYwJMBqAyv0ESy3jDUyshMhZlbUiwAm6B6+uUmigNDHU+uq7j4SFiDJEZlFFIz397yBzKn06SUdqutdQzGnCA==", + "dependencies": { + "@firebase/auth": "1.8.1", + "@firebase/auth-types": "0.12.3", + "@firebase/component": "0.6.11", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", + "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==" + }, + "node_modules/@firebase/auth-types": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.3.tgz", + "integrity": "sha512-Zq9zI0o5hqXDtKg6yDkSnvMCMuLU6qAVS51PANQx+ZZX5xnzyNLEBO3GZgBUPsV5qIMFhjhqmLDxUqCbnAYy2A==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/component": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", + "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "dependencies": { + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/data-connect": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.3.tgz", + "integrity": "sha512-FbAQpWNHownJx1VTCQI4ydbWGOZmSWXoFlirQn3ItHqsLJYSywqxSgDafzvyooifFh3J/2WqaM8y9hInnPcsTw==", + "dependencies": { + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/database": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.10.tgz", + "integrity": "sha512-sWp2g92u7xT4BojGbTXZ80iaSIaL6GAL0pwvM0CO/hb0nHSnABAqsH7AhnWGsGvXuEvbPr7blZylPaR9J+GSuQ==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.1.tgz", + "integrity": "sha512-IsFivOjdE1GrjTeKoBU/ZMenESKDXidFDzZzHBPQ/4P20ptGdrl3oLlWrV/QJqJ9lND4IidE3z4Xr5JyfUW1vg==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/database": "1.0.10", + "@firebase/database-types": "1.0.7", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.7.tgz", + "integrity": "sha512-I7zcLfJXrM0WM+ksFmFdAMdlq/DFmpeMNa+/GNsLyFo5u/lX5zzkPzGe3srVWqaBQBY5KprylDGxOsP6ETfL0A==", + "dependencies": { + "@firebase/app-types": "0.9.3", + "@firebase/util": "1.10.2" + } + }, + "node_modules/@firebase/firestore": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.5.tgz", + "integrity": "sha512-OO3rHvjC07jL2ITN255xH/UzCVSvh6xG8oTzQdFScQvFbcm1fjCL1hgAdpDZcx3vVcKMV+6ktr8wbllkB8r+FQ==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "@firebase/webchannel-wrapper": "1.0.3", + "@grpc/grpc-js": "~1.9.0", + "@grpc/proto-loader": "^0.7.8", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/firestore-compat": { + "version": "0.3.40", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.40.tgz", + "integrity": "sha512-18HopMN811KYBc9Ptpr1Rewwio0XF09FF3jc5wtV6rGyAs815SlFFw5vW7ZeLd43zv9tlEc2FzM0H+5Vr9ZRxw==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/firestore": "4.7.5", + "@firebase/firestore-types": "3.0.3", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/firestore-types": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz", + "integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/functions": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.0.tgz", + "integrity": "sha512-plTtzY/nT0jOgHzT0vB9qch4FpHFOhCnR8HhYBqqdArG6GOQMIruKZbiTyLybO8bcaaNgQ6kSm9yohGUwxHcIw==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.11", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/functions-compat": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.17.tgz", + "integrity": "sha512-oj2XV8YsJYutyPCRYUfbN6swmfrL6zar0/qtqZsKT7P7btOiYRl+lD6fxtQaT+pKE5YgOBGZW//kLPZfY0jWhw==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/functions": "0.12.0", + "@firebase/functions-types": "0.6.3", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/functions-types": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz", + "integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==" + }, + "node_modules/@firebase/installations": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.11.tgz", + "integrity": "sha512-w8fY8mw6fxJzsZM2ufmTtomopXl1+bn/syYon+Gpn+0p0nO1cIUEVEFrFazTLaaL9q1CaVhc3HmseRTsI3igAA==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/util": "1.10.2", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/installations-compat": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.11.tgz", + "integrity": "sha512-SHRgw5LTa6v8LubmJZxcOCwEd1MfWQPUtKdiuCx2VMWnapX54skZd1PkQg0K4l3k+4ujbI2cn7FE6Li9hbChBw==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/installations": "0.6.11", + "@firebase/installations-types": "0.5.3", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/installations-types": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz", + "integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==", + "peerDependencies": { + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/messaging": { + "version": "0.12.15", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.15.tgz", + "integrity": "sha512-Bz+qvWNEwEWAbYtG4An8hgcNco6NWNoNLuLbGVwPL2fAoCF1zz+dcaBp+iTR2+K199JyRyDT9yDPAXhNHNDaKQ==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/installations": "0.6.11", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.10.2", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/messaging-compat": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.15.tgz", + "integrity": "sha512-mEKKASRvRWq1aBNHgioGsOYR2c5nBZpO7k90K794zjKe0WkGNf0k7PLs5SlCf8FKnzumEkhTAp/SjYxovuxa8A==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/messaging": "0.12.15", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/messaging-interop-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz", + "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==" + }, + "node_modules/@firebase/performance": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.11.tgz", + "integrity": "sha512-FlkJFeqLlIeh5T4Am3uE38HVzggliDIEFy/fErEc1faINOUFCb6vQBEoNZGaXvRnTR8lh3X/hP7tv37C7BsK9g==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/installations": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/performance-compat": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.11.tgz", + "integrity": "sha512-DqeNBy51W2xzlklyC7Ht9JQ94HhTA08PCcM4MDeyG/ol3fqum/+YgtHWQ2IQuduqH9afETthZqLwCZiSgY7hiA==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/performance": "0.6.11", + "@firebase/performance-types": "0.2.3", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/performance-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz", + "integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==" + }, + "node_modules/@firebase/remote-config": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.11.tgz", + "integrity": "sha512-9z0rgKuws2nj+7cdiqF+NY1QR4na6KnuOvP+jQvgilDOhGtKOcCMq5XHiu66i73A9kFhyU6QQ2pHXxcmaq1pBw==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/installations": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/remote-config-compat": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.11.tgz", + "integrity": "sha512-zfIjpwPrGuIOZDmduukN086qjhZ1LnbJi/iYzgua+2qeTlO0XdlE1v66gJPwygGB3TOhT0yb9EiUZ3nBNttMqg==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/remote-config": "0.4.11", + "@firebase/remote-config-types": "0.3.3", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/remote-config-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.3.tgz", + "integrity": "sha512-YlRI9CHxrk3lpQuFup9N1eohpwdWayKZUNZ/YeQ0PZoncJ66P32UsKUKqVXOaieTjJIOh7yH8JEzRdht5s+d6g==" + }, + "node_modules/@firebase/storage": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.4.tgz", + "integrity": "sha512-b1KaTTRiMupFurIhpGIbReaWev0k5O3ouTHkAPcEssT+FvU3q/1JwzvkX4+ZdB60Fc43Mbp8qQ1gWfT0Z2FP9Q==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/storage-compat": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.14.tgz", + "integrity": "sha512-Ok5FmXJiapaNAOQ8W8qppnfwgP8540jw2B8M0c4TFZqF4BD+CoKBxW0dRtOuLNGadLhzqqkDZZZtkexxrveQqA==", + "dependencies": { + "@firebase/component": "0.6.11", + "@firebase/storage": "0.13.4", + "@firebase/storage-types": "0.8.3", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/storage-types": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz", + "integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/util": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", + "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@firebase/vertexai": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.2.tgz", + "integrity": "sha512-4dC9m2nD0tkfKJT5v+i27tELrmUePjFXW3CDAxhVHUEv647B2R7kqpGQnyPkNEeaXkCr76THe7GGg35EWn4lDw==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/component": "0.6.11", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.2", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/webchannel-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz", + "integrity": "sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==" + }, + "node_modules/@grpc/grpc-js": { + "version": "1.9.15", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", + "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", + "dependencies": { + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@schematics/angular": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.1.0.tgz", + "integrity": "sha512-ygSnRtd/DQg+V4tsWH/44waXSUv2d8iq+R6phAJ72JRiRZKbcQxkj1Rsar/9yfxEXC+xz+0HE5Rb5XJ2Kh7T5w==", + "dependencies": { + "@angular-devkit/core": "19.1.0", + "@angular-devkit/schematics": "19.1.0", + "jsonc-parser": "3.3.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@tanstack/angular-query-experimental": { + "version": "5.64.1", + "resolved": "https://registry.npmjs.org/@tanstack/angular-query-experimental/-/angular-query-experimental-5.64.1.tgz", + "integrity": "sha512-JMLxcQgdXATg54ZE9hdsGGb5V0ZKbfwnuQsyOHSU9bVaSpg0o/ps1Z8ngRbdOAjVuvjYbkte/Cn6aIpt29BaCQ==", + "dependencies": { + "@tanstack/query-core": "5.64.1", + "@tanstack/query-devtools": "5.62.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@angular/common": ">=16.0.0", + "@angular/core": ">=16.0.0" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.64.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.64.1.tgz", + "integrity": "sha512-978Wx4Wl4UJZbmvU/rkaM9cQtXXrbhK0lsz/UZhYIbyKYA8E4LdomTwyh2GHZ4oU0BKKoDH4YlKk2VscCUgNmg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-devtools": { + "version": "5.62.16", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.62.16.tgz", + "integrity": "sha512-3ff6UBJr0H3nIhfLSl9911rvKqXf0u4B58jl0uYdDWLqPk9pCvYIbxC35cGxK2+8INl4IaFVUHb/IdgWrNkg3Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@types/node": { + "version": "22.10.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.6.tgz", + "integrity": "sha512-qNiuwC4ZDAUNcY47xgaSuS92cjf8JbSUoaKS77bmLG1rU7MlATVSiw/IlrjtIyyskXBZ8KkNfjK/P5na7rgXbQ==", + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", + "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/firebase": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.1.0.tgz", + "integrity": "sha512-3OoNW3vBXmBLYJvcwbPCwfluptbDVp2zZYjrfHPVFAXfPgmyy/LWjidt+Sw2WNvRelsG0v++WN2Wor6J3OwDRg==", + "dependencies": { + "@firebase/analytics": "0.10.10", + "@firebase/analytics-compat": "0.2.16", + "@firebase/app": "0.10.17", + "@firebase/app-check": "0.8.10", + "@firebase/app-check-compat": "0.3.17", + "@firebase/app-compat": "0.2.47", + "@firebase/app-types": "0.9.3", + "@firebase/auth": "1.8.1", + "@firebase/auth-compat": "0.5.16", + "@firebase/data-connect": "0.1.3", + "@firebase/database": "1.0.10", + "@firebase/database-compat": "2.0.1", + "@firebase/firestore": "4.7.5", + "@firebase/firestore-compat": "0.3.40", + "@firebase/functions": "0.12.0", + "@firebase/functions-compat": "0.3.17", + "@firebase/installations": "0.6.11", + "@firebase/installations-compat": "0.2.11", + "@firebase/messaging": "0.12.15", + "@firebase/messaging-compat": "0.2.15", + "@firebase/performance": "0.6.11", + "@firebase/performance-compat": "0.2.11", + "@firebase/remote-config": "0.4.11", + "@firebase/remote-config-compat": "0.2.11", + "@firebase/storage": "0.13.4", + "@firebase/storage-compat": "0.3.14", + "@firebase/util": "1.10.2", + "@firebase/vertexai": "1.0.2" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz", + "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==" + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/long": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.4.tgz", + "integrity": "sha512-qtzLbJE8hq7VabR3mISmVGtoXP8KGc2Z/AT8OuqlYD7JTR3oqrgwdjnk07wpj1twXxYmgDXgoKVWUG/fReSzHg==" + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/protobufjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rxfire": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/rxfire/-/rxfire-6.1.0.tgz", + "integrity": "sha512-NezdjeY32VZcCuGO0bbb8H8seBsJSCaWdUwGsHNzUcAOHR0VGpzgPtzjuuLXr8R/iemkqSzbx/ioS7VwV43ynA==", + "peerDependencies": { + "firebase": "^9.0.0 || ^10.0.0 || ^11.0.0", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/zone.js": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.0.tgz", + "integrity": "sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA==", + "peer": true + } + } +} diff --git a/packages/angular/package.json b/packages/angular/package.json new file mode 100644 index 00000000..cca93451 --- /dev/null +++ b/packages/angular/package.json @@ -0,0 +1,24 @@ +{ + "name": "@tanstack-query-firebase/angular", + "version": "0.0.1", + "description": "Tanstack Query bindings for Firebase and Angular", + "type": "module", + "scripts": { + "build": "tsup", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "exports": { + "./data-connect": { + "types": "./dist/data-connect/index.d.ts", + "import": "./dist/data-connect/index.js" + } + }, + "author": "", + "license": "ISC", + "dependencies": { + "@angular/core": "^19.1.0", + "@angular/fire": "^19.0.0-rc.5", + "@tanstack/angular-query-experimental": "^5.64.1", + "firebase": "^11.1.0" + } +} diff --git a/packages/angular/src/data-connect/index.ts b/packages/angular/src/data-connect/index.ts new file mode 100644 index 00000000..2fd8dc39 --- /dev/null +++ b/packages/angular/src/data-connect/index.ts @@ -0,0 +1,65 @@ +import { CreateMutationOptions, CreateMutationResult, CreateQueryOptions, injectMutation, injectQueries, injectQuery, QueryFunction, QueryKey, } from '@tanstack/angular-query-experimental'; +import { executeMutation, executeQuery, MutationRef, QueryRef, type DataConnect } from 'firebase/data-connect'; +import { FirebaseError } from 'firebase/app'; +import { FlattenedMutationResult } from '../../../react/src/data-connect'; +type DataConnectMutationOptions = CreateMutationOptions & { + invalidate?: QueryKey | QueryRef[] +}; + +type MutationsOptionsFn = DataConnectMutationOptions, FirebaseError, Variables, Arguments> & { + dataConnect?: DataConnect; +}; +export function injectDataConnectMutation( + mutationFn: (args: Arguments) => MutationRef, + optionsFn?: () => MutationsOptionsFn +): CreateMutationResult, FirebaseError, Arguments> { + function fdcOptionsFn(): DataConnectMutationOptions, FirebaseError, Variables, Arguments> { + const modifiedFn = (args: Arguments) => { + const ref: MutationRef = mutationFn(args); + return executeMutation(ref).then(res => { + const { data, ...rest} = res; + return { + ...data, + ...rest + } + }) as Promise>; + }; + if(optionsFn) { + const options = optionsFn(); + return { + mutationFn: modifiedFn, + ...options, + } + } + return { + mutationFn: modifiedFn + } + } + return injectMutation(fdcOptionsFn); +} +interface CreateDataConnectQueryOptions extends Omit, 'queryFn'> { + queryFn: () => QueryRef +} +export function injectDataConnectQuery( + optionsFn: () => CreateDataConnectQueryOptions +) { + function fdcOptionsFn() { + const options = optionsFn(); + const modifiedFn = () => { + const ref: QueryRef = options.queryFn(); + return executeQuery(ref).then(res => { + const { data, ...rest} = res; + return { + ...data, + ...rest + } + }) as Promise>; + }; + + return { + ...options, + queryFn: modifiedFn, + } + } + return injectQuery(fdcOptionsFn); +} diff --git a/packages/angular/src/index.ts b/packages/angular/src/index.ts new file mode 100644 index 00000000..8cec2e9c --- /dev/null +++ b/packages/angular/src/index.ts @@ -0,0 +1 @@ +export {}; \ No newline at end of file diff --git a/packages/angular/tsup.config.ts b/packages/angular/tsup.config.ts new file mode 100644 index 00000000..d473def8 --- /dev/null +++ b/packages/angular/tsup.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from "tsup"; + +const supportedPackages = ['data-connect']; +export default defineConfig({ + entry: [`src/data-connect/index.ts`, 'src/index.ts'], + format: ["esm"], + dts: true, // generates .d.ts files + outDir: "dist", + esbuildOptions(options, context) { + options.outbase = './src'; + }, + // splitting: false, // Disable code splitting to generate distinct files + clean: true, +}); From b0b6667772073014ffbccb9e1a6137bb1d777d84 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 15 Jan 2025 16:42:18 -0800 Subject: [PATCH 02/10] Added tsconfig.json --- packages/angular/tsconfig.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 packages/angular/tsconfig.json diff --git a/packages/angular/tsconfig.json b/packages/angular/tsconfig.json new file mode 100644 index 00000000..cb0abdf9 --- /dev/null +++ b/packages/angular/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "es2015", + "module": "esnext", + "moduleResolution": "node", + "declaration": true, + "jsx": "react", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "types": ["vitest/globals"], + "paths": { + "~/testing-utils": ["../../vitest/utils.ts"], + "@/dataconnect/*": ["../../dataconnect-sdk/js/*"] + } + }, + "include": ["src", "utils.tsx"] +} From 677f024486850c101523daed02dbf3af762fbd9e Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 17 Jan 2025 10:42:27 -0800 Subject: [PATCH 03/10] WIP --- packages/angular/package-lock.json | 1812 +++++++++++--------- packages/angular/package.json | 14 +- packages/angular/src/data-connect/index.ts | 21 +- packages/angular/tsconfig.json | 3 +- packages/angular/tsup.config.ts | 4 +- 5 files changed, 1027 insertions(+), 827 deletions(-) diff --git a/packages/angular/package-lock.json b/packages/angular/package-lock.json index 6f645100..a37ca2c7 100644 --- a/packages/angular/package-lock.json +++ b/packages/angular/package-lock.json @@ -15,53 +15,502 @@ "firebase": "^11.1.0" } }, - "node_modules/@angular-devkit/core": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.0.tgz", - "integrity": "sha512-DAHd1TX4aiWTqW0eUDIXuntE/nd//SGnjJzIaqKGtj1/bngoY76S/DS7uStgxcZRD4VmprM0cJ0w68w3CMtzrA==", + "node_modules/@angular-devkit/schematics": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.1.1.tgz", + "integrity": "sha512-4xodirv/kErn7L5N6NhIDfuVuNgNDmGX1+Pdu3yG2c1moOTyRBV684lv2qQJClNctOpELDM55IuX3MXud2qQaw==", + "dependencies": { + "@angular-devkit/core": "19.1.1", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.17", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.1.tgz", + "integrity": "sha512-CAqst7WEasPHR4OFdbxxX3+NVqNTvYk3vtPbXT/jZ0L2EZRICQta2EClkdhSIiMkiMf0/2LNT05rYD7k4NHIQA==", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@angular-devkit/schematics/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/@angular-devkit/schematics/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@angular-devkit/schematics/node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/@angular-devkit/schematics/node_modules/fast-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", + "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, + "node_modules/@angular-devkit/schematics/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/@angular-devkit/schematics/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/@angular-devkit/schematics/node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/@angular-devkit/schematics/node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" + }, + "node_modules/@angular-devkit/schematics/node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dependencies": { - "ajv": "8.17.1", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.2", - "rxjs": "7.8.1", - "source-map": "0.7.4" + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": ">=10" }, - "peerDependencies": { - "chokidar": "^4.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } + ] + }, + "node_modules/@angular-devkit/schematics/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/@angular-devkit/schematics/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" } }, - "node_modules/@angular-devkit/schematics": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.1.0.tgz", - "integrity": "sha512-S+MUDHiK+51I9KdYcNbeSfChmPXnLaQWy9lCjxYktzj0dP6Jvcp9vvdmgc83kVaPBcHepBCZhqqaPVvUzoBihQ==", + "node_modules/@angular-devkit/schematics/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dependencies": { - "@angular-devkit/core": "19.1.0", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.17", - "ora": "5.4.1", - "rxjs": "7.8.1" + "safe-buffer": "~5.2.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": ">=8" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/@angular-devkit/schematics/node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dependencies": { + "defaults": "^1.0.3" } }, "node_modules/@angular/common": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.1.0.tgz", - "integrity": "sha512-At7Rj/RbXBcXBPYfBkgnBKyUDgZBiq7NNSnBbFnbIOkP6lY8JT8Y2fN0JX7Q+Hrmw4U2ysjM3A7cHiwdGLd8Nw==", + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.1.1.tgz", + "integrity": "sha512-2ZbnV8lM81ekLjRMRufRho7N8adz+Yjwj+3y5RB7+GW8fX5f9mm740ifyieBCXPLtiWb8ZK1i9gime6y64BEBQ==", "peer": true, "dependencies": { "tslib": "^2.3.0" @@ -70,14 +519,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "19.1.0", + "@angular/core": "19.1.1", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.1.0.tgz", - "integrity": "sha512-kqmTuUZlTMGeR0iXFjCDQYOYUR6N6hCHDyzgmGUH0cm+gRg2RJCrhEk7D3lttlVDo4ZvIyJ/4vkah0K623U7yA==", + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.1.1.tgz", + "integrity": "sha512-bXPiJKQYjH6kSBnlVHx8aLzYY7YhWw1cidthWwqNaXyZ4YYILom1lN3C7nJYOVDX8W64QCMimHqf8iD4guByxA==", "peer": true, "dependencies": { "tslib": "^2.3.0" @@ -86,7 +535,7 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "19.1.0" + "@angular/core": "19.1.1" }, "peerDependenciesMeta": { "@angular/core": { @@ -95,9 +544,9 @@ } }, "node_modules/@angular/core": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.1.0.tgz", - "integrity": "sha512-mbqBkq4Fz61pfmmZDHcH64BzXw8jRUGAdaCOykZO11BuTLPHVZMGWepWtQScuYTZCCj8BR+rfrCULe5TGEQcCA==", + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.1.1.tgz", + "integrity": "sha512-uEDnomaIh7yUPx6hHWMFcWrUMOwishkkPToSFMltVLfRrfmAQL+WMpOGtR6qiFG6PIppsADIxXPRWVzfnYOYZg==", "dependencies": { "tslib": "^2.3.0" }, @@ -110,13 +559,13 @@ } }, "node_modules/@angular/fire": { - "version": "19.0.0-rc.5", - "resolved": "https://registry.npmjs.org/@angular/fire/-/fire-19.0.0-rc.5.tgz", - "integrity": "sha512-432Um0KvqOa8B9OG3z8aKeY5b97Od+WXtQxUrj3ADugpw564oTNLRTO45l2TW1se52GvoWKz8oXjdv80hMY8Mw==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@angular/fire/-/fire-19.0.0.tgz", + "integrity": "sha512-dVU9IdL9sGKe1fV7g2iGgkjUQIYrbnljHtHUgNpZaskyW+Vy6ndtsEbSUoRd6sLP8WpThWH7WvITKhu/8a6qfQ==", "dependencies": { "@angular-devkit/schematics": "^19.0.0", "@schematics/angular": "^19.0.0", - "firebase": "^11.0.2", + "firebase": "^11.2.0", "rxfire": "^6.1.0", "tslib": "^2.3.0" }, @@ -139,9 +588,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.1.0.tgz", - "integrity": "sha512-nDSHx1WJZbrVjXNKG1qYgmS1fojKbxdWPye1teH0qHjBcZBYa5i9na2HHooBBPBLLVkgst8+ewuVb4cZHaEESg==", + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.1.1.tgz", + "integrity": "sha512-L33rk7j3FepDqHo29iqp7ucL1tBjGQed+e22ei9bCsj7CG0GNi5w8id3nyNImhwN26wtg++4cu4la+XxKWIkXg==", "peer": true, "dependencies": { "tslib": "^2.3.0" @@ -150,9 +599,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "19.1.0", - "@angular/common": "19.1.0", - "@angular/core": "19.1.0" + "@angular/animations": "19.1.1", + "@angular/common": "19.1.1", + "@angular/core": "19.1.1" }, "peerDependenciesMeta": { "@angular/animations": { @@ -160,67 +609,266 @@ } } }, - "node_modules/@angular/platform-browser-dynamic": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.1.0.tgz", - "integrity": "sha512-ZN2BR3uhtAJZggOfpdAuQy2QtO0w46ofG3boFfsW8HQP7ed3GzItEfMLLTcX9ypIu+YVygRwZRLuf0KUsYSJIA==", - "peer": true, + "node_modules/@angular/platform-browser-dynamic": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.1.1.tgz", + "integrity": "sha512-iEVOFKpBEFXKDqQb42xhEXpseQc2vpl16kuT9gbjuvBC8KJLsTdvE34HIoZN1Igm22wZzp+PBzSWYa8WiQK83A==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/common": "19.1.1", + "@angular/compiler": "19.1.1", + "@angular/core": "19.1.1", + "@angular/platform-browser": "19.1.1" + } + }, + "node_modules/@schematics/angular": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.1.1.tgz", + "integrity": "sha512-XrnmSbCcDPePCbEVhgEPFZFiL/fowvkPJ8qOa1m9tWHSPYb739Vk3g+VDrAqNMm7FULcRzQzqHBq/IBB8qYfIg==", + "dependencies": { + "@angular-devkit/core": "19.1.1", + "@angular-devkit/schematics": "19.1.1", + "jsonc-parser": "3.3.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.1.tgz", + "integrity": "sha512-CAqst7WEasPHR4OFdbxxX3+NVqNTvYk3vtPbXT/jZ0L2EZRICQta2EClkdhSIiMkiMf0/2LNT05rYD7k4NHIQA==", + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@schematics/angular/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@schematics/angular/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@schematics/angular/node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/@schematics/angular/node_modules/fast-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", + "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, + "node_modules/@schematics/angular/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/@schematics/angular/node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" + }, + "node_modules/@schematics/angular/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@schematics/angular/node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@schematics/angular/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@tanstack/angular-query-experimental": { + "version": "5.64.1", + "resolved": "https://registry.npmjs.org/@tanstack/angular-query-experimental/-/angular-query-experimental-5.64.1.tgz", + "integrity": "sha512-JMLxcQgdXATg54ZE9hdsGGb5V0ZKbfwnuQsyOHSU9bVaSpg0o/ps1Z8ngRbdOAjVuvjYbkte/Cn6aIpt29BaCQ==", "dependencies": { - "tslib": "^2.3.0" + "@tanstack/query-core": "5.64.1", + "@tanstack/query-devtools": "5.62.16" }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" }, "peerDependencies": { - "@angular/common": "19.1.0", - "@angular/compiler": "19.1.0", - "@angular/core": "19.1.0", - "@angular/platform-browser": "19.1.0" + "@angular/common": ">=16.0.0", + "@angular/core": ">=16.0.0" } }, - "node_modules/@firebase/analytics": { - "version": "0.10.10", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.10.tgz", - "integrity": "sha512-Psdo7c9g2SLAYh6u1XRA+RZ7ab2JfBVuAt/kLzXkhKZL/gS2cQUCMsOW5p0RIlDPRKqpdNSmvujd2TeRWLKOkQ==", - "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/installations": "0.6.11", + "node_modules/@tanstack/query-core": { + "version": "5.64.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.64.1.tgz", + "integrity": "sha512-978Wx4Wl4UJZbmvU/rkaM9cQtXXrbhK0lsz/UZhYIbyKYA8E4LdomTwyh2GHZ4oU0BKKoDH4YlKk2VscCUgNmg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-devtools": { + "version": "5.62.16", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.62.16.tgz", + "integrity": "sha512-3ff6UBJr0H3nIhfLSl9911rvKqXf0u4B58jl0uYdDWLqPk9pCvYIbxC35cGxK2+8INl4IaFVUHb/IdgWrNkg3Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/firebase": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.2.0.tgz", + "integrity": "sha512-ztwPhBLAZMVNZjBeQzzTM4rk2rsRXmdFYcnvjAXh+StbiFVshHKaPO9VRGMUzF48du4Mkz6jN1wkmYCuUJPxLA==", + "dependencies": { + "@firebase/analytics": "0.10.11", + "@firebase/analytics-compat": "0.2.17", + "@firebase/app": "0.10.18", + "@firebase/app-check": "0.8.11", + "@firebase/app-check-compat": "0.3.18", + "@firebase/app-compat": "0.2.48", + "@firebase/app-types": "0.9.3", + "@firebase/auth": "1.8.2", + "@firebase/auth-compat": "0.5.17", + "@firebase/data-connect": "0.2.0", + "@firebase/database": "1.0.11", + "@firebase/database-compat": "2.0.2", + "@firebase/firestore": "4.7.6", + "@firebase/firestore-compat": "0.3.41", + "@firebase/functions": "0.12.1", + "@firebase/functions-compat": "0.3.18", + "@firebase/installations": "0.6.12", + "@firebase/installations-compat": "0.2.12", + "@firebase/messaging": "0.12.16", + "@firebase/messaging-compat": "0.2.16", + "@firebase/performance": "0.6.12", + "@firebase/performance-compat": "0.2.12", + "@firebase/remote-config": "0.5.0", + "@firebase/remote-config-compat": "0.2.12", + "@firebase/storage": "0.13.5", + "@firebase/storage-compat": "0.3.15", + "@firebase/util": "1.10.3", + "@firebase/vertexai": "1.0.3" + } + }, + "node_modules/firebase/node_modules/@firebase/analytics": { + "version": "0.10.11", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.11.tgz", + "integrity": "sha512-zwuPiRE0+hgcS95JZbJ6DFQN4xYFO8IyGxpeePTV51YJMwCf3lkBa6FnZ/iXIqDKcBPMgMuuEZozI0BJWaLEYg==", + "dependencies": { + "@firebase/component": "0.6.12", + "@firebase/installations": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, - "node_modules/@firebase/analytics-compat": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.16.tgz", - "integrity": "sha512-Q/s+u/TEMSb2EDJFQMGsOzpSosybBl8HuoSEMyGZ99+0Pu7SIR9MPDGUjc8PKiCFQWDJ3QXxgqh1d/rujyAMbA==", + "node_modules/firebase/node_modules/@firebase/analytics-compat": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.17.tgz", + "integrity": "sha512-SJNVOeTvzdqZQvXFzj7yAirXnYcLDxh57wBFROfeowq/kRN1AqOw1tG6U4OiFOEhqi7s3xLze/LMkZatk2IEww==", "dependencies": { - "@firebase/analytics": "0.10.10", + "@firebase/analytics": "0.10.11", "@firebase/analytics-types": "0.8.3", - "@firebase/component": "0.6.11", - "@firebase/util": "1.10.2", + "@firebase/component": "0.6.12", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/analytics-types": { + "node_modules/firebase/node_modules/@firebase/analytics-types": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz", "integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==" }, - "node_modules/@firebase/app": { - "version": "0.10.17", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.17.tgz", - "integrity": "sha512-53sIYyAnYEPIZdaxuyq5OST7j4KBc2pqmktz+tEb1BIUSbXh8Gp4k/o6qzLelLpm4ngrBz7SRN0PZJqNRAyPog==", + "node_modules/firebase/node_modules/@firebase/app": { + "version": "0.10.18", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.18.tgz", + "integrity": "sha512-VuqEwD/QRisKd/zsFsqgvSAx34mZ3WEF47i97FD6Vw4GWAhdjepYf0Hmi6K0b4QMSgWcv/x0C30Slm5NjjERXg==", "dependencies": { - "@firebase/component": "0.6.11", + "@firebase/component": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -228,14 +876,14 @@ "node": ">=18.0.0" } }, - "node_modules/@firebase/app-check": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.10.tgz", - "integrity": "sha512-DWFfxxif/t+Ow4MmRUevDX+A3hVxm1rUf6y5ZP4sIomfnVCO1NNahqtsv9rb1/tKGkTeoVT40weiTS/WjQG1mA==", + "node_modules/firebase/node_modules/@firebase/app-check": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.11.tgz", + "integrity": "sha512-42zIfRI08/7bQqczAy7sY2JqZYEv3a1eNa4fLFdtJ54vNevbBIRSEA3fZgRqWFNHalh5ohsBXdrYgFqaRIuCcQ==", "dependencies": { - "@firebase/component": "0.6.11", + "@firebase/component": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { @@ -245,16 +893,16 @@ "@firebase/app": "0.x" } }, - "node_modules/@firebase/app-check-compat": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.17.tgz", - "integrity": "sha512-a/eadrGsY0MVCBPhrNbKUhoYpms4UKTYLKO7nswwSFVsm3Rw6NslQQCNLfvljcDqP4E7alQDRGJXjkxd/5gJ+Q==", + "node_modules/firebase/node_modules/@firebase/app-check-compat": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.18.tgz", + "integrity": "sha512-qjozwnwYmAIdrsVGrJk+hnF1WBois54IhZR6gO0wtZQoTvWL/GtiA2F31TIgAhF0ayUiZhztOv1RfC7YyrZGDQ==", "dependencies": { - "@firebase/app-check": "0.8.10", + "@firebase/app-check": "0.8.11", "@firebase/app-check-types": "0.5.3", - "@firebase/component": "0.6.11", + "@firebase/component": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { @@ -264,44 +912,44 @@ "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/app-check-interop-types": { + "node_modules/firebase/node_modules/@firebase/app-check-interop-types": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==" }, - "node_modules/@firebase/app-check-types": { + "node_modules/firebase/node_modules/@firebase/app-check-types": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz", "integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==" }, - "node_modules/@firebase/app-compat": { - "version": "0.2.47", - "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.47.tgz", - "integrity": "sha512-TdEWGDp6kSwuO1mxiM2Fe39eLWygfyzqTZcoU3aPV0viqqphPCbBBnVjPbFJErZ4+yaS7uCWXEbFEP9m5/COKA==", + "node_modules/firebase/node_modules/@firebase/app-compat": { + "version": "0.2.48", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.48.tgz", + "integrity": "sha512-wVNU1foBIaJncUmiALyRxhHHHC3ZPMLIETTAk+2PG87eP9B/IDBsYUiTpHyboDPEI8CgBPat/zN2v+Snkz6lBw==", "dependencies": { - "@firebase/app": "0.10.17", - "@firebase/component": "0.6.11", + "@firebase/app": "0.10.18", + "@firebase/component": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@firebase/app-types": { + "node_modules/firebase/node_modules/@firebase/app-types": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==" }, - "node_modules/@firebase/auth": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.8.1.tgz", - "integrity": "sha512-LX9N/Cf5Z35r5yqm2+5M3+2bRRe/+RFaa/+u4HDni7TA27C/Xm4XHLKcWcLg1BzjrS4zngSaBEOSODvp6RFOqQ==", + "node_modules/firebase/node_modules/@firebase/auth": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.8.2.tgz", + "integrity": "sha512-q+071y2LWe0bVnjqaX3BscqZwzdP0GKN2YBKapLq4bV88MPfCtWwGKmDhNDEDUmioOjudGXkUY5cvvKqk3mlUg==", "dependencies": { - "@firebase/component": "0.6.11", + "@firebase/component": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { @@ -317,15 +965,15 @@ } } }, - "node_modules/@firebase/auth-compat": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.16.tgz", - "integrity": "sha512-YlYwJMBqAyv0ESy3jDUyshMhZlbUiwAm6B6+uUmigNDHU+uq7j4SFiDJEZlFFIz397yBzKn06SUdqutdQzGnCA==", + "node_modules/firebase/node_modules/@firebase/auth-compat": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.17.tgz", + "integrity": "sha512-Shi6rqLqzU9KLXnUCmlLvVByq1kiG3oe7Wpbf5m1CgS7NiRx2pSSn0HLaRRozdkaizNzMGGj+3oHmNYQ7kU6xA==", "dependencies": { - "@firebase/auth": "1.8.1", + "@firebase/auth": "1.8.2", "@firebase/auth-types": "0.12.3", - "@firebase/component": "0.6.11", - "@firebase/util": "1.10.2", + "@firebase/component": "0.6.12", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { @@ -335,12 +983,12 @@ "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/auth-interop-types": { + "node_modules/firebase/node_modules/@firebase/auth-interop-types": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==" }, - "node_modules/@firebase/auth-types": { + "node_modules/firebase/node_modules/@firebase/auth-types": { "version": "0.12.3", "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.3.tgz", "integrity": "sha512-Zq9zI0o5hqXDtKg6yDkSnvMCMuLU6qAVS51PANQx+ZZX5xnzyNLEBO3GZgBUPsV5qIMFhjhqmLDxUqCbnAYy2A==", @@ -349,43 +997,43 @@ "@firebase/util": "1.x" } }, - "node_modules/@firebase/component": { - "version": "0.6.11", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.11.tgz", - "integrity": "sha512-eQbeCgPukLgsKD0Kw5wQgsMDX5LeoI1MIrziNDjmc6XDq5ZQnuUymANQgAb2wp1tSF9zDSXyxJmIUXaKgN58Ug==", + "node_modules/firebase/node_modules/@firebase/component": { + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.12.tgz", + "integrity": "sha512-YnxqjtohLbnb7raXt2YuA44cC1wA9GiehM/cmxrsoxKlFxBLy2V0OkRSj9gpngAE0UoJ421Wlav9ycO7lTPAUw==", "dependencies": { - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@firebase/data-connect": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.3.tgz", - "integrity": "sha512-FbAQpWNHownJx1VTCQI4ydbWGOZmSWXoFlirQn3ItHqsLJYSywqxSgDafzvyooifFh3J/2WqaM8y9hInnPcsTw==", + "node_modules/firebase/node_modules/@firebase/data-connect": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.2.0.tgz", + "integrity": "sha512-7OrZtQoLSk2fiGijhIdUnTSqEFti3h1EMhw9nNiSZ6jJGduw4Pz6jrVvxjpZJtGH/JiljbMkBnPBS2h8CTRKEw==", "dependencies": { "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.11", + "@firebase/component": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, - "node_modules/@firebase/database": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.10.tgz", - "integrity": "sha512-sWp2g92u7xT4BojGbTXZ80iaSIaL6GAL0pwvM0CO/hb0nHSnABAqsH7AhnWGsGvXuEvbPr7blZylPaR9J+GSuQ==", + "node_modules/firebase/node_modules/@firebase/database": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.11.tgz", + "integrity": "sha512-gLrw/XeioswWUXgpVKCPAzzoOuvYNqK5fRUeiJTzO7Mlp9P6ylFEyPJlRBl1djqYye641r3MX6AmIeMXwjgwuQ==", "dependencies": { "@firebase/app-check-interop-types": "0.3.3", "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.11", + "@firebase/component": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "faye-websocket": "0.11.4", "tslib": "^2.1.0" }, @@ -393,39 +1041,39 @@ "node": ">=18.0.0" } }, - "node_modules/@firebase/database-compat": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.1.tgz", - "integrity": "sha512-IsFivOjdE1GrjTeKoBU/ZMenESKDXidFDzZzHBPQ/4P20ptGdrl3oLlWrV/QJqJ9lND4IidE3z4Xr5JyfUW1vg==", + "node_modules/firebase/node_modules/@firebase/database-compat": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.2.tgz", + "integrity": "sha512-5zvdnMsfDHvrQAVM6jBS7CkBpu+z3YbpFdhxRsrK1FP45IEfxlzpeuEUb17D/tpM10vfq4Ok0x5akIBaCv7gfA==", "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/database": "1.0.10", - "@firebase/database-types": "1.0.7", + "@firebase/component": "0.6.12", + "@firebase/database": "1.0.11", + "@firebase/database-types": "1.0.8", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@firebase/database-types": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.7.tgz", - "integrity": "sha512-I7zcLfJXrM0WM+ksFmFdAMdlq/DFmpeMNa+/GNsLyFo5u/lX5zzkPzGe3srVWqaBQBY5KprylDGxOsP6ETfL0A==", + "node_modules/firebase/node_modules/@firebase/database-types": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.8.tgz", + "integrity": "sha512-6lPWIGeufhUq1heofZULyVvWFhD01TUrkkB9vyhmksjZ4XF7NaivQp9rICMk7QNhqwa+uDCaj4j+Q8qqcSVZ9g==", "dependencies": { "@firebase/app-types": "0.9.3", - "@firebase/util": "1.10.2" + "@firebase/util": "1.10.3" } }, - "node_modules/@firebase/firestore": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.5.tgz", - "integrity": "sha512-OO3rHvjC07jL2ITN255xH/UzCVSvh6xG8oTzQdFScQvFbcm1fjCL1hgAdpDZcx3vVcKMV+6ktr8wbllkB8r+FQ==", + "node_modules/firebase/node_modules/@firebase/firestore": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.6.tgz", + "integrity": "sha512-aVDboR+upR/44qZDLR4tnZ9pepSOFBbDJnwk7eWzmTyQq2nZAVG+HIhrqpQawmUVcDRkuJv2K2UT2+oqR8F8TA==", "dependencies": { - "@firebase/component": "0.6.11", + "@firebase/component": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "@firebase/webchannel-wrapper": "1.0.3", "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", @@ -438,15 +1086,15 @@ "@firebase/app": "0.x" } }, - "node_modules/@firebase/firestore-compat": { - "version": "0.3.40", - "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.40.tgz", - "integrity": "sha512-18HopMN811KYBc9Ptpr1Rewwio0XF09FF3jc5wtV6rGyAs815SlFFw5vW7ZeLd43zv9tlEc2FzM0H+5Vr9ZRxw==", + "node_modules/firebase/node_modules/@firebase/firestore-compat": { + "version": "0.3.41", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.41.tgz", + "integrity": "sha512-J/PgWKEt0yugETOE7lOabT16hsV21cLzSxERD7ZhaiwBQkBTSf0Mx9RhjZRT0Ttqe4weM90HGZFyUBqYA73fVA==", "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/firestore": "4.7.5", + "@firebase/component": "0.6.12", + "@firebase/firestore": "4.7.6", "@firebase/firestore-types": "3.0.3", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { @@ -456,7 +1104,7 @@ "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/firestore-types": { + "node_modules/firebase/node_modules/@firebase/firestore-types": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz", "integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==", @@ -465,16 +1113,16 @@ "@firebase/util": "1.x" } }, - "node_modules/@firebase/functions": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.0.tgz", - "integrity": "sha512-plTtzY/nT0jOgHzT0vB9qch4FpHFOhCnR8HhYBqqdArG6GOQMIruKZbiTyLybO8bcaaNgQ6kSm9yohGUwxHcIw==", + "node_modules/firebase/node_modules/@firebase/functions": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.1.tgz", + "integrity": "sha512-QucRiFrvMMmIGTRhL7ZK2IeBnAWP7lAmfFREMpEtX47GjVqDqGxdFs+Mg7XBzxSc9UjDO4Rxf+aE9xJHU6bGwg==", "dependencies": { "@firebase/app-check-interop-types": "0.3.3", "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.11", + "@firebase/component": "0.6.12", "@firebase/messaging-interop-types": "0.2.3", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { @@ -484,15 +1132,15 @@ "@firebase/app": "0.x" } }, - "node_modules/@firebase/functions-compat": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.17.tgz", - "integrity": "sha512-oj2XV8YsJYutyPCRYUfbN6swmfrL6zar0/qtqZsKT7P7btOiYRl+lD6fxtQaT+pKE5YgOBGZW//kLPZfY0jWhw==", + "node_modules/firebase/node_modules/@firebase/functions-compat": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.18.tgz", + "integrity": "sha512-N7+RN5GVus2ORB8cqfSNhfSn4iaYws6F8uCCfn4mtjC7zYS/KH6muzNAhZUdUqlv5YazbVmvxlAoYYF39i8Qzg==", "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/functions": "0.12.0", + "@firebase/component": "0.6.12", + "@firebase/functions": "0.12.1", "@firebase/functions-types": "0.6.3", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { @@ -502,18 +1150,18 @@ "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/functions-types": { + "node_modules/firebase/node_modules/@firebase/functions-types": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz", "integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==" }, - "node_modules/@firebase/installations": { - "version": "0.6.11", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.11.tgz", - "integrity": "sha512-w8fY8mw6fxJzsZM2ufmTtomopXl1+bn/syYon+Gpn+0p0nO1cIUEVEFrFazTLaaL9q1CaVhc3HmseRTsI3igAA==", + "node_modules/firebase/node_modules/@firebase/installations": { + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.12.tgz", + "integrity": "sha512-ES/WpuAV2k2YtBTvdaknEo7IY8vaGjIjS3zhnHSAIvY9KwTR8XZFXOJoZ3nSkjN1A5R4MtEh+07drnzPDg9vaw==", "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/util": "1.10.2", + "@firebase/component": "0.6.12", + "@firebase/util": "1.10.3", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -521,22 +1169,22 @@ "@firebase/app": "0.x" } }, - "node_modules/@firebase/installations-compat": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.11.tgz", - "integrity": "sha512-SHRgw5LTa6v8LubmJZxcOCwEd1MfWQPUtKdiuCx2VMWnapX54skZd1PkQg0K4l3k+4ujbI2cn7FE6Li9hbChBw==", + "node_modules/firebase/node_modules/@firebase/installations-compat": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.12.tgz", + "integrity": "sha512-RhcGknkxmFu92F6Jb3rXxv6a4sytPjJGifRZj8MSURPuv2Xu+/AispCXEfY1ZraobhEHTG5HLGsP6R4l9qB5aA==", "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/installations": "0.6.11", + "@firebase/component": "0.6.12", + "@firebase/installations": "0.6.12", "@firebase/installations-types": "0.5.3", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/installations-types": { + "node_modules/firebase/node_modules/@firebase/installations-types": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz", "integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==", @@ -544,7 +1192,7 @@ "@firebase/app-types": "0.x" } }, - "node_modules/@firebase/logger": { + "node_modules/firebase/node_modules/@firebase/logger": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", @@ -555,15 +1203,15 @@ "node": ">=18.0.0" } }, - "node_modules/@firebase/messaging": { - "version": "0.12.15", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.15.tgz", - "integrity": "sha512-Bz+qvWNEwEWAbYtG4An8hgcNco6NWNoNLuLbGVwPL2fAoCF1zz+dcaBp+iTR2+K199JyRyDT9yDPAXhNHNDaKQ==", + "node_modules/firebase/node_modules/@firebase/messaging": { + "version": "0.12.16", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.16.tgz", + "integrity": "sha512-VJ8sCEIeP3+XkfbJA7410WhYGHdloYFZXoHe/vt+vNVDGw8JQPTQSVTRvjrUprEf5I4Tbcnpr2H34lS6zhCHSA==", "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/installations": "0.6.11", + "@firebase/component": "0.6.12", + "@firebase/installations": "0.6.12", "@firebase/messaging-interop-types": "0.2.3", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -571,104 +1219,104 @@ "@firebase/app": "0.x" } }, - "node_modules/@firebase/messaging-compat": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.15.tgz", - "integrity": "sha512-mEKKASRvRWq1aBNHgioGsOYR2c5nBZpO7k90K794zjKe0WkGNf0k7PLs5SlCf8FKnzumEkhTAp/SjYxovuxa8A==", + "node_modules/firebase/node_modules/@firebase/messaging-compat": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.16.tgz", + "integrity": "sha512-9HZZ88Ig3zQ0ok/Pwt4gQcNsOhoEy8hDHoGsV1am6ulgMuGuDVD2gl11Lere2ksL+msM12Lddi2x/7TCqmODZw==", "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/messaging": "0.12.15", - "@firebase/util": "1.10.2", + "@firebase/component": "0.6.12", + "@firebase/messaging": "0.12.16", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/messaging-interop-types": { + "node_modules/firebase/node_modules/@firebase/messaging-interop-types": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz", "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==" }, - "node_modules/@firebase/performance": { - "version": "0.6.11", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.11.tgz", - "integrity": "sha512-FlkJFeqLlIeh5T4Am3uE38HVzggliDIEFy/fErEc1faINOUFCb6vQBEoNZGaXvRnTR8lh3X/hP7tv37C7BsK9g==", + "node_modules/firebase/node_modules/@firebase/performance": { + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.12.tgz", + "integrity": "sha512-8mYL4z2jRlKXAi2hjk4G7o2sQLnJCCuTbyvti/xmHf5ZvOIGB01BZec0aDuBIXO+H1MLF62dbye/k91Fr+yc8g==", "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/installations": "0.6.11", + "@firebase/component": "0.6.12", + "@firebase/installations": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, - "node_modules/@firebase/performance-compat": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.11.tgz", - "integrity": "sha512-DqeNBy51W2xzlklyC7Ht9JQ94HhTA08PCcM4MDeyG/ol3fqum/+YgtHWQ2IQuduqH9afETthZqLwCZiSgY7hiA==", + "node_modules/firebase/node_modules/@firebase/performance-compat": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.12.tgz", + "integrity": "sha512-DyCbDTIwtBTGsEiQxTz/TD23a0na2nrDozceQ5kVkszyFYvliB0YK/9el0wAGIG91SqgTG9pxHtYErzfZc0VWw==", "dependencies": { - "@firebase/component": "0.6.11", + "@firebase/component": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/performance": "0.6.11", + "@firebase/performance": "0.6.12", "@firebase/performance-types": "0.2.3", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/performance-types": { + "node_modules/firebase/node_modules/@firebase/performance-types": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz", "integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==" }, - "node_modules/@firebase/remote-config": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.11.tgz", - "integrity": "sha512-9z0rgKuws2nj+7cdiqF+NY1QR4na6KnuOvP+jQvgilDOhGtKOcCMq5XHiu66i73A9kFhyU6QQ2pHXxcmaq1pBw==", + "node_modules/firebase/node_modules/@firebase/remote-config": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.5.0.tgz", + "integrity": "sha512-weiEbpBp5PBJTHUWR4GwI7ZacaAg68BKha5QnZ8Go65W4oQjEWqCW/rfskABI/OkrGijlL3CUmCB/SA6mVo0qA==", "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/installations": "0.6.11", + "@firebase/component": "0.6.12", + "@firebase/installations": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, - "node_modules/@firebase/remote-config-compat": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.11.tgz", - "integrity": "sha512-zfIjpwPrGuIOZDmduukN086qjhZ1LnbJi/iYzgua+2qeTlO0XdlE1v66gJPwygGB3TOhT0yb9EiUZ3nBNttMqg==", + "node_modules/firebase/node_modules/@firebase/remote-config-compat": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.12.tgz", + "integrity": "sha512-91jLWPtubIuPBngg9SzwvNCWzhMLcyBccmt7TNZP+y1cuYFNOWWHKUXQ3IrxCLB7WwLqQaEu7fTDAjHsTyBsSw==", "dependencies": { - "@firebase/component": "0.6.11", + "@firebase/component": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/remote-config": "0.4.11", - "@firebase/remote-config-types": "0.3.3", - "@firebase/util": "1.10.2", + "@firebase/remote-config": "0.5.0", + "@firebase/remote-config-types": "0.4.0", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/remote-config-types": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.3.tgz", - "integrity": "sha512-YlRI9CHxrk3lpQuFup9N1eohpwdWayKZUNZ/YeQ0PZoncJ66P32UsKUKqVXOaieTjJIOh7yH8JEzRdht5s+d6g==" + "node_modules/firebase/node_modules/@firebase/remote-config-types": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz", + "integrity": "sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg==" }, - "node_modules/@firebase/storage": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.4.tgz", - "integrity": "sha512-b1KaTTRiMupFurIhpGIbReaWev0k5O3ouTHkAPcEssT+FvU3q/1JwzvkX4+ZdB60Fc43Mbp8qQ1gWfT0Z2FP9Q==", + "node_modules/firebase/node_modules/@firebase/storage": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.5.tgz", + "integrity": "sha512-sB/7HNuW0N9tITyD0RxVLNCROuCXkml5i/iPqjwOGKC0xiUfpCOjBE+bb0ABMoN1qYZfqk0y9IuI2TdomjmkNw==", "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/util": "1.10.2", + "@firebase/component": "0.6.12", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { @@ -678,15 +1326,15 @@ "@firebase/app": "0.x" } }, - "node_modules/@firebase/storage-compat": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.14.tgz", - "integrity": "sha512-Ok5FmXJiapaNAOQ8W8qppnfwgP8540jw2B8M0c4TFZqF4BD+CoKBxW0dRtOuLNGadLhzqqkDZZZtkexxrveQqA==", + "node_modules/firebase/node_modules/@firebase/storage-compat": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.15.tgz", + "integrity": "sha512-Z9afjrK2O9o1ZHWCpprCGZ1BTc3BbvpZvi6tkSteC8H3W/fMM6x+RoSunlzD3hEVV5bkbwdJIqNClLMchvyoPA==", "dependencies": { - "@firebase/component": "0.6.11", - "@firebase/storage": "0.13.4", + "@firebase/component": "0.6.12", + "@firebase/storage": "0.13.5", "@firebase/storage-types": "0.8.3", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { @@ -696,7 +1344,7 @@ "@firebase/app-compat": "0.x" } }, - "node_modules/@firebase/storage-types": { + "node_modules/firebase/node_modules/@firebase/storage-types": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz", "integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==", @@ -705,10 +1353,10 @@ "@firebase/util": "1.x" } }, - "node_modules/@firebase/util": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.2.tgz", - "integrity": "sha512-qnSHIoE9FK+HYnNhTI8q14evyqbc/vHRivfB4TgCIUOl4tosmKSQlp7ltymOlMP4xVIJTg5wrkfcZ60X4nUf7Q==", + "node_modules/firebase/node_modules/@firebase/util": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.3.tgz", + "integrity": "sha512-wfoF5LTy0m2ufUapV0ZnpcGQvuavTbJ5Qr1Ze9OJGL70cSMvhDyjS4w2121XdA3lGZSTOsDOyGhpoDtYwck85A==", "dependencies": { "tslib": "^2.1.0" }, @@ -716,15 +1364,15 @@ "node": ">=18.0.0" } }, - "node_modules/@firebase/vertexai": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.2.tgz", - "integrity": "sha512-4dC9m2nD0tkfKJT5v+i27tELrmUePjFXW3CDAxhVHUEv647B2R7kqpGQnyPkNEeaXkCr76THe7GGg35EWn4lDw==", + "node_modules/firebase/node_modules/@firebase/vertexai": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.3.tgz", + "integrity": "sha512-SQHg/RPb3LwQs/xiLcvAZYz9NXyDSZUIIwvgsKh6e4wdULAfyPCZIu6Y2ZYIhZLfk9Q44cKZ+++7RPTaqQJdYA==", "dependencies": { "@firebase/app-check-interop-types": "0.3.3", - "@firebase/component": "0.6.11", + "@firebase/component": "0.6.12", "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.2", + "@firebase/util": "1.10.3", "tslib": "^2.1.0" }, "engines": { @@ -735,12 +1383,12 @@ "@firebase/app-types": "0.x" } }, - "node_modules/@firebase/webchannel-wrapper": { + "node_modules/firebase/node_modules/@firebase/webchannel-wrapper": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz", "integrity": "sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==" }, - "node_modules/@grpc/grpc-js": { + "node_modules/firebase/node_modules/@grpc/grpc-js": { "version": "1.9.15", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", @@ -752,7 +1400,7 @@ "node": "^8.13.0 || >=10.10.0" } }, - "node_modules/@grpc/proto-loader": { + "node_modules/firebase/node_modules/@grpc/proto-loader": { "version": "0.7.13", "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", @@ -769,32 +1417,27 @@ "node": ">=6" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@protobufjs/aspromise": { + "node_modules/firebase/node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" }, - "node_modules/@protobufjs/base64": { + "node_modules/firebase/node_modules/@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" }, - "node_modules/@protobufjs/codegen": { + "node_modules/firebase/node_modules/@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" }, - "node_modules/@protobufjs/eventemitter": { + "node_modules/firebase/node_modules/@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" }, - "node_modules/@protobufjs/fetch": { + "node_modules/firebase/node_modules/@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", @@ -803,121 +1446,40 @@ "@protobufjs/inquire": "^1.1.0" } }, - "node_modules/@protobufjs/float": { + "node_modules/firebase/node_modules/@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" }, - "node_modules/@protobufjs/inquire": { + "node_modules/firebase/node_modules/@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" }, - "node_modules/@protobufjs/path": { + "node_modules/firebase/node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" }, - "node_modules/@protobufjs/pool": { + "node_modules/firebase/node_modules/@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" }, - "node_modules/@protobufjs/utf8": { + "node_modules/firebase/node_modules/@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, - "node_modules/@schematics/angular": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.1.0.tgz", - "integrity": "sha512-ygSnRtd/DQg+V4tsWH/44waXSUv2d8iq+R6phAJ72JRiRZKbcQxkj1Rsar/9yfxEXC+xz+0HE5Rb5XJ2Kh7T5w==", - "dependencies": { - "@angular-devkit/core": "19.1.0", - "@angular-devkit/schematics": "19.1.0", - "jsonc-parser": "3.3.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@tanstack/angular-query-experimental": { - "version": "5.64.1", - "resolved": "https://registry.npmjs.org/@tanstack/angular-query-experimental/-/angular-query-experimental-5.64.1.tgz", - "integrity": "sha512-JMLxcQgdXATg54ZE9hdsGGb5V0ZKbfwnuQsyOHSU9bVaSpg0o/ps1Z8ngRbdOAjVuvjYbkte/Cn6aIpt29BaCQ==", - "dependencies": { - "@tanstack/query-core": "5.64.1", - "@tanstack/query-devtools": "5.62.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "@angular/common": ">=16.0.0", - "@angular/core": ">=16.0.0" - } - }, - "node_modules/@tanstack/query-core": { - "version": "5.64.1", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.64.1.tgz", - "integrity": "sha512-978Wx4Wl4UJZbmvU/rkaM9cQtXXrbhK0lsz/UZhYIbyKYA8E4LdomTwyh2GHZ4oU0BKKoDH4YlKk2VscCUgNmg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/query-devtools": { - "version": "5.62.16", - "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.62.16.tgz", - "integrity": "sha512-3ff6UBJr0H3nIhfLSl9911rvKqXf0u4B58jl0uYdDWLqPk9pCvYIbxC35cGxK2+8INl4IaFVUHb/IdgWrNkg3Q==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@types/node": { - "version": "22.10.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.6.tgz", - "integrity": "sha512-qNiuwC4ZDAUNcY47xgaSuS92cjf8JbSUoaKS77bmLG1rU7MlATVSiw/IlrjtIyyskXBZ8KkNfjK/P5na7rgXbQ==", + "node_modules/firebase/node_modules/@types/node": { + "version": "22.10.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", + "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", "dependencies": { "undici-types": "~6.20.0" } }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ansi-regex": { + "node_modules/firebase/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", @@ -925,7 +1487,7 @@ "node": ">=8" } }, - "node_modules/ansi-styles": { + "node_modules/firebase/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -939,96 +1501,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { + "node_modules/firebase/node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", @@ -1041,15 +1514,7 @@ "node": ">=12" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/color-convert": { + "node_modules/firebase/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -1060,56 +1525,25 @@ "node": ">=7.0.0" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", - "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ] - }, - "node_modules/faye-websocket": { + "node_modules/firebase/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/firebase/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/firebase/node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/firebase/node_modules/faye-websocket": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", @@ -1120,42 +1554,7 @@ "node": ">=0.8.0" } }, - "node_modules/firebase": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.1.0.tgz", - "integrity": "sha512-3OoNW3vBXmBLYJvcwbPCwfluptbDVp2zZYjrfHPVFAXfPgmyy/LWjidt+Sw2WNvRelsG0v++WN2Wor6J3OwDRg==", - "dependencies": { - "@firebase/analytics": "0.10.10", - "@firebase/analytics-compat": "0.2.16", - "@firebase/app": "0.10.17", - "@firebase/app-check": "0.8.10", - "@firebase/app-check-compat": "0.3.17", - "@firebase/app-compat": "0.2.47", - "@firebase/app-types": "0.9.3", - "@firebase/auth": "1.8.1", - "@firebase/auth-compat": "0.5.16", - "@firebase/data-connect": "0.1.3", - "@firebase/database": "1.0.10", - "@firebase/database-compat": "2.0.1", - "@firebase/firestore": "4.7.5", - "@firebase/firestore-compat": "0.3.40", - "@firebase/functions": "0.12.0", - "@firebase/functions-compat": "0.3.17", - "@firebase/installations": "0.6.11", - "@firebase/installations-compat": "0.2.11", - "@firebase/messaging": "0.12.15", - "@firebase/messaging-compat": "0.2.15", - "@firebase/performance": "0.6.11", - "@firebase/performance-compat": "0.2.11", - "@firebase/remote-config": "0.4.11", - "@firebase/remote-config-compat": "0.2.11", - "@firebase/storage": "0.13.4", - "@firebase/storage-compat": "0.3.14", - "@firebase/util": "1.10.2", - "@firebase/vertexai": "1.0.2" - } - }, - "node_modules/get-caller-file": { + "node_modules/firebase/node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", @@ -1163,49 +1562,17 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/http-parser-js": { + "node_modules/firebase/node_modules/http-parser-js": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz", "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==" }, - "node_modules/idb": { + "node_modules/firebase/node_modules/idb": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-fullwidth-code-point": { + "node_modules/firebase/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", @@ -1213,124 +1580,17 @@ "node": ">=8" } }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" - }, - "node_modules/lodash.camelcase": { + "node_modules/firebase/node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/long": { + "node_modules/firebase/node_modules/long": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/long/-/long-5.2.4.tgz", "integrity": "sha512-qtzLbJE8hq7VabR3mISmVGtoXP8KGc2Z/AT8OuqlYD7JTR3oqrgwdjnk07wpj1twXxYmgDXgoKVWUG/fReSzHg==" }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/protobufjs": { + "node_modules/firebase/node_modules/protobufjs": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", @@ -1353,20 +1613,7 @@ "node": ">=12.0.0" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-directory": { + "node_modules/firebase/node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", @@ -1374,44 +1621,7 @@ "node": ">=0.10.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/rxfire": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/rxfire/-/rxfire-6.1.0.tgz", - "integrity": "sha512-NezdjeY32VZcCuGO0bbb8H8seBsJSCaWdUwGsHNzUcAOHR0VGpzgPtzjuuLXr8R/iemkqSzbx/ioS7VwV43ynA==", - "peerDependencies": { - "firebase": "^9.0.0 || ^10.0.0 || ^11.0.0", - "rxjs": "^6.0.0 || ^7.0.0" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { + "node_modules/firebase/node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", @@ -1430,28 +1640,7 @@ } ] }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { + "node_modules/firebase/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", @@ -1464,7 +1653,7 @@ "node": ">=8" } }, - "node_modules/strip-ansi": { + "node_modules/firebase/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", @@ -1475,41 +1664,12 @@ "node": ">=8" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/undici-types": { + "node_modules/firebase/node_modules/undici-types": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/websocket-driver": { + "node_modules/firebase/node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", @@ -1522,7 +1682,7 @@ "node": ">=0.8.0" } }, - "node_modules/websocket-extensions": { + "node_modules/firebase/node_modules/websocket-extensions": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", @@ -1530,7 +1690,7 @@ "node": ">=0.8.0" } }, - "node_modules/wrap-ansi": { + "node_modules/firebase/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", @@ -1546,7 +1706,7 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/y18n": { + "node_modules/firebase/node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", @@ -1554,7 +1714,7 @@ "node": ">=10" } }, - "node_modules/yargs": { + "node_modules/firebase/node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", @@ -1571,7 +1731,7 @@ "node": ">=12" } }, - "node_modules/yargs-parser": { + "node_modules/firebase/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", @@ -1579,6 +1739,28 @@ "node": ">=12" } }, + "node_modules/rxfire": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/rxfire/-/rxfire-6.1.0.tgz", + "integrity": "sha512-NezdjeY32VZcCuGO0bbb8H8seBsJSCaWdUwGsHNzUcAOHR0VGpzgPtzjuuLXr8R/iemkqSzbx/ioS7VwV43ynA==", + "peerDependencies": { + "firebase": "^9.0.0 || ^10.0.0 || ^11.0.0", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, "node_modules/zone.js": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.0.tgz", diff --git a/packages/angular/package.json b/packages/angular/package.json index cca93451..f3696e9f 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -3,14 +3,24 @@ "version": "0.0.1", "description": "Tanstack Query bindings for Firebase and Angular", "type": "module", + "files": [ + "dist" + ], "scripts": { "build": "tsup", "test": "echo \"Error: no test specified\" && exit 1" }, + "typings": "./dist/index.d.ts", + "module": "./dist/index.js", "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, "./data-connect": { - "types": "./dist/data-connect/index.d.ts", - "import": "./dist/data-connect/index.js" + "import": "./data-connect/index.js", + "types": "./data-connect/index.d.ts", + "default": "./data-connect/index.js" } }, "author": "", diff --git a/packages/angular/src/data-connect/index.ts b/packages/angular/src/data-connect/index.ts index 2fd8dc39..04a456d1 100644 --- a/packages/angular/src/data-connect/index.ts +++ b/packages/angular/src/data-connect/index.ts @@ -1,7 +1,7 @@ -import { CreateMutationOptions, CreateMutationResult, CreateQueryOptions, injectMutation, injectQueries, injectQuery, QueryFunction, QueryKey, } from '@tanstack/angular-query-experimental'; +import { CreateMutationOptions, CreateMutationResult, CreateQueryOptions, CreateQueryResult, injectMutation, injectQueries, injectQuery, QueryFunction, QueryKey, } from '@tanstack/angular-query-experimental'; import { executeMutation, executeQuery, MutationRef, QueryRef, type DataConnect } from 'firebase/data-connect'; import { FirebaseError } from 'firebase/app'; -import { FlattenedMutationResult } from '../../../react/src/data-connect'; +import { FlattenedMutationResult, FlattenedQueryResult } from '../../../react/src/data-connect'; type DataConnectMutationOptions = CreateMutationOptions & { invalidate?: QueryKey | QueryRef[] }; @@ -37,12 +37,21 @@ export function injectDataConnectMutation( } return injectMutation(fdcOptionsFn); } -interface CreateDataConnectQueryOptions extends Omit, 'queryFn'> { - queryFn: () => QueryRef +interface CreateDataConnectQueryOptions + extends Omit< + CreateQueryOptions< + FlattenedQueryResult, + FirebaseError, + FlattenedQueryResult, + QueryKey + >, + "queryFn" + > { + queryFn: () => QueryRef; } export function injectDataConnectQuery( optionsFn: () => CreateDataConnectQueryOptions -) { +): CreateQueryResult, FirebaseError> { function fdcOptionsFn() { const options = optionsFn(); const modifiedFn = () => { @@ -53,7 +62,7 @@ export function injectDataConnectQuery( ...data, ...rest } - }) as Promise>; + }) as Promise>; }; return { diff --git a/packages/angular/tsconfig.json b/packages/angular/tsconfig.json index cb0abdf9..c17ccc04 100644 --- a/packages/angular/tsconfig.json +++ b/packages/angular/tsconfig.json @@ -8,6 +8,7 @@ "strict": true, "esModuleInterop": true, "skipLibCheck": true, + "resolveJsonModule": true, "forceConsistentCasingInFileNames": true, "types": ["vitest/globals"], "paths": { @@ -15,5 +16,5 @@ "@/dataconnect/*": ["../../dataconnect-sdk/js/*"] } }, - "include": ["src", "utils.tsx"] + "include": ["src", "utils.tsx", "./package.json"] } diff --git a/packages/angular/tsup.config.ts b/packages/angular/tsup.config.ts index d473def8..7c11b030 100644 --- a/packages/angular/tsup.config.ts +++ b/packages/angular/tsup.config.ts @@ -5,10 +5,8 @@ export default defineConfig({ entry: [`src/data-connect/index.ts`, 'src/index.ts'], format: ["esm"], dts: true, // generates .d.ts files - outDir: "dist", + outDir: "./", esbuildOptions(options, context) { options.outbase = './src'; }, - // splitting: false, // Disable code splitting to generate distinct files - clean: true, }); From 5909920acc738a5f5b0e9b60e7debc19a05ecd03 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 17 Jan 2025 15:32:37 -0800 Subject: [PATCH 04/10] First pass at angular query --- packages/angular/package-lock.json | 13 ++ packages/angular/package.json | 4 +- packages/angular/src/data-connect/index.ts | 166 ++++++++++++++------- 3 files changed, 130 insertions(+), 53 deletions(-) diff --git a/packages/angular/package-lock.json b/packages/angular/package-lock.json index a37ca2c7..0df9d20d 100644 --- a/packages/angular/package-lock.json +++ b/packages/angular/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@angular/core": "^19.1.0", "@angular/fire": "^19.0.0-rc.5", + "@tanstack-query-firebase/angular": "file:../../../../bin/tanstack-query-firebase-angular-0.0.1.tgz", "@tanstack/angular-query-experimental": "^5.64.1", "firebase": "^11.1.0" } @@ -756,6 +757,18 @@ "node": ">= 8" } }, + "node_modules/@tanstack-query-firebase/angular": { + "version": "0.0.1", + "resolved": "file:../../../../bin/tanstack-query-firebase-angular-0.0.1.tgz", + "integrity": "sha512-9TpELHRj9UGhuR/hKCMsDo7uoxampon6HX6v4UMxaLqA8p3jvnG2cS1DKaRdnpOvBX11CuRztv9iwVl3yCqFHw==", + "license": "ISC", + "dependencies": { + "@angular/core": "^19.1.0", + "@angular/fire": "^19.0.0-rc.5", + "@tanstack/angular-query-experimental": "^5.64.1", + "firebase": "^11.1.0" + } + }, "node_modules/@tanstack/angular-query-experimental": { "version": "5.64.1", "resolved": "https://registry.npmjs.org/@tanstack/angular-query-experimental/-/angular-query-experimental-5.64.1.tgz", diff --git a/packages/angular/package.json b/packages/angular/package.json index f3696e9f..43f1acc0 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -4,10 +4,12 @@ "description": "Tanstack Query bindings for Firebase and Angular", "type": "module", "files": [ - "dist" + "dist", + "data-connect" ], "scripts": { "build": "tsup", + "watch": "tsup --watch", "test": "echo \"Error: no test specified\" && exit 1" }, "typings": "./dist/index.d.ts", diff --git a/packages/angular/src/data-connect/index.ts b/packages/angular/src/data-connect/index.ts index 04a456d1..7c5cbd32 100644 --- a/packages/angular/src/data-connect/index.ts +++ b/packages/angular/src/data-connect/index.ts @@ -1,41 +1,98 @@ -import { CreateMutationOptions, CreateMutationResult, CreateQueryOptions, CreateQueryResult, injectMutation, injectQueries, injectQuery, QueryFunction, QueryKey, } from '@tanstack/angular-query-experimental'; -import { executeMutation, executeQuery, MutationRef, QueryRef, type DataConnect } from 'firebase/data-connect'; -import { FirebaseError } from 'firebase/app'; -import { FlattenedMutationResult, FlattenedQueryResult } from '../../../react/src/data-connect'; -type DataConnectMutationOptions = CreateMutationOptions & { - invalidate?: QueryKey | QueryRef[] -}; +import { + CreateMutationOptions, + CreateMutationResult, + CreateQueryOptions, + CreateQueryResult, + injectMutation, + injectQueries, + injectQuery, + QueryClient, + QueryKey, +} from "@tanstack/angular-query-experimental"; +import { + executeMutation, + executeQuery, + MutationRef, + QueryRef, + type DataConnect, +} from "firebase/data-connect"; +import { FirebaseError } from "firebase/app"; +import { + FlattenedMutationResult, + FlattenedQueryResult, +} from "../../../react/src/data-connect"; +import { assertInInjectionContext, inject, signal } from "@angular/core"; +function getQueryKey(queryRef: QueryRef) { + return [ + queryRef.name, + queryRef.variables + ] +} +type DataConnectMutationOptions = + CreateMutationOptions & { + invalidate?: QueryKey | QueryRef[]; + }; -type MutationsOptionsFn = DataConnectMutationOptions, FirebaseError, Variables, Arguments> & { - dataConnect?: DataConnect; +type MutationsOptionsFn< + Data, + Variables, + Arguments = void +> = DataConnectMutationOptions< + FlattenedMutationResult, + FirebaseError, + Variables, + Arguments +> & { + dataConnect?: DataConnect; }; export function injectDataConnectMutation( - mutationFn: (args: Arguments) => MutationRef, - optionsFn?: () => MutationsOptionsFn -): CreateMutationResult, FirebaseError, Arguments> { - function fdcOptionsFn(): DataConnectMutationOptions, FirebaseError, Variables, Arguments> { - const modifiedFn = (args: Arguments) => { - const ref: MutationRef = mutationFn(args); - return executeMutation(ref).then(res => { - const { data, ...rest} = res; - return { - ...data, - ...rest - } - }) as Promise>; - }; - if(optionsFn) { - const options = optionsFn(); - return { - mutationFn: modifiedFn, - ...options, - } + mutationFn: (args: Arguments) => MutationRef, + optionsFn?: () => MutationsOptionsFn +): CreateMutationResult< + FlattenedMutationResult, + FirebaseError, + Arguments +> { + const fdcOptionsFn: () => DataConnectMutationOptions< + FlattenedMutationResult, + FirebaseError, + Variables, + Arguments + > = () => { + const queryClient = inject(QueryClient); + const modifiedFn = (args: Arguments, options?: MutationsOptionsFn) => { + const ref: MutationRef = mutationFn(args); + const keys = options?.invalidate?.map(qk => { + let key = qk; + if('name' in (qk as Object)) { + const queryKey = getQueryKey((qk as QueryRef)); + console.log(queryKey); + key = queryKey; } + queryClient.invalidateQueries({ queryKey: key}); + }); + return executeMutation(ref).then((res) => { + const { data, ...rest } = res; return { - mutationFn: modifiedFn - } + ...data, + ...rest, + }; + }) as Promise>; + }; + if (optionsFn) { + const options = optionsFn(); + return { + mutationFn: (args: Arguments) => { + return modifiedFn(args, options); + }, + ...options, + }; } - return injectMutation(fdcOptionsFn); + return { + mutationFn: modifiedFn, + }; + } + return injectMutation(fdcOptionsFn); } interface CreateDataConnectQueryOptions extends Omit< @@ -45,30 +102,35 @@ interface CreateDataConnectQueryOptions FlattenedQueryResult, QueryKey >, - "queryFn" + "queryFn"| + "queryKey" > { queryFn: () => QueryRef; } export function injectDataConnectQuery( - optionsFn: () => CreateDataConnectQueryOptions + optionsFn: () => CreateDataConnectQueryOptions ): CreateQueryResult, FirebaseError> { - function fdcOptionsFn() { - const options = optionsFn(); - const modifiedFn = () => { - const ref: QueryRef = options.queryFn(); - return executeQuery(ref).then(res => { - const { data, ...rest} = res; - return { - ...data, - ...rest - } - }) as Promise>; - }; - + const queryKey = signal([]) + function fdcOptionsFn() { + const options = optionsFn(); + const modifiedFn = () => { + const ref: QueryRef = options.queryFn(); + queryKey.set([ref.name, ref.variables]) + console.log(queryKey()); + return executeQuery(ref).then((res) => { + const { data, ...rest } = res; return { - ...options, - queryFn: modifiedFn, - } - } - return injectQuery(fdcOptionsFn); + ...data, + ...rest, + }; + }) as Promise>; + }; + + return { + queryKey: queryKey(), + ...options, + queryFn: modifiedFn, + }; + } + return injectQuery(fdcOptionsFn); } From e184206a4510bf105674f5a450fb31143a3e7aa8 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 17 Jan 2025 15:49:27 -0800 Subject: [PATCH 05/10] Fixed auto-reload queries --- packages/angular/src/data-connect/index.ts | 102 +++++++++------------ 1 file changed, 45 insertions(+), 57 deletions(-) diff --git a/packages/angular/src/data-connect/index.ts b/packages/angular/src/data-connect/index.ts index 7c5cbd32..8a30290f 100644 --- a/packages/angular/src/data-connect/index.ts +++ b/packages/angular/src/data-connect/index.ts @@ -23,75 +23,64 @@ import { } from "../../../react/src/data-connect"; import { assertInInjectionContext, inject, signal } from "@angular/core"; function getQueryKey(queryRef: QueryRef) { - return [ - queryRef.name, - queryRef.variables - ] + return [queryRef.name, queryRef.variables]; } -type DataConnectMutationOptions = - CreateMutationOptions & { - invalidate?: QueryKey | QueryRef[]; - }; +type DataConnectMutationOptions = Omit< + CreateMutationOptions, + "mutationFn" +> & { + invalidate?: QueryKey | QueryRef[]; + dataConnect?: DataConnect; + mutationFn: (args: Arguments) => MutationRef; +}; type MutationsOptionsFn< Data, Variables, Arguments = void -> = DataConnectMutationOptions< - FlattenedMutationResult, - FirebaseError, - Variables, - Arguments -> & { - dataConnect?: DataConnect; -}; +> = DataConnectMutationOptions; export function injectDataConnectMutation( - mutationFn: (args: Arguments) => MutationRef, - optionsFn?: () => MutationsOptionsFn + optionsFn: () => MutationsOptionsFn ): CreateMutationResult< FlattenedMutationResult, FirebaseError, Arguments > { - const fdcOptionsFn: () => DataConnectMutationOptions< - FlattenedMutationResult, - FirebaseError, - Variables, - Arguments - > = () => { + const fdcOptionsFn = () => { const queryClient = inject(QueryClient); - const modifiedFn = (args: Arguments, options?: MutationsOptionsFn) => { - const ref: MutationRef = mutationFn(args); - const keys = options?.invalidate?.map(qk => { - let key = qk; - if('name' in (qk as Object)) { - const queryKey = getQueryKey((qk as QueryRef)); - console.log(queryKey); - key = queryKey; - } - queryClient.invalidateQueries({ queryKey: key}); - }); - return executeMutation(ref).then((res) => { - const { data, ...rest } = res; - return { - ...data, - ...rest, - }; - }) as Promise>; - }; - if (optionsFn) { + const modifiedFn = (args: Arguments) => { const options = optionsFn(); - return { - mutationFn: (args: Arguments) => { - return modifiedFn(args, options); - }, - ...options, - }; - } + const ref: MutationRef = options.mutationFn(args); + + return executeMutation(ref) + .then((res) => { + const { data, ...rest } = res; + return { + ...data, + ...rest, + }; + }) + .then((ret) => { + options?.invalidate?.forEach((qk) => { + let key = qk; + if ("name" in (qk as Object)) { + const queryKey = getQueryKey(qk as QueryRef); + key = queryKey; + } + console.log("invalidating", key); + queryClient.invalidateQueries({ + queryKey: ["listAllMovies", undefined], + }); + }); + return ret; + }) as Promise>; + }; + return { + ...optionsFn(), mutationFn: modifiedFn, }; - } + }; return injectMutation(fdcOptionsFn); } interface CreateDataConnectQueryOptions @@ -102,20 +91,19 @@ interface CreateDataConnectQueryOptions FlattenedQueryResult, QueryKey >, - "queryFn"| - "queryKey" + "queryFn" | "queryKey" > { queryFn: () => QueryRef; } export function injectDataConnectQuery( optionsFn: () => CreateDataConnectQueryOptions ): CreateQueryResult, FirebaseError> { - const queryKey = signal([]) - function fdcOptionsFn() { + const queryKey = signal([]); + function fdcOptionsFn() { const options = optionsFn(); const modifiedFn = () => { const ref: QueryRef = options.queryFn(); - queryKey.set([ref.name, ref.variables]) + queryKey.set([ref.name, ref.variables]); console.log(queryKey()); return executeQuery(ref).then((res) => { const { data, ...rest } = res; From f91922d6a2a6a315a78f3c6a437a666ed7cc3b3b Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 21 Jan 2025 17:44:16 -0800 Subject: [PATCH 06/10] second run-through of tanstack query --- .../js/default-connector/esm/index.esm.js | 2 +- .../js/default-connector/index.cjs.js | 2 +- .../js/default-connector/index.d.ts | 26 ++-- .../js/default-connector/package.json | 10 +- dataconnect/connector/connector.yaml | 1 + packages/angular/src/data-connect/index.ts | 127 ++++++++---------- packages/react/package.json | 8 +- 7 files changed, 84 insertions(+), 92 deletions(-) diff --git a/dataconnect-sdk/js/default-connector/esm/index.esm.js b/dataconnect-sdk/js/default-connector/esm/index.esm.js index 96abe7c5..f0bc4d83 100644 --- a/dataconnect-sdk/js/default-connector/esm/index.esm.js +++ b/dataconnect-sdk/js/default-connector/esm/index.esm.js @@ -1,4 +1,4 @@ -import { getDataConnect, queryRef, executeQuery, mutationRef, executeMutation, validateArgs } from 'firebase/data-connect'; +import { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } from 'firebase/data-connect'; export const connectorConfig = { connector: 'default', diff --git a/dataconnect-sdk/js/default-connector/index.cjs.js b/dataconnect-sdk/js/default-connector/index.cjs.js index 012bc15e..cbb24321 100644 --- a/dataconnect-sdk/js/default-connector/index.cjs.js +++ b/dataconnect-sdk/js/default-connector/index.cjs.js @@ -1,4 +1,4 @@ -const { getDataConnect, queryRef, executeQuery, mutationRef, executeMutation, validateArgs } = require('firebase/data-connect'); +const { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } = require('firebase/data-connect'); const connectorConfig = { connector: 'default', diff --git a/dataconnect-sdk/js/default-connector/index.d.ts b/dataconnect-sdk/js/default-connector/index.d.ts index 2d01de34..077a3f8a 100644 --- a/dataconnect-sdk/js/default-connector/index.d.ts +++ b/dataconnect-sdk/js/default-connector/index.d.ts @@ -10,7 +10,6 @@ export type Int64String = string; export type DateString = string; - export interface CreateMovieData { movie_insert: Movie_Key; } @@ -72,48 +71,47 @@ export interface UpsertMovieVariables { } - /* Allow users to create refs without passing in DataConnect */ export function createMovieRef(vars: CreateMovieVariables): MutationRef; /* Allow users to pass in custom DataConnect instances */ -export function createMovieRef(dc: DataConnect, vars: CreateMovieVariables): MutationRef; +export function createMovieRef(dc: DataConnect, vars: CreateMovieVariables): MutationRef; export function createMovie(vars: CreateMovieVariables): MutationPromise; -export function createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; +export function createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; /* Allow users to create refs without passing in DataConnect */ export function upsertMovieRef(vars: UpsertMovieVariables): MutationRef; /* Allow users to pass in custom DataConnect instances */ -export function upsertMovieRef(dc: DataConnect, vars: UpsertMovieVariables): MutationRef; +export function upsertMovieRef(dc: DataConnect, vars: UpsertMovieVariables): MutationRef; export function upsertMovie(vars: UpsertMovieVariables): MutationPromise; -export function upsertMovie(dc: DataConnect, vars: UpsertMovieVariables): MutationPromise; +export function upsertMovie(dc: DataConnect, vars: UpsertMovieVariables): MutationPromise; /* Allow users to create refs without passing in DataConnect */ export function deleteMovieRef(vars: DeleteMovieVariables): MutationRef; /* Allow users to pass in custom DataConnect instances */ -export function deleteMovieRef(dc: DataConnect, vars: DeleteMovieVariables): MutationRef; +export function deleteMovieRef(dc: DataConnect, vars: DeleteMovieVariables): MutationRef; export function deleteMovie(vars: DeleteMovieVariables): MutationPromise; -export function deleteMovie(dc: DataConnect, vars: DeleteMovieVariables): MutationPromise; +export function deleteMovie(dc: DataConnect, vars: DeleteMovieVariables): MutationPromise; /* Allow users to create refs without passing in DataConnect */ -export function listMoviesRef(): QueryRef;/* Allow users to pass in custom DataConnect instances */ -export function listMoviesRef(dc: DataConnect): QueryRef; +export function listMoviesRef(): QueryRef; +/* Allow users to pass in custom DataConnect instances */ +export function listMoviesRef(dc: DataConnect): QueryRef; export function listMovies(): QueryPromise; -export function listMovies(dc: DataConnect): QueryPromise; +export function listMovies(dc: DataConnect): QueryPromise; /* Allow users to create refs without passing in DataConnect */ export function getMovieByIdRef(vars: GetMovieByIdVariables): QueryRef; /* Allow users to pass in custom DataConnect instances */ -export function getMovieByIdRef(dc: DataConnect, vars: GetMovieByIdVariables): QueryRef; +export function getMovieByIdRef(dc: DataConnect, vars: GetMovieByIdVariables): QueryRef; export function getMovieById(vars: GetMovieByIdVariables): QueryPromise; -export function getMovieById(dc: DataConnect, vars: GetMovieByIdVariables): QueryPromise; - +export function getMovieById(dc: DataConnect, vars: GetMovieByIdVariables): QueryPromise; diff --git a/dataconnect-sdk/js/default-connector/package.json b/dataconnect-sdk/js/default-connector/package.json index d77efcc5..156155dd 100644 --- a/dataconnect-sdk/js/default-connector/package.json +++ b/dataconnect-sdk/js/default-connector/package.json @@ -17,9 +17,17 @@ "require": "./index.cjs.js", "default": "./esm/index.esm.js" }, + "./react": { + "types": "./react/index.d.ts", + "import": "./react/esm/index.esm.js", + "default": "./react/esm/index.esm.js" + }, "./package.json": "./package.json" }, "peerDependencies": { - "firebase": "^10.14.0 || ^11.0.0" + "firebase": "^10.14.0 || ^11.0.0", + "@tanstack-query-firebase/react": "^0.1.4", + "@tanstack/react-query": "^5" + } } \ No newline at end of file diff --git a/dataconnect/connector/connector.yaml b/dataconnect/connector/connector.yaml index 3e518c87..5b7e5f00 100644 --- a/dataconnect/connector/connector.yaml +++ b/dataconnect/connector/connector.yaml @@ -4,3 +4,4 @@ generate: outputDir: ../../dataconnect-sdk/js/default-connector package: "@dataconnect/default-connector" packageJsonDir: ../.. + react: true diff --git a/packages/angular/src/data-connect/index.ts b/packages/angular/src/data-connect/index.ts index 8a30290f..56b31725 100644 --- a/packages/angular/src/data-connect/index.ts +++ b/packages/angular/src/data-connect/index.ts @@ -4,53 +4,77 @@ import { CreateQueryOptions, CreateQueryResult, injectMutation, - injectQueries, injectQuery, QueryClient, QueryKey, } from "@tanstack/angular-query-experimental"; import { + DataConnect, executeMutation, executeQuery, MutationRef, + MutationResult, QueryRef, - type DataConnect, + QueryResult, } from "firebase/data-connect"; import { FirebaseError } from "firebase/app"; -import { - FlattenedMutationResult, - FlattenedQueryResult, -} from "../../../react/src/data-connect"; -import { assertInInjectionContext, inject, signal } from "@angular/core"; + +import { inject, signal } from "@angular/core"; function getQueryKey(queryRef: QueryRef) { return [queryRef.name, queryRef.variables]; } -type DataConnectMutationOptions = Omit< - CreateMutationOptions, - "mutationFn" -> & { +type FlattenedQueryResult = Omit, "data" | "toJSON"> & Data; +interface CreateDataConnectQueryOptions extends Omit, FirebaseError, FlattenedQueryResult, QueryKey>, "queryFn" | "queryKey"> { + queryFn: () => QueryRef; +} + +export function injectDataConnectQuery(queryRefOrOptionsFn: QueryRef | (() => CreateDataConnectQueryOptions)) : CreateQueryResult, FirebaseError> { + const queryKey = signal([]); + function fdcOptionsFn() { + const passedInOptions = typeof queryRefOrOptionsFn === 'function' ? queryRefOrOptionsFn() : undefined; + + const modifiedFn = () => { + const ref: QueryRef =passedInOptions?.queryFn() || queryRefOrOptionsFn as QueryRef; + queryKey.set([ref.name, ref.variables]); + console.log('mutationfn!') + return executeQuery(ref).then((res) => { + const { data, ...rest } = res; + return { + ...data, + ...rest, + }; + }) as Promise>; + }; +return { + queryKey: queryKey(), + ...passedInOptions, + queryFn: modifiedFn, + } + + } + return injectQuery(fdcOptionsFn); +} + +export type GeneratedSignature = (dc: DataConnect, vars: Variables) => MutationRef; +export type DataConnectMutationOptionsFn = () => Omit, "mutationFn"> & { invalidate?: QueryKey | QueryRef[]; dataConnect?: DataConnect; mutationFn: (args: Arguments) => MutationRef; -}; +} +export type DataConnectMutationOptionsUndefinedMutationFn = () => (Omit>, 'mutationFn'>); +export type FlattenedMutationResult = Omit, "data" | "toJSON"> & Data; -type MutationsOptionsFn< - Data, - Variables, - Arguments = void -> = DataConnectMutationOptions; -export function injectDataConnectMutation( - optionsFn: () => MutationsOptionsFn -): CreateMutationResult< - FlattenedMutationResult, - FirebaseError, - Arguments -> { - const fdcOptionsFn = () => { +export function injectDataConnectMutation(factoryFn: undefined, optionsFn: DataConnectMutationOptionsFn): CreateMutationResult, FirebaseError, Arguments>; +export function injectDataConnectMutation(factoryFn: GeneratedSignature): CreateMutationResult, FirebaseError, Arguments>; +export function injectDataConnectMutation(factoryFn: GeneratedSignature): CreateMutationResult, FirebaseError, Arguments>; +export function injectDataConnectMutation(factoryFn: GeneratedSignature, optionsFn?: DataConnectMutationOptionsUndefinedMutationFn): CreateMutationResult, FirebaseError, Arguments>; +export function injectDataConnectMutation(factoryFn: GeneratedSignature | undefined, optionsFn?: DataConnectMutationOptionsFn | DataConnectMutationOptionsUndefinedMutationFn):CreateMutationResult, FirebaseError, Arguments> { + const injectCb = () => { const queryClient = inject(QueryClient); + const providedOptions = optionsFn ? optionsFn() : undefined; const modifiedFn = (args: Arguments) => { - const options = optionsFn(); - const ref: MutationRef = options.mutationFn(args); + const dataConnect = inject(DataConnect); + const ref = (providedOptions && 'mutationFn' in providedOptions && providedOptions.mutationFn(args as Arguments)) || factoryFn!(dataConnect, args as Variables); return executeMutation(ref) .then((res) => { @@ -61,7 +85,7 @@ export function injectDataConnectMutation( }; }) .then((ret) => { - options?.invalidate?.forEach((qk) => { + providedOptions?.invalidate?.forEach((qk) => { let key = qk; if ("name" in (qk as Object)) { const queryKey = getQueryKey(qk as QueryRef); @@ -69,7 +93,7 @@ export function injectDataConnectMutation( } console.log("invalidating", key); queryClient.invalidateQueries({ - queryKey: ["listAllMovies", undefined], + queryKey: key, }); }); return ret; @@ -77,48 +101,9 @@ export function injectDataConnectMutation( }; return { - ...optionsFn(), + ...providedOptions, mutationFn: modifiedFn, }; }; - return injectMutation(fdcOptionsFn); -} -interface CreateDataConnectQueryOptions - extends Omit< - CreateQueryOptions< - FlattenedQueryResult, - FirebaseError, - FlattenedQueryResult, - QueryKey - >, - "queryFn" | "queryKey" - > { - queryFn: () => QueryRef; -} -export function injectDataConnectQuery( - optionsFn: () => CreateDataConnectQueryOptions -): CreateQueryResult, FirebaseError> { - const queryKey = signal([]); - function fdcOptionsFn() { - const options = optionsFn(); - const modifiedFn = () => { - const ref: QueryRef = options.queryFn(); - queryKey.set([ref.name, ref.variables]); - console.log(queryKey()); - return executeQuery(ref).then((res) => { - const { data, ...rest } = res; - return { - ...data, - ...rest, - }; - }) as Promise>; - }; - - return { - queryKey: queryKey(), - ...options, - queryFn: modifiedFn, - }; - } - return injectQuery(fdcOptionsFn); -} + return injectMutation(injectCb); +} \ No newline at end of file diff --git a/packages/react/package.json b/packages/react/package.json index 672e8149..7123ce02 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -36,13 +36,13 @@ ], "license": "Apache-2.0", "devDependencies": { + "@dataconnect/default-connector": "file:../../dataconnect-sdk/js/default-connector", "@testing-library/react": "^16.0.1", - "react": "^19.0.0", "@types/react": "^19.0.1", - "@dataconnect/default-connector": "workspace:*" + "react": "^19.0.0" }, "peerDependencies": { - "firebase": "^11", - "@tanstack/react-query": "^5" + "@tanstack/react-query": "^5", + "firebase": "^11" } } From 780559586a3bee4b3a5abb6727e31c32c5bcda96 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 21 Jan 2025 17:48:33 -0800 Subject: [PATCH 07/10] Added comments --- packages/angular/src/data-connect/index.ts | 165 +++++++++++++++++---- 1 file changed, 135 insertions(+), 30 deletions(-) diff --git a/packages/angular/src/data-connect/index.ts b/packages/angular/src/data-connect/index.ts index 56b31725..c2b372d3 100644 --- a/packages/angular/src/data-connect/index.ts +++ b/packages/angular/src/data-connect/index.ts @@ -9,7 +9,7 @@ import { QueryKey, } from "@tanstack/angular-query-experimental"; import { - DataConnect, + DataConnect, executeMutation, executeQuery, MutationRef, @@ -19,24 +19,50 @@ import { } from "firebase/data-connect"; import { FirebaseError } from "firebase/app"; -import { inject, signal } from "@angular/core"; +import { inject, signal } from "@angular/core"; function getQueryKey(queryRef: QueryRef) { return [queryRef.name, queryRef.variables]; } -type FlattenedQueryResult = Omit, "data" | "toJSON"> & Data; -interface CreateDataConnectQueryOptions extends Omit, FirebaseError, FlattenedQueryResult, QueryKey>, "queryFn" | "queryKey"> { - queryFn: () => QueryRef; +type FlattenedQueryResult = Omit< + QueryResult, + "data" | "toJSON" +> & + Data; +interface CreateDataConnectQueryOptions + extends Omit< + CreateQueryOptions< + FlattenedQueryResult, + FirebaseError, + FlattenedQueryResult, + QueryKey + >, + "queryFn" | "queryKey" + > { + queryFn: () => QueryRef; } -export function injectDataConnectQuery(queryRefOrOptionsFn: QueryRef | (() => CreateDataConnectQueryOptions)) : CreateQueryResult, FirebaseError> { +/** + * injectDataConnectQuery takes a query ref and returns a wrapper function around Tanstack's `injectQuery` + * @param queryRefOrOptionsFn Query Ref or callback function for calling a new query + * @returns {CreateQueryResult>} + */ +export function injectDataConnectQuery( + queryRefOrOptionsFn: + | QueryRef + | (() => CreateDataConnectQueryOptions) +): CreateQueryResult, FirebaseError> { const queryKey = signal([]); function fdcOptionsFn() { - const passedInOptions = typeof queryRefOrOptionsFn === 'function' ? queryRefOrOptionsFn() : undefined; - + const passedInOptions = + typeof queryRefOrOptionsFn === "function" + ? queryRefOrOptionsFn() + : undefined; + const modifiedFn = () => { - const ref: QueryRef =passedInOptions?.queryFn() || queryRefOrOptionsFn as QueryRef; + const ref: QueryRef = + passedInOptions?.queryFn() || + (queryRefOrOptionsFn as QueryRef); queryKey.set([ref.name, ref.variables]); - console.log('mutationfn!') return executeQuery(ref).then((res) => { const { data, ...rest } = res; return { @@ -45,36 +71,116 @@ export function injectDataConnectQuery(queryRefOrOptionsFn: Que }; }) as Promise>; }; -return { + return { queryKey: queryKey(), ...passedInOptions, queryFn: modifiedFn, - } - + }; } return injectQuery(fdcOptionsFn); } -export type GeneratedSignature = (dc: DataConnect, vars: Variables) => MutationRef; -export type DataConnectMutationOptionsFn = () => Omit, "mutationFn"> & { - invalidate?: QueryKey | QueryRef[]; - dataConnect?: DataConnect; - mutationFn: (args: Arguments) => MutationRef; -} -export type DataConnectMutationOptionsUndefinedMutationFn = () => (Omit>, 'mutationFn'>); -export type FlattenedMutationResult = Omit, "data" | "toJSON"> & Data; +export type GeneratedSignature = ( + dc: DataConnect, + vars: Variables +) => MutationRef; +export type DataConnectMutationOptionsFn = + () => Omit, "mutationFn"> & { + invalidate?: QueryKey | QueryRef[]; + dataConnect?: DataConnect; + mutationFn: (args: Arguments) => MutationRef; + }; +export type DataConnectMutationOptionsUndefinedMutationFn< + Data, + Error, + Variables +> = () => Omit< + ReturnType>, + "mutationFn" +>; +export type FlattenedMutationResult = Omit< + MutationResult, + "data" | "toJSON" +> & + Data; -export function injectDataConnectMutation(factoryFn: undefined, optionsFn: DataConnectMutationOptionsFn): CreateMutationResult, FirebaseError, Arguments>; -export function injectDataConnectMutation(factoryFn: GeneratedSignature): CreateMutationResult, FirebaseError, Arguments>; -export function injectDataConnectMutation(factoryFn: GeneratedSignature): CreateMutationResult, FirebaseError, Arguments>; -export function injectDataConnectMutation(factoryFn: GeneratedSignature, optionsFn?: DataConnectMutationOptionsUndefinedMutationFn): CreateMutationResult, FirebaseError, Arguments>; -export function injectDataConnectMutation(factoryFn: GeneratedSignature | undefined, optionsFn?: DataConnectMutationOptionsFn | DataConnectMutationOptionsUndefinedMutationFn):CreateMutationResult, FirebaseError, Arguments> { +export function injectDataConnectMutation( + factoryFn: undefined, + optionsFn: DataConnectMutationOptionsFn< + Data, + FirebaseError, + Variables, + Arguments + > +): CreateMutationResult< + FlattenedMutationResult, + FirebaseError, + Arguments +>; +export function injectDataConnectMutation< + Data, + Variables extends undefined, + Arguments = void | undefined +>( + factoryFn: GeneratedSignature +): CreateMutationResult< + FlattenedMutationResult, + FirebaseError, + Arguments +>; +export function injectDataConnectMutation( + factoryFn: GeneratedSignature +): CreateMutationResult< + FlattenedMutationResult, + FirebaseError, + Arguments +>; +export function injectDataConnectMutation( + factoryFn: GeneratedSignature, + optionsFn?: DataConnectMutationOptionsUndefinedMutationFn< + Data, + FirebaseError, + Arguments + > +): CreateMutationResult< + FlattenedMutationResult, + FirebaseError, + Arguments +>; +/** + * injectDataConnectMutation takes a mutation ref factory function and returns a tanstack wrapper around `injectMutation` + * @param factoryFn generated SDK factory function + * @param optionsFn options function to create a new mutation + * @returns {CreateMutationResult, FirebaseError, Arguments>} + */ +export function injectDataConnectMutation< + Data, + Variables, + Arguments extends Variables +>( + factoryFn: GeneratedSignature | undefined, + optionsFn?: + | DataConnectMutationOptionsFn + | DataConnectMutationOptionsUndefinedMutationFn< + Data, + FirebaseError, + Variables + > +): CreateMutationResult< + FlattenedMutationResult, + FirebaseError, + Arguments +> { const injectCb = () => { const queryClient = inject(QueryClient); - const providedOptions = optionsFn ? optionsFn() : undefined; + const providedOptions = optionsFn ? optionsFn() : undefined; const modifiedFn = (args: Arguments) => { const dataConnect = inject(DataConnect); - const ref = (providedOptions && 'mutationFn' in providedOptions && providedOptions.mutationFn(args as Arguments)) || factoryFn!(dataConnect, args as Variables); + const ref = + (providedOptions && + "mutationFn" in providedOptions && + providedOptions.mutationFn(args as Arguments)) || + factoryFn!(dataConnect, args as Variables); return executeMutation(ref) .then((res) => { @@ -91,7 +197,6 @@ export function injectDataConnectMutation); key = queryKey; } - console.log("invalidating", key); queryClient.invalidateQueries({ queryKey: key, }); @@ -106,4 +211,4 @@ export function injectDataConnectMutation Date: Fri, 14 Feb 2025 16:51:11 -0800 Subject: [PATCH 08/10] completed first pass --- .../js/default-connector/esm/index.esm.js | 68 - .../js/default-connector/esm/package.json | 1 - .../js/default-connector/index.cjs.js | 79 - .../js/default-connector/index.d.ts | 117 - .../js/default-connector/package.json | 33 - dataconnect/.dataconnect/schema/prelude.gql | 140 +- dataconnect/connector/connector.yaml | 1 + packages/angular/package-lock.json | 2790 ++++++++++------- packages/angular/package.json | 20 +- packages/angular/src/data-connect/index.ts | 87 +- .../data-connect/useDataConnectMutation.ts | 1 + 11 files changed, 1737 insertions(+), 1600 deletions(-) delete mode 100644 dataconnect-sdk/js/default-connector/esm/index.esm.js delete mode 100644 dataconnect-sdk/js/default-connector/esm/package.json delete mode 100644 dataconnect-sdk/js/default-connector/index.cjs.js delete mode 100644 dataconnect-sdk/js/default-connector/index.d.ts delete mode 100644 dataconnect-sdk/js/default-connector/package.json diff --git a/dataconnect-sdk/js/default-connector/esm/index.esm.js b/dataconnect-sdk/js/default-connector/esm/index.esm.js deleted file mode 100644 index f0bc4d83..00000000 --- a/dataconnect-sdk/js/default-connector/esm/index.esm.js +++ /dev/null @@ -1,68 +0,0 @@ -import { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } from 'firebase/data-connect'; - -export const connectorConfig = { - connector: 'default', - service: 'tanstack-query-firebase', - location: 'us-central1' -}; - -export function createMovieRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); - if('_useGeneratedSdk' in dcInstance) { - dcInstance._useGeneratedSdk(); - } else { - console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); - } - return mutationRef(dcInstance, 'CreateMovie', inputVars); -} -export function createMovie(dcOrVars, vars) { - return executeMutation(createMovieRef(dcOrVars, vars)); -} -export function upsertMovieRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); - if('_useGeneratedSdk' in dcInstance) { - dcInstance._useGeneratedSdk(); - } else { - console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); - } - return mutationRef(dcInstance, 'UpsertMovie', inputVars); -} -export function upsertMovie(dcOrVars, vars) { - return executeMutation(upsertMovieRef(dcOrVars, vars)); -} -export function deleteMovieRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); - if('_useGeneratedSdk' in dcInstance) { - dcInstance._useGeneratedSdk(); - } else { - console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); - } - return mutationRef(dcInstance, 'DeleteMovie', inputVars); -} -export function deleteMovie(dcOrVars, vars) { - return executeMutation(deleteMovieRef(dcOrVars, vars)); -} -export function listMoviesRef(dc) { - const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); - if('_useGeneratedSdk' in dcInstance) { - dcInstance._useGeneratedSdk(); - } else { - console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); - } - return queryRef(dcInstance, 'ListMovies'); -} -export function listMovies(dc) { - return executeQuery(listMoviesRef(dc)); -} -export function getMovieByIdRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); - if('_useGeneratedSdk' in dcInstance) { - dcInstance._useGeneratedSdk(); - } else { - console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); - } - return queryRef(dcInstance, 'GetMovieById', inputVars); -} -export function getMovieById(dcOrVars, vars) { - return executeQuery(getMovieByIdRef(dcOrVars, vars)); -} diff --git a/dataconnect-sdk/js/default-connector/esm/package.json b/dataconnect-sdk/js/default-connector/esm/package.json deleted file mode 100644 index 7c34deb5..00000000 --- a/dataconnect-sdk/js/default-connector/esm/package.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"module"} \ No newline at end of file diff --git a/dataconnect-sdk/js/default-connector/index.cjs.js b/dataconnect-sdk/js/default-connector/index.cjs.js deleted file mode 100644 index cbb24321..00000000 --- a/dataconnect-sdk/js/default-connector/index.cjs.js +++ /dev/null @@ -1,79 +0,0 @@ -const { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } = require('firebase/data-connect'); - -const connectorConfig = { - connector: 'default', - service: 'tanstack-query-firebase', - location: 'us-central1' -}; -exports.connectorConfig = connectorConfig; - -function createMovieRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); - if('_useGeneratedSdk' in dcInstance) { - dcInstance._useGeneratedSdk(); - } else { - console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); - } - return mutationRef(dcInstance, 'CreateMovie', inputVars); -} -exports.createMovieRef = createMovieRef; -exports.createMovie = function createMovie(dcOrVars, vars) { - return executeMutation(createMovieRef(dcOrVars, vars)); -}; - -function upsertMovieRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); - if('_useGeneratedSdk' in dcInstance) { - dcInstance._useGeneratedSdk(); - } else { - console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); - } - return mutationRef(dcInstance, 'UpsertMovie', inputVars); -} -exports.upsertMovieRef = upsertMovieRef; -exports.upsertMovie = function upsertMovie(dcOrVars, vars) { - return executeMutation(upsertMovieRef(dcOrVars, vars)); -}; - -function deleteMovieRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); - if('_useGeneratedSdk' in dcInstance) { - dcInstance._useGeneratedSdk(); - } else { - console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); - } - return mutationRef(dcInstance, 'DeleteMovie', inputVars); -} -exports.deleteMovieRef = deleteMovieRef; -exports.deleteMovie = function deleteMovie(dcOrVars, vars) { - return executeMutation(deleteMovieRef(dcOrVars, vars)); -}; - -function listMoviesRef(dc) { - const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); - if('_useGeneratedSdk' in dcInstance) { - dcInstance._useGeneratedSdk(); - } else { - console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); - } - return queryRef(dcInstance, 'ListMovies'); -} -exports.listMoviesRef = listMoviesRef; -exports.listMovies = function listMovies(dc) { - return executeQuery(listMoviesRef(dc)); -}; - -function getMovieByIdRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); - if('_useGeneratedSdk' in dcInstance) { - dcInstance._useGeneratedSdk(); - } else { - console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); - } - return queryRef(dcInstance, 'GetMovieById', inputVars); -} -exports.getMovieByIdRef = getMovieByIdRef; -exports.getMovieById = function getMovieById(dcOrVars, vars) { - return executeQuery(getMovieByIdRef(dcOrVars, vars)); -}; - diff --git a/dataconnect-sdk/js/default-connector/index.d.ts b/dataconnect-sdk/js/default-connector/index.d.ts deleted file mode 100644 index 077a3f8a..00000000 --- a/dataconnect-sdk/js/default-connector/index.d.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { ConnectorConfig, DataConnect, QueryRef, QueryPromise, MutationRef, MutationPromise } from 'firebase/data-connect'; -export const connectorConfig: ConnectorConfig; - -export type TimestampString = string; - -export type UUIDString = string; - -export type Int64String = string; - -export type DateString = string; - - -export interface CreateMovieData { - movie_insert: Movie_Key; -} - -export interface CreateMovieVariables { - title: string; - genre: string; - imageUrl: string; -} - -export interface DeleteMovieData { - movie_delete?: Movie_Key | null; -} - -export interface DeleteMovieVariables { - id: UUIDString; -} - -export interface GetMovieByIdData { - movie?: { - id: UUIDString; - title: string; - imageUrl: string; - genre?: string | null; - } & Movie_Key; -} - -export interface GetMovieByIdVariables { - id: UUIDString; -} - -export interface ListMoviesData { - movies: ({ - id: UUIDString; - title: string; - imageUrl: string; - genre?: string | null; - } & Movie_Key)[]; -} - -export interface MovieMetadata_Key { - id: UUIDString; - __typename?: 'MovieMetadata_Key'; -} - -export interface Movie_Key { - id: UUIDString; - __typename?: 'Movie_Key'; -} - -export interface UpsertMovieData { - movie_upsert: Movie_Key; -} - -export interface UpsertMovieVariables { - id: UUIDString; - title: string; - imageUrl: string; -} - - -/* Allow users to create refs without passing in DataConnect */ -export function createMovieRef(vars: CreateMovieVariables): MutationRef; -/* Allow users to pass in custom DataConnect instances */ -export function createMovieRef(dc: DataConnect, vars: CreateMovieVariables): MutationRef; - -export function createMovie(vars: CreateMovieVariables): MutationPromise; -export function createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; - - -/* Allow users to create refs without passing in DataConnect */ -export function upsertMovieRef(vars: UpsertMovieVariables): MutationRef; -/* Allow users to pass in custom DataConnect instances */ -export function upsertMovieRef(dc: DataConnect, vars: UpsertMovieVariables): MutationRef; - -export function upsertMovie(vars: UpsertMovieVariables): MutationPromise; -export function upsertMovie(dc: DataConnect, vars: UpsertMovieVariables): MutationPromise; - - -/* Allow users to create refs without passing in DataConnect */ -export function deleteMovieRef(vars: DeleteMovieVariables): MutationRef; -/* Allow users to pass in custom DataConnect instances */ -export function deleteMovieRef(dc: DataConnect, vars: DeleteMovieVariables): MutationRef; - -export function deleteMovie(vars: DeleteMovieVariables): MutationPromise; -export function deleteMovie(dc: DataConnect, vars: DeleteMovieVariables): MutationPromise; - - -/* Allow users to create refs without passing in DataConnect */ -export function listMoviesRef(): QueryRef; -/* Allow users to pass in custom DataConnect instances */ -export function listMoviesRef(dc: DataConnect): QueryRef; - -export function listMovies(): QueryPromise; -export function listMovies(dc: DataConnect): QueryPromise; - - -/* Allow users to create refs without passing in DataConnect */ -export function getMovieByIdRef(vars: GetMovieByIdVariables): QueryRef; -/* Allow users to pass in custom DataConnect instances */ -export function getMovieByIdRef(dc: DataConnect, vars: GetMovieByIdVariables): QueryRef; - -export function getMovieById(vars: GetMovieByIdVariables): QueryPromise; -export function getMovieById(dc: DataConnect, vars: GetMovieByIdVariables): QueryPromise; - diff --git a/dataconnect-sdk/js/default-connector/package.json b/dataconnect-sdk/js/default-connector/package.json deleted file mode 100644 index 156155dd..00000000 --- a/dataconnect-sdk/js/default-connector/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "@dataconnect/default-connector", - "version": "1.0.0", - "author": "Firebase (https://firebase.google.com/)", - "description": "Generated SDK For default", - "license": "Apache-2.0", - "engines": { - "node": " >=18.0" - }, - "typings": "index.d.ts", - "module": "esm/index.esm.js", - "main": "index.cjs.js", - "browser": "esm/index.esm.js", - "exports": { - ".": { - "types": "./index.d.ts", - "require": "./index.cjs.js", - "default": "./esm/index.esm.js" - }, - "./react": { - "types": "./react/index.d.ts", - "import": "./react/esm/index.esm.js", - "default": "./react/esm/index.esm.js" - }, - "./package.json": "./package.json" - }, - "peerDependencies": { - "firebase": "^10.14.0 || ^11.0.0", - "@tanstack-query-firebase/react": "^0.1.4", - "@tanstack/react-query": "^5" - - } -} \ No newline at end of file diff --git a/dataconnect/.dataconnect/schema/prelude.gql b/dataconnect/.dataconnect/schema/prelude.gql index bc21c044..cfff7d55 100644 --- a/dataconnect/.dataconnect/schema/prelude.gql +++ b/dataconnect/.dataconnect/schema/prelude.gql @@ -1,3 +1,62 @@ +""" +Redact a part of the response from the client. + +Redacted fields are still evaluated for side effects (including data changes and +`@check`) and the results are still available to later steps in CEL expressions +(via `response.fieldName`). +""" +directive @redact on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT + +""" +Ensure this field is present and is not null or `[]`, or abort the request / transaction. + +A CEL expression, `expr` is used to test the field value. It defaults to +rejecting null and `[]` but a custom expression can be provided instead. + +If the field occurs multiple times (i.e. directly or indirectly nested under a +list), `expr` will be executed once for each occurrence and `@check` succeeds if +all values succeed. `@check` fails when the field is not present at all (i.e. +all ancestor paths contain `null` or `[]`), unless `optional` is true. + +If a `@check` fails in a mutation, the top-level field containing it will be +replaced with a partial error, whose message can be customzied via the `message` +argument. Each subsequent top-level fields will return an aborted error (i.e. +not executed). To rollback previous steps, see `@transaction`. +""" +directive @check( + """ + The CEL expression to test the field value (or values if nested under a list). + + Within the CEL expression, a special value `this` evaluates to the field that + this directive is attached to. If this field occurs multiple times because + any ancestor is a list, each occurrence is tested with `this` bound to each + value. When the field itself is a list or object, `this` follows the same + structure (including all decendants selected in case of objects). + + For any given path, if an ancestor is `null` or `[]`, the field will not be + reached and the CEL evaluation will be skipped for that path. In other words, + evaluation only takes place when `this` is `null` or non-null, but never + undefined. (See also the `optional` argument.) + """ + expr: Boolean_Expr! = "!(this in [null, []])" + """ + The error message to return to the client if the check fails. + + Defaults to "permission denied" if not specified. + """ + message: String! = "permission denied" + """ + Whether the check should pass or fail (default) when the field is not present. + + A field will not be reached at a given path if its parent or any ancestor is + `[]` or `null`. When this happens to all paths, the field will not be present + anywhere in the response tree. In other words, `expr` is evaluated 0 times. + By default, @check will automatically fail in this case. Set this argument to + `true` to make it pass even if no tests are run (a.k.a. "vacuously true"). + """ + optional: Boolean = false +) repeatable on QUERY | MUTATION | FIELD | FRAGMENT_DEFINITION | FRAGMENT_SPREAD | INLINE_FRAGMENT + "AccessLevel specifies coarse access policies for common situations." enum AccessLevel { """ @@ -445,6 +504,17 @@ directive @fdc_oneOf( required: Boolean! = false ) repeatable on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION +type Mutation { + """ + Run a query during the mutation and add fields into the response. + + Example: foo: query { users { id } } will add a field foo: {users: [{id: "..."}, …]} into the response JSON. + + Note: Data fetched this way can be handy for permission checks. See @check. + """ + query: Query +} + """ `UUID` is a string of hexadecimal digits representing an RFC4122-compliant UUID. @@ -1934,73 +2004,3 @@ scalar Vector_Embed_Model @fdc_example(value: "textembedding-gecko@001", description: "An older version of the textembedding-gecko model") @fdc_example(value: "text-embedding-004", description: "Another text embedding model") -""" -Redact a part of the response from the client. - -Redacted fields are still evaluated for side effects (including data changes and -`@check`) and the results are still available to later steps in CEL expressions -(via `response.fieldName`). -""" -directive @redact on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT - -""" -Ensure this field is present and is not null or `[]`, or abort the request / transaction. - -A CEL expression, `expr` is used to test the field value. It defaults to -rejecting null and `[]` but a custom expression can be provided instead. - -If the field occurs multiple times (i.e. directly or indirectly nested under a -list), `expr` will be executed once for each occurrence and `@check` succeeds if -all values succeed. `@check` fails when the field is not present at all (i.e. -all ancestor paths contain `null` or `[]`), unless `optional` is true. - -If a `@check` fails in a mutation, the top-level field containing it will be -replaced with a partial error, whose message can be customzied via the `message` -argument. Each subsequent top-level fields will return an aborted error (i.e. -not executed). To rollback previous steps, see `@transaction`. -""" -directive @check( - """ - The CEL expression to test the field value (or values if nested under a list). - - Within the CEL expression, a special value `this` evaluates to the field that - this directive is attached to. If this field occurs multiple times because - any ancestor is a list, each occurrence is tested with `this` bound to each - value. When the field itself is a list or object, `this` follows the same - structure (including all decendants selected in case of objects). - - For any given path, if an ancestor is `null` or `[]`, the field will not be - reached and the CEL evaluation will be skipped for that path. In other words, - evaluation only takes place when `this` is `null` or non-null, but never - undefined. (See also the `optional` argument.) - """ - expr: Boolean_Expr! = "!(this in [null, []])" - """ - The error message to return to the client if the check fails. - - Defaults to "permission denied" if not specified. - """ - message: String! = "permission denied" - """ - Whether the check should pass or fail (default) when the field is not present. - - A field will not be reached at a given path if its parent or any ancestor is - `[]` or `null`. When this happens to all paths, the field will not be present - anywhere in the response tree. In other words, `expr` is evaluated 0 times. - By default, @check will automatically fail in this case. Set this argument to - `true` to make it pass even if no tests are run (a.k.a. "vacuously true"). - """ - optional: Boolean = false -) repeatable on QUERY | MUTATION | FIELD | FRAGMENT_DEFINITION | FRAGMENT_SPREAD | INLINE_FRAGMENT - -type Mutation { - """ - Run a query during the mutation and add fields into the response. - - Example: foo: query { users { id } } will add a field foo: {users: [{id: "..."}, …]} into the response JSON. - - Note: Data fetched this way can be handy for permission checks. See @check. - """ - query: Query -} - diff --git a/dataconnect/connector/connector.yaml b/dataconnect/connector/connector.yaml index 5b7e5f00..933ef4c6 100644 --- a/dataconnect/connector/connector.yaml +++ b/dataconnect/connector/connector.yaml @@ -5,3 +5,4 @@ generate: package: "@dataconnect/default-connector" packageJsonDir: ../.. react: true + angular: true diff --git a/packages/angular/package-lock.json b/packages/angular/package-lock.json index 0df9d20d..a70d5215 100644 --- a/packages/angular/package-lock.json +++ b/packages/angular/package-lock.json @@ -9,34 +9,48 @@ "version": "0.0.1", "license": "ISC", "dependencies": { + "@angular/animations": "^19.1.6", "@angular/core": "^19.1.0", "@angular/fire": "^19.0.0-rc.5", - "@tanstack-query-firebase/angular": "file:../../../../bin/tanstack-query-firebase-angular-0.0.1.tgz", "@tanstack/angular-query-experimental": "^5.64.1", "firebase": "^11.1.0" + }, + "devDependencies": { + "@analogjs/vite-plugin-angular": "^1.13.0", + "@testing-library/angular": "^17.3.5", + "@testing-library/dom": "^10.4.0" } }, - "node_modules/@angular-devkit/schematics": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.1.1.tgz", - "integrity": "sha512-4xodirv/kErn7L5N6NhIDfuVuNgNDmGX1+Pdu3yG2c1moOTyRBV684lv2qQJClNctOpELDM55IuX3MXud2qQaw==", + "node_modules/@analogjs/vite-plugin-angular": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@analogjs/vite-plugin-angular/-/vite-plugin-angular-1.13.0.tgz", + "integrity": "sha512-h9XTXtbOKXyjrjFdy5qy40wam3vTttujWCpnoqygnopWaKS9T86LVnBFAW1p2yaBa7Wzz/BKDs2MtBBPWht8Sw==", + "dev": true, "dependencies": { - "@angular-devkit/core": "19.1.1", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.17", - "ora": "5.4.1", - "rxjs": "7.8.1" + "ts-morph": "^21.0.0", + "vfile": "^6.0.3" }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/brandonroberts" + }, + "peerDependencies": { + "@angular-devkit/build-angular": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "@angular/build": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@angular-devkit/build-angular": { + "optional": true + }, + "@angular/build": { + "optional": true + } } }, - "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.1.tgz", - "integrity": "sha512-CAqst7WEasPHR4OFdbxxX3+NVqNTvYk3vtPbXT/jZ0L2EZRICQta2EClkdhSIiMkiMf0/2LNT05rYD7k4NHIQA==", + "node_modules/@angular-devkit/core": { + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.7.tgz", + "integrity": "sha512-q0I6L9KTqyQ7D5M8H+fWLT+yjapvMNb7SRdfU6GzmexO66Dpo83q4HDzuDKIPDF29Yl0ELs9ICJqe9yUXh6yDQ==", "dependencies": { "ajv": "8.17.1", "ajv-formats": "3.0.1", @@ -59,723 +73,919 @@ } } }, - "node_modules/@angular-devkit/schematics/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "node_modules/@angular-devkit/schematics": { + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.1.7.tgz", + "integrity": "sha512-AP6FvhMybCYs3gs+vzEAzSU1K//AFT3SVTRFv+C3WMO5dLeAHeGzM8I2dxD5EHQQtqIE/8apP6CxGrnpA5YlFg==", + "dependencies": { + "@angular-devkit/core": "19.1.7", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.17", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } }, - "node_modules/@angular-devkit/schematics/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/@angular/animations": { + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.1.6.tgz", + "integrity": "sha512-iacosz3fygp0AyT57+suVpLChl10xS5RBje09TfQIKHTUY0LWkMspgaK9gwtlflpIhjedPV0UmgRIKhhFcQM1A==", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "tslib": "^2.3.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/core": "19.1.6" } }, - "node_modules/@angular-devkit/schematics/node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "node_modules/@angular/common": { + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.1.6.tgz", + "integrity": "sha512-FkuejwbxsOLhcyOgDM/7YEYvMG3tuyOvr+831VzPwMwYp5QO9AUYtn4ffGf698JccbA+Ocw3BAdhPU6i+YZC1A==", + "peer": true, "dependencies": { - "ajv": "^8.0.0" + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "ajv": "^8.0.0" + "@angular/core": "19.1.6", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/compiler": { + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.1.6.tgz", + "integrity": "sha512-Tl2PFEtnU8UgSqtEKG827xDUGZrErhR6S1JICeV1kbRCYmwQA4hhG25tzi+ifSAOPW7eJiyzP2LWIvOuZkq3Vw==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/core": "19.1.6" }, "peerDependenciesMeta": { - "ajv": { + "@angular/core": { "optional": true } } }, - "node_modules/@angular-devkit/schematics/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@angular/core": { + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.1.6.tgz", + "integrity": "sha512-FD167URT+apxjzj9sG/MzffW5G6YyQiPQ6nrrIoYi9jeY3LYurybuOgvcXrU8PT4Z3+CKMq9k/ZnmrlHU72BpA==", "dependencies": { - "color-convert": "^2.0.1" + "tslib": "^2.3.0" }, "engines": { - "node": ">=8" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.15.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "node_modules/@angular/fire": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@angular/fire/-/fire-19.0.0.tgz", + "integrity": "sha512-dVU9IdL9sGKe1fV7g2iGgkjUQIYrbnljHtHUgNpZaskyW+Vy6ndtsEbSUoRd6sLP8WpThWH7WvITKhu/8a6qfQ==", + "dependencies": { + "@angular-devkit/schematics": "^19.0.0", + "@schematics/angular": "^19.0.0", + "firebase": "^11.2.0", + "rxfire": "^6.1.0", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0", + "@angular/platform-browser": "^19.0.0", + "@angular/platform-browser-dynamic": "^19.0.0", + "@angular/platform-server": "^19.0.0", + "firebase-tools": "^13.0.0", + "rxjs": "~7.8.0" + }, + "peerDependenciesMeta": { + "@angular/platform-server": { + "optional": true }, - { - "type": "consulting", - "url": "https://feross.org/support" + "firebase-tools": { + "optional": true } - ] - }, - "node_modules/@angular-devkit/schematics/node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/@angular/platform-browser": { + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.1.6.tgz", + "integrity": "sha512-sfWU+gMpqQ6GYtE3tAfDktftC01NgtqAOKfeCQ/KY2rxRTIxYahenW0Licuzgmd+8AZtmncoZaYX0Fd/5XMqzQ==", + "peer": true, "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/animations": "19.1.6", + "@angular/common": "19.1.6", + "@angular/core": "19.1.6" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } } }, - "node_modules/@angular-devkit/schematics/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@angular/platform-browser-dynamic": { + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.1.6.tgz", + "integrity": "sha512-QedjG7/ctPtzgJ3LcWv4yMcSivKlwcZ8ge8zPe7eu9Ft6mDZZat65gJEjDuvevJoeNbo2dQODFDiyPJNmnNA9A==", + "peer": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "tslib": "^2.3.0" }, "engines": { - "node": ">=10" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "@angular/common": "19.1.6", + "@angular/compiler": "19.1.6", + "@angular/core": "19.1.6", + "@angular/platform-browser": "19.1.6" } }, - "node_modules/@angular-devkit/schematics/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/@angular/router": { + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.1.6.tgz", + "integrity": "sha512-TEfw3W5jVodVDMD4krhXGog1THZN3x1yoh2oZmCv3lXg22+pVC6Cp+x3vVExq0mS+g3/6uZwy/3qAYdlzqYjTg==", + "dev": true, + "peer": true, "dependencies": { - "restore-cursor": "^3.1.0" + "tslib": "^2.3.0" }, "engines": { - "node": ">=8" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/common": "19.1.6", + "@angular/core": "19.1.6", + "@angular/platform-browser": "19.1.6", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "engines": { - "node": ">=6" + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, "engines": { - "node": ">=0.8" + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@babel/runtime": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", + "dev": true, "dependencies": { - "color-name": "~1.1.4" + "regenerator-runtime": "^0.14.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=6.9.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "node_modules/@firebase/analytics": { + "version": "0.10.11", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.11.tgz", + "integrity": "sha512-zwuPiRE0+hgcS95JZbJ6DFQN4xYFO8IyGxpeePTV51YJMwCf3lkBa6FnZ/iXIqDKcBPMgMuuEZozI0BJWaLEYg==", + "dependencies": { + "@firebase/component": "0.6.12", + "@firebase/installations": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } }, - "node_modules/@angular-devkit/schematics/node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "node_modules/@firebase/analytics-compat": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.17.tgz", + "integrity": "sha512-SJNVOeTvzdqZQvXFzj7yAirXnYcLDxh57wBFROfeowq/kRN1AqOw1tG6U4OiFOEhqi7s3xLze/LMkZatk2IEww==", "dependencies": { - "clone": "^1.0.2" + "@firebase/analytics": "0.10.11", + "@firebase/analytics-types": "0.8.3", + "@firebase/component": "0.6.12", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@firebase/app-compat": "0.x" } }, - "node_modules/@angular-devkit/schematics/node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "node_modules/@firebase/analytics-types": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz", + "integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==" }, - "node_modules/@angular-devkit/schematics/node_modules/fast-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", - "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ] + "node_modules/@firebase/app": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.11.1.tgz", + "integrity": "sha512-Vz4DrNLPfDx3RwQf+4klXtu7OUYDO6xz2hlRyFawWskS7YqdtNzkDDxrqH20KDfjCF1lib46/NgchIj1+8h4wQ==", + "dependencies": { + "@firebase/component": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + } }, - "node_modules/@angular-devkit/schematics/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@firebase/app-check": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.11.tgz", + "integrity": "sha512-42zIfRI08/7bQqczAy7sY2JqZYEv3a1eNa4fLFdtJ54vNevbBIRSEA3fZgRqWFNHalh5ohsBXdrYgFqaRIuCcQ==", + "dependencies": { + "@firebase/component": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" + }, "engines": { - "node": ">=8" + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" } }, - "node_modules/@angular-devkit/schematics/node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/@firebase/app-check-compat": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.18.tgz", + "integrity": "sha512-qjozwnwYmAIdrsVGrJk+hnF1WBois54IhZR6gO0wtZQoTvWL/GtiA2F31TIgAhF0ayUiZhztOv1RfC7YyrZGDQ==", + "dependencies": { + "@firebase/app-check": "0.8.11", + "@firebase/app-check-types": "0.5.3", + "@firebase/component": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } }, - "node_modules/@angular-devkit/schematics/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "node_modules/@firebase/app-check-interop-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", + "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==" }, - "node_modules/@angular-devkit/schematics/node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "node_modules/@firebase/app-check-types": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz", + "integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==" + }, + "node_modules/@firebase/app-compat": { + "version": "0.2.50", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.50.tgz", + "integrity": "sha512-7yD362icKgjoNvFxwth420TNZgqCfuTJ28yQCdpyjC2fXyaZHhAbxVKnHEXGTAaUKSHWxsIy46lBKGi/x/Mflw==", + "dependencies": { + "@firebase/app": "0.11.1", + "@firebase/component": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" + }, "engines": { - "node": ">=8" + "node": ">=18.0.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/@firebase/app-types": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", + "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==" + }, + "node_modules/@firebase/auth": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.9.0.tgz", + "integrity": "sha512-Xz2mbEYauF689qXG/4HppS2+/yGo9R7B6eNUBh3H2+XpAZTGdx8d8TFsW/BMTAK9Q95NB0pb1Bbvfx0lwofq8Q==", + "dependencies": { + "@firebase/component": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" + }, "engines": { - "node": ">=10" + "node": ">=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@firebase/app": "0.x", + "@react-native-async-storage/async-storage": "^1.18.1" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } } }, - "node_modules/@angular-devkit/schematics/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "node_modules/@firebase/auth-compat": { + "version": "0.5.18", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.18.tgz", + "integrity": "sha512-dFBev8AMNb2AgIt9afwf/Ku4/0Wq9R9OFSeBB/xjyJt+RfQ9PnNWqU2oFphews23byLg6jle8twRA7iOYfRGRw==", + "dependencies": { + "@firebase/auth": "1.9.0", + "@firebase/auth-types": "0.13.0", + "@firebase/component": "0.6.12", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } }, - "node_modules/@angular-devkit/schematics/node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" + "node_modules/@firebase/auth-interop-types": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", + "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==" }, - "node_modules/@angular-devkit/schematics/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/@firebase/auth-types": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.13.0.tgz", + "integrity": "sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/component": { + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.12.tgz", + "integrity": "sha512-YnxqjtohLbnb7raXt2YuA44cC1wA9GiehM/cmxrsoxKlFxBLy2V0OkRSj9gpngAE0UoJ421Wlav9ycO7lTPAUw==", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18.0.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "node_modules/@firebase/data-connect": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.3.0.tgz", + "integrity": "sha512-inbLq0JyQD/d02Al3Lso0Hc8z1BVpB3dYSMFcQkeKhYyjn5bspLczLdasPbCOEUp8MOkLblLZhJuRs7Q/spFnw==", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" } }, - "node_modules/@angular-devkit/schematics/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/@firebase/database": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.12.tgz", + "integrity": "sha512-psFl5t6rSFHq3i3fnU1QQlc4BB9Hnhh8TgEqvQlPPm8kDLw8gYxvjqYw3c5CZW0+zKR837nwT6im/wtJUivMKw==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + }, "engines": { - "node": ">=6" + "node": ">=18.0.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/@firebase/database-compat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.3.tgz", + "integrity": "sha512-uHGQrSUeJvsDfA+IyHW5O4vdRPsCksEzv4T4Jins+bmQgYy20ZESU4x01xrQCn/nzqKHuQMEW99CoCO7D+5NiQ==", "dependencies": { - "mimic-fn": "^2.1.0" + "@firebase/component": "0.6.12", + "@firebase/database": "1.0.12", + "@firebase/database-types": "1.0.8", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18.0.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "node_modules/@firebase/database-types": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.8.tgz", + "integrity": "sha512-6lPWIGeufhUq1heofZULyVvWFhD01TUrkkB9vyhmksjZ4XF7NaivQp9rICMk7QNhqwa+uDCaj4j+Q8qqcSVZ9g==", "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "@firebase/app-types": "0.9.3", + "@firebase/util": "1.10.3" + } + }, + "node_modules/@firebase/firestore": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.8.tgz", + "integrity": "sha512-eDvVJ/I5vSmIdGmLHJAK1OcviigIxjjia6i5/AkMFq6vZMt7CBXA0B5Xz9pGRCZ7WewFcsCbK1ZUQoYJ91+Cew==", + "dependencies": { + "@firebase/component": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "@firebase/webchannel-wrapper": "1.0.3", + "@grpc/grpc-js": "~1.9.0", + "@grpc/proto-loader": "^0.7.8", + "tslib": "^2.1.0" }, "engines": { - "node": ">=10" + "node": ">=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@firebase/app": "0.x" } }, - "node_modules/@angular-devkit/schematics/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "node_modules/@firebase/firestore-compat": { + "version": "0.3.43", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.43.tgz", + "integrity": "sha512-zxg7YS07XQnTetGs3GADM/eA6HB4vWUp+Av4iugmTbft0fQxuTSnGm7ifctaYuR7VMTPckU9CW+oFC9QUNSYvg==", + "dependencies": { + "@firebase/component": "0.6.12", + "@firebase/firestore": "4.7.8", + "@firebase/firestore-types": "3.0.3", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" + }, "engines": { - "node": ">=12" + "node": ">=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "peerDependencies": { + "@firebase/app-compat": "0.x" } }, - "node_modules/@angular-devkit/schematics/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/@firebase/firestore-types": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz", + "integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/functions": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.2.tgz", + "integrity": "sha512-iKpFDoCYk/Qm+Qwv5ynRb9/yq64QOt0A0+t9NuekyAZnSoV56kSNq/PmsVmBauar5SlmEjhHk6QKdMBP9S0gXA==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.12", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" }, "engines": { - "node": ">= 6" + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" } }, - "node_modules/@angular-devkit/schematics/node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/@firebase/functions-compat": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.19.tgz", + "integrity": "sha512-uw4tR8NcJCDu86UD63Za8A8SgFgmAVFb1XsGlkuBY7gpLyZWEFavWnwRkZ/8cUwpqUhp/SptXFZ1WFJSnOokLw==", + "dependencies": { + "@firebase/component": "0.6.12", + "@firebase/functions": "0.12.2", + "@firebase/functions-types": "0.6.3", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" } }, - "node_modules/@angular-devkit/schematics/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "node_modules/@firebase/functions-types": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz", + "integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==" + }, + "node_modules/@firebase/installations": { + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.12.tgz", + "integrity": "sha512-ES/WpuAV2k2YtBTvdaknEo7IY8vaGjIjS3zhnHSAIvY9KwTR8XZFXOJoZ3nSkjN1A5R4MtEh+07drnzPDg9vaw==", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "@firebase/component": "0.6.12", + "@firebase/util": "1.10.3", + "idb": "7.1.1", + "tslib": "^2.1.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@firebase/app": "0.x" } }, - "node_modules/@angular-devkit/schematics/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/@firebase/installations-compat": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.12.tgz", + "integrity": "sha512-RhcGknkxmFu92F6Jb3rXxv6a4sytPjJGifRZj8MSURPuv2Xu+/AispCXEfY1ZraobhEHTG5HLGsP6R4l9qB5aA==", + "dependencies": { + "@firebase/component": "0.6.12", + "@firebase/installations": "0.6.12", + "@firebase/installations-types": "0.5.3", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } }, - "node_modules/@angular-devkit/schematics/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "node_modules/@firebase/installations-types": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz", + "integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==", + "peerDependencies": { + "@firebase/app-types": "0.x" + } }, - "node_modules/@angular-devkit/schematics/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/@firebase/logger": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", + "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", + "dependencies": { + "tslib": "^2.1.0" + }, "engines": { - "node": ">= 8" + "node": ">=18.0.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/@firebase/messaging": { + "version": "0.12.16", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.16.tgz", + "integrity": "sha512-VJ8sCEIeP3+XkfbJA7410WhYGHdloYFZXoHe/vt+vNVDGw8JQPTQSVTRvjrUprEf5I4Tbcnpr2H34lS6zhCHSA==", "dependencies": { - "safe-buffer": "~5.2.0" + "@firebase/component": "0.6.12", + "@firebase/installations": "0.6.12", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.10.3", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" } }, - "node_modules/@angular-devkit/schematics/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/@firebase/messaging-compat": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.16.tgz", + "integrity": "sha512-9HZZ88Ig3zQ0ok/Pwt4gQcNsOhoEy8hDHoGsV1am6ulgMuGuDVD2gl11Lere2ksL+msM12Lddi2x/7TCqmODZw==", "dependencies": { - "ansi-regex": "^5.0.1" + "@firebase/component": "0.6.12", + "@firebase/messaging": "0.12.16", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@firebase/app-compat": "0.x" } }, - "node_modules/@angular-devkit/schematics/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@firebase/messaging-interop-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz", + "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==" + }, + "node_modules/@firebase/performance": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.0.tgz", + "integrity": "sha512-L91PwYuiJdKXKSRqsWNicvTppAJVzKjye03UlegeD6TkpKjb93T8AmJ9B0Mt0bcWHCNtnnRBCdSCvD2U9GZDjw==", "dependencies": { - "has-flag": "^4.0.0" + "@firebase/component": "0.6.12", + "@firebase/installations": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0", + "web-vitals": "^4.2.4" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/performance-compat": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.13.tgz", + "integrity": "sha512-pB0SMQj2TLQ6roDcX0YQDWvUnVgsVOl0VnUvyT/VBdCUuQYDHobZsPEuQsoEqmPA44KS/Gl0oyKqf+I8UPtRgw==", + "dependencies": { + "@firebase/component": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/performance": "0.7.0", + "@firebase/performance-types": "0.2.3", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@firebase/app-compat": "0.x" } }, - "node_modules/@angular-devkit/schematics/node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "node_modules/@firebase/performance-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz", + "integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==" }, - "node_modules/@angular-devkit/schematics/node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "node_modules/@firebase/remote-config": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.5.0.tgz", + "integrity": "sha512-weiEbpBp5PBJTHUWR4GwI7ZacaAg68BKha5QnZ8Go65W4oQjEWqCW/rfskABI/OkrGijlL3CUmCB/SA6mVo0qA==", "dependencies": { - "defaults": "^1.0.3" + "@firebase/component": "0.6.12", + "@firebase/installations": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" } }, - "node_modules/@angular/common": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.1.1.tgz", - "integrity": "sha512-2ZbnV8lM81ekLjRMRufRho7N8adz+Yjwj+3y5RB7+GW8fX5f9mm740ifyieBCXPLtiWb8ZK1i9gime6y64BEBQ==", - "peer": true, + "node_modules/@firebase/remote-config-compat": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.12.tgz", + "integrity": "sha512-91jLWPtubIuPBngg9SzwvNCWzhMLcyBccmt7TNZP+y1cuYFNOWWHKUXQ3IrxCLB7WwLqQaEu7fTDAjHsTyBsSw==", "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "@firebase/component": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/remote-config": "0.5.0", + "@firebase/remote-config-types": "0.4.0", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" }, "peerDependencies": { - "@angular/core": "19.1.1", - "rxjs": "^6.5.3 || ^7.4.0" + "@firebase/app-compat": "0.x" } }, - "node_modules/@angular/compiler": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.1.1.tgz", - "integrity": "sha512-bXPiJKQYjH6kSBnlVHx8aLzYY7YhWw1cidthWwqNaXyZ4YYILom1lN3C7nJYOVDX8W64QCMimHqf8iD4guByxA==", - "peer": true, + "node_modules/@firebase/remote-config-types": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz", + "integrity": "sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg==" + }, + "node_modules/@firebase/storage": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.6.tgz", + "integrity": "sha512-BEJLYQzVgAoglRl5VRIRZ91RRBZgS/O37/PSGQJBYNuoLmFZUrtwrlLTOAwG776NlO9VQR+K2j15/36Lr2EqHA==", "dependencies": { - "tslib": "^2.3.0" + "@firebase/component": "0.6.12", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=18.0.0" }, "peerDependencies": { - "@angular/core": "19.1.1" - }, - "peerDependenciesMeta": { - "@angular/core": { - "optional": true - } + "@firebase/app": "0.x" } }, - "node_modules/@angular/core": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.1.1.tgz", - "integrity": "sha512-uEDnomaIh7yUPx6hHWMFcWrUMOwishkkPToSFMltVLfRrfmAQL+WMpOGtR6qiFG6PIppsADIxXPRWVzfnYOYZg==", + "node_modules/@firebase/storage-compat": { + "version": "0.3.16", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.16.tgz", + "integrity": "sha512-EeMuok/s0r938lEomia8XILEqSYULm7HcYZ/GTZLDWur0kMf2ktuPVZiTdRiwEV3Iki7FtQO5txrQ/0pLRVLAw==", "dependencies": { - "tslib": "^2.3.0" + "@firebase/component": "0.6.12", + "@firebase/storage": "0.13.6", + "@firebase/storage-types": "0.8.3", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=18.0.0" }, "peerDependencies": { - "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.15.0" + "@firebase/app-compat": "0.x" } }, - "node_modules/@angular/fire": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/@angular/fire/-/fire-19.0.0.tgz", - "integrity": "sha512-dVU9IdL9sGKe1fV7g2iGgkjUQIYrbnljHtHUgNpZaskyW+Vy6ndtsEbSUoRd6sLP8WpThWH7WvITKhu/8a6qfQ==", - "dependencies": { - "@angular-devkit/schematics": "^19.0.0", - "@schematics/angular": "^19.0.0", - "firebase": "^11.2.0", - "rxfire": "^6.1.0", - "tslib": "^2.3.0" - }, + "node_modules/@firebase/storage-types": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz", + "integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==", "peerDependencies": { - "@angular/common": "^19.0.0", - "@angular/core": "^19.0.0", - "@angular/platform-browser": "^19.0.0", - "@angular/platform-browser-dynamic": "^19.0.0", - "@angular/platform-server": "^19.0.0", - "firebase-tools": "^13.0.0", - "rxjs": "~7.8.0" - }, - "peerDependenciesMeta": { - "@angular/platform-server": { - "optional": true - }, - "firebase-tools": { - "optional": true - } + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" } }, - "node_modules/@angular/platform-browser": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.1.1.tgz", - "integrity": "sha512-L33rk7j3FepDqHo29iqp7ucL1tBjGQed+e22ei9bCsj7CG0GNi5w8id3nyNImhwN26wtg++4cu4la+XxKWIkXg==", - "peer": true, + "node_modules/@firebase/util": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.3.tgz", + "integrity": "sha512-wfoF5LTy0m2ufUapV0ZnpcGQvuavTbJ5Qr1Ze9OJGL70cSMvhDyjS4w2121XdA3lGZSTOsDOyGhpoDtYwck85A==", "dependencies": { - "tslib": "^2.3.0" + "tslib": "^2.1.0" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/animations": "19.1.1", - "@angular/common": "19.1.1", - "@angular/core": "19.1.1" - }, - "peerDependenciesMeta": { - "@angular/animations": { - "optional": true - } + "node": ">=18.0.0" } }, - "node_modules/@angular/platform-browser-dynamic": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.1.1.tgz", - "integrity": "sha512-iEVOFKpBEFXKDqQb42xhEXpseQc2vpl16kuT9gbjuvBC8KJLsTdvE34HIoZN1Igm22wZzp+PBzSWYa8WiQK83A==", - "peer": true, + "node_modules/@firebase/vertexai": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.4.tgz", + "integrity": "sha512-Nkf/r4u166b4Id6zrrW0Qtg1KyZpQvvYchtkebamnHtIfY+Qnt51I/sx4Saos/WrmO8SnrSU850LfmJ7pehYXg==", "dependencies": { - "tslib": "^2.3.0" + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/component": "0.6.12", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.10.3", + "tslib": "^2.1.0" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=18.0.0" }, "peerDependencies": { - "@angular/common": "19.1.1", - "@angular/compiler": "19.1.1", - "@angular/core": "19.1.1", - "@angular/platform-browser": "19.1.1" + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" } }, - "node_modules/@schematics/angular": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.1.1.tgz", - "integrity": "sha512-XrnmSbCcDPePCbEVhgEPFZFiL/fowvkPJ8qOa1m9tWHSPYb739Vk3g+VDrAqNMm7FULcRzQzqHBq/IBB8qYfIg==", + "node_modules/@firebase/webchannel-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz", + "integrity": "sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==" + }, + "node_modules/@grpc/grpc-js": { + "version": "1.9.15", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", + "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", "dependencies": { - "@angular-devkit/core": "19.1.1", - "@angular-devkit/schematics": "19.1.1", - "jsonc-parser": "3.3.1" + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": "^8.13.0 || >=10.10.0" } }, - "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.1.tgz", - "integrity": "sha512-CAqst7WEasPHR4OFdbxxX3+NVqNTvYk3vtPbXT/jZ0L2EZRICQta2EClkdhSIiMkiMf0/2LNT05rYD7k4NHIQA==", + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", "dependencies": { - "ajv": "8.17.1", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.2", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" }, - "peerDependencies": { - "chokidar": "^4.0.0" + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } + "engines": { + "node": ">=6" } }, - "node_modules/@schematics/angular/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">= 8" } }, - "node_modules/@schematics/angular/node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "dependencies": { - "ajv": "^8.0.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "engines": { + "node": ">= 8" } }, - "node_modules/@schematics/angular/node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" }, - "node_modules/@schematics/angular/node_modules/fast-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", - "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ] + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" }, - "node_modules/@schematics/angular/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" }, - "node_modules/@schematics/angular/node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" }, - "node_modules/@schematics/angular/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" } }, - "node_modules/@schematics/angular/node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" }, - "node_modules/@schematics/angular/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "engines": { - "node": ">= 8" - } + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" }, - "node_modules/@tanstack-query-firebase/angular": { - "version": "0.0.1", - "resolved": "file:../../../../bin/tanstack-query-firebase-angular-0.0.1.tgz", - "integrity": "sha512-9TpELHRj9UGhuR/hKCMsDo7uoxampon6HX6v4UMxaLqA8p3jvnG2cS1DKaRdnpOvBX11CuRztv9iwVl3yCqFHw==", - "license": "ISC", + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@schematics/angular": { + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.1.7.tgz", + "integrity": "sha512-BB8yMGmYDZzSb8Nu+Ln0TKyeoS3++f9STCYw30NwM3IViHxJJYxu/zowzwSa9TjftIzdCpbOaPxGS0vU9UOUDQ==", "dependencies": { - "@angular/core": "^19.1.0", - "@angular/fire": "^19.0.0-rc.5", - "@tanstack/angular-query-experimental": "^5.64.1", - "firebase": "^11.1.0" + "@angular-devkit/core": "19.1.7", + "@angular-devkit/schematics": "19.1.7", + "jsonc-parser": "3.3.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, "node_modules/@tanstack/angular-query-experimental": { - "version": "5.64.1", - "resolved": "https://registry.npmjs.org/@tanstack/angular-query-experimental/-/angular-query-experimental-5.64.1.tgz", - "integrity": "sha512-JMLxcQgdXATg54ZE9hdsGGb5V0ZKbfwnuQsyOHSU9bVaSpg0o/ps1Z8ngRbdOAjVuvjYbkte/Cn6aIpt29BaCQ==", + "version": "5.66.0", + "resolved": "https://registry.npmjs.org/@tanstack/angular-query-experimental/-/angular-query-experimental-5.66.0.tgz", + "integrity": "sha512-wECwAbsIQWXiKXNOjvAWeyw44KZJ/q0hWdWUy4SV3vp8eFW3f0LvAlkuLvUSA8jdcC5NvO2VO8T/gLRE9YjArg==", "dependencies": { - "@tanstack/query-core": "5.64.1", - "@tanstack/query-devtools": "5.62.16" + "@tanstack/query-core": "5.66.0", + "@tanstack/query-devtools": "5.65.0" }, "funding": { "type": "github", @@ -787,823 +997,788 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.64.1", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.64.1.tgz", - "integrity": "sha512-978Wx4Wl4UJZbmvU/rkaM9cQtXXrbhK0lsz/UZhYIbyKYA8E4LdomTwyh2GHZ4oU0BKKoDH4YlKk2VscCUgNmg==", + "version": "5.66.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.66.0.tgz", + "integrity": "sha512-J+JeBtthiKxrpzUu7rfIPDzhscXF2p5zE/hVdrqkACBP8Yu0M96mwJ5m/8cPPYQE9aRNvXztXHlNwIh4FEeMZw==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/query-devtools": { - "version": "5.62.16", - "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.62.16.tgz", - "integrity": "sha512-3ff6UBJr0H3nIhfLSl9911rvKqXf0u4B58jl0uYdDWLqPk9pCvYIbxC35cGxK2+8INl4IaFVUHb/IdgWrNkg3Q==", + "version": "5.65.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.65.0.tgz", + "integrity": "sha512-g5y7zc07U9D3esMdqUfTEVu9kMHoIaVBsD0+M3LPdAdD710RpTcLiNvJY1JkYXqkq9+NV+CQoemVNpQPBXVsJg==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/firebase": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.2.0.tgz", - "integrity": "sha512-ztwPhBLAZMVNZjBeQzzTM4rk2rsRXmdFYcnvjAXh+StbiFVshHKaPO9VRGMUzF48du4Mkz6jN1wkmYCuUJPxLA==", - "dependencies": { - "@firebase/analytics": "0.10.11", - "@firebase/analytics-compat": "0.2.17", - "@firebase/app": "0.10.18", - "@firebase/app-check": "0.8.11", - "@firebase/app-check-compat": "0.3.18", - "@firebase/app-compat": "0.2.48", - "@firebase/app-types": "0.9.3", - "@firebase/auth": "1.8.2", - "@firebase/auth-compat": "0.5.17", - "@firebase/data-connect": "0.2.0", - "@firebase/database": "1.0.11", - "@firebase/database-compat": "2.0.2", - "@firebase/firestore": "4.7.6", - "@firebase/firestore-compat": "0.3.41", - "@firebase/functions": "0.12.1", - "@firebase/functions-compat": "0.3.18", - "@firebase/installations": "0.6.12", - "@firebase/installations-compat": "0.2.12", - "@firebase/messaging": "0.12.16", - "@firebase/messaging-compat": "0.2.16", - "@firebase/performance": "0.6.12", - "@firebase/performance-compat": "0.2.12", - "@firebase/remote-config": "0.5.0", - "@firebase/remote-config-compat": "0.2.12", - "@firebase/storage": "0.13.5", - "@firebase/storage-compat": "0.3.15", - "@firebase/util": "1.10.3", - "@firebase/vertexai": "1.0.3" - } - }, - "node_modules/firebase/node_modules/@firebase/analytics": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.11.tgz", - "integrity": "sha512-zwuPiRE0+hgcS95JZbJ6DFQN4xYFO8IyGxpeePTV51YJMwCf3lkBa6FnZ/iXIqDKcBPMgMuuEZozI0BJWaLEYg==", - "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/installations": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/firebase/node_modules/@firebase/analytics-compat": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.17.tgz", - "integrity": "sha512-SJNVOeTvzdqZQvXFzj7yAirXnYcLDxh57wBFROfeowq/kRN1AqOw1tG6U4OiFOEhqi7s3xLze/LMkZatk2IEww==", + "node_modules/@testing-library/angular": { + "version": "17.3.5", + "resolved": "https://registry.npmjs.org/@testing-library/angular/-/angular-17.3.5.tgz", + "integrity": "sha512-B79mN7kNDY9/+0Kc6cVGnVptQ03oHVL1at1tMu44wvr7Ksk10g11lZw7BA0c7rHAJQoXgiWrXmvtJxkPA1R2uA==", + "dev": true, "dependencies": { - "@firebase/analytics": "0.10.11", - "@firebase/analytics-types": "0.8.3", - "@firebase/component": "0.6.12", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "tslib": "^2.3.1" }, "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/firebase/node_modules/@firebase/analytics-types": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz", - "integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==" - }, - "node_modules/firebase/node_modules/@firebase/app": { - "version": "0.10.18", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.18.tgz", - "integrity": "sha512-VuqEwD/QRisKd/zsFsqgvSAx34mZ3WEF47i97FD6Vw4GWAhdjepYf0Hmi6K0b4QMSgWcv/x0C30Slm5NjjERXg==", - "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "idb": "7.1.1", - "tslib": "^2.1.0" + "@angular/common": ">= 17.0.0", + "@angular/core": ">= 17.0.0", + "@angular/platform-browser": ">= 17.0.0", + "@angular/router": ">= 17.0.0", + "@testing-library/dom": "^10.0.0" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/firebase/node_modules/@firebase/app-check": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.11.tgz", - "integrity": "sha512-42zIfRI08/7bQqczAy7sY2JqZYEv3a1eNa4fLFdtJ54vNevbBIRSEA3fZgRqWFNHalh5ohsBXdrYgFqaRIuCcQ==", + "node_modules/@ts-morph/common": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.22.0.tgz", + "integrity": "sha512-HqNBuV/oIlMKdkLshXd1zKBqNQCsuPEsgQOkfFQ/eUKjRlwndXW1AjN9LVkBEIukm00gGXSRmfkl0Wv5VXLnlw==", + "dev": true, "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" + "fast-glob": "^3.3.2", + "minimatch": "^9.0.3", + "mkdirp": "^3.0.1", + "path-browserify": "^1.0.1" } }, - "node_modules/firebase/node_modules/@firebase/app-check-compat": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.18.tgz", - "integrity": "sha512-qjozwnwYmAIdrsVGrJk+hnF1WBois54IhZR6gO0wtZQoTvWL/GtiA2F31TIgAhF0ayUiZhztOv1RfC7YyrZGDQ==", + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "22.13.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", + "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", "dependencies": { - "@firebase/app-check": "0.8.11", - "@firebase/app-check-types": "0.5.3", - "@firebase/component": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "undici-types": "~6.20.0" } }, - "node_modules/firebase/node_modules/@firebase/app-check-interop-types": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", - "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==" - }, - "node_modules/firebase/node_modules/@firebase/app-check-types": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz", - "integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==" + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true }, - "node_modules/firebase/node_modules/@firebase/app-compat": { - "version": "0.2.48", - "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.48.tgz", - "integrity": "sha512-wVNU1foBIaJncUmiALyRxhHHHC3ZPMLIETTAk+2PG87eP9B/IDBsYUiTpHyboDPEI8CgBPat/zN2v+Snkz6lBw==", + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dependencies": { - "@firebase/app": "0.10.18", - "@firebase/component": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, - "engines": { - "node": ">=18.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/firebase/node_modules/@firebase/app-types": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", - "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==" - }, - "node_modules/firebase/node_modules/@firebase/auth": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.8.2.tgz", - "integrity": "sha512-q+071y2LWe0bVnjqaX3BscqZwzdP0GKN2YBKapLq4bV88MPfCtWwGKmDhNDEDUmioOjudGXkUY5cvvKqk3mlUg==", + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" + "ajv": "^8.0.0" }, "peerDependencies": { - "@firebase/app": "0.x", - "@react-native-async-storage/async-storage": "^1.18.1" + "ajv": "^8.0.0" }, "peerDependenciesMeta": { - "@react-native-async-storage/async-storage": { + "ajv": { "optional": true } } }, - "node_modules/firebase/node_modules/@firebase/auth-compat": { - "version": "0.5.17", - "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.17.tgz", - "integrity": "sha512-Shi6rqLqzU9KLXnUCmlLvVByq1kiG3oe7Wpbf5m1CgS7NiRx2pSSn0HLaRRozdkaizNzMGGj+3oHmNYQ7kU6xA==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "@firebase/auth": "1.8.2", - "@firebase/auth-types": "0.12.3", - "@firebase/component": "0.6.12", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=18.0.0" + "node": ">=8" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/firebase/node_modules/@firebase/auth-interop-types": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", - "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==" - }, - "node_modules/firebase/node_modules/@firebase/auth-types": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.3.tgz", - "integrity": "sha512-Zq9zI0o5hqXDtKg6yDkSnvMCMuLU6qAVS51PANQx+ZZX5xnzyNLEBO3GZgBUPsV5qIMFhjhqmLDxUqCbnAYy2A==", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/firebase/node_modules/@firebase/component": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.12.tgz", - "integrity": "sha512-YnxqjtohLbnb7raXt2YuA44cC1wA9GiehM/cmxrsoxKlFxBLy2V0OkRSj9gpngAE0UoJ421Wlav9ycO7lTPAUw==", + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, "dependencies": { - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" + "dequal": "^2.0.3" } }, - "node_modules/firebase/node_modules/@firebase/data-connect": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.2.0.tgz", - "integrity": "sha512-7OrZtQoLSk2fiGijhIdUnTSqEFti3h1EMhw9nNiSZ6jJGduw4Pz6jrVvxjpZJtGH/JiljbMkBnPBS2h8CTRKEw==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dependencies": { - "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/firebase/node_modules/@firebase/database": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.11.tgz", - "integrity": "sha512-gLrw/XeioswWUXgpVKCPAzzoOuvYNqK5fRUeiJTzO7Mlp9P6ylFEyPJlRBl1djqYye641r3MX6AmIeMXwjgwuQ==", + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { - "@firebase/app-check-interop-types": "0.3.3", - "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "faye-websocket": "0.11.4", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=18.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/firebase/node_modules/@firebase/database-compat": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.2.tgz", - "integrity": "sha512-5zvdnMsfDHvrQAVM6jBS7CkBpu+z3YbpFdhxRsrK1FP45IEfxlzpeuEUb17D/tpM10vfq4Ok0x5akIBaCv7gfA==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/database": "1.0.11", - "@firebase/database-types": "1.0.8", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "fill-range": "^7.1.1" }, "engines": { - "node": ">=18.0.0" + "node": ">=8" } }, - "node_modules/firebase/node_modules/@firebase/database-types": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.8.tgz", - "integrity": "sha512-6lPWIGeufhUq1heofZULyVvWFhD01TUrkkB9vyhmksjZ4XF7NaivQp9rICMk7QNhqwa+uDCaj4j+Q8qqcSVZ9g==", + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "@firebase/app-types": "0.9.3", - "@firebase/util": "1.10.3" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/firebase/node_modules/@firebase/firestore": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.6.tgz", - "integrity": "sha512-aVDboR+upR/44qZDLR4tnZ9pepSOFBbDJnwk7eWzmTyQq2nZAVG+HIhrqpQawmUVcDRkuJv2K2UT2+oqR8F8TA==", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "@firebase/webchannel-wrapper": "1.0.3", - "@grpc/grpc-js": "~1.9.0", - "@grpc/proto-loader": "^0.7.8", - "tslib": "^2.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=10" }, - "peerDependencies": { - "@firebase/app": "0.x" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/firebase/node_modules/@firebase/firestore-compat": { - "version": "0.3.41", - "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.41.tgz", - "integrity": "sha512-J/PgWKEt0yugETOE7lOabT16hsV21cLzSxERD7ZhaiwBQkBTSf0Mx9RhjZRT0Ttqe4weM90HGZFyUBqYA73fVA==", + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/firestore": "4.7.6", - "@firebase/firestore-types": "3.0.3", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "restore-cursor": "^3.1.0" }, "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "node": ">=8" } }, - "node_modules/firebase/node_modules/@firebase/firestore-types": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz", - "integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/firebase/node_modules/@firebase/functions": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.1.tgz", - "integrity": "sha512-QucRiFrvMMmIGTRhL7ZK2IeBnAWP7lAmfFREMpEtX47GjVqDqGxdFs+Mg7XBzxSc9UjDO4Rxf+aE9xJHU6bGwg==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dependencies": { - "@firebase/app-check-interop-types": "0.3.3", - "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.12", - "@firebase/messaging-interop-types": "0.2.3", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" + "node": ">=12" } }, - "node_modules/firebase/node_modules/@firebase/functions-compat": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.18.tgz", - "integrity": "sha512-N7+RN5GVus2ORB8cqfSNhfSn4iaYws6F8uCCfn4mtjC7zYS/KH6muzNAhZUdUqlv5YazbVmvxlAoYYF39i8Qzg==", - "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/functions": "0.12.1", - "@firebase/functions-types": "0.6.3", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" - }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "node": ">=0.8" } }, - "node_modules/firebase/node_modules/@firebase/functions-types": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz", - "integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==" + "node_modules/code-block-writer": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-12.0.0.tgz", + "integrity": "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==", + "dev": true }, - "node_modules/firebase/node_modules/@firebase/installations": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.12.tgz", - "integrity": "sha512-ES/WpuAV2k2YtBTvdaknEo7IY8vaGjIjS3zhnHSAIvY9KwTR8XZFXOJoZ3nSkjN1A5R4MtEh+07drnzPDg9vaw==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/util": "1.10.3", - "idb": "7.1.1", - "tslib": "^2.1.0" + "color-name": "~1.1.4" }, - "peerDependencies": { - "@firebase/app": "0.x" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/firebase/node_modules/@firebase/installations-compat": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.12.tgz", - "integrity": "sha512-RhcGknkxmFu92F6Jb3rXxv6a4sytPjJGifRZj8MSURPuv2Xu+/AispCXEfY1ZraobhEHTG5HLGsP6R4l9qB5aA==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/installations": "0.6.12", - "@firebase/installations-types": "0.5.3", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "clone": "^1.0.2" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/firebase/node_modules/@firebase/installations-types": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz", - "integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==", - "peerDependencies": { - "@firebase/app-types": "0.x" + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" } }, - "node_modules/firebase/node_modules/@firebase/logger": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz", - "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==", - "dependencies": { - "tslib": "^2.1.0" - }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { - "node": ">=18.0.0" + "node": ">=6" } }, - "node_modules/firebase/node_modules/@firebase/messaging": { - "version": "0.12.16", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.16.tgz", - "integrity": "sha512-VJ8sCEIeP3+XkfbJA7410WhYGHdloYFZXoHe/vt+vNVDGw8JQPTQSVTRvjrUprEf5I4Tbcnpr2H34lS6zhCHSA==", - "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/installations": "0.6.12", - "@firebase/messaging-interop-types": "0.2.3", - "@firebase/util": "1.10.3", - "idb": "7.1.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "node_modules/firebase/node_modules/@firebase/messaging-compat": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.16.tgz", - "integrity": "sha512-9HZZ88Ig3zQ0ok/Pwt4gQcNsOhoEy8hDHoGsV1am6ulgMuGuDVD2gl11Lere2ksL+msM12Lddi2x/7TCqmODZw==", + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/messaging": "0.12.16", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=8.6.0" } }, - "node_modules/firebase/node_modules/@firebase/messaging-interop-types": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz", - "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==" + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] }, - "node_modules/firebase/node_modules/@firebase/performance": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.12.tgz", - "integrity": "sha512-8mYL4z2jRlKXAi2hjk4G7o2sQLnJCCuTbyvti/xmHf5ZvOIGB01BZec0aDuBIXO+H1MLF62dbye/k91Fr+yc8g==", + "node_modules/fastq": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", + "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", + "dev": true, "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/installations": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" + "reusify": "^1.0.4" } }, - "node_modules/firebase/node_modules/@firebase/performance-compat": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.12.tgz", - "integrity": "sha512-DyCbDTIwtBTGsEiQxTz/TD23a0na2nrDozceQ5kVkszyFYvliB0YK/9el0wAGIG91SqgTG9pxHtYErzfZc0VWw==", + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/performance": "0.6.12", - "@firebase/performance-types": "0.2.3", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "websocket-driver": ">=0.5.1" }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/firebase/node_modules/@firebase/performance-types": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz", - "integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==" - }, - "node_modules/firebase/node_modules/@firebase/remote-config": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.5.0.tgz", - "integrity": "sha512-weiEbpBp5PBJTHUWR4GwI7ZacaAg68BKha5QnZ8Go65W4oQjEWqCW/rfskABI/OkrGijlL3CUmCB/SA6mVo0qA==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/installations": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "to-regex-range": "^5.0.1" }, - "peerDependencies": { - "@firebase/app": "0.x" + "engines": { + "node": ">=8" } }, - "node_modules/firebase/node_modules/@firebase/remote-config-compat": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.12.tgz", - "integrity": "sha512-91jLWPtubIuPBngg9SzwvNCWzhMLcyBccmt7TNZP+y1cuYFNOWWHKUXQ3IrxCLB7WwLqQaEu7fTDAjHsTyBsSw==", - "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/logger": "0.4.4", + "node_modules/firebase": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.3.1.tgz", + "integrity": "sha512-P4YVFM0Bm2d8aO61SCEMF8E1pYgieGLrmr/LFw7vs6sAMebwuwHt+Wug+1qL2fhAHWPwpWbCLsdJH8NQ+4Sw8Q==", + "dependencies": { + "@firebase/analytics": "0.10.11", + "@firebase/analytics-compat": "0.2.17", + "@firebase/app": "0.11.1", + "@firebase/app-check": "0.8.11", + "@firebase/app-check-compat": "0.3.18", + "@firebase/app-compat": "0.2.50", + "@firebase/app-types": "0.9.3", + "@firebase/auth": "1.9.0", + "@firebase/auth-compat": "0.5.18", + "@firebase/data-connect": "0.3.0", + "@firebase/database": "1.0.12", + "@firebase/database-compat": "2.0.3", + "@firebase/firestore": "4.7.8", + "@firebase/firestore-compat": "0.3.43", + "@firebase/functions": "0.12.2", + "@firebase/functions-compat": "0.3.19", + "@firebase/installations": "0.6.12", + "@firebase/installations-compat": "0.2.12", + "@firebase/messaging": "0.12.16", + "@firebase/messaging-compat": "0.2.16", + "@firebase/performance": "0.7.0", + "@firebase/performance-compat": "0.2.13", "@firebase/remote-config": "0.5.0", - "@firebase/remote-config-types": "0.4.0", + "@firebase/remote-config-compat": "0.2.12", + "@firebase/storage": "0.13.6", + "@firebase/storage-compat": "0.3.16", "@firebase/util": "1.10.3", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "@firebase/vertexai": "1.0.4" } }, - "node_modules/firebase/node_modules/@firebase/remote-config-types": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz", - "integrity": "sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg==" + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } }, - "node_modules/firebase/node_modules/@firebase/storage": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.5.tgz", - "integrity": "sha512-sB/7HNuW0N9tITyD0RxVLNCROuCXkml5i/iPqjwOGKC0xiUfpCOjBE+bb0ABMoN1qYZfqk0y9IuI2TdomjmkNw==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" + "node": ">= 6" } }, - "node_modules/firebase/node_modules/@firebase/storage-compat": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.15.tgz", - "integrity": "sha512-Z9afjrK2O9o1ZHWCpprCGZ1BTc3BbvpZvi6tkSteC8H3W/fMM6x+RoSunlzD3hEVV5bkbwdJIqNClLMchvyoPA==", - "dependencies": { - "@firebase/component": "0.6.12", - "@firebase/storage": "0.13.5", - "@firebase/storage-types": "0.8.3", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" - }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" + "node": ">=8" } }, - "node_modules/firebase/node_modules/@firebase/storage-types": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz", - "integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" + "node_modules/http-parser-js": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz", + "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==" + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/firebase/node_modules/@firebase/util": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.3.tgz", - "integrity": "sha512-wfoF5LTy0m2ufUapV0ZnpcGQvuavTbJ5Qr1Ze9OJGL70cSMvhDyjS4w2121XdA3lGZSTOsDOyGhpoDtYwck85A==", - "dependencies": { - "tslib": "^2.1.0" - }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": ">=18.0.0" + "node": ">=8" } }, - "node_modules/firebase/node_modules/@firebase/vertexai": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.0.3.tgz", - "integrity": "sha512-SQHg/RPb3LwQs/xiLcvAZYz9NXyDSZUIIwvgsKh6e4wdULAfyPCZIu6Y2ZYIhZLfk9Q44cKZ+++7RPTaqQJdYA==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "dependencies": { - "@firebase/app-check-interop-types": "0.3.3", - "@firebase/component": "0.6.12", - "@firebase/logger": "0.4.4", - "@firebase/util": "1.10.3", - "tslib": "^2.1.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" + "node": ">=0.10.0" } }, - "node_modules/firebase/node_modules/@firebase/webchannel-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz", - "integrity": "sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==" + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } }, - "node_modules/firebase/node_modules/@grpc/grpc-js": { - "version": "1.9.15", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", - "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", - "dependencies": { - "@grpc/proto-loader": "^0.7.8", - "@types/node": ">=12.12.47" - }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=0.12.0" } }, - "node_modules/firebase/node_modules/@grpc/proto-loader": { - "version": "0.7.13", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", - "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/firebase/node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, - "node_modules/firebase/node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, - "node_modules/firebase/node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" }, - "node_modules/firebase/node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" }, - "node_modules/firebase/node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/firebase/node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "node_modules/firebase/node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "node_modules/long": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.0.tgz", + "integrity": "sha512-5vvY5yF1zF/kXk+L94FRiTDa1Znom46UjPCH6/XbSvS8zBKMFBHTJk8KDMqJ+2J6QezQFi7k1k8v21ClJYHPaw==" }, - "node_modules/firebase/node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } }, - "node_modules/firebase/node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } }, - "node_modules/firebase/node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } }, - "node_modules/firebase/node_modules/@types/node": { - "version": "22.10.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", - "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "dependencies": { - "undici-types": "~6.20.0" + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" } }, - "node_modules/firebase/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/firebase/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/firebase/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=12" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/firebase/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dependencies": { - "color-name": "~1.1.4" + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, "engines": { - "node": ">=7.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/firebase/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true }, - "node_modules/firebase/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true }, - "node_modules/firebase/node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/firebase/node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "dependencies": { - "websocket-driver": ">=0.5.1" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" }, "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/firebase/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/firebase/node_modules/http-parser-js": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz", - "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==" - }, - "node_modules/firebase/node_modules/idb": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", - "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" - }, - "node_modules/firebase/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/firebase/node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" - }, - "node_modules/firebase/node_modules/long": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.4.tgz", - "integrity": "sha512-qtzLbJE8hq7VabR3mISmVGtoXP8KGc2Z/AT8OuqlYD7JTR3oqrgwdjnk07wpj1twXxYmgDXgoKVWUG/fReSzHg==" - }, - "node_modules/firebase/node_modules/protobufjs": { + "node_modules/protobufjs": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", @@ -1626,7 +1801,52 @@ "node": ">=12.0.0" } }, - "node_modules/firebase/node_modules/require-directory": { + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", @@ -1634,7 +1854,77 @@ "node": ">=0.10.0" } }, - "node_modules/firebase/node_modules/safe-buffer": { + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxfire": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/rxfire/-/rxfire-6.1.0.tgz", + "integrity": "sha512-NezdjeY32VZcCuGO0bbb8H8seBsJSCaWdUwGsHNzUcAOHR0VGpzgPtzjuuLXr8R/iemkqSzbx/ioS7VwV43ynA==", + "peerDependencies": { + "firebase": "^9.0.0 || ^10.0.0 || ^11.0.0", + "rxjs": "^6.0.0 || ^7.0.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", @@ -1653,7 +1943,28 @@ } ] }, - "node_modules/firebase/node_modules/string-width": { + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", @@ -1666,7 +1977,7 @@ "node": ">=8" } }, - "node_modules/firebase/node_modules/strip-ansi": { + "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", @@ -1677,12 +1988,109 @@ "node": ">=8" } }, - "node_modules/firebase/node_modules/undici-types": { + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-morph": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-21.0.1.tgz", + "integrity": "sha512-dbDtVdEAncKctzrVZ+Nr7kHpHkv+0JDJb2MjjpBaj8bFeCkePU9rHfMklmhuLFnpeq/EJZk2IhStY6NzqgjOkg==", + "dev": true, + "dependencies": { + "@ts-morph/common": "~0.22.0", + "code-block-writer": "^12.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/undici-types": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, - "node_modules/firebase/node_modules/websocket-driver": { + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-vitals": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", + "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==" + }, + "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", @@ -1695,7 +2103,7 @@ "node": ">=0.8.0" } }, - "node_modules/firebase/node_modules/websocket-extensions": { + "node_modules/websocket-extensions": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", @@ -1703,7 +2111,7 @@ "node": ">=0.8.0" } }, - "node_modules/firebase/node_modules/wrap-ansi": { + "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", @@ -1719,7 +2127,7 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/firebase/node_modules/y18n": { + "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", @@ -1727,7 +2135,7 @@ "node": ">=10" } }, - "node_modules/firebase/node_modules/yargs": { + "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", @@ -1744,7 +2152,7 @@ "node": ">=12" } }, - "node_modules/firebase/node_modules/yargs-parser": { + "node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", @@ -1752,28 +2160,6 @@ "node": ">=12" } }, - "node_modules/rxfire": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/rxfire/-/rxfire-6.1.0.tgz", - "integrity": "sha512-NezdjeY32VZcCuGO0bbb8H8seBsJSCaWdUwGsHNzUcAOHR0VGpzgPtzjuuLXr8R/iemkqSzbx/ioS7VwV43ynA==", - "peerDependencies": { - "firebase": "^9.0.0 || ^10.0.0 || ^11.0.0", - "rxjs": "^6.0.0 || ^7.0.0" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, "node_modules/zone.js": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.0.tgz", diff --git a/packages/angular/package.json b/packages/angular/package.json index 43f1acc0..0f189abf 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -4,20 +4,22 @@ "description": "Tanstack Query bindings for Firebase and Angular", "type": "module", "files": [ - "dist", + "./index.js", + "./index.d.ts", "data-connect" ], "scripts": { "build": "tsup", "watch": "tsup --watch", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "vitest --dom --coverage" }, - "typings": "./dist/index.d.ts", - "module": "./dist/index.js", + "typings": "./index.d.ts", + "module": "./index.js", "exports": { ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" + "types": "./index.d.ts", + "import": "./index.js", + "default": "./data-connect/index.js" }, "./data-connect": { "import": "./data-connect/index.js", @@ -28,9 +30,15 @@ "author": "", "license": "ISC", "dependencies": { + "@angular/animations": "^19.1.6", "@angular/core": "^19.1.0", "@angular/fire": "^19.0.0-rc.5", "@tanstack/angular-query-experimental": "^5.64.1", "firebase": "^11.1.0" + }, + "devDependencies": { + "@analogjs/vite-plugin-angular": "^1.13.0", + "@testing-library/angular": "^17.3.5", + "@testing-library/dom": "^10.4.0" } } diff --git a/packages/angular/src/data-connect/index.ts b/packages/angular/src/data-connect/index.ts index c2b372d3..7416121e 100644 --- a/packages/angular/src/data-connect/index.ts +++ b/packages/angular/src/data-connect/index.ts @@ -8,6 +8,15 @@ import { QueryClient, QueryKey, } from "@tanstack/angular-query-experimental"; + +import { FirebaseError } from "firebase/app"; + +import { + assertInInjectionContext, + computed, + inject, + signal, +} from "@angular/core"; import { DataConnect, executeMutation, @@ -16,12 +25,14 @@ import { MutationResult, QueryRef, QueryResult, -} from "firebase/data-connect"; -import { FirebaseError } from "firebase/app"; - -import { inject, signal } from "@angular/core"; +} from "@angular/fire/data-connect"; +import { createMovieRef } from "../../dataconnect-sdk/js/default-connector/angular"; function getQueryKey(queryRef: QueryRef) { - return [queryRef.name, queryRef.variables]; + const key: (string | Record)[] = [queryRef.name]; + if ("variables" in queryRef && queryRef.variables !== undefined) { + key.push(queryRef.variables as unknown as Record); + } + return key; } type FlattenedQueryResult = Omit< QueryResult, @@ -49,6 +60,7 @@ interface CreateDataConnectQueryOptions export function injectDataConnectQuery( queryRefOrOptionsFn: | QueryRef + | (QueryRef ) | (() => CreateDataConnectQueryOptions) ): CreateQueryResult, FirebaseError> { const queryKey = signal([]); @@ -80,13 +92,13 @@ export function injectDataConnectQuery( return injectQuery(fdcOptionsFn); } -export type GeneratedSignature = ( +export type GeneratedSignature = (( dc: DataConnect, vars: Variables -) => MutationRef; +) => MutationRef); // TODO(mtewani): Add export type DataConnectMutationOptionsFn = () => Omit, "mutationFn"> & { - invalidate?: QueryKey | QueryRef[]; + invalidate?: QueryKey | QueryRef[]; dataConnect?: DataConnect; mutationFn: (args: Arguments) => MutationRef; }; @@ -135,7 +147,11 @@ export function injectDataConnectMutation( FirebaseError, Arguments >; -export function injectDataConnectMutation( +export function injectDataConnectMutation< + Data, + Variables, + Arguments extends Variables +>( factoryFn: GeneratedSignature, optionsFn?: DataConnectMutationOptionsUndefinedMutationFn< Data, @@ -147,6 +163,7 @@ export function injectDataConnectMutation( FirebaseError, Arguments >; +// TODO(mtewani): Just check for the fact that the user has passed in a generated Angular fn. AKA __angular: true /** * injectDataConnectMutation takes a mutation ref factory function and returns a tanstack wrapper around `injectMutation` * @param factoryFn generated SDK factory function @@ -171,15 +188,21 @@ export function injectDataConnectMutation< FirebaseError, Arguments > { + assertInInjectionContext(injectDataConnectMutation); + const dataConnect = inject(DataConnect); + const queryClient = inject(QueryClient); const injectCb = () => { - const queryClient = inject(QueryClient); - const providedOptions = optionsFn ? optionsFn() : undefined; + // TODO(mtewani): Figure out why this is needed + // Remember: there's a compute() on the optionsFn that's passed on the injectionMutation + const optionsSignal = computed(() => { + return optionsFn ? optionsFn() : undefined; + }); const modifiedFn = (args: Arguments) => { - const dataConnect = inject(DataConnect); + const providedOptions = optionsSignal(); const ref = (providedOptions && - "mutationFn" in providedOptions && - providedOptions.mutationFn(args as Arguments)) || + "mutationFn" in providedOptions! && + providedOptions!.mutationFn(args as Arguments)) || factoryFn!(dataConnect, args as Variables); return executeMutation(ref) @@ -191,24 +214,40 @@ export function injectDataConnectMutation< }; }) .then((ret) => { - providedOptions?.invalidate?.forEach((qk) => { - let key = qk; - if ("name" in (qk as Object)) { - const queryKey = getQueryKey(qk as QueryRef); - key = queryKey; + if (providedOptions?.invalidate) { + for (const qk of providedOptions.invalidate) { + // @ts-ignore + let key = qk; + if ("name" in (key as Object)) { + // @ts-ignore + const queryKey = getQueryKey(key as QueryRef); + key = queryKey; + if ( + key && + "variables" in (qk as Object) && + (qk as QueryRef).variables !== undefined + ) { + queryClient.invalidateQueries({ + queryKey: key, + exact: true, + }); + } else { + queryClient.invalidateQueries({ + queryKey: key, + }); + } + } } - queryClient.invalidateQueries({ - queryKey: key, - }); - }); + } return ret; }) as Promise>; }; return { - ...providedOptions, mutationFn: modifiedFn, }; }; return injectMutation(injectCb); } + + diff --git a/packages/react/src/data-connect/useDataConnectMutation.ts b/packages/react/src/data-connect/useDataConnectMutation.ts index d277d4c9..72b2853d 100644 --- a/packages/react/src/data-connect/useDataConnectMutation.ts +++ b/packages/react/src/data-connect/useDataConnectMutation.ts @@ -9,6 +9,7 @@ import { type MutationRef, type QueryRef, executeMutation, + mutationRef, } from "firebase/data-connect"; import type { FlattenedMutationResult } from "./types"; From 88d6c7615feb25c0e940ba8fb032090a10ced69f Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 19 Feb 2025 15:52:24 -0800 Subject: [PATCH 09/10] First pass at angular framework --- .vscode/launch.json | 27 + .../js/default-connector/README.md | 531 ++++++++++ .../js/default-connector/esm/index.esm.js | 58 ++ .../js/default-connector/esm/package.json | 1 + .../js/default-connector/index.cjs.js | 64 ++ .../js/default-connector/index.d.ts | 115 +++ .../js/default-connector/package.json | 31 + .../default-connector/react/esm/index.esm.js | 40 + .../default-connector/react/esm/package.json | 1 + .../js/default-connector/react/index.cjs.js | 41 + .../js/default-connector/react/index.d.ts | 20 + .../js/default-connector/react/package.json | 17 + dataconnect/.dataconnect/schema/prelude.gql | 5 +- packages/angular/.gitignore | 2 + .../js/default-connector/README.md | 531 ++++++++++ .../angular/esm/index.esm.js | 113 ++ .../angular/esm/package.json | 1 + .../js/default-connector/angular/index.cjs.js | 146 +++ .../js/default-connector/angular/index.d.ts | 91 ++ .../js/default-connector/angular/package.json | 25 + .../js/default-connector/esm/index.esm.js | 68 ++ .../js/default-connector/esm/package.json | 1 + .../js/default-connector/index.cjs.js | 94 ++ .../js/default-connector/index.d.ts | 117 +++ .../js/default-connector/package.json | 37 + .../default-connector/react/esm/index.esm.js | 49 + .../default-connector/react/esm/package.json | 1 + .../js/default-connector/react/index.cjs.js | 50 + .../js/default-connector/react/index.d.ts | 10 + .../js/default-connector/react/package.json | 17 + packages/angular/index.d.ts | 2 + packages/angular/package-lock.json | 146 +-- packages/angular/package.json | 8 +- packages/angular/src/data-connect/index.ts | 65 +- .../injectDataConnectMutation.test.ts | 969 ++++++++++++++++++ .../injectDataConnectQuery.test.ts | 202 ++++ packages/angular/test-setup.ts | 10 + packages/angular/vitest.config.ts | 31 + .../data-connect/useDataConnectMutation.ts | 3 + 39 files changed, 3649 insertions(+), 91 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 dataconnect-sdk/js/default-connector/README.md create mode 100644 dataconnect-sdk/js/default-connector/esm/index.esm.js create mode 100644 dataconnect-sdk/js/default-connector/esm/package.json create mode 100644 dataconnect-sdk/js/default-connector/index.cjs.js create mode 100644 dataconnect-sdk/js/default-connector/index.d.ts create mode 100644 dataconnect-sdk/js/default-connector/package.json create mode 100644 dataconnect-sdk/js/default-connector/react/esm/index.esm.js create mode 100644 dataconnect-sdk/js/default-connector/react/esm/package.json create mode 100644 dataconnect-sdk/js/default-connector/react/index.cjs.js create mode 100644 dataconnect-sdk/js/default-connector/react/index.d.ts create mode 100644 dataconnect-sdk/js/default-connector/react/package.json create mode 100644 packages/angular/.gitignore create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/README.md create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/angular/esm/index.esm.js create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/angular/esm/package.json create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/angular/index.cjs.js create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/angular/index.d.ts create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/angular/package.json create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/esm/index.esm.js create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/esm/package.json create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/index.cjs.js create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/index.d.ts create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/package.json create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/react/esm/index.esm.js create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/react/esm/package.json create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/react/index.cjs.js create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/react/index.d.ts create mode 100644 packages/angular/dataconnect-sdk/js/default-connector/react/package.json create mode 100644 packages/angular/index.d.ts create mode 100644 packages/angular/src/data-connect/injectDataConnectMutation.test.ts create mode 100644 packages/angular/src/data-connect/injectDataConnectQuery.test.ts create mode 100644 packages/angular/test-setup.ts create mode 100644 packages/angular/vitest.config.ts diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..d4b60469 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,27 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "name": "vscode-jest-tests.v2", + "request": "launch", + "runtimeExecutable": "yarn", + "args": [ + "test", + "--watch-all=false", + "--test-name-pattern", + "${jest.testNamePattern}", + "--test-path-pattern", + "${jest.testFilePattern}" + ], + "cwd": "${workspaceFolder}/packages/angular", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true + } + + ] +} \ No newline at end of file diff --git a/dataconnect-sdk/js/default-connector/README.md b/dataconnect-sdk/js/default-connector/README.md new file mode 100644 index 00000000..e786f630 --- /dev/null +++ b/dataconnect-sdk/js/default-connector/README.md @@ -0,0 +1,531 @@ +# Generated TypeScript README +This README will guide you through the process of using the generated TypeScript SDK package for the connector `default`. It will also provide examples on how to use your generated SDK to call your Data Connect queries and mutations. + +***NOTE:** This README is generated alongside the generated SDK. If you make changes to this file, they will be overwritten when the SDK is regenerated.* + +You can use this generated SDK by importing from the package `@dataconnect/default-connector` as shown below. Both CommonJS and ESM imports are supported. +You can also follow the instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#set-client). + +# Accessing the connector +A connector is a collection of queries and mutations. One SDK is generated for each connector - this SDK is generated for the connector `default`. + +You can find more information about connectors in the [Data Connect documentation](https://firebase.google.com/docs/data-connect#how-does). + +In order to call Data Connect queries and mutations, you need to create an instance of the connector in your application code. + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig } from '@dataconnect/default-connector'; + +const connector: DataConnect = getDataConnect(connectorConfig); +``` + +## Connecting to the local Emulator +By default, the connector will connect to the production service. + +To connect to the emulator, you can use the following code. +You can also follow the emulator instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#instrument-clients). + +```javascript +// add connectDataConnectEmulator to your imports +import { connectDataConnectEmulator, getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig } from '@dataconnect/default-connector'; + +const connector: DataConnect = getDataConnect(connectorConfig); +connectDataConnectEmulator(connector, 'localhost', 9399); +``` + +After it's initialized, you can call your Data Connect [queries](#queries) and [mutations](#mutations) from your generated SDK. + +# Queries +There are two ways to execute a Data Connect Query using the generated Web SDK: +- Using a Query Reference function, which returns a `QueryRef` + - The `QueryRef` can be used as an argument to `executeQuery()`, which will execute the Query and return a `QueryPromise` +- Using an action shortcut function, which returns a `QueryPromise` + - Calling the action shortcut function will execute the Query and return a `QueryPromise` + +The following is true for both the action shortcut function and the `QueryRef` function: +- The `QueryPromise` returned will resolve to the result of the Query once it has finished executing +- If the Query accepts arguments, both the action shortcut function and the `QueryRef` function accept a single argument: an object that contains all the required variables (and the optional variables) for the Query +- Both functions can be called with or without passing in a `DataConnect` instance as an argument + +Below are examples of how to use the `default` connector's generated functions to execute each query. You can also follow the examples from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#using-queries). + +## ListMovies +You can execute the `ListMovies` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +listMovies(): QueryPromise; + +listMoviesRef(): (QueryRef & { __angular?: false }); +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. +```javascript +listMovies(dc: DataConnect): QueryPromise; + +listMoviesRef(dc: DataConnect): (QueryRef & { __angular?: false }); +``` + +### Variables +The `ListMovies` query has no variables. +### Return Type +Recall that executing the `ListMovies` query returns a `QueryPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `ListMoviesData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface ListMoviesData { + movies: ({ + id: UUIDString; + title: string; + imageUrl: string; + genre?: string | null; + } & Movie_Key)[]; +} +``` +### Using `ListMovies`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, listMovies } from '@dataconnect/default-connector'; + +// Call the `listMovies()` function to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await listMovies(); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await listMovies(connector); + +console.log(data.movies); + +// Or, you can use the `Promise` API. +listMovies().then((response) => { + const data = response.data; + console.log(data.movies); +}); +``` + +### Using `ListMovies`'s `QueryRef` function + +```javascript +import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; +import { connectorConfig, listMoviesRef } from '@dataconnect/default-connector'; + +// Call the `listMoviesRef()` function to get a reference to the query. +const ref = listMoviesRef(); + +// You can also pass in a `DataConnect` instance to the `QueryRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = listMoviesRef(connector); + +// Call `executeQuery()` on the reference to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeQuery(ref); + +console.log(data.movies); + +// Or, you can use the `Promise` API. +executeQuery(ref).then((response) => { + const data = response.data; + console.log(data.movies); +}); +``` + +## GetMovieById +You can execute the `GetMovieById` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +getMovieById(vars: GetMovieByIdVariables): QueryPromise; + +getMovieByIdRef(vars: GetMovieByIdVariables): (QueryRef & { __angular?: false }); +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. +```javascript +getMovieById(dc: DataConnect, vars: GetMovieByIdVariables): QueryPromise; + +getMovieByIdRef(dc: DataConnect, vars: GetMovieByIdVariables): (QueryRef & { __angular?: false }); +``` + +### Variables +The `GetMovieById` query requires an argument of type `GetMovieByIdVariables`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface GetMovieByIdVariables { + id: UUIDString; +} +``` +### Return Type +Recall that executing the `GetMovieById` query returns a `QueryPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `GetMovieByIdData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface GetMovieByIdData { + movie?: { + id: UUIDString; + title: string; + imageUrl: string; + genre?: string | null; + } & Movie_Key; +} +``` +### Using `GetMovieById`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, getMovieById, GetMovieByIdVariables } from '@dataconnect/default-connector'; +// The `GetMovieById` query requires an argument of type `GetMovieByIdVariables`: +const getMovieByIdVars: GetMovieByIdVariables = { + id: ..., +} + +// Call the `getMovieById()` function to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await getMovieById(getMovieByIdVars); +// Variables can be defined inline as well. +const { data } = await getMovieById({ id: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await getMovieById(connector, getMovieByIdVars); + +console.log(data.movie); + +// Or, you can use the `Promise` API. +getMovieById(getMovieByIdVars).then((response) => { + const data = response.data; + console.log(data.movie); +}); +``` + +### Using `GetMovieById`'s `QueryRef` function + +```javascript +import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; +import { connectorConfig, getMovieByIdRef, GetMovieByIdVariables } from '@dataconnect/default-connector'; +// The `GetMovieById` query requires an argument of type `GetMovieByIdVariables`: +const getMovieByIdVars: GetMovieByIdVariables = { + id: ..., +} + +// Call the `getMovieByIdRef()` function to get a reference to the query. +const ref = getMovieByIdRef(getMovieByIdVars); +// Variables can be defined inline as well. +const ref = getMovieByIdRef({ id: ..., }); + +// You can also pass in a `DataConnect` instance to the `QueryRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = getMovieByIdRef(connector, getMovieByIdVars); + +// Call `executeQuery()` on the reference to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeQuery(ref); + +console.log(data.movie); + +// Or, you can use the `Promise` API. +executeQuery(ref).then((response) => { + const data = response.data; + console.log(data.movie); +}); +``` + +# Mutations +There are two ways to execute a Data Connect Mutation using the generated Web SDK: +- Using a Mutation Reference function, which returns a `MutationRef` + - The `MutationRef` can be used as an argument to `executeMutation()`, which will execute the Mutation and return a `MutationPromise` +- Using an action shortcut function, which returns a `MutationPromise` + - Calling the action shortcut function will execute the Mutation and return a `MutationPromise` + +The following is true for both the action shortcut function and the `MutationRef` function: +- The `MutationPromise` returned will resolve to the result of the Mutation once it has finished executing +- If the Mutation accepts arguments, both the action shortcut function and the `MutationRef` function accept a single argument: an object that contains all the required variables (and the optional variables) for the Mutation +- Both functions can be called with or without passing in a `DataConnect` instance as an argument + +Below are examples of how to use the `default` connector's generated functions to execute each mutation. You can also follow the examples from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#using-mutations). + +## CreateMovie +You can execute the `CreateMovie` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +createMovie(vars: CreateMovieVariables): MutationPromise; + +createMovieRef(vars: CreateMovieVariables): (MutationRef & { __angular?: false }); +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; + +createMovieRef(dc: DataConnect, vars: CreateMovieVariables): (MutationRef & { __angular?: false }); +``` + +### Variables +The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface CreateMovieVariables { + title: string; + genre: string; + imageUrl: string; +} +``` +### Return Type +Recall that executing the `CreateMovie` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `CreateMovieData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface CreateMovieData { + movie_insert: Movie_Key; +} +``` +### Using `CreateMovie`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, createMovie, CreateMovieVariables } from '@dataconnect/default-connector'; +// The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: +const createMovieVars: CreateMovieVariables = { + title: ..., + genre: ..., + imageUrl: ..., +} + +// Call the `createMovie()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await createMovie(createMovieVars); +// Variables can be defined inline as well. +const { data } = await createMovie({ title: ..., genre: ..., imageUrl: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await createMovie(connector, createMovieVars); + +console.log(data.movie_insert); + +// Or, you can use the `Promise` API. +createMovie(createMovieVars).then((response) => { + const data = response.data; + console.log(data.movie_insert); +}); +``` + +### Using `CreateMovie`'s `MutationRef` function + +```javascript +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, createMovieRef, CreateMovieVariables } from '@dataconnect/default-connector'; +// The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: +const createMovieVars: CreateMovieVariables = { + title: ..., + genre: ..., + imageUrl: ..., +} + +// Call the `createMovieRef()` function to get a reference to the mutation. +const ref = createMovieRef(createMovieVars); +// Variables can be defined inline as well. +const ref = createMovieRef({ title: ..., genre: ..., imageUrl: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = createMovieRef(connector, createMovieVars); + +// Call `executeMutation()` on the reference to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeMutation(ref); + +console.log(data.movie_insert); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.movie_insert); +}); +``` + +## UpsertMovie +You can execute the `UpsertMovie` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +upsertMovie(vars: UpsertMovieVariables): MutationPromise; + +upsertMovieRef(vars: UpsertMovieVariables): (MutationRef & { __angular?: false }); +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +upsertMovie(dc: DataConnect, vars: UpsertMovieVariables): MutationPromise; + +upsertMovieRef(dc: DataConnect, vars: UpsertMovieVariables): (MutationRef & { __angular?: false }); +``` + +### Variables +The `UpsertMovie` mutation requires an argument of type `UpsertMovieVariables`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface UpsertMovieVariables { + id: UUIDString; + title: string; + imageUrl: string; +} +``` +### Return Type +Recall that executing the `UpsertMovie` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `UpsertMovieData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface UpsertMovieData { + movie_upsert: Movie_Key; +} +``` +### Using `UpsertMovie`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, upsertMovie, UpsertMovieVariables } from '@dataconnect/default-connector'; +// The `UpsertMovie` mutation requires an argument of type `UpsertMovieVariables`: +const upsertMovieVars: UpsertMovieVariables = { + id: ..., + title: ..., + imageUrl: ..., +} + +// Call the `upsertMovie()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await upsertMovie(upsertMovieVars); +// Variables can be defined inline as well. +const { data } = await upsertMovie({ id: ..., title: ..., imageUrl: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await upsertMovie(connector, upsertMovieVars); + +console.log(data.movie_upsert); + +// Or, you can use the `Promise` API. +upsertMovie(upsertMovieVars).then((response) => { + const data = response.data; + console.log(data.movie_upsert); +}); +``` + +### Using `UpsertMovie`'s `MutationRef` function + +```javascript +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, upsertMovieRef, UpsertMovieVariables } from '@dataconnect/default-connector'; +// The `UpsertMovie` mutation requires an argument of type `UpsertMovieVariables`: +const upsertMovieVars: UpsertMovieVariables = { + id: ..., + title: ..., + imageUrl: ..., +} + +// Call the `upsertMovieRef()` function to get a reference to the mutation. +const ref = upsertMovieRef(upsertMovieVars); +// Variables can be defined inline as well. +const ref = upsertMovieRef({ id: ..., title: ..., imageUrl: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = upsertMovieRef(connector, upsertMovieVars); + +// Call `executeMutation()` on the reference to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeMutation(ref); + +console.log(data.movie_upsert); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.movie_upsert); +}); +``` + +## DeleteMovie +You can execute the `DeleteMovie` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +deleteMovie(vars: DeleteMovieVariables): MutationPromise; + +deleteMovieRef(vars: DeleteMovieVariables): (MutationRef & { __angular?: false }); +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +deleteMovie(dc: DataConnect, vars: DeleteMovieVariables): MutationPromise; + +deleteMovieRef(dc: DataConnect, vars: DeleteMovieVariables): (MutationRef & { __angular?: false }); +``` + +### Variables +The `DeleteMovie` mutation requires an argument of type `DeleteMovieVariables`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface DeleteMovieVariables { + id: UUIDString; +} +``` +### Return Type +Recall that executing the `DeleteMovie` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `DeleteMovieData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface DeleteMovieData { + movie_delete?: Movie_Key | null; +} +``` +### Using `DeleteMovie`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, deleteMovie, DeleteMovieVariables } from '@dataconnect/default-connector'; +// The `DeleteMovie` mutation requires an argument of type `DeleteMovieVariables`: +const deleteMovieVars: DeleteMovieVariables = { + id: ..., +} + +// Call the `deleteMovie()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await deleteMovie(deleteMovieVars); +// Variables can be defined inline as well. +const { data } = await deleteMovie({ id: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await deleteMovie(connector, deleteMovieVars); + +console.log(data.movie_delete); + +// Or, you can use the `Promise` API. +deleteMovie(deleteMovieVars).then((response) => { + const data = response.data; + console.log(data.movie_delete); +}); +``` + +### Using `DeleteMovie`'s `MutationRef` function + +```javascript +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, deleteMovieRef, DeleteMovieVariables } from '@dataconnect/default-connector'; +// The `DeleteMovie` mutation requires an argument of type `DeleteMovieVariables`: +const deleteMovieVars: DeleteMovieVariables = { + id: ..., +} + +// Call the `deleteMovieRef()` function to get a reference to the mutation. +const ref = deleteMovieRef(deleteMovieVars); +// Variables can be defined inline as well. +const ref = deleteMovieRef({ id: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = deleteMovieRef(connector, deleteMovieVars); + +// Call `executeMutation()` on the reference to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeMutation(ref); + +console.log(data.movie_delete); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.movie_delete); +}); +``` + diff --git a/dataconnect-sdk/js/default-connector/esm/index.esm.js b/dataconnect-sdk/js/default-connector/esm/index.esm.js new file mode 100644 index 00000000..a599e114 --- /dev/null +++ b/dataconnect-sdk/js/default-connector/esm/index.esm.js @@ -0,0 +1,58 @@ +import { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } from 'firebase/data-connect'; + + +export const connectorConfig = { + connector: 'default', + service: 'tanstack-query-firebase', + location: 'us-central1' +}; + +export function createMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'CreateMovie', inputVars); +} + +export function createMovie(dcOrVars, vars) { + return executeMutation(createMovieRef(dcOrVars, vars)); +} + +export function upsertMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'UpsertMovie', inputVars); +} + +export function upsertMovie(dcOrVars, vars) { + return executeMutation(upsertMovieRef(dcOrVars, vars)); +} + +export function deleteMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'DeleteMovie', inputVars); +} + +export function deleteMovie(dcOrVars, vars) { + return executeMutation(deleteMovieRef(dcOrVars, vars)); +} + +export function listMoviesRef(dc) { + const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'ListMovies'); +} + +export function listMovies(dc) { + return executeQuery(listMoviesRef(dc)); +} + +export function getMovieByIdRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'GetMovieById', inputVars); +} + +export function getMovieById(dcOrVars, vars) { + return executeQuery(getMovieByIdRef(dcOrVars, vars)); +} diff --git a/dataconnect-sdk/js/default-connector/esm/package.json b/dataconnect-sdk/js/default-connector/esm/package.json new file mode 100644 index 00000000..7c34deb5 --- /dev/null +++ b/dataconnect-sdk/js/default-connector/esm/package.json @@ -0,0 +1 @@ +{"type":"module"} \ No newline at end of file diff --git a/dataconnect-sdk/js/default-connector/index.cjs.js b/dataconnect-sdk/js/default-connector/index.cjs.js new file mode 100644 index 00000000..13685044 --- /dev/null +++ b/dataconnect-sdk/js/default-connector/index.cjs.js @@ -0,0 +1,64 @@ +const { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } = require('firebase/data-connect'); + +const connectorConfig = { + connector: 'default', + service: 'tanstack-query-firebase', + location: 'us-central1' +}; +exports.connectorConfig = connectorConfig; + +function createMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'CreateMovie', inputVars); +} +exports.createMovieRef = createMovieRef; + +exports.createMovie = function createMovie(dcOrVars, vars) { + return executeMutation(createMovieRef(dcOrVars, vars)); +}; + +function upsertMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'UpsertMovie', inputVars); +} +exports.upsertMovieRef = upsertMovieRef; + +exports.upsertMovie = function upsertMovie(dcOrVars, vars) { + return executeMutation(upsertMovieRef(dcOrVars, vars)); +}; + +function deleteMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'DeleteMovie', inputVars); +} +exports.deleteMovieRef = deleteMovieRef; + +exports.deleteMovie = function deleteMovie(dcOrVars, vars) { + return executeMutation(deleteMovieRef(dcOrVars, vars)); +}; + +function listMoviesRef(dc) { + const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'ListMovies'); +} +exports.listMoviesRef = listMoviesRef; + +exports.listMovies = function listMovies(dc) { + return executeQuery(listMoviesRef(dc)); +}; + +function getMovieByIdRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'GetMovieById', inputVars); +} +exports.getMovieByIdRef = getMovieByIdRef; + +exports.getMovieById = function getMovieById(dcOrVars, vars) { + return executeQuery(getMovieByIdRef(dcOrVars, vars)); +}; + diff --git a/dataconnect-sdk/js/default-connector/index.d.ts b/dataconnect-sdk/js/default-connector/index.d.ts new file mode 100644 index 00000000..a4fd0588 --- /dev/null +++ b/dataconnect-sdk/js/default-connector/index.d.ts @@ -0,0 +1,115 @@ +import { ConnectorConfig, DataConnect, QueryRef, QueryPromise, MutationRef, MutationPromise } from 'firebase/data-connect'; + +export const connectorConfig: ConnectorConfig; + +export type TimestampString = string; +export type UUIDString = string; +export type Int64String = string; +export type DateString = string; + + +export interface CreateMovieData { + movie_insert: Movie_Key; +} + +export interface CreateMovieVariables { + title: string; + genre: string; + imageUrl: string; +} + +export interface DeleteMovieData { + movie_delete?: Movie_Key | null; +} + +export interface DeleteMovieVariables { + id: UUIDString; +} + +export interface GetMovieByIdData { + movie?: { + id: UUIDString; + title: string; + imageUrl: string; + genre?: string | null; + } & Movie_Key; +} + +export interface GetMovieByIdVariables { + id: UUIDString; +} + +export interface ListMoviesData { + movies: ({ + id: UUIDString; + title: string; + imageUrl: string; + genre?: string | null; + } & Movie_Key)[]; +} + +export interface MovieMetadata_Key { + id: UUIDString; + __typename?: 'MovieMetadata_Key'; +} + +export interface Movie_Key { + id: UUIDString; + __typename?: 'Movie_Key'; +} + +export interface UpsertMovieData { + movie_upsert: Movie_Key; +} + +export interface UpsertMovieVariables { + id: UUIDString; + title: string; + imageUrl: string; +} + + +/* Allow users to create refs without passing in DataConnect */ +export function createMovieRef(vars: CreateMovieVariables): (MutationRef & { __angular?: false }); +/* Allow users to pass in custom DataConnect instances */ +export function createMovieRef(dc: DataConnect, vars: CreateMovieVariables): (MutationRef & { __angular?: false }); + +export function createMovie(vars: CreateMovieVariables): MutationPromise; +export function createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function upsertMovieRef(vars: UpsertMovieVariables): (MutationRef & { __angular?: false }); +/* Allow users to pass in custom DataConnect instances */ +export function upsertMovieRef(dc: DataConnect, vars: UpsertMovieVariables): (MutationRef & { __angular?: false }); + +export function upsertMovie(vars: UpsertMovieVariables): MutationPromise; +export function upsertMovie(dc: DataConnect, vars: UpsertMovieVariables): MutationPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function deleteMovieRef(vars: DeleteMovieVariables): (MutationRef & { __angular?: false }); +/* Allow users to pass in custom DataConnect instances */ +export function deleteMovieRef(dc: DataConnect, vars: DeleteMovieVariables): (MutationRef & { __angular?: false }); + +export function deleteMovie(vars: DeleteMovieVariables): MutationPromise; +export function deleteMovie(dc: DataConnect, vars: DeleteMovieVariables): MutationPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function listMoviesRef(): (QueryRef & { __angular?: false }); +/* Allow users to pass in custom DataConnect instances */ +export function listMoviesRef(dc: DataConnect): (QueryRef & { __angular?: false }); + +export function listMovies(): QueryPromise; +export function listMovies(dc: DataConnect): QueryPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function getMovieByIdRef(vars: GetMovieByIdVariables): (QueryRef & { __angular?: false }); +/* Allow users to pass in custom DataConnect instances */ +export function getMovieByIdRef(dc: DataConnect, vars: GetMovieByIdVariables): (QueryRef & { __angular?: false }); + +export function getMovieById(vars: GetMovieByIdVariables): QueryPromise; +export function getMovieById(dc: DataConnect, vars: GetMovieByIdVariables): QueryPromise; + diff --git a/dataconnect-sdk/js/default-connector/package.json b/dataconnect-sdk/js/default-connector/package.json new file mode 100644 index 00000000..072295b6 --- /dev/null +++ b/dataconnect-sdk/js/default-connector/package.json @@ -0,0 +1,31 @@ +{ + "name": "@dataconnect/default-connector", + "version": "1.0.0", + "author": "Firebase (https://firebase.google.com/)", + "description": "Generated SDK For default", + "license": "Apache-2.0", + "engines": { + "node": " >=18.0" + }, + "typings": "index.d.ts", + "module": "esm/index.esm.js", + "main": "index.cjs.js", + "browser": "esm/index.esm.js", + "exports": { + ".": { + "types": "./index.d.ts", + "require": "./index.cjs.js", + "default": "./esm/index.esm.js" + }, + "./react": { + "types": "./react/index.d.ts", + "import": "./react/esm/index.esm.js", + "default": "./react/esm/index.esm.js" + }, + "./package.json": "./package.json" + }, + "peerDependencies": { + "firebase": "^11.3.0", + "@tanstack-query-firebase/react": "^1.0.5" + } +} \ No newline at end of file diff --git a/dataconnect-sdk/js/default-connector/react/esm/index.esm.js b/dataconnect-sdk/js/default-connector/react/esm/index.esm.js new file mode 100644 index 00000000..be7e2b22 --- /dev/null +++ b/dataconnect-sdk/js/default-connector/react/esm/index.esm.js @@ -0,0 +1,40 @@ +import { createMovieRef, upsertMovieRef, deleteMovieRef, listMoviesRef, getMovieByIdRef, connectorConfig } from '../../'; +import { CallerSdkTypeEnum, validateArgs } from '@firebase/data-connect'; +import { useDataConnectQuery, useDataConnectMutation } from '@tanstack-query-firebase/react/data-connect'; + +export function useCreateMovie(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return createMovieRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +export function useUpsertMovie(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return upsertMovieRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +export function useDeleteMovie(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return deleteMovieRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + + +export function useListMovies(dc, options) { + const { dc: dcInstance } = validateArgs(connectorConfig, dc, undefined, false); + const ref = listMoviesRef(dcInstance); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} + +export function useGetMovieById(dcOrVars, vars, options) { + const { dc: dcInstance, vars: inputVars } = validateArgs(connectorConfig, dcOrVars, vars, false); + const ref = getMovieByIdRef(dcInstance, inputVars); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} \ No newline at end of file diff --git a/dataconnect-sdk/js/default-connector/react/esm/package.json b/dataconnect-sdk/js/default-connector/react/esm/package.json new file mode 100644 index 00000000..7c34deb5 --- /dev/null +++ b/dataconnect-sdk/js/default-connector/react/esm/package.json @@ -0,0 +1 @@ +{"type":"module"} \ No newline at end of file diff --git a/dataconnect-sdk/js/default-connector/react/index.cjs.js b/dataconnect-sdk/js/default-connector/react/index.cjs.js new file mode 100644 index 00000000..500a11dc --- /dev/null +++ b/dataconnect-sdk/js/default-connector/react/index.cjs.js @@ -0,0 +1,41 @@ +const { createMovieRef, upsertMovieRef, deleteMovieRef, listMoviesRef, getMovieByIdRef, connectorConfig } = require('../'); +const { CallerSdkTypeEnum, validateArgs } = require('@firebase/data-connect'); +const { useDataConnectQuery, useDataConnectMutation } = require('@tanstack-query-firebase/react/data-connect'); + + +exports.useCreateMovie = function useCreateMovie(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return createMovieRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +exports.useUpsertMovie = function useUpsertMovie(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return upsertMovieRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +exports.useDeleteMovie = function useDeleteMovie(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return deleteMovieRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + + +exports.useListMovies = function useListMovies(dc, options) { + const { dc: dcInstance } = validateArgs(connectorConfig, dc, undefined, false); + const ref = listMoviesRef(dcInstance); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} + +exports.useGetMovieById = function useGetMovieById(dcOrVars, vars, options) { + const { dc: dcInstance, vars: inputVars } = validateArgs(connectorConfig, dcOrVars, vars, false); + const ref = getMovieByIdRef(dcInstance, inputVars); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} \ No newline at end of file diff --git a/dataconnect-sdk/js/default-connector/react/index.d.ts b/dataconnect-sdk/js/default-connector/react/index.d.ts new file mode 100644 index 00000000..bbd50c8c --- /dev/null +++ b/dataconnect-sdk/js/default-connector/react/index.d.ts @@ -0,0 +1,20 @@ +import { CreateMovieData, CreateMovieVariables, UpsertMovieData, UpsertMovieVariables, DeleteMovieData, DeleteMovieVariables, ListMoviesData, GetMovieByIdData, GetMovieByIdVariables} from '../'; +import { useDataConnectQueryOptions, FlattenedQueryResult, useDataConnectMutationOptions, FlattenedMutationResult} from '@tanstack-query-firebase/react/data-connect'; +import { UseQueryResult, UseMutationResult} from '@tanstack/react-query'; +import { DataConnect } from 'firebase/data-connect'; + + +export function useCreateMovie(options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, CreateMovieVariables>; +export function useCreateMovie(dc: DataConnect, options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, CreateMovieVariables>; + +export function useUpsertMovie(options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, UpsertMovieVariables>; +export function useUpsertMovie(dc: DataConnect, options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, UpsertMovieVariables>; + +export function useDeleteMovie(options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, DeleteMovieVariables>; +export function useDeleteMovie(dc: DataConnect, options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, DeleteMovieVariables>; + +export function useListMovies(options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; +export function useListMovies(dc: DataConnect, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; + +export function useGetMovieById(vars: GetMovieByIdVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; +export function useGetMovieById(dc: DataConnect, vars: GetMovieByIdVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; diff --git a/dataconnect-sdk/js/default-connector/react/package.json b/dataconnect-sdk/js/default-connector/react/package.json new file mode 100644 index 00000000..f2fee700 --- /dev/null +++ b/dataconnect-sdk/js/default-connector/react/package.json @@ -0,0 +1,17 @@ +{ + "name": "@dataconnect/default-connector-react", + "version": "1.0.0", + "author": "Firebase (https://firebase.google.com/)", + "description": "Generated SDK For default", + "license": "Apache-2.0", + "engines": { + "node": " >=18.0" + }, + "typings": "index.d.ts", + "main": "index.cjs.js", + "module": "esm/index.esm.js", + "browser": "esm/index.esm.js", + "peerDependencies": { + "@tanstack-query-firebase/react": "^1.0.5" + } +} \ No newline at end of file diff --git a/dataconnect/.dataconnect/schema/prelude.gql b/dataconnect/.dataconnect/schema/prelude.gql index cfff7d55..b38ec616 100644 --- a/dataconnect/.dataconnect/schema/prelude.gql +++ b/dataconnect/.dataconnect/schema/prelude.gql @@ -390,6 +390,9 @@ enum GeneratedPurpose { IMPLICIT_KEY_FIELD IMPLICIT_REF_FIELD + # Generated static fields extended to table types. + METADATA_FIELD + # Relational non-column fields extended to table types. QUERY_MULTIPLE_ONE_TO_MANY QUERY_MULTIPLE_MANY_TO_MANY @@ -1053,7 +1056,7 @@ type OneTable @table { ``` Data Connect generates the necessary foreign key constraint. -```graphql +```sql CREATE TABLE "public"."many_table" ( "id" uuid NOT NULL DEFAULT uuid_generate_v4(), "ref_field_id" uuid NOT NULL, diff --git a/packages/angular/.gitignore b/packages/angular/.gitignore new file mode 100644 index 00000000..fe2c13d9 --- /dev/null +++ b/packages/angular/.gitignore @@ -0,0 +1,2 @@ +data-connect/* +index.js \ No newline at end of file diff --git a/packages/angular/dataconnect-sdk/js/default-connector/README.md b/packages/angular/dataconnect-sdk/js/default-connector/README.md new file mode 100644 index 00000000..6ad5971f --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/README.md @@ -0,0 +1,531 @@ +# Generated TypeScript README +This README will guide you through the process of using the generated TypeScript SDK package for the connector `default`. It will also provide examples on how to use your generated SDK to call your Data Connect queries and mutations. + +***NOTE:** This README is generated alongside the generated SDK. If you make changes to this file, they will be overwritten when the SDK is regenerated.* + +You can use this generated SDK by importing from the package `@dataconnect/default-connector` as shown below. Both CommonJS and ESM imports are supported. +You can also follow the instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#set-client). + +# Accessing the connector +A connector is a collection of queries and mutations. One SDK is generated for each connector - this SDK is generated for the connector `default`. + +You can find more information about connectors in the [Data Connect documentation](https://firebase.google.com/docs/data-connect#how-does). + +In order to call Data Connect queries and mutations, you need to create an instance of the connector in your application code. + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig } from '@dataconnect/default-connector'; + +const connector: DataConnect = getDataConnect(connectorConfig); +``` + +## Connecting to the local Emulator +By default, the connector will connect to the production service. + +To connect to the emulator, you can use the following code. +You can also follow the emulator instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#instrument-clients). + +```javascript +// add connectDataConnectEmulator to your imports +import { connectDataConnectEmulator, getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig } from '@dataconnect/default-connector'; + +const connector: DataConnect = getDataConnect(connectorConfig); +connectDataConnectEmulator(connector, 'localhost', 9399); +``` + +After it's initialized, you can call your Data Connect [queries](#queries) and [mutations](#mutations) from your generated SDK. + +# Queries +There are two ways to execute a Data Connect Query using the generated Web SDK: +- Using a Query Reference function, which returns a `QueryRef` + - The `QueryRef` can be used as an argument to `executeQuery()`, which will execute the Query and return a `QueryPromise` +- Using an action shortcut function, which returns a `QueryPromise` + - Calling the action shortcut function will execute the Query and return a `QueryPromise` + +The following is true for both the action shortcut function and the `QueryRef` function: +- The `QueryPromise` returned will resolve to the result of the Query once it has finished executing +- If the Query accepts arguments, both the action shortcut function and the `QueryRef` function accept a single argument: an object that contains all the required variables (and the optional variables) for the Query +- Both functions can be called with or without passing in a `DataConnect` instance as an argument + +Below are examples of how to use the `default` connector's generated functions to execute each query. You can also follow the examples from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#using-queries). + +## ListMovies +You can execute the `ListMovies` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +listMovies(): QueryPromise; + +listMoviesRef(): QueryRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. +```javascript +listMovies(dc: DataConnect): QueryPromise; + +listMoviesRef(dc: DataConnect): QueryRef; +``` + +### Variables +The `ListMovies` query has no variables. +### Return Type +Recall that executing the `ListMovies` query returns a `QueryPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `ListMoviesData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface ListMoviesData { + movies: ({ + id: UUIDString; + title: string; + imageUrl: string; + genre?: string | null; + } & Movie_Key)[]; +} +``` +### Using `ListMovies`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, listMovies } from '@dataconnect/default-connector'; + +// Call the `listMovies()` function to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await listMovies(); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await listMovies(connector); + +console.log(data.movies); + +// Or, you can use the `Promise` API. +listMovies().then((response) => { + const data = response.data; + console.log(data.movies); +}); +``` + +### Using `ListMovies`'s `QueryRef` function + +```javascript +import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; +import { connectorConfig, listMoviesRef } from '@dataconnect/default-connector'; + +// Call the `listMoviesRef()` function to get a reference to the query. +const ref = listMoviesRef(); + +// You can also pass in a `DataConnect` instance to the `QueryRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = listMoviesRef(connector); + +// Call `executeQuery()` on the reference to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeQuery(ref); + +console.log(data.movies); + +// Or, you can use the `Promise` API. +executeQuery(ref).then((response) => { + const data = response.data; + console.log(data.movies); +}); +``` + +## GetMovieById +You can execute the `GetMovieById` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +getMovieById(vars: GetMovieByIdVariables): QueryPromise; + +getMovieByIdRef(vars: GetMovieByIdVariables): QueryRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. +```javascript +getMovieById(dc: DataConnect, vars: GetMovieByIdVariables): QueryPromise; + +getMovieByIdRef(dc: DataConnect, vars: GetMovieByIdVariables): QueryRef; +``` + +### Variables +The `GetMovieById` query requires an argument of type `GetMovieByIdVariables`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface GetMovieByIdVariables { + id: UUIDString; +} +``` +### Return Type +Recall that executing the `GetMovieById` query returns a `QueryPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `GetMovieByIdData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface GetMovieByIdData { + movie?: { + id: UUIDString; + title: string; + imageUrl: string; + genre?: string | null; + } & Movie_Key; +} +``` +### Using `GetMovieById`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, getMovieById, GetMovieByIdVariables } from '@dataconnect/default-connector'; +// The `GetMovieById` query requires an argument of type `GetMovieByIdVariables`: +const getMovieByIdVars: GetMovieByIdVariables = { + id: ..., +} + +// Call the `getMovieById()` function to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await getMovieById(getMovieByIdVars); +// Variables can be defined inline as well. +const { data } = await getMovieById({ id: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await getMovieById(connector, getMovieByIdVars); + +console.log(data.movie); + +// Or, you can use the `Promise` API. +getMovieById(getMovieByIdVars).then((response) => { + const data = response.data; + console.log(data.movie); +}); +``` + +### Using `GetMovieById`'s `QueryRef` function + +```javascript +import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; +import { connectorConfig, getMovieByIdRef, GetMovieByIdVariables } from '@dataconnect/default-connector'; +// The `GetMovieById` query requires an argument of type `GetMovieByIdVariables`: +const getMovieByIdVars: GetMovieByIdVariables = { + id: ..., +} + +// Call the `getMovieByIdRef()` function to get a reference to the query. +const ref = getMovieByIdRef(getMovieByIdVars); +// Variables can be defined inline as well. +const ref = getMovieByIdRef({ id: ..., }); + +// You can also pass in a `DataConnect` instance to the `QueryRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = getMovieByIdRef(connector, getMovieByIdVars); + +// Call `executeQuery()` on the reference to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeQuery(ref); + +console.log(data.movie); + +// Or, you can use the `Promise` API. +executeQuery(ref).then((response) => { + const data = response.data; + console.log(data.movie); +}); +``` + +# Mutations +There are two ways to execute a Data Connect Mutation using the generated Web SDK: +- Using a Mutation Reference function, which returns a `MutationRef` + - The `MutationRef` can be used as an argument to `executeMutation()`, which will execute the Mutation and return a `MutationPromise` +- Using an action shortcut function, which returns a `MutationPromise` + - Calling the action shortcut function will execute the Mutation and return a `MutationPromise` + +The following is true for both the action shortcut function and the `MutationRef` function: +- The `MutationPromise` returned will resolve to the result of the Mutation once it has finished executing +- If the Mutation accepts arguments, both the action shortcut function and the `MutationRef` function accept a single argument: an object that contains all the required variables (and the optional variables) for the Mutation +- Both functions can be called with or without passing in a `DataConnect` instance as an argument + +Below are examples of how to use the `default` connector's generated functions to execute each mutation. You can also follow the examples from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#using-mutations). + +## CreateMovie +You can execute the `CreateMovie` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +createMovie(vars: CreateMovieVariables): MutationPromise; + +createMovieRef(vars: CreateMovieVariables): MutationRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; + +createMovieRef(dc: DataConnect, vars: CreateMovieVariables): MutationRef; +``` + +### Variables +The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface CreateMovieVariables { + title: string; + genre: string; + imageUrl: string; +} +``` +### Return Type +Recall that executing the `CreateMovie` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `CreateMovieData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface CreateMovieData { + movie_insert: Movie_Key; +} +``` +### Using `CreateMovie`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, createMovie, CreateMovieVariables } from '@dataconnect/default-connector'; +// The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: +const createMovieVars: CreateMovieVariables = { + title: ..., + genre: ..., + imageUrl: ..., +} + +// Call the `createMovie()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await createMovie(createMovieVars); +// Variables can be defined inline as well. +const { data } = await createMovie({ title: ..., genre: ..., imageUrl: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await createMovie(connector, createMovieVars); + +console.log(data.movie_insert); + +// Or, you can use the `Promise` API. +createMovie(createMovieVars).then((response) => { + const data = response.data; + console.log(data.movie_insert); +}); +``` + +### Using `CreateMovie`'s `MutationRef` function + +```javascript +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, createMovieRef, CreateMovieVariables } from '@dataconnect/default-connector'; +// The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: +const createMovieVars: CreateMovieVariables = { + title: ..., + genre: ..., + imageUrl: ..., +} + +// Call the `createMovieRef()` function to get a reference to the mutation. +const ref = createMovieRef(createMovieVars); +// Variables can be defined inline as well. +const ref = createMovieRef({ title: ..., genre: ..., imageUrl: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = createMovieRef(connector, createMovieVars); + +// Call `executeMutation()` on the reference to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeMutation(ref); + +console.log(data.movie_insert); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.movie_insert); +}); +``` + +## UpsertMovie +You can execute the `UpsertMovie` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +upsertMovie(vars: UpsertMovieVariables): MutationPromise; + +upsertMovieRef(vars: UpsertMovieVariables): MutationRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +upsertMovie(dc: DataConnect, vars: UpsertMovieVariables): MutationPromise; + +upsertMovieRef(dc: DataConnect, vars: UpsertMovieVariables): MutationRef; +``` + +### Variables +The `UpsertMovie` mutation requires an argument of type `UpsertMovieVariables`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface UpsertMovieVariables { + id: UUIDString; + title: string; + imageUrl: string; +} +``` +### Return Type +Recall that executing the `UpsertMovie` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `UpsertMovieData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface UpsertMovieData { + movie_upsert: Movie_Key; +} +``` +### Using `UpsertMovie`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, upsertMovie, UpsertMovieVariables } from '@dataconnect/default-connector'; +// The `UpsertMovie` mutation requires an argument of type `UpsertMovieVariables`: +const upsertMovieVars: UpsertMovieVariables = { + id: ..., + title: ..., + imageUrl: ..., +} + +// Call the `upsertMovie()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await upsertMovie(upsertMovieVars); +// Variables can be defined inline as well. +const { data } = await upsertMovie({ id: ..., title: ..., imageUrl: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await upsertMovie(connector, upsertMovieVars); + +console.log(data.movie_upsert); + +// Or, you can use the `Promise` API. +upsertMovie(upsertMovieVars).then((response) => { + const data = response.data; + console.log(data.movie_upsert); +}); +``` + +### Using `UpsertMovie`'s `MutationRef` function + +```javascript +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, upsertMovieRef, UpsertMovieVariables } from '@dataconnect/default-connector'; +// The `UpsertMovie` mutation requires an argument of type `UpsertMovieVariables`: +const upsertMovieVars: UpsertMovieVariables = { + id: ..., + title: ..., + imageUrl: ..., +} + +// Call the `upsertMovieRef()` function to get a reference to the mutation. +const ref = upsertMovieRef(upsertMovieVars); +// Variables can be defined inline as well. +const ref = upsertMovieRef({ id: ..., title: ..., imageUrl: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = upsertMovieRef(connector, upsertMovieVars); + +// Call `executeMutation()` on the reference to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeMutation(ref); + +console.log(data.movie_upsert); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.movie_upsert); +}); +``` + +## DeleteMovie +You can execute the `DeleteMovie` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +deleteMovie(vars: DeleteMovieVariables): MutationPromise; + +deleteMovieRef(vars: DeleteMovieVariables): MutationRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +deleteMovie(dc: DataConnect, vars: DeleteMovieVariables): MutationPromise; + +deleteMovieRef(dc: DataConnect, vars: DeleteMovieVariables): MutationRef; +``` + +### Variables +The `DeleteMovie` mutation requires an argument of type `DeleteMovieVariables`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface DeleteMovieVariables { + id: UUIDString; +} +``` +### Return Type +Recall that executing the `DeleteMovie` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `DeleteMovieData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface DeleteMovieData { + movie_delete?: Movie_Key | null; +} +``` +### Using `DeleteMovie`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, deleteMovie, DeleteMovieVariables } from '@dataconnect/default-connector'; +// The `DeleteMovie` mutation requires an argument of type `DeleteMovieVariables`: +const deleteMovieVars: DeleteMovieVariables = { + id: ..., +} + +// Call the `deleteMovie()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await deleteMovie(deleteMovieVars); +// Variables can be defined inline as well. +const { data } = await deleteMovie({ id: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await deleteMovie(connector, deleteMovieVars); + +console.log(data.movie_delete); + +// Or, you can use the `Promise` API. +deleteMovie(deleteMovieVars).then((response) => { + const data = response.data; + console.log(data.movie_delete); +}); +``` + +### Using `DeleteMovie`'s `MutationRef` function + +```javascript +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, deleteMovieRef, DeleteMovieVariables } from '@dataconnect/default-connector'; +// The `DeleteMovie` mutation requires an argument of type `DeleteMovieVariables`: +const deleteMovieVars: DeleteMovieVariables = { + id: ..., +} + +// Call the `deleteMovieRef()` function to get a reference to the mutation. +const ref = deleteMovieRef(deleteMovieVars); +// Variables can be defined inline as well. +const ref = deleteMovieRef({ id: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = deleteMovieRef(connector, deleteMovieVars); + +// Call `executeMutation()` on the reference to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeMutation(ref); + +console.log(data.movie_delete); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.movie_delete); +}); +``` + diff --git a/packages/angular/dataconnect-sdk/js/default-connector/angular/esm/index.esm.js b/packages/angular/dataconnect-sdk/js/default-connector/angular/esm/index.esm.js new file mode 100644 index 00000000..8652740e --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/angular/esm/index.esm.js @@ -0,0 +1,113 @@ +import { inject } from '@angular/core'; +import { queryRef, executeQuery, mutationRef, executeMutation, validateArgs, DataConnect } from '@angular/fire/data-connect'; +import { injectDataConnectQuery, injectDataConnectMutation } from '../../../../../'; + +export const connectorConfig = { + connector: 'default', + service: 'tanstack-query-firebase', + location: 'us-central1' +}; +export function listMoviesRef(dc) { + const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return queryRef(dcInstance, 'ListMovies'); +} +export function listMovies(dc) { + return executeQuery(listMoviesRef(dc)); +} + +export function injectListMovies(options) { + const dc = inject(DataConnect); + + return injectDataConnectQuery(() => { + const addOpn = options && options(); + return { + queryFn: () => ListMoviesRef(dc), + ...addOpn + }; + }); +} + +export function getMovieByIdRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return queryRef(dcInstance, 'GetMovieById', inputVars); +} +export function getMovieById(dcOrVars, vars) { + return executeQuery(getMovieByIdRef(dcOrVars, vars)); +} + +export function injectGetMovieById(args, options) { + const dc = inject(DataConnect); + + const varsFactoryFn = (typeof args === 'function') ? args : () => args; + + return injectDataConnectQuery(() => { + const addOpn = options && options(); + return { + queryFn: () => GetMovieByIdRef(dc, varsFactoryFn()), + ...addOpn + }; + }); +} + +export function createMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'CreateMovie', inputVars); +} +export function createMovie(dcOrVars, vars) { + return executeMutation(createMovieRef(dcOrVars, vars)); +} + +export function injectCreateMovie(args) { + return injectDataConnectMutation(CreateMovieRef, args); +} + +export function upsertMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'UpsertMovie', inputVars); +} +export function upsertMovie(dcOrVars, vars) { + return executeMutation(upsertMovieRef(dcOrVars, vars)); +} + +export function injectUpsertMovie(args) { + return injectDataConnectMutation(UpsertMovieRef, args); +} + +export function deleteMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'DeleteMovie', inputVars); +} +export function deleteMovie(dcOrVars, vars) { + return executeMutation(deleteMovieRef(dcOrVars, vars)); +} + +export function injectDeleteMovie(args) { + return injectDataConnectMutation(DeleteMovieRef, args); +} + + diff --git a/packages/angular/dataconnect-sdk/js/default-connector/angular/esm/package.json b/packages/angular/dataconnect-sdk/js/default-connector/angular/esm/package.json new file mode 100644 index 00000000..7c34deb5 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/angular/esm/package.json @@ -0,0 +1 @@ +{"type":"module"} \ No newline at end of file diff --git a/packages/angular/dataconnect-sdk/js/default-connector/angular/index.cjs.js b/packages/angular/dataconnect-sdk/js/default-connector/angular/index.cjs.js new file mode 100644 index 00000000..d10a6057 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/angular/index.cjs.js @@ -0,0 +1,146 @@ +const { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } = require('@angular/fire/data-connect'); +const { inject } = require('@angular/core'); + +const genSdkImports = require('../'); + + +const connectorConfig = { + connector: 'default', + service: 'tanstack-query-firebase', + location: 'us-central1' +}; +exports.connectorConfig = connectorConfig; + +function listMoviesRef(dc) { + const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return queryRef(dcInstance, 'ListMovies'); +} +exports.listMoviesRef = listMoviesRef; +exports.listMovies = function listMovies(dc) { + return executeQuery(listMoviesRef(dc)); +}; + +exports.injectListMovies = function injectListMovies(options) { + const dc = inject(DataConnect); + + return injectDataConnectQuery(() => { + const addOpn = options && options(); + return { + queryFn: () => ListMoviesRef(dc), + ...addOpn + }; + }); +} + + + + + + +function getMovieByIdRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return queryRef(dcInstance, 'GetMovieById', inputVars); +} +exports.getMovieByIdRef = getMovieByIdRef; +exports.getMovieById = function getMovieById(dcOrVars, vars) { + return executeQuery(getMovieByIdRef(dcOrVars, vars)); +}; + +exports.injectGetMovieById = function injectGetMovieById(args, options) { + const dc = inject(DataConnect); + + const varsFactoryFn = (typeof args === 'function') ? args : () => args; + + return injectDataConnectQuery(() => { + const addOpn = options && options(); + return { + queryFn: () => GetMovieByIdRef(dc, varsFactoryFn()), + ...addOpn + }; + }); +} + + + + + + +function createMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'CreateMovie', inputVars); +} +exports.createMovieRef = createMovieRef; +exports.createMovie = function createMovie(dcOrVars, vars) { + return executeMutation(createMovieRef(dcOrVars, vars)); +}; + +exports.injectCreateMovie = function injectCreateMovie(args) { + return injectDataConnectMutation(CreateMovieRef, args); +} + + + + + + +function upsertMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'UpsertMovie', inputVars); +} +exports.upsertMovieRef = upsertMovieRef; +exports.upsertMovie = function upsertMovie(dcOrVars, vars) { + return executeMutation(upsertMovieRef(dcOrVars, vars)); +}; + +exports.injectUpsertMovie = function injectUpsertMovie(args) { + return injectDataConnectMutation(UpsertMovieRef, args); +} + + + + + + +function deleteMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'DeleteMovie', inputVars); +} +exports.deleteMovieRef = deleteMovieRef; +exports.deleteMovie = function deleteMovie(dcOrVars, vars) { + return executeMutation(deleteMovieRef(dcOrVars, vars)); +}; + +exports.injectDeleteMovie = function injectDeleteMovie(args) { + return injectDataConnectMutation(DeleteMovieRef, args); +} + + + + + + diff --git a/packages/angular/dataconnect-sdk/js/default-connector/angular/index.d.ts b/packages/angular/dataconnect-sdk/js/default-connector/angular/index.d.ts new file mode 100644 index 00000000..98c09057 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/angular/index.d.ts @@ -0,0 +1,91 @@ +import { ListMoviesData, GetMovieByIdData, GetMovieByIdVariables, CreateMovieData, CreateMovieVariables, UpsertMovieData, UpsertMovieVariables, DeleteMovieData, DeleteMovieVariables } from '../'; +export { ListMoviesData, GetMovieByIdData, GetMovieByIdVariables, CreateMovieData, CreateMovieVariables, UpsertMovieData, UpsertMovieVariables, DeleteMovieData, DeleteMovieVariables } from '../'; +export { TimestampString, UUIDString, Int64String, DateString } from '../'; +import { ConnectorConfig, DataConnect, QueryRef, QueryPromise, MutationRef, MutationPromise} from '@angular/fire/data-connect'; +import { FlattenedQueryResult, CreateDataConnectQueryOptions, FlattenedMutationResult, CreateDataConnectMutationOptions} from '@tanstack-query-firebase/angular/data-connect'; +import { CreateQueryResult, CreateMutationResult} from '@tanstack/angular-query-experimental'; + +export const connectorConfig: ConnectorConfig; + +/* Allow users to create refs without passing in DataConnect */ +export function listMoviesRef(): QueryRef; +/* Allow users to pass in custom DataConnect instances */ +export function listMoviesRef(dc: DataConnect): QueryRef; + +export function listMovies(): QueryPromise; +export function listMovies(dc: DataConnect): QueryPromise; + + + + +type ListMoviesOptions = () => Omit, 'queryFn'>; +export function injectListMovies(options?: ListMoviesOptions): CreateQueryResult, FirebaseError, undefined>; + + + +/* Allow users to create refs without passing in DataConnect */ +export function getMovieByIdRef(vars: GetMovieByIdVariables): QueryRef; +/* Allow users to pass in custom DataConnect instances */ +export function getMovieByIdRef(dc: DataConnect, vars: GetMovieByIdVariables): QueryRef; + +export function getMovieById(vars: GetMovieByIdVariables): QueryPromise; +export function getMovieById(dc: DataConnect, vars: GetMovieByIdVariables): QueryPromise; + + + + +type GetMovieByIdArgs = GetMovieByIdVariables | (() => GetMovieByIdVariables); + +type GetMovieByIdOptions = () => Omit, 'queryFn'>; +export function injectGetMovieById(args: GetMovieByIdArgs, options?: GetMovieByIdOptions): CreateQueryResult, FirebaseError, GetMovieByIdVariables>; + + + +/* Allow users to create refs without passing in DataConnect */ +export function createMovieRef(vars: CreateMovieVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function createMovieRef(dc: DataConnect, vars: CreateMovieVariables): MutationRef; + +export function createMovie(vars: CreateMovieVariables): MutationPromise; +export function createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; + + + +type CreateMovieOptions = () => Omit, 'mutationFn'>; +export function injectCreateMovie(options?: CreateMovieOptions): CreateMutationResult; + + + +/* Allow users to create refs without passing in DataConnect */ +export function upsertMovieRef(vars: UpsertMovieVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function upsertMovieRef(dc: DataConnect, vars: UpsertMovieVariables): MutationRef; + +export function upsertMovie(vars: UpsertMovieVariables): MutationPromise; +export function upsertMovie(dc: DataConnect, vars: UpsertMovieVariables): MutationPromise; + + + +type UpsertMovieOptions = () => Omit, 'mutationFn'>; +export function injectUpsertMovie(options?: UpsertMovieOptions): CreateMutationResult; + + + +/* Allow users to create refs without passing in DataConnect */ +export function deleteMovieRef(vars: DeleteMovieVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function deleteMovieRef(dc: DataConnect, vars: DeleteMovieVariables): MutationRef; + +export function deleteMovie(vars: DeleteMovieVariables): MutationPromise; +export function deleteMovie(dc: DataConnect, vars: DeleteMovieVariables): MutationPromise; + + + +type DeleteMovieOptions = () => Omit, 'mutationFn'>; +export function injectDeleteMovie(options?: DeleteMovieOptions): CreateMutationResult; + + + + + + diff --git a/packages/angular/dataconnect-sdk/js/default-connector/angular/package.json b/packages/angular/dataconnect-sdk/js/default-connector/angular/package.json new file mode 100644 index 00000000..43b5d285 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/angular/package.json @@ -0,0 +1,25 @@ +{ + "name": "@dataconnect/default-connector-angular", + "version": "1.0.0", + "author": "Firebase (https://firebase.google.com/)", + "description": "Generated SDK For default-angular", + "license": "Apache-2.0", + "engines": { + "node": " >=18.0" + }, + "typings": "index.d.ts", + "main": "index.cjs.js", + "module": "esm/index.esm.js", + "browser": "esm/index.esm.js", + "exports": { + ".": { + "types": "./index.d.ts", + "require": "./index.cjs.js", + "default": "./esm/index.esm.js" + }, + "./package.json": "./package.json" + }, + "peerDependencies": { + "@angular/fire": "^19.0.0" + } +} \ No newline at end of file diff --git a/packages/angular/dataconnect-sdk/js/default-connector/esm/index.esm.js b/packages/angular/dataconnect-sdk/js/default-connector/esm/index.esm.js new file mode 100644 index 00000000..2a710e5d --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/esm/index.esm.js @@ -0,0 +1,68 @@ +import { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } from 'firebase/data-connect'; + +export const connectorConfig = { + connector: 'default', + service: 'tanstack-query-firebase', + location: 'us-central1' +}; + +export function listMoviesRef(dc) { + const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return queryRef(dcInstance, 'ListMovies'); +} +export function listMovies(dc) { + return executeQuery(listMoviesRef(dc)); +} +export function getMovieByIdRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return queryRef(dcInstance, 'GetMovieById', inputVars); +} +export function getMovieById(dcOrVars, vars) { + return executeQuery(getMovieByIdRef(dcOrVars, vars)); +} +export function createMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'CreateMovie', inputVars); +} +export function createMovie(dcOrVars, vars) { + return executeMutation(createMovieRef(dcOrVars, vars)); +} +export function upsertMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'UpsertMovie', inputVars); +} +export function upsertMovie(dcOrVars, vars) { + return executeMutation(upsertMovieRef(dcOrVars, vars)); +} +export function deleteMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'DeleteMovie', inputVars); +} +export function deleteMovie(dcOrVars, vars) { + return executeMutation(deleteMovieRef(dcOrVars, vars)); +} diff --git a/packages/angular/dataconnect-sdk/js/default-connector/esm/package.json b/packages/angular/dataconnect-sdk/js/default-connector/esm/package.json new file mode 100644 index 00000000..7c34deb5 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/esm/package.json @@ -0,0 +1 @@ +{"type":"module"} \ No newline at end of file diff --git a/packages/angular/dataconnect-sdk/js/default-connector/index.cjs.js b/packages/angular/dataconnect-sdk/js/default-connector/index.cjs.js new file mode 100644 index 00000000..0062b790 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/index.cjs.js @@ -0,0 +1,94 @@ +const { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } = require('firebase/data-connect'); + +const connectorConfig = { + connector: 'default', + service: 'tanstack-query-firebase', + location: 'us-central1' +}; +exports.connectorConfig = connectorConfig; + +function listMoviesRef(dc) { + const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return queryRef(dcInstance, 'ListMovies'); +} +exports.listMoviesRef = listMoviesRef; +exports.listMovies = function listMovies(dc) { + return executeQuery(listMoviesRef(dc)); +}; + + + + +function getMovieByIdRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return queryRef(dcInstance, 'GetMovieById', inputVars); +} +exports.getMovieByIdRef = getMovieByIdRef; +exports.getMovieById = function getMovieById(dcOrVars, vars) { + return executeQuery(getMovieByIdRef(dcOrVars, vars)); +}; + + + + +function createMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'CreateMovie', inputVars); +} +exports.createMovieRef = createMovieRef; +exports.createMovie = function createMovie(dcOrVars, vars) { + return executeMutation(createMovieRef(dcOrVars, vars)); +}; + + + + +function upsertMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'UpsertMovie', inputVars); +} +exports.upsertMovieRef = upsertMovieRef; +exports.upsertMovie = function upsertMovie(dcOrVars, vars) { + return executeMutation(upsertMovieRef(dcOrVars, vars)); +}; + + + + +function deleteMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + if('_useGeneratedSdk' in dcInstance) { + dcInstance._useGeneratedSdk(); + } else { + console.error('Please update to the latest version of the Data Connect SDK by running `npm install firebase@dataconnect-preview`.'); + } + return mutationRef(dcInstance, 'DeleteMovie', inputVars); +} +exports.deleteMovieRef = deleteMovieRef; +exports.deleteMovie = function deleteMovie(dcOrVars, vars) { + return executeMutation(deleteMovieRef(dcOrVars, vars)); +}; + + + + diff --git a/packages/angular/dataconnect-sdk/js/default-connector/index.d.ts b/packages/angular/dataconnect-sdk/js/default-connector/index.d.ts new file mode 100644 index 00000000..fe9d2d07 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/index.d.ts @@ -0,0 +1,117 @@ +import { ConnectorConfig, DataConnect, QueryRef, QueryPromise, MutationRef, MutationPromise } from 'firebase/data-connect'; +export const connectorConfig: ConnectorConfig; + +export type TimestampString = string; + +export type UUIDString = string; + +export type Int64String = string; + +export type DateString = string; + + +export interface CreateMovieData { + movie_insert: Movie_Key; +} + +export interface CreateMovieVariables { + title: string; + genre: string; + imageUrl: string; +} + +export interface DeleteMovieData { + movie_delete?: Movie_Key | null; +} + +export interface DeleteMovieVariables { + id: UUIDString; +} + +export interface GetMovieByIdData { + movie?: { + id: UUIDString; + title: string; + imageUrl: string; + genre?: string | null; + } & Movie_Key; +} + +export interface GetMovieByIdVariables { + id: UUIDString; +} + +export interface ListMoviesData { + movies: ({ + id: UUIDString; + title: string; + imageUrl: string; + genre?: string | null; + } & Movie_Key)[]; +} + +export interface MovieMetadata_Key { + id: UUIDString; + __typename?: 'MovieMetadata_Key'; +} + +export interface Movie_Key { + id: UUIDString; + __typename?: 'Movie_Key'; +} + +export interface UpsertMovieData { + movie_upsert: Movie_Key; +} + +export interface UpsertMovieVariables { + id: UUIDString; + title: string; + imageUrl: string; +} + + +/* Allow users to create refs without passing in DataConnect */ +export function listMoviesRef(): QueryRef; +/* Allow users to pass in custom DataConnect instances */ +export function listMoviesRef(dc: DataConnect): QueryRef; + +export function listMovies(): QueryPromise; +export function listMovies(dc: DataConnect): QueryPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function getMovieByIdRef(vars: GetMovieByIdVariables): QueryRef; +/* Allow users to pass in custom DataConnect instances */ +export function getMovieByIdRef(dc: DataConnect, vars: GetMovieByIdVariables): QueryRef; + +export function getMovieById(vars: GetMovieByIdVariables): QueryPromise; +export function getMovieById(dc: DataConnect, vars: GetMovieByIdVariables): QueryPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function createMovieRef(vars: CreateMovieVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function createMovieRef(dc: DataConnect, vars: CreateMovieVariables): MutationRef; + +export function createMovie(vars: CreateMovieVariables): MutationPromise; +export function createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function upsertMovieRef(vars: UpsertMovieVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function upsertMovieRef(dc: DataConnect, vars: UpsertMovieVariables): MutationRef; + +export function upsertMovie(vars: UpsertMovieVariables): MutationPromise; +export function upsertMovie(dc: DataConnect, vars: UpsertMovieVariables): MutationPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function deleteMovieRef(vars: DeleteMovieVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function deleteMovieRef(dc: DataConnect, vars: DeleteMovieVariables): MutationRef; + +export function deleteMovie(vars: DeleteMovieVariables): MutationPromise; +export function deleteMovie(dc: DataConnect, vars: DeleteMovieVariables): MutationPromise; + diff --git a/packages/angular/dataconnect-sdk/js/default-connector/package.json b/packages/angular/dataconnect-sdk/js/default-connector/package.json new file mode 100644 index 00000000..c9eaefe3 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/package.json @@ -0,0 +1,37 @@ +{ + "name": "@dataconnect/default-connector", + "version": "1.0.0", + "author": "Firebase (https://firebase.google.com/)", + "description": "Generated SDK For default", + "license": "Apache-2.0", + "engines": { + "node": " >=18.0" + }, + "typings": "index.d.ts", + "module": "esm/index.esm.js", + "main": "index.cjs.js", + "browser": "esm/index.esm.js", + "exports": { + ".": { + "types": "./index.d.ts", + "require": "./index.cjs.js", + "default": "./esm/index.esm.js" + }, + "./react": { + "types": "./react/index.d.ts", + "import": "./react/esm/index.esm.js", + "default": "./react/esm/index.esm.js" + }, + "./angular": { + "types": "./angular/index.d.ts", + "import": "./angular/esm/index.esm.js", + "default": "./angular/esm/index.esm.js" + }, + "./package.json": "./package.json" + }, + "peerDependencies": { + "firebase": "^10.14.0 || ^11.0.0", + "@tanstack-query-firebase/react": "^1.0.5" + + } +} \ No newline at end of file diff --git a/packages/angular/dataconnect-sdk/js/default-connector/react/esm/index.esm.js b/packages/angular/dataconnect-sdk/js/default-connector/react/esm/index.esm.js new file mode 100644 index 00000000..1619ab92 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/react/esm/index.esm.js @@ -0,0 +1,49 @@ +import { listMoviesRef, getMovieByIdRef, createMovieRef, upsertMovieRef, deleteMovieRef } from '../../'; +import { useDataConnectQuery, useDataConnectMutation } from '@tanstack-query-firebase/react/data-connect'; + + + + + +export function useListMovies( options) { + return useDataConnectQuery(listMoviesRef(), options); +} + + + + + + +export function useGetMovieById(vars, options) { + return useDataConnectQuery(getMovieByIdRef(vars), options); +} + + + + + + +export function useCreateMovie(options) { + return useDataConnectMutation(createMovieRef, options); +} + + + + + + +export function useUpsertMovie(options) { + return useDataConnectMutation(upsertMovieRef, options); +} + + + + + + +export function useDeleteMovie(options) { + return useDataConnectMutation(deleteMovieRef, options); +} + + + diff --git a/packages/angular/dataconnect-sdk/js/default-connector/react/esm/package.json b/packages/angular/dataconnect-sdk/js/default-connector/react/esm/package.json new file mode 100644 index 00000000..7c34deb5 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/react/esm/package.json @@ -0,0 +1 @@ +{"type":"module"} \ No newline at end of file diff --git a/packages/angular/dataconnect-sdk/js/default-connector/react/index.cjs.js b/packages/angular/dataconnect-sdk/js/default-connector/react/index.cjs.js new file mode 100644 index 00000000..137c62b7 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/react/index.cjs.js @@ -0,0 +1,50 @@ +const { listMoviesRef, getMovieByIdRef, createMovieRef, upsertMovieRef, deleteMovieRef } = require('../'); +const { useDataConnectQuery, useDataConnectMutation } = require( '@tanstack-query-firebase/react/data-connect'); + + + + + +exports.useListMovies = function useListMovies( options) { + return useDataConnectQuery(listMoviesRef(), options); +} + + + + + + +exports.useGetMovieById = function useGetMovieById(vars, options) { + return useDataConnectQuery(getMovieByIdRef(vars), options); +} + + + + + + +exports.useCreateMovie = function useCreateMovie(options) { + return useDataConnectMutation(createMovieRef, options); +} + + + + + + +exports.useUpsertMovie = function useUpsertMovie(options) { + return useDataConnectMutation(upsertMovieRef, options); +} + + + + + + +exports.useDeleteMovie = function useDeleteMovie(options) { + return useDataConnectMutation(deleteMovieRef, options); +} + + + + diff --git a/packages/angular/dataconnect-sdk/js/default-connector/react/index.d.ts b/packages/angular/dataconnect-sdk/js/default-connector/react/index.d.ts new file mode 100644 index 00000000..05ac3574 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/react/index.d.ts @@ -0,0 +1,10 @@ +import { ListMoviesData, GetMovieByIdData, GetMovieByIdVariables, CreateMovieData, CreateMovieVariables, UpsertMovieData, UpsertMovieVariables, DeleteMovieData, DeleteMovieVariables} from '../'; +import { FlattenedQueryResult, useDataConnectQueryOptions, FlattenedMutationResult, useDataConnectMutationOptions} from '@tanstack-query-firebase/react/data-connect'; +import { UseQueryResult, UseMutationResult} from '@tanstack/react-query'; +import { FirebaseError } from 'firebase/app'; + +export function useListMovies(options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; +export function useGetMovieById(vars: GetMovieByIdVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; +export function useCreateMovie(options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, CreateMovieVariables>; +export function useUpsertMovie(options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, UpsertMovieVariables>; +export function useDeleteMovie(options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, DeleteMovieVariables>; diff --git a/packages/angular/dataconnect-sdk/js/default-connector/react/package.json b/packages/angular/dataconnect-sdk/js/default-connector/react/package.json new file mode 100644 index 00000000..f2fee700 --- /dev/null +++ b/packages/angular/dataconnect-sdk/js/default-connector/react/package.json @@ -0,0 +1,17 @@ +{ + "name": "@dataconnect/default-connector-react", + "version": "1.0.0", + "author": "Firebase (https://firebase.google.com/)", + "description": "Generated SDK For default", + "license": "Apache-2.0", + "engines": { + "node": " >=18.0" + }, + "typings": "index.d.ts", + "main": "index.cjs.js", + "module": "esm/index.esm.js", + "browser": "esm/index.esm.js", + "peerDependencies": { + "@tanstack-query-firebase/react": "^1.0.5" + } +} \ No newline at end of file diff --git a/packages/angular/index.d.ts b/packages/angular/index.d.ts new file mode 100644 index 00000000..223e65e8 --- /dev/null +++ b/packages/angular/index.d.ts @@ -0,0 +1,2 @@ + +export { } diff --git a/packages/angular/package-lock.json b/packages/angular/package-lock.json index a70d5215..54385da8 100644 --- a/packages/angular/package-lock.json +++ b/packages/angular/package-lock.json @@ -9,22 +9,24 @@ "version": "0.0.1", "license": "ISC", "dependencies": { - "@angular/animations": "^19.1.6", - "@angular/core": "^19.1.0", "@angular/fire": "^19.0.0-rc.5", - "@tanstack/angular-query-experimental": "^5.64.1", + "@tanstack/angular-query-experimental": "^5.66.4", "firebase": "^11.1.0" }, "devDependencies": { "@analogjs/vite-plugin-angular": "^1.13.0", + "@angular/animations": "^19.0.0", "@testing-library/angular": "^17.3.5", "@testing-library/dom": "^10.4.0" + }, + "peerDependencies": { + "@angular/core": "^19.0.0" } }, "node_modules/@analogjs/vite-plugin-angular": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@analogjs/vite-plugin-angular/-/vite-plugin-angular-1.13.0.tgz", - "integrity": "sha512-h9XTXtbOKXyjrjFdy5qy40wam3vTttujWCpnoqygnopWaKS9T86LVnBFAW1p2yaBa7Wzz/BKDs2MtBBPWht8Sw==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@analogjs/vite-plugin-angular/-/vite-plugin-angular-1.13.1.tgz", + "integrity": "sha512-9+zd7K3Vur3UzSTu2PUdPMPrBD/JDOxz5TF2GzbqhdlWEdKL8odC7mnkKdCwzYFkcB+x9E8j4hPPpmXnMnY5Jg==", "dev": true, "dependencies": { "ts-morph": "^21.0.0", @@ -48,9 +50,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "19.1.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.7.tgz", - "integrity": "sha512-q0I6L9KTqyQ7D5M8H+fWLT+yjapvMNb7SRdfU6GzmexO66Dpo83q4HDzuDKIPDF29Yl0ELs9ICJqe9yUXh6yDQ==", + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.8.tgz", + "integrity": "sha512-j1zHKvOsGwu5YwAZGuzi835R9vcW7PkfxmSRIJeVl+vawgk31K3zFb4UPH8AY/NPWYqXIAnwpka3HC1+JrWLWA==", "dependencies": { "ajv": "8.17.1", "ajv-formats": "3.0.1", @@ -74,11 +76,11 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "19.1.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.1.7.tgz", - "integrity": "sha512-AP6FvhMybCYs3gs+vzEAzSU1K//AFT3SVTRFv+C3WMO5dLeAHeGzM8I2dxD5EHQQtqIE/8apP6CxGrnpA5YlFg==", + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.1.8.tgz", + "integrity": "sha512-2JGUMD3zjfY8G4RYpypm2/1YEO+O4DtFycUvptIpsBYyULgnEbJ3tlp2oRiXI2vp9tC8IyWqa/swlA8DTI6ZYQ==", "dependencies": { - "@angular-devkit/core": "19.1.7", + "@angular-devkit/core": "19.1.8", "jsonc-parser": "3.3.1", "magic-string": "0.30.17", "ora": "5.4.1", @@ -91,9 +93,10 @@ } }, "node_modules/@angular/animations": { - "version": "19.1.6", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.1.6.tgz", - "integrity": "sha512-iacosz3fygp0AyT57+suVpLChl10xS5RBje09TfQIKHTUY0LWkMspgaK9gwtlflpIhjedPV0UmgRIKhhFcQM1A==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.1.7.tgz", + "integrity": "sha512-EnyQTCNc1nWnjc5V3HPlClpJIS2R2XAfIEUCyI3lE4FLQxcXyhIsM9NmacAZT3Ai8RL+8JVCttPmBZXMpjP6Ug==", + "devOptional": true, "dependencies": { "tslib": "^2.3.0" }, @@ -101,13 +104,13 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "19.1.6" + "@angular/core": "19.1.7" } }, "node_modules/@angular/common": { - "version": "19.1.6", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.1.6.tgz", - "integrity": "sha512-FkuejwbxsOLhcyOgDM/7YEYvMG3tuyOvr+831VzPwMwYp5QO9AUYtn4ffGf698JccbA+Ocw3BAdhPU6i+YZC1A==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.1.7.tgz", + "integrity": "sha512-MXfUGfWeesTQ12HXgeoVIXsS+r1jZxT2FkLQtqS+NRsRD4T1vlyvD7kTI+Ku1NAjdt3mB8TJ0cZHubvmml8I+Q==", "peer": true, "dependencies": { "tslib": "^2.3.0" @@ -116,14 +119,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "19.1.6", + "@angular/core": "19.1.7", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "19.1.6", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.1.6.tgz", - "integrity": "sha512-Tl2PFEtnU8UgSqtEKG827xDUGZrErhR6S1JICeV1kbRCYmwQA4hhG25tzi+ifSAOPW7eJiyzP2LWIvOuZkq3Vw==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.1.7.tgz", + "integrity": "sha512-Q3eqqIhMEzrnmFJtUO0K+WPpCfP/JTl9lJXZKe0zgNPdRFUufjSUcPHGzd7OjN2gPpiAvS1yBvENvqs+g/MejQ==", "peer": true, "dependencies": { "tslib": "^2.3.0" @@ -132,7 +135,7 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "19.1.6" + "@angular/core": "19.1.7" }, "peerDependenciesMeta": { "@angular/core": { @@ -141,9 +144,10 @@ } }, "node_modules/@angular/core": { - "version": "19.1.6", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.1.6.tgz", - "integrity": "sha512-FD167URT+apxjzj9sG/MzffW5G6YyQiPQ6nrrIoYi9jeY3LYurybuOgvcXrU8PT4Z3+CKMq9k/ZnmrlHU72BpA==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.1.7.tgz", + "integrity": "sha512-P+e4ekJYWMFhWSzJav0R51bFAfUhIOmnqmG9mlI/ZONu2qcTTmyIG9AW5x1qhrMHEH42RaeK60RkKyqgcHaGDg==", + "peer": true, "dependencies": { "tslib": "^2.3.0" }, @@ -185,9 +189,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "19.1.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.1.6.tgz", - "integrity": "sha512-sfWU+gMpqQ6GYtE3tAfDktftC01NgtqAOKfeCQ/KY2rxRTIxYahenW0Licuzgmd+8AZtmncoZaYX0Fd/5XMqzQ==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.1.7.tgz", + "integrity": "sha512-QKakWl+CeVVwn22yjRHBXm6BvDsHoo+9u1pJGGk2smKSYjHW6qAly28+P7FUfVXUQI7rg++M66JwzNOFfYMDQA==", "peer": true, "dependencies": { "tslib": "^2.3.0" @@ -196,9 +200,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "19.1.6", - "@angular/common": "19.1.6", - "@angular/core": "19.1.6" + "@angular/animations": "19.1.7", + "@angular/common": "19.1.7", + "@angular/core": "19.1.7" }, "peerDependenciesMeta": { "@angular/animations": { @@ -207,9 +211,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "19.1.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.1.6.tgz", - "integrity": "sha512-QedjG7/ctPtzgJ3LcWv4yMcSivKlwcZ8ge8zPe7eu9Ft6mDZZat65gJEjDuvevJoeNbo2dQODFDiyPJNmnNA9A==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.1.7.tgz", + "integrity": "sha512-rp7IXun1fHeScpIni0l2VRxBW5LzokHYfZ69K4BRhE7FpVA6hP2c9fhCJeo7681c/Q882Kom0tmsedOcF/zwMQ==", "peer": true, "dependencies": { "tslib": "^2.3.0" @@ -218,16 +222,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "19.1.6", - "@angular/compiler": "19.1.6", - "@angular/core": "19.1.6", - "@angular/platform-browser": "19.1.6" + "@angular/common": "19.1.7", + "@angular/compiler": "19.1.7", + "@angular/core": "19.1.7", + "@angular/platform-browser": "19.1.7" } }, "node_modules/@angular/router": { - "version": "19.1.6", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.1.6.tgz", - "integrity": "sha512-TEfw3W5jVodVDMD4krhXGog1THZN3x1yoh2oZmCv3lXg22+pVC6Cp+x3vVExq0mS+g3/6uZwy/3qAYdlzqYjTg==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.1.7.tgz", + "integrity": "sha512-4wqfHxVvMmnpRyRhOClo0qX7li1MnWaQ8U1ZMd8gsZgE3SKkOxXdHg/jO4tcbLMLD4QAZ82uB8MBvHl1vVMhKg==", "dev": true, "peer": true, "dependencies": { @@ -237,9 +241,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "19.1.6", - "@angular/core": "19.1.6", - "@angular/platform-browser": "19.1.6", + "@angular/common": "19.1.7", + "@angular/core": "19.1.7", + "@angular/platform-browser": "19.1.7", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -267,9 +271,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", - "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz", + "integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -965,12 +969,12 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "node_modules/@schematics/angular": { - "version": "19.1.7", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.1.7.tgz", - "integrity": "sha512-BB8yMGmYDZzSb8Nu+Ln0TKyeoS3++f9STCYw30NwM3IViHxJJYxu/zowzwSa9TjftIzdCpbOaPxGS0vU9UOUDQ==", + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.1.8.tgz", + "integrity": "sha512-ytgClbMPn+i+w1S3QukR/Vdge+sfU9aX49ao+XRwoWdOssHUjmVjQcCEdzu0ucSrNPZnhm34bdDPzADLhln60w==", "dependencies": { - "@angular-devkit/core": "19.1.7", - "@angular-devkit/schematics": "19.1.7", + "@angular-devkit/core": "19.1.8", + "@angular-devkit/schematics": "19.1.8", "jsonc-parser": "3.3.1" }, "engines": { @@ -980,11 +984,11 @@ } }, "node_modules/@tanstack/angular-query-experimental": { - "version": "5.66.0", - "resolved": "https://registry.npmjs.org/@tanstack/angular-query-experimental/-/angular-query-experimental-5.66.0.tgz", - "integrity": "sha512-wECwAbsIQWXiKXNOjvAWeyw44KZJ/q0hWdWUy4SV3vp8eFW3f0LvAlkuLvUSA8jdcC5NvO2VO8T/gLRE9YjArg==", + "version": "5.66.4", + "resolved": "https://registry.npmjs.org/@tanstack/angular-query-experimental/-/angular-query-experimental-5.66.4.tgz", + "integrity": "sha512-MELhfZLKCNMyHvAna8qFZFW5CLRpJ87qjj+e8PB1H/tbtqi9d2oWKUw6KC+XkRRVh2kauvtsyn3HBTKr063B3w==", "dependencies": { - "@tanstack/query-core": "5.66.0", + "@tanstack/query-core": "5.66.4", "@tanstack/query-devtools": "5.65.0" }, "funding": { @@ -997,9 +1001,9 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.66.0", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.66.0.tgz", - "integrity": "sha512-J+JeBtthiKxrpzUu7rfIPDzhscXF2p5zE/hVdrqkACBP8Yu0M96mwJ5m/8cPPYQE9aRNvXztXHlNwIh4FEeMZw==", + "version": "5.66.4", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.66.4.tgz", + "integrity": "sha512-skM/gzNX4shPkqmdTCSoHtJAPMTtmIJNS0hE+xwTTUVYwezArCT34NMermABmBVUg5Ls5aiUXEDXfqwR1oVkcA==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" @@ -1015,9 +1019,9 @@ } }, "node_modules/@testing-library/angular": { - "version": "17.3.5", - "resolved": "https://registry.npmjs.org/@testing-library/angular/-/angular-17.3.5.tgz", - "integrity": "sha512-B79mN7kNDY9/+0Kc6cVGnVptQ03oHVL1at1tMu44wvr7Ksk10g11lZw7BA0c7rHAJQoXgiWrXmvtJxkPA1R2uA==", + "version": "17.3.6", + "resolved": "https://registry.npmjs.org/@testing-library/angular/-/angular-17.3.6.tgz", + "integrity": "sha512-8LxEfNtjhd6iguWus8TQngMwXfw8Y4qPMXeeCqtxbIf7gbhnPA52R8ofiqCMy+p9cD/kMOY9KZAxj18P+5vNHw==", "dev": true, "dependencies": { "tslib": "^2.3.1" @@ -1068,9 +1072,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", + "version": "22.13.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz", + "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==", "dependencies": { "undici-types": "~6.20.0" } @@ -1600,9 +1604,9 @@ } }, "node_modules/long": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.0.tgz", - "integrity": "sha512-5vvY5yF1zF/kXk+L94FRiTDa1Znom46UjPCH6/XbSvS8zBKMFBHTJk8KDMqJ+2J6QezQFi7k1k8v21ClJYHPaw==" + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", + "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==" }, "node_modules/lz-string": { "version": "1.5.0", diff --git a/packages/angular/package.json b/packages/angular/package.json index 0f189abf..26bdee24 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -30,15 +30,17 @@ "author": "", "license": "ISC", "dependencies": { - "@angular/animations": "^19.1.6", - "@angular/core": "^19.1.0", "@angular/fire": "^19.0.0-rc.5", - "@tanstack/angular-query-experimental": "^5.64.1", + "@tanstack/angular-query-experimental": "^5.66.4", "firebase": "^11.1.0" }, "devDependencies": { + "@angular/animations": "^19.0.0", "@analogjs/vite-plugin-angular": "^1.13.0", "@testing-library/angular": "^17.3.5", "@testing-library/dom": "^10.4.0" + }, + "peerDependencies": { + "@angular/core": "^19.0.0" } } diff --git a/packages/angular/src/data-connect/index.ts b/packages/angular/src/data-connect/index.ts index 7416121e..d5646a4e 100644 --- a/packages/angular/src/data-connect/index.ts +++ b/packages/angular/src/data-connect/index.ts @@ -15,6 +15,10 @@ import { assertInInjectionContext, computed, inject, + InjectionToken, + Injector, + isSignal, + runInInjectionContext, signal, } from "@angular/core"; import { @@ -27,6 +31,8 @@ import { QueryResult, } from "@angular/fire/data-connect"; import { createMovieRef } from "../../dataconnect-sdk/js/default-connector/angular"; +import { mutationRef } from "firebase/data-connect"; +import { SIGNAL } from "@angular/core/primitives/signals"; function getQueryKey(queryRef: QueryRef) { const key: (string | Record)[] = [queryRef.name]; if ("variables" in queryRef && queryRef.variables !== undefined) { @@ -95,7 +101,7 @@ export function injectDataConnectQuery( export type GeneratedSignature = (( dc: DataConnect, vars: Variables -) => MutationRef); // TODO(mtewani): Add +) => MutationRef); // TODO(mtewani): Add __angular: true export type DataConnectMutationOptionsFn = () => Omit, "mutationFn"> & { invalidate?: QueryKey | QueryRef[]; @@ -116,8 +122,9 @@ export type FlattenedMutationResult = Omit< > & Data; +type EmptyFactoryFn = () => MutationRef; export function injectDataConnectMutation( - factoryFn: undefined, + factoryFn: undefined | null, optionsFn: DataConnectMutationOptionsFn< Data, FirebaseError, @@ -129,19 +136,42 @@ export function injectDataConnectMutation( FirebaseError, Arguments >; +export function injectDataConnectMutation< + Data, + Variables, + Arguments = void | undefined +>( + factoryFn: EmptyFactoryFn, + options?: DataConnectMutationOptionsUndefinedMutationFn +): CreateMutationResult< + FlattenedMutationResult, + FirebaseError, + Arguments +>; + export function injectDataConnectMutation< Data, Variables extends undefined, Arguments = void | undefined >( - factoryFn: GeneratedSignature + factoryFn: EmptyFactoryFn, + options?: DataConnectMutationOptionsUndefinedMutationFn ): CreateMutationResult< FlattenedMutationResult, FirebaseError, Arguments >; -export function injectDataConnectMutation( - factoryFn: GeneratedSignature +export function injectDataConnectMutation< + Data, + Variables extends undefined, + Arguments = Variables +>( + factoryFn: GeneratedSignature, + optionsFn?: DataConnectMutationOptionsUndefinedMutationFn< + Data, + FirebaseError, + Arguments + > ): CreateMutationResult< FlattenedMutationResult, FirebaseError, @@ -166,6 +196,7 @@ export function injectDataConnectMutation< // TODO(mtewani): Just check for the fact that the user has passed in a generated Angular fn. AKA __angular: true /** * injectDataConnectMutation takes a mutation ref factory function and returns a tanstack wrapper around `injectMutation` + * @example injectDataConnectMutation(createMovieRef); * @param factoryFn generated SDK factory function * @param optionsFn options function to create a new mutation * @returns {CreateMutationResult, FirebaseError, Arguments>} @@ -175,7 +206,7 @@ export function injectDataConnectMutation< Variables, Arguments extends Variables >( - factoryFn: GeneratedSignature | undefined, + factoryFn: GeneratedSignature | EmptyFactoryFn | undefined | null, optionsFn?: | DataConnectMutationOptionsFn | DataConnectMutationOptionsUndefinedMutationFn< @@ -188,21 +219,23 @@ export function injectDataConnectMutation< FirebaseError, Arguments > { - assertInInjectionContext(injectDataConnectMutation); + /** + * Hypothesis: + * It seems like optionsSignal is causing observerSignal to get called again + * + */ const dataConnect = inject(DataConnect); const queryClient = inject(QueryClient); + const injectCb = () => { - // TODO(mtewani): Figure out why this is needed - // Remember: there's a compute() on the optionsFn that's passed on the injectionMutation - const optionsSignal = computed(() => { - return optionsFn ? optionsFn() : undefined; - }); + + + const providedOptions = optionsFn && optionsFn(); const modifiedFn = (args: Arguments) => { - const providedOptions = optionsSignal(); const ref = (providedOptions && "mutationFn" in providedOptions! && - providedOptions!.mutationFn(args as Arguments)) || + providedOptions!.mutationFn(args)) || factoryFn!(dataConnect, args as Variables); return executeMutation(ref) @@ -244,10 +277,10 @@ export function injectDataConnectMutation< }; return { + ...providedOptions, mutationFn: modifiedFn, }; }; + return injectMutation(injectCb); } - - diff --git a/packages/angular/src/data-connect/injectDataConnectMutation.test.ts b/packages/angular/src/data-connect/injectDataConnectMutation.test.ts new file mode 100644 index 00000000..8b8cedfa --- /dev/null +++ b/packages/angular/src/data-connect/injectDataConnectMutation.test.ts @@ -0,0 +1,969 @@ +import { TestBed } from "@angular/core/testing"; +import { provideHttpClient } from '@angular/common/http'; +import { + connectorConfig, + createMovie, + +} from "../../dataconnect-sdk/js/default-connector"; +import { + createMovieRef, + upsertMovieRef, + deleteMovieRef, + getMovieByIdRef, + UpsertMovieVariables, + listMoviesRef, +} from "../../dataconnect-sdk/js/default-connector/angular"; +import { waitFor } from '@testing-library/angular'; +import { beforeEach, afterEach, describe, expect, test, vi } from "vitest"; +import { injectDataConnectMutation } from "./index"; +import { + provideTanStackQuery, + QueryClient, +} from "@tanstack/angular-query-experimental"; +import { + provideDataConnect, + connectDataConnectEmulator, + DataConnect, + getDataConnect, +} from "@angular/fire/data-connect"; + +import { provideFirebaseApp, initializeApp } from "@angular/fire/app"; +import { inject, isSignal, provideExperimentalZonelessChangeDetection, Signal, untracked } from "@angular/core"; + +// initialize firebase app +initializeApp({projectId: 'p'}); + +describe("injectDataConnectMutation", () => { + let queryClient: QueryClient = new QueryClient(); + const onSuccess = vi.fn(); + let invalidateQueriesSpy = vi.spyOn(queryClient, "invalidateQueries"); + let oldMutationObserver: typeof window.MutationObserver; + + beforeEach(() => { + vi.resetAllMocks(); + oldMutationObserver = window.MutationObserver; + queryClient = new QueryClient(); + invalidateQueriesSpy = vi.spyOn(queryClient, "invalidateQueries"); + TestBed.configureTestingModule({ + providers: [ + provideExperimentalZonelessChangeDetection(), // Required as angularfire's ZoneScheduler breaks tests. + provideFirebaseApp(() => initializeApp({ projectId: "p" })), + provideDataConnect(() => { + const dc = getDataConnect(connectorConfig); + connectDataConnectEmulator(dc, "localhost", 9399); + return dc; + }), + provideHttpClient(), + provideTanStackQuery(queryClient), + ], + }); + // queryClient.clear(); + }); + + afterEach(() => { + window.MutationObserver = oldMutationObserver; + vi.restoreAllMocks(); + vi.useRealTimers() + }); + + test("returns initial state correctly for create mutation", () => { + const mutation = TestBed.runInInjectionContext(() => { + return injectDataConnectMutation(createMovieRef); + }); + expect(mutation.isIdle()).toBe(true); + expect(mutation.status()).toBe("idle"); + }); + + test("returns initial state correctly for update mutation", () => { + const result = TestBed.runInInjectionContext(() => + injectDataConnectMutation(upsertMovieRef) + ); + + expect(result.isIdle()).toBe(true); + expect(result.status()).toBe("idle"); + }); + + test("returns initial state correctly for delete mutation", () => { + const result = TestBed.runInInjectionContext(() => + injectDataConnectMutation(deleteMovieRef) + ); + + expect(result.isIdle()).toBe(true); + expect(result.status()).toBe("idle"); + }); + + test("executes create mutation successfully thus returning flattened data including ref, source, and fetchTime", async () => { + const mutation = TestBed.runInInjectionContext(() => { + return injectDataConnectMutation(createMovieRef); + }); + const fdc = TestBed.runInInjectionContext(() => { + return inject(DataConnect); + }); + + expect(mutation.isIdle()).toBe(true); + + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + await mutation.mutateAsync(movie); + + await waitFor(() => { + expect(mutation.isSuccess()).toBe(true); + expect(mutation.data()).toBeDefined(); + expect(mutation.data()).toHaveProperty("ref"); + expect(mutation.data()).toHaveProperty("source"); + expect(mutation.data()).toHaveProperty("fetchTime"); + expect(mutation.data()).toHaveProperty("movie_insert"); + expect(mutation.data()?.ref?.variables).toMatchObject(movie); + }); + }); + + test("executes update mutation successfully thus returning flattened data including ref, source, and fetchTime", async () => { + const createMutationResult = TestBed.runInInjectionContext(() => + injectDataConnectMutation(createMovieRef) + ); + + expect(createMutationResult.isIdle()).toBe(true); + + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + + await createMutationResult.mutateAsync(movie); + + await waitFor(() => { + expect(createMutationResult.isSuccess()).toBe(true); + expect(createMutationResult.data()).toHaveProperty("movie_insert"); + }); + + const movieId = createMutationResult.data()?.movie_insert.id!; + + const upsertMutationResult = TestBed.runInInjectionContext(() => + injectDataConnectMutation(upsertMovieRef) + ); + + await upsertMutationResult.mutateAsync({ + id: movieId, + imageUrl: "https://updated-image-url.com/", + title: "TanStack Query Firebase - updated", + }); + await waitFor(() => { + expect(upsertMutationResult.isSuccess()).toBe(true); + expect(upsertMutationResult.data()).toBeDefined(); + expect(upsertMutationResult.data()).toHaveProperty("ref"); + expect(upsertMutationResult.data()).toHaveProperty("source"); + expect(upsertMutationResult.data()).toHaveProperty("fetchTime"); + expect(upsertMutationResult.data()).toHaveProperty("movie_upsert"); + expect(upsertMutationResult.data()?.movie_upsert.id).toBe(movieId); + }); + }); + + test("executes delete mutation successfully thus returning flattened data including ref, source, and fetchTime", async () => { + const createMutationResult = TestBed.runInInjectionContext(() => + injectDataConnectMutation(createMovieRef) + ); + + expect(createMutationResult.isIdle()).toBe(true); + + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + + await createMutationResult.mutateAsync(movie); + + await waitFor(() => { + expect(createMutationResult.isSuccess()).toBe(true); + expect(createMutationResult.data()).toHaveProperty("movie_insert"); + }); + + const movieId = createMutationResult.data()?.movie_insert.id!; + + const deleteMutationResult = TestBed.runInInjectionContext(() => + injectDataConnectMutation(deleteMovieRef) + ); + + await deleteMutationResult.mutateAsync({ + id: movieId, + }); + + await waitFor(() => { + expect(deleteMutationResult.isSuccess()).toBe(true); + expect(deleteMutationResult.data()).toBeDefined(); + expect(deleteMutationResult.data()).toHaveProperty("ref"); + expect(deleteMutationResult.data()).toHaveProperty("source"); + expect(deleteMutationResult.data()).toHaveProperty("fetchTime"); + expect(deleteMutationResult.data()).toHaveProperty("movie_delete"); + expect(deleteMutationResult.data()?.movie_delete?.id).toBe(movieId); + }); + }); + + test("handles concurrent create mutations", async () => { + const result = TestBed.runInInjectionContext(() => + injectDataConnectMutation(createMovieRef) + ); + + const movies = [ + { + title: "Concurrent Test 1", + genre: "concurrent_test", + imageUrl: "https://test-image-url-1.com/", + }, + { + title: "Concurrent Test 2", + genre: "concurrent_test", + imageUrl: "https://test-image-url-2.com/", + }, + { + title: "Concurrent Test 3", + genre: "concurrent_test", + imageUrl: "https://test-image-url-3.com/", + }, + ]; + + const createdMovies: { id: string }[] = []; + + await Promise.all( + movies.map(async (movie) => { + const data = await result.mutateAsync(movie); + createdMovies.push(data?.movie_insert); + }) + ); + + await waitFor(() => { + expect(result.isSuccess()).toBe(true); + + // Assert that all movies were created + expect(createdMovies).toHaveLength(3); + createdMovies.forEach((movie) => { + expect(movie).toHaveProperty("id"); + }); + + // Check if all IDs are unique + const ids = createdMovies.map((movie) => movie.id); + expect(new Set(ids).size).toBe(ids.length); + }); + }); + + test("handles concurrent upsert mutations", async () => { + const createMutationResult = TestBed.runInInjectionContext(() => + injectDataConnectMutation(createMovieRef) + ); + + const movies = [ + { + title: "Concurrent Test 1", + genre: "concurrent_test", + imageUrl: "https://test-image-url-1.com/", + }, + { + title: "Concurrent Test 2", + genre: "concurrent_test", + imageUrl: "https://test-image-url-2.com/", + }, + { + title: "Concurrent Test 3", + genre: "concurrent_test", + imageUrl: "https://test-image-url-3.com/", + }, + ]; + + const createdMovies: { id: string }[] = []; + + await Promise.all( + movies.map(async (movie) => { + const data = await createMutationResult.mutateAsync(movie); + createdMovies.push(data?.movie_insert); + }) + ); + + await waitFor(() => { + expect(createMutationResult.isSuccess()).toBe(true); + }); + + const upsertMutationResult = TestBed.runInInjectionContext(() => + injectDataConnectMutation(upsertMovieRef) + ); + + const upsertData = createdMovies.map((movie, index) => ({ + id: movie.id, + title: `Updated Test ${index + 1}`, + imageUrl: `https://updated-image-url-${index + 1}.com/`, + })); + + // concurrent upsert operations + const upsertedMovies: { id: string }[] = []; + await Promise.all( + upsertData.map(async (update) => { + const data = await upsertMutationResult.mutateAsync(update); + upsertedMovies.push(data?.movie_upsert); + }) + ); + + await waitFor(() => { + expect(upsertMutationResult.isSuccess()).toBe(true); + expect(upsertedMovies).toHaveLength(3); + + // Check if all upserted IDs match original IDs + const upsertedIds = upsertedMovies.map((movie) => movie.id); + expect(upsertedIds).toEqual( + expect.arrayContaining(createdMovies.map((m) => m.id)) + ); + }); + }); + + test("handles concurrent delete mutations", async () => { + const createMutationResult = TestBed.runInInjectionContext(() => + injectDataConnectMutation(createMovieRef) + ); + + const movies = [ + { + title: "Concurrent Test 1", + genre: "concurrent_test", + imageUrl: "https://test-image-url-1.com/", + }, + { + title: "Concurrent Test 2", + genre: "concurrent_test", + imageUrl: "https://test-image-url-2.com/", + }, + { + title: "Concurrent Test 3", + genre: "concurrent_test", + imageUrl: "https://test-image-url-3.com/", + }, + ]; + + const createdMovies: { id: string }[] = []; + + await Promise.all( + movies.map(async (movie) => { + const data = await createMutationResult.mutateAsync(movie); + createdMovies.push(data?.movie_insert); + }) + ); + + await waitFor(() => { + expect(createMutationResult.isSuccess()).toBe(true); + }); + + const deleteMutationResult = TestBed.runInInjectionContext(() => + injectDataConnectMutation(deleteMovieRef) + ); + + const deleteData = createdMovies.map((movie, index) => ({ + id: movie.id, + })); + + // concurrent delete operations + const deletedMovies: { id: string }[] = []; + await Promise.all( + deleteData.map(async (i) => { + const data = await deleteMutationResult.mutateAsync(i); + deletedMovies.push(data.movie_delete!); + }) + ); + + await waitFor(() => { + expect(deleteMutationResult.isSuccess()).toBe(true); + expect(deletedMovies).toHaveLength(3); + + // Check if all deleted IDs match original IDs + const deletedIds = deletedMovies.map((movie) => movie.id); + expect(deletedIds).toEqual( + expect.arrayContaining(createdMovies.map((m) => m.id)) + ); + }); + }); + + test("invalidates queries specified in the invalidate option for create mutations with non-variable refs", async () => { + const result = TestBed.runInInjectionContext(() => + injectDataConnectMutation(createMovieRef, () => ({ + invalidate: [listMoviesRef()] + })) + ); + const movie = { + title: "TanStack Query Firebase", + genre: "invalidate_option_test", + imageUrl: "https://test-image-url.com/", + }; + TestBed.flushEffects(); + + // @ts-ignore + await result.mutateAsync(movie); + + await waitFor(() => { + expect(result.status()).toBe("success"); + }); + + // expect(invalidateQueriesSpy.mock.calls).toHaveLength(1); + // expect(invalidateQueriesSpy).toHaveBeenCalledWith( + // expect.objectContaining({ + // queryKey: [listMoviesRef().name], + // }) + // ); + }); + + test("invalidates queries specified in the invalidate option for create mutations with variable refs", async () => { + const movieData = { + title: "tanstack query firebase", + genre: "library", + imageUrl: "https://invertase.io/", + }; + + const createdMovie = await createMovie(movieData); + + const movieId = createdMovie?.data?.movie_insert?.id; + + const result = TestBed.runInInjectionContext(() => + injectDataConnectMutation(createMovieRef, () => ({ + invalidate: [getMovieByIdRef({ id: movieId })], + })) + ); + const movie = { + title: "TanStack Query Firebase", + genre: "invalidate_option_test", + imageUrl: "https://test-image-url.com/", + }; + + await result.mutateAsync(movie); + + await waitFor(() => { + expect(result.status()).toBe("success"); + }); + + expect(invalidateQueriesSpy.mock.calls).toHaveLength(1); + expect(invalidateQueriesSpy).toHaveBeenCalledWith( + expect.objectContaining({ + queryKey: ["GetMovieById", { id: movieId }], + exact: true, + }) + ); + }); + + test("invalidates queries specified in the invalidate option for create mutations with both variable and non-variable refs", async () => { + const movieData = { + title: "tanstack query firebase", + genre: "library", + imageUrl: "https://invertase.io/", + }; + + const createdMovie = await createMovie(movieData); + + const movieId = createdMovie?.data?.movie_insert?.id; + + const result = TestBed.runInInjectionContext(() => + injectDataConnectMutation(createMovieRef, () => ({ + invalidate: [listMoviesRef(), getMovieByIdRef({ id: movieId })], + })) + ); + const movie = { + title: "TanStack Query Firebase", + genre: "invalidate_option_test", + imageUrl: "https://test-image-url.com/", + }; + + await result.mutateAsync(movie); + + await waitFor(() => { + expect(result.status()).toBe("success"); + }); + + expect(invalidateQueriesSpy.mock.calls).toHaveLength(2); + expect(invalidateQueriesSpy.mock.calls).toEqual( + expect.arrayContaining([ + [ + expect.objectContaining({ + queryKey: ["ListMovies"], + }), + ], + [ + expect.objectContaining({ + queryKey: ["GetMovieById", { id: movieId }], + exact: true, + }), + ], + ]) + ); + }); + + + test("invalidates queries specified in the invalidate option for upsert mutations with non-variable refs", async () => { + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + const createMutationResult = TestBed.runInInjectionContext(() => + injectDataConnectMutation( + createMovieRef + ) + ); + + + await createMutationResult.mutateAsync(movie); + + + await waitFor(() => { + expect(createMutationResult.isSuccess()).to.be.true; + }); + + + expect(createMutationResult.data()).toHaveProperty("movie_insert"); + + const movieId = createMutationResult.data()?.movie_insert.id!; + + + const upsertMutationResult = TestBed.runInInjectionContext( + () => + injectDataConnectMutation((_: DataConnect, vars: UpsertMovieVariables) => upsertMovieRef(vars), () => ({ + invalidate: [ listMoviesRef()], + })), + ); + + await upsertMutationResult.mutateAsync({ + id: movieId, + imageUrl: "https://updated-image-url.com/", + title: "TanStack Query Firebase - updated", + }); + upsertMutationResult.data() + + await waitFor(() => { + expect(upsertMutationResult.isSuccess()).toBe(true); + expect(upsertMutationResult.data()).toHaveProperty("movie_upsert"); + expect(upsertMutationResult.data()?.movie_upsert.id).toBe(movieId); + }, { timeout: 10000}); + + expect(invalidateQueriesSpy.mock.calls).toHaveLength(1); + expect(invalidateQueriesSpy).toHaveBeenCalledWith( + expect.objectContaining({ + queryKey: [listMoviesRef().name], + }) + ); + }); + + test("invalidates queries specified in the invalidate option for upsert mutations with variable refs", async () => { + const createMutationResult = TestBed.runInInjectionContext( + () => injectDataConnectMutation(createMovieRef), + ); + + expect(createMutationResult.isIdle()).toBe(true); + + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + + await createMutationResult.mutateAsync(movie); + + await waitFor(() => { + expect(createMutationResult.isSuccess()).toBe(true); + expect(createMutationResult.data()).toHaveProperty("movie_insert"); + }); + + const movieId = createMutationResult.data()?.movie_insert.id!; + + const upsertMutationResult = TestBed.runInInjectionContext( + () => + injectDataConnectMutation(upsertMovieRef, () => ({ + invalidate: [getMovieByIdRef({ id: movieId })], + })), + ); + + await upsertMutationResult.mutateAsync({ + id: movieId, + imageUrl: "https://updated-image-url.com/", + title: "TanStack Query Firebase - updated", + }); + + await waitFor(() => { + expect(upsertMutationResult.isSuccess()).toBe(true); + expect(upsertMutationResult.data()).toHaveProperty("movie_upsert"); + expect(upsertMutationResult.data()?.movie_upsert.id).toBe(movieId); + }); + + expect(invalidateQueriesSpy.mock.calls).toHaveLength(1); + expect(invalidateQueriesSpy).toHaveBeenCalledWith( + expect.objectContaining({ + queryKey: ["GetMovieById", { id: movieId }], + exact: true, + }) + ); + }); + + test("invalidates queries specified in the invalidate option for upsert mutations with both variable and non-variable refs", async () => { + const createMutationResult = TestBed.runInInjectionContext( + () => injectDataConnectMutation(createMovieRef), + ); + + expect(createMutationResult.isIdle()).toBe(true); + + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + + await createMutationResult.mutateAsync(movie); + + await waitFor(() => { + expect(createMutationResult.isSuccess()).toBe(true); + expect(createMutationResult.data()).toHaveProperty("movie_insert"); + }); + + const movieId = createMutationResult.data()?.movie_insert.id!; + + const upsertMutationResult = TestBed.runInInjectionContext( + () => + injectDataConnectMutation(upsertMovieRef, () => ({ + invalidate: [listMoviesRef(), getMovieByIdRef({ id: movieId })], + })), + ); + + await upsertMutationResult.mutateAsync({ + id: movieId, + imageUrl: "https://updated-image-url.com/", + title: "TanStack Query Firebase - updated", + }); + + await waitFor(() => { + expect(upsertMutationResult.isSuccess()).toBe(true); + expect(upsertMutationResult.data()).toHaveProperty("movie_upsert"); + expect(upsertMutationResult.data()?.movie_upsert.id).toBe(movieId); + }); + + expect(invalidateQueriesSpy.mock.calls).toHaveLength(2); + expect(invalidateQueriesSpy.mock.calls).toEqual( + expect.arrayContaining([ + [ + expect.objectContaining({ + queryKey: ["GetMovieById", { id: movieId }], + exact: true, + }), + ], + [ + expect.objectContaining({ + queryKey: ["ListMovies"], + }), + ], + ]) + ); + }); + + test("invalidates queries specified in the invalidate option for delete mutations with non-variable refs", async () => { + const createMutationResult = TestBed.runInInjectionContext( + () => injectDataConnectMutation(createMovieRef), + ); + + expect(createMutationResult.isIdle()).toBe(true); + + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + + await createMutationResult.mutateAsync(movie); + + await waitFor(() => { + expect(createMutationResult.isSuccess()).toBe(true); + expect(createMutationResult.data()).toHaveProperty("movie_insert"); + }); + + const movieId = createMutationResult.data()?.movie_insert.id!; + + const deleteMutationResult = TestBed.runInInjectionContext( + () => + injectDataConnectMutation(deleteMovieRef, () => ({ + invalidate: [listMoviesRef()], + })), + + ); + + await deleteMutationResult.mutateAsync({ + id: movieId, + }); + + await waitFor(() => { + expect(deleteMutationResult.isSuccess()).toBe(true); + expect(deleteMutationResult.data()).toHaveProperty("movie_delete"); + expect(deleteMutationResult.data()?.movie_delete?.id).toBe(movieId); + }); + + expect(invalidateQueriesSpy.mock.calls).toHaveLength(1); + expect(invalidateQueriesSpy).toHaveBeenCalledWith( + expect.objectContaining({ + queryKey: [listMoviesRef().name], + }) + ); + }); + + test("invalidates queries specified in the invalidate option for delete mutations with variable refs", async () => { + const createMutationResult = TestBed.runInInjectionContext( + () => injectDataConnectMutation(createMovieRef), + + ); + + expect(createMutationResult.isIdle()).toBe(true); + + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + + await createMutationResult.mutateAsync(movie); + + await waitFor(() => { + expect(createMutationResult.isSuccess()).toBe(true); + expect(createMutationResult.data()).toHaveProperty("movie_insert"); + }); + + const movieId = createMutationResult.data()?.movie_insert.id!; + + const deleteMutationResult = TestBed.runInInjectionContext( + () => + injectDataConnectMutation(deleteMovieRef, () => ({ + invalidate: [getMovieByIdRef({ id: movieId })], + })), + ); + + await deleteMutationResult.mutateAsync({ + id: movieId, + }); + + await waitFor(() => { + expect(deleteMutationResult.isSuccess()).toBe(true); + expect(deleteMutationResult.data()).toHaveProperty("movie_delete"); + expect(deleteMutationResult.data()?.movie_delete?.id).toBe(movieId); + }); + + expect(invalidateQueriesSpy.mock.calls).toHaveLength(1); + expect(invalidateQueriesSpy).toHaveBeenCalledWith( + expect.objectContaining({ + queryKey: ["GetMovieById", { id: movieId }], + exact: true, + }) + ); + }); + + test("invalidates queries specified in the invalidate option for delete mutations with both variable and non-variable refs", async () => { + const createMutationResult = TestBed.runInInjectionContext( + () => injectDataConnectMutation(createMovieRef), + + ); + + expect(createMutationResult.isIdle()).toBe(true); + + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + + await createMutationResult.mutateAsync(movie); + + await waitFor(() => { + expect(createMutationResult.isSuccess()).toBe(true); + expect(createMutationResult.data()).toHaveProperty("movie_insert"); + }); + + const movieId = createMutationResult.data()?.movie_insert.id!; + + const deleteMutationResult = TestBed.runInInjectionContext( + () => + injectDataConnectMutation(deleteMovieRef, () => ({ + invalidate: [listMoviesRef(), getMovieByIdRef({ id: movieId })], + })), + ); + + await deleteMutationResult.mutateAsync({ + id: movieId, + }); + + await waitFor(() => { + expect(deleteMutationResult.isSuccess()).toBe(true); + expect(deleteMutationResult.data()).toHaveProperty("movie_delete"); + expect(deleteMutationResult.data()?.movie_delete?.id).toBe(movieId); + }); + + expect(invalidateQueriesSpy.mock.calls).toHaveLength(2); + expect(invalidateQueriesSpy.mock.calls).toEqual( + expect.arrayContaining([ + [ + expect.objectContaining({ + queryKey: ["GetMovieById", { id: movieId }], + exact: true, + }), + ], + [ + expect.objectContaining({ + queryKey: ["ListMovies"], + }), + ], + ]) + ); + }); + + test("calls onSuccess callback after successful create mutation", async () => { + const result = TestBed.runInInjectionContext( + () => injectDataConnectMutation(createMovieRef, () => ({ onSuccess })), + ); + + const movie = { + title: "TanStack Query Firebase", + genre: "onsuccess_callback_test", + imageUrl: "https://test-image-url.com/", + }; + + await result.mutateAsync(movie); + + await waitFor(() => { + expect(onSuccess).toHaveBeenCalled(); + expect(result.isSuccess()).toBe(true); + expect(result.data()).toHaveProperty("movie_insert"); + }); + }); + + test("calls onSuccess callback after successful upsert mutation", async () => { + const createMutationResult = TestBed.runInInjectionContext( + () => injectDataConnectMutation(createMovieRef), + + ); + + expect(createMutationResult.isIdle()).toBe(true); + + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + + await createMutationResult.mutateAsync(movie); + + await waitFor(() => { + expect(createMutationResult.isSuccess()).toBe(true); + expect(createMutationResult.data()).toHaveProperty("movie_insert"); + }); + + const movieId = createMutationResult.data()?.movie_insert.id!; + + const upsertMutationResult = TestBed.runInInjectionContext( + () => injectDataConnectMutation(upsertMovieRef, () => ({ onSuccess })), + ); + + await upsertMutationResult.mutateAsync({ + id: movieId, + imageUrl: "https://updated-image-url.com/", + title: "TanStack Query Firebase - updated", + }); + + await waitFor(() => { + expect(upsertMutationResult.isSuccess()).toBe(true); + expect(onSuccess).toHaveBeenCalled(); + expect(upsertMutationResult.data()).toHaveProperty("movie_upsert"); + expect(upsertMutationResult.data()?.movie_upsert.id).toBe(movieId); + }); + }); + + test("calls onSuccess callback after successful delete mutation", async () => { + const createMutationResult = TestBed.runInInjectionContext( + () => injectDataConnectMutation(createMovieRef), + ); + + expect(createMutationResult.isIdle()).toBe(true); + + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + + await createMutationResult.mutateAsync(movie); + + await waitFor(() => { + expect(createMutationResult.isSuccess()).toBe(true); + expect(createMutationResult.data()).toHaveProperty("movie_insert"); + }); + + const movieId = createMutationResult.data()?.movie_insert.id!; + + const deleteMutationResult = TestBed.runInInjectionContext( + () => injectDataConnectMutation(deleteMovieRef, () => ({ onSuccess })), + + ); + + await deleteMutationResult.mutateAsync({ + id: movieId, + }); + + await waitFor(() => { + expect(deleteMutationResult.isSuccess()).toBe(true); + expect(onSuccess).toHaveBeenCalled(); + expect(deleteMutationResult.data()).toHaveProperty("movie_delete"); + expect(deleteMutationResult.data()?.movie_delete?.id).toBe(movieId); + }); + }); + + test("executes mutation successfully with function ref", async () => { + const movie = { + title: "TanStack Query Firebase", + genre: "library", + imageUrl: "https://test-image-url.com/", + }; + + const result = TestBed.runInInjectionContext( + () => injectDataConnectMutation(() => createMovieRef(movie)), + + ); + + await result.mutateAsync(); + + await waitFor(() => { + expect(result.isSuccess()).toBe(true); + expect(result.data()).toHaveProperty("movie_insert"); + expect(result.data()?.ref.variables).toMatchObject({ + title: movie.title, + genre: movie.genre, + imageUrl: movie.imageUrl, + }); + }); + }); + + test("executes mutation successfully with function ref that accepts variables", async () => { + const result = TestBed.runInInjectionContext( + () => + injectDataConnectMutation(null, () => + ({ + mutationFn: (title: string) => createMovieRef({ + title, + genre: "library", + imageUrl: "https://test-image-url.com/", + }) + }) + + ), + ); + + const movieTitle = "TanStack Query Firebase"; + + await result.mutateAsync(movieTitle); + + await waitFor(() => { + expect(result.isSuccess()).toBe(true); + expect(result.data()).toHaveProperty("movie_insert"); + expect(result.data()?.ref.variables).toMatchObject({ + title: movieTitle, + genre: "library", + imageUrl: "https://test-image-url.com/", + }); + }); + }); +}); diff --git a/packages/angular/src/data-connect/injectDataConnectQuery.test.ts b/packages/angular/src/data-connect/injectDataConnectQuery.test.ts new file mode 100644 index 00000000..0663117c --- /dev/null +++ b/packages/angular/src/data-connect/injectDataConnectQuery.test.ts @@ -0,0 +1,202 @@ +import { + connectorConfig, + createMovie, + getMovieByIdRef, + listMoviesRef, +} from "../../dataconnect-sdk/js/default-connector/angular"; +import { provideHttpClient } from '@angular/common/http'; +import { waitFor } from "@testing-library/angular"; +import { connectDataConnectEmulator, DataConnect, getDataConnect, provideDataConnect } from "@angular/fire/data-connect"; +import { beforeEach, describe, expect, test } from "vitest"; +import { provideFirebaseApp, initializeApp } from "@angular/fire/app"; +import {injectDataConnectQuery } from "./index"; +import { provideTanStackQuery, QueryClient } from "@tanstack/angular-query-experimental"; +import { TestBed } from "@angular/core/testing"; +import { inject, provideExperimentalZonelessChangeDetection } from "@angular/core"; + +// initialize firebase app +initializeApp({projectId: 'p'}); + +describe("injectDataConnectQuery", () => { + let queryClient: QueryClient = new QueryClient(); + const onSuccess = vi.fn(); + let invalidateQueriesSpy = vi.spyOn(queryClient, "invalidateQueries"); + let oldMutationObserver: typeof window.MutationObserver; + let dc: DataConnect; + beforeEach(async () => { + queryClient.clear(); + TestBed.configureTestingModule({ + providers: [ + provideExperimentalZonelessChangeDetection(), // Required as angularfire's ZoneScheduler breaks tests. + provideFirebaseApp(() => initializeApp({ projectId: "p" })), + provideDataConnect(() => { + const dc = getDataConnect(connectorConfig); + connectDataConnectEmulator(dc, "localhost", 9399); + return dc; + }), + provideHttpClient(), + provideTanStackQuery(queryClient), + ], + }); + dc = TestBed.runInInjectionContext(() => inject(DataConnect)); + }); + + test("returns pending state initially", async () => { + const result = TestBed.runInInjectionContext(() => injectDataConnectQuery(listMoviesRef(dc))); + + expect(result.isPending()).toBe(true); + expect(result.status()).toBe("pending"); + + await waitFor(() => expect(result.isSuccess()).toBe(true)); + + expect(result.data()).toBeDefined(); + }); + + test("fetches data successfully", async () => { + const result = TestBed.runInInjectionContext(() => injectDataConnectQuery(listMoviesRef(dc))); + + expect(result.isPending()).toBe(true); + + await waitFor(() => expect(result.isSuccess()).toBe(true)); + + expect(result.data()).toBeDefined(); + expect(result.data()).toHaveProperty("movies"); + expect(Array.isArray(result.data()?.movies)).toBe(true); + expect(result.data()?.movies.length).toBeGreaterThanOrEqual(0); + }); + + test("refetches data successfully", async () => { + const result = TestBed.runInInjectionContext(() => injectDataConnectQuery(listMoviesRef(dc)), ); + + await waitFor(() => { + expect(result.isSuccess()).toBe(true); + expect(result.data()).toBeDefined(); + expect(result.data()).toHaveProperty("ref"); + expect(result.data()).toHaveProperty("source"); + expect(result.data()).toHaveProperty("fetchTime"); + }); + + const initialFetchTime = result.data()?.fetchTime; + + await new Promise((resolve) => setTimeout(resolve, 2000)); // 2 seconds delay before refetching + + result.refetch(); + + await waitFor(() => { + expect(result.isSuccess()).toBe(true); + expect(result.data()).toBeDefined(); + expect(result.data()).toHaveProperty("ref"); + expect(result.data()).toHaveProperty("source"); + expect(result.data()).toHaveProperty("fetchTime"); + expect(result.data()).toHaveProperty("movies"); + expect(Array.isArray(result.data()?.movies)).toBe(true); + expect(result.data()?.movies.length).toBeGreaterThanOrEqual(0); + }); + + const refetchTime = result.data()?.fetchTime; + }); + + test("returns correct data", async () => { + const result = TestBed.runInInjectionContext(() => injectDataConnectQuery(listMoviesRef(dc))); + + await createMovie({ + title: "tanstack query firebase", + genre: "library", + imageUrl: "https://invertase.io/", + }); + + await waitFor(() => expect(result.isSuccess()).toBe(true)); + + expect(result.data()).toBeDefined(); + expect(result.data()?.movies).toBeDefined(); + expect(Array.isArray(result.data()?.movies)).toBe(true); + + const movie = result.data()?.movies.find( + (m) => m.title === "tanstack query firebase", + ); + + expect(movie).toBeDefined(); + expect(movie).toHaveProperty("title", "tanstack query firebase"); + expect(movie).toHaveProperty("genre", "library"); + expect(movie).toHaveProperty("imageUrl", "https://invertase.io/"); + }); + + test("returns the correct data properties", async () => { + const result = TestBed.runInInjectionContext(() => injectDataConnectQuery(listMoviesRef(dc))); + + await createMovie({ + title: "tanstack query firebase", + genre: "library", + imageUrl: "https://invertase.io/", + }); + + await waitFor(() => expect(result.isSuccess()).toBe(true)); + + result.data()?.movies.forEach((i) => { + expect(i).toHaveProperty("title"); + expect(i).toHaveProperty("genre"); + expect(i).toHaveProperty("imageUrl"); + }); + }); + + test("fetches data by unique identifier", async () => { + const movieData = { + title: "tanstack query firebase", + genre: "library", + imageUrl: "https://invertase.io/", + }; + const createdMovie = await createMovie(movieData); + + const movieId = createdMovie?.data?.movie_insert?.id; + + const result = TestBed.runInInjectionContext( + () => injectDataConnectQuery(getMovieByIdRef({ id: movieId })), + ); + + await waitFor(() => { + expect(result.isSuccess()).toBe(true); + expect(result.data()?.movie?.title).toBe(movieData?.title); + expect(result.data()?.movie?.genre).toBe(movieData?.genre); + expect(result.data()?.movie?.imageUrl).toBe(movieData?.imageUrl); + }); + }); + + test("returns flattened data including ref, source, and fetchTime", async () => { + const result = TestBed.runInInjectionContext(() => injectDataConnectQuery(listMoviesRef(dc))); + + expect(result.isLoading()).toBe(true); + + await waitFor(() => expect(result.isSuccess()).toBe(true)); + + expect(result.data()).toBeDefined(); + expect(result.data()).toHaveProperty("ref"); + expect(result.data()).toHaveProperty("source"); + expect(result.data()).toHaveProperty("fetchTime"); + }); + + test("returns flattened data including ref, source, and fetchTime for queries with unique identifier", async () => { + const movieData = { + title: "tanstack query firebase", + genre: "library", + imageUrl: "https://invertase.io/", + }; + const createdMovie = await createMovie(movieData); + + const movieId = createdMovie?.data?.movie_insert?.id; + + const result = TestBed.runInInjectionContext( + () => injectDataConnectQuery(getMovieByIdRef({ id: movieId })) + + ); + + expect(result.isPending()).toBe(true); + + await waitFor(() => expect(result.isSuccess()).toBe(true)); + + expect(result.data()).toBeDefined(); + expect(result.data()).toHaveProperty("ref"); + expect(result.data()).toHaveProperty("source"); + expect(result.data()).toHaveProperty("fetchTime"); + }); + +}); diff --git a/packages/angular/test-setup.ts b/packages/angular/test-setup.ts new file mode 100644 index 00000000..bc6df85d --- /dev/null +++ b/packages/angular/test-setup.ts @@ -0,0 +1,10 @@ +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from '@angular/platform-browser-dynamic/testing' +import { getTestBed } from '@angular/core/testing' + +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting(), +) \ No newline at end of file diff --git a/packages/angular/vitest.config.ts b/packages/angular/vitest.config.ts new file mode 100644 index 00000000..38fb1cbf --- /dev/null +++ b/packages/angular/vitest.config.ts @@ -0,0 +1,31 @@ +import { defineConfig } from 'vitest/config' +import * as path from 'path'; + +import packageJson from './package.json' + +export default defineConfig({ + resolve: { + alias: { + "~/testing-utils": path.resolve(__dirname, "../../vitest/utils"), +"@/dataconnect/default-connector": path.resolve( + __dirname, + "./dataconnect-sdk/js/default-connector" + ), + } +, + }, + test: { + fakeTimers: { + toFake: ['setTimeout', 'clearTimeout', 'Date'] + }, + name: packageJson.name, + dir: './src', + watch: false, + environment: 'happy-dom', + setupFiles: ['test-setup.ts'], + coverage: { enabled: true, provider: 'istanbul', include: ['src/**/*'] }, + typecheck: { enabled: true }, + globals: true, + restoreMocks: true, + }, +}) \ No newline at end of file diff --git a/packages/react/src/data-connect/useDataConnectMutation.ts b/packages/react/src/data-connect/useDataConnectMutation.ts index 72b2853d..c32fa335 100644 --- a/packages/react/src/data-connect/useDataConnectMutation.ts +++ b/packages/react/src/data-connect/useDataConnectMutation.ts @@ -5,10 +5,12 @@ import { } from "@tanstack/react-query"; import type { FirebaseError } from "firebase/app"; import { + ConnectorConfig, type DataConnect, type MutationRef, type QueryRef, executeMutation, + getDataConnect, mutationRef, } from "firebase/data-connect"; import type { FlattenedMutationResult } from "./types"; @@ -90,3 +92,4 @@ export function useDataConnectMutation< }, }); } +const res = useDataConnectMutation((abc: string) => abc === 'a' ? mutationRef(getDataConnect({} as ConnectorConfig), '', { abc: 1 }) : mutationRef(getDataConnect({} as ConnectorConfig), '', { abc: 2})) From 154727ea6babc2daa7150402da4fd191c7af8807 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Thu, 20 Feb 2025 11:12:51 -0800 Subject: [PATCH 10/10] Fixed typings --- .firebaserc | 7 - .../.dataconnect/schema/main/implicit.gql | 10 - .../.dataconnect/schema/main/input.gql | 296 --- .../.dataconnect/schema/main/mutation.gql | 226 -- .../.dataconnect/schema/main/query.gql | 88 - .../.dataconnect/schema/main/relation.gql | 6 - dataconnect/.dataconnect/schema/prelude.gql | 2009 ----------------- dataconnect/connector/connector.yaml | 8 - dataconnect/connector/mutations.gql | 52 - dataconnect/connector/queries.gql | 68 - dataconnect/dataconnect.yaml | 12 - dataconnect/schema/schema.gql | 45 - firebase.json | 29 - packages/angular/package.json | 2 +- packages/angular/src/data-connect/index.ts | 46 +- .../injectDataConnectMutation.test.ts | 10 +- .../injectDataConnectQuery.test.ts | 2 +- packages/angular/tsconfig.json | 4 +- packages/react/package.json | 2 +- .../data-connect/useDataConnectMutation.ts | 1 - .../data-connect/useDataConnectQuery.test.tsx | 21 +- .../src/data-connect/useDataConnectQuery.ts | 17 +- packages/react/tsconfig.json | 4 +- pnpm-workspace.yaml | 3 +- vitest.config.ts | 18 - vitest/utils.ts | 105 - 26 files changed, 59 insertions(+), 3032 deletions(-) delete mode 100644 .firebaserc delete mode 100644 dataconnect/.dataconnect/schema/main/implicit.gql delete mode 100644 dataconnect/.dataconnect/schema/main/input.gql delete mode 100644 dataconnect/.dataconnect/schema/main/mutation.gql delete mode 100644 dataconnect/.dataconnect/schema/main/query.gql delete mode 100644 dataconnect/.dataconnect/schema/main/relation.gql delete mode 100644 dataconnect/.dataconnect/schema/prelude.gql delete mode 100644 dataconnect/connector/connector.yaml delete mode 100644 dataconnect/connector/mutations.gql delete mode 100644 dataconnect/connector/queries.gql delete mode 100644 dataconnect/dataconnect.yaml delete mode 100644 dataconnect/schema/schema.gql delete mode 100644 firebase.json delete mode 100644 vitest.config.ts delete mode 100644 vitest/utils.ts diff --git a/.firebaserc b/.firebaserc deleted file mode 100644 index 40c5a6ed..00000000 --- a/.firebaserc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "projects": { - "default": "demo-project" - }, - "targets": {}, - "etags": {} -} diff --git a/dataconnect/.dataconnect/schema/main/implicit.gql b/dataconnect/.dataconnect/schema/main/implicit.gql deleted file mode 100644 index b4fc81d7..00000000 --- a/dataconnect/.dataconnect/schema/main/implicit.gql +++ /dev/null @@ -1,10 +0,0 @@ -extend type MovieMetadata { - """ - ✨ Implicit primary key field. It's a UUID column default to a generated new value. See `@table` for how to customize it. - """ - id: UUID! @default(expr: "uuidV4()") @fdc_generated(from: "MovieMetadata", purpose: IMPLICIT_KEY_FIELD) - """ - ✨ Implicit foreign key field based on `MovieMetadata`.`movie`. It must match the value of `Movie`.`id`. See `@ref` for how to customize it. - """ - movieId: UUID! @fdc_generated(from: "MovieMetadata.movie", purpose: IMPLICIT_REF_FIELD) -} diff --git a/dataconnect/.dataconnect/schema/main/input.gql b/dataconnect/.dataconnect/schema/main/input.gql deleted file mode 100644 index 0b662a21..00000000 --- a/dataconnect/.dataconnect/schema/main/input.gql +++ /dev/null @@ -1,296 +0,0 @@ -""" -✨ `Movie_KeyOutput` returns the primary key fields of table type `Movie`. - -It has the same format as `Movie_Key`, but is only used as mutation return value. -""" -scalar Movie_KeyOutput -""" -✨ `MovieMetadata_KeyOutput` returns the primary key fields of table type `MovieMetadata`. - -It has the same format as `MovieMetadata_Key`, but is only used as mutation return value. -""" -scalar MovieMetadata_KeyOutput -""" -✨ Generated data input type for table 'Movie'. It includes all necessary fields for creating or upserting rows into table. -""" -input Movie_Data { - """ - ✨ Generated from Field `Movie`.`id` of type `UUID!` - """ - id: UUID - """ - ✨ `_expr` server value variant of `id` (✨ Generated from Field `Movie`.`id` of type `UUID!`) - """ - id_expr: UUID_Expr - """ - ✨ Generated from Field `Movie`.`genre` of type `String` - """ - genre: String - """ - ✨ `_expr` server value variant of `genre` (✨ Generated from Field `Movie`.`genre` of type `String`) - """ - genre_expr: String_Expr - """ - ✨ Generated from Field `Movie`.`imageUrl` of type `String!` - """ - imageUrl: String - """ - ✨ `_expr` server value variant of `imageUrl` (✨ Generated from Field `Movie`.`imageUrl` of type `String!`) - """ - imageUrl_expr: String_Expr - """ - ✨ Generated from Field `Movie`.`title` of type `String!` - """ - title: String - """ - ✨ `_expr` server value variant of `title` (✨ Generated from Field `Movie`.`title` of type `String!`) - """ - title_expr: String_Expr -} -""" -✨ Generated filter input type for table 'Movie'. This input allows filtering objects using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. -""" -input Movie_Filter { - """ - Apply multiple filter conditions using `AND` logic. - """ - _and: [Movie_Filter!] - """ - Negate the result of the provided filter condition. - """ - _not: Movie_Filter - """ - Apply multiple filter conditions using `OR` logic. - """ - _or: [Movie_Filter!] - """ - ✨ Generated from Field `Movie`.`id` of type `UUID!` - """ - id: UUID_Filter - """ - ✨ Generated from Field `Movie`.`genre` of type `String` - """ - genre: String_Filter - """ - ✨ Generated from Field `Movie`.`imageUrl` of type `String!` - """ - imageUrl: String_Filter - """ - ✨ Generated from Field `Movie`.`title` of type `String!` - """ - title: String_Filter - """ - ✨ Generated from Field `Movie`.`movieMetadata_on_movie` of type `MovieMetadata` - """ - movieMetadata_on_movie: MovieMetadata_Filter -} -""" -✨ Generated first-row input type for table 'Movie'. This input selects the first row matching the filter criteria, ordered according to the specified conditions. -""" -input Movie_FirstRow { - """ - Order the result by the specified fields. - """ - orderBy: [Movie_Order!] - """ - Filters rows based on the specified conditions. - """ - where: Movie_Filter -} -""" -✨ Generated key input type for table 'Movie'. It represents the primary key fields used to uniquely identify a row in the table. -""" -input Movie_Key { - """ - ✨ Generated from Field `Movie`.`id` of type `UUID!` - """ - id: UUID - """ - ✨ `_expr` server value variant of `id` (✨ Generated from Field `Movie`.`id` of type `UUID!`) - """ - id_expr: UUID_Expr -} -""" -✨ Generated list filter input type for table 'Movie'. This input applies filtering logic based on the count or existence of related objects that matches certain criteria. -""" -input Movie_ListFilter { - """ - The desired number of objects that match the condition (defaults to at least one). - """ - count: Int_Filter = {gt:0} - """ - Condition of the related objects to filter for. - """ - exist: Movie_Filter -} -""" -✨ Generated order input type for table 'Movie'. This input defines the sorting order of rows in query results based on one or more fields. -""" -input Movie_Order { - """ - ✨ Generated from Field `Movie`.`id` of type `UUID!` - """ - id: OrderDirection - """ - ✨ Generated from Field `Movie`.`genre` of type `String` - """ - genre: OrderDirection - """ - ✨ Generated from Field `Movie`.`imageUrl` of type `String!` - """ - imageUrl: OrderDirection - """ - ✨ Generated from Field `Movie`.`title` of type `String!` - """ - title: OrderDirection -} -""" -✨ Generated data input type for table 'MovieMetadata'. It includes all necessary fields for creating or upserting rows into table. -""" -input MovieMetadata_Data { - """ - ✨ Generated from Field `MovieMetadata`.`id` of type `UUID!` - """ - id: UUID - """ - ✨ `_expr` server value variant of `id` (✨ Generated from Field `MovieMetadata`.`id` of type `UUID!`) - """ - id_expr: UUID_Expr - """ - ✨ Generated from Field `MovieMetadata`.`movieId` of type `UUID!` - """ - movieId: UUID - """ - ✨ `_expr` server value variant of `movieId` (✨ Generated from Field `MovieMetadata`.`movieId` of type `UUID!`) - """ - movieId_expr: UUID_Expr - """ - ✨ Generated from Field `MovieMetadata`.`movie` of type `Movie!` - """ - movie: Movie_Key - """ - ✨ Generated from Field `MovieMetadata`.`description` of type `String` - """ - description: String - """ - ✨ `_expr` server value variant of `description` (✨ Generated from Field `MovieMetadata`.`description` of type `String`) - """ - description_expr: String_Expr - """ - ✨ Generated from Field `MovieMetadata`.`rating` of type `Float` - """ - rating: Float - """ - ✨ Generated from Field `MovieMetadata`.`releaseYear` of type `Int` - """ - releaseYear: Int -} -""" -✨ Generated filter input type for table 'MovieMetadata'. This input allows filtering objects using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. -""" -input MovieMetadata_Filter { - """ - Apply multiple filter conditions using `AND` logic. - """ - _and: [MovieMetadata_Filter!] - """ - Negate the result of the provided filter condition. - """ - _not: MovieMetadata_Filter - """ - Apply multiple filter conditions using `OR` logic. - """ - _or: [MovieMetadata_Filter!] - """ - ✨ Generated from Field `MovieMetadata`.`id` of type `UUID!` - """ - id: UUID_Filter - """ - ✨ Generated from Field `MovieMetadata`.`movieId` of type `UUID!` - """ - movieId: UUID_Filter - """ - ✨ Generated from Field `MovieMetadata`.`movie` of type `Movie!` - """ - movie: Movie_Filter - """ - ✨ Generated from Field `MovieMetadata`.`description` of type `String` - """ - description: String_Filter - """ - ✨ Generated from Field `MovieMetadata`.`rating` of type `Float` - """ - rating: Float_Filter - """ - ✨ Generated from Field `MovieMetadata`.`releaseYear` of type `Int` - """ - releaseYear: Int_Filter -} -""" -✨ Generated first-row input type for table 'MovieMetadata'. This input selects the first row matching the filter criteria, ordered according to the specified conditions. -""" -input MovieMetadata_FirstRow { - """ - Order the result by the specified fields. - """ - orderBy: [MovieMetadata_Order!] - """ - Filters rows based on the specified conditions. - """ - where: MovieMetadata_Filter -} -""" -✨ Generated key input type for table 'MovieMetadata'. It represents the primary key fields used to uniquely identify a row in the table. -""" -input MovieMetadata_Key { - """ - ✨ Generated from Field `MovieMetadata`.`id` of type `UUID!` - """ - id: UUID - """ - ✨ `_expr` server value variant of `id` (✨ Generated from Field `MovieMetadata`.`id` of type `UUID!`) - """ - id_expr: UUID_Expr -} -""" -✨ Generated list filter input type for table 'MovieMetadata'. This input applies filtering logic based on the count or existence of related objects that matches certain criteria. -""" -input MovieMetadata_ListFilter { - """ - The desired number of objects that match the condition (defaults to at least one). - """ - count: Int_Filter = {gt:0} - """ - Condition of the related objects to filter for. - """ - exist: MovieMetadata_Filter -} -""" -✨ Generated order input type for table 'MovieMetadata'. This input defines the sorting order of rows in query results based on one or more fields. -""" -input MovieMetadata_Order { - """ - ✨ Generated from Field `MovieMetadata`.`id` of type `UUID!` - """ - id: OrderDirection - """ - ✨ Generated from Field `MovieMetadata`.`movieId` of type `UUID!` - """ - movieId: OrderDirection - """ - ✨ Generated from Field `MovieMetadata`.`movie` of type `Movie!` - """ - movie: Movie_Order - """ - ✨ Generated from Field `MovieMetadata`.`description` of type `String` - """ - description: OrderDirection - """ - ✨ Generated from Field `MovieMetadata`.`rating` of type `Float` - """ - rating: OrderDirection - """ - ✨ Generated from Field `MovieMetadata`.`releaseYear` of type `Int` - """ - releaseYear: OrderDirection -} diff --git a/dataconnect/.dataconnect/schema/main/mutation.gql b/dataconnect/.dataconnect/schema/main/mutation.gql deleted file mode 100644 index 111464cb..00000000 --- a/dataconnect/.dataconnect/schema/main/mutation.gql +++ /dev/null @@ -1,226 +0,0 @@ -extend type Mutation { - """ - ✨ Insert a single `Movie` into the table. Columns not specified in `data` will receive defaults (e.g. `null`). - """ - movie_insert( - """ - Data object to insert into the table. - """ - data: Movie_Data! - ): Movie_KeyOutput! @fdc_generated(from: "Movie", purpose: INSERT_SINGLE) - """ - ✨ Insert a single `MovieMetadata` into the table. Columns not specified in `data` will receive defaults (e.g. `null`). - """ - movieMetadata_insert( - """ - Data object to insert into the table. - """ - data: MovieMetadata_Data! - ): MovieMetadata_KeyOutput! @fdc_generated(from: "MovieMetadata", purpose: INSERT_SINGLE) - """ - ✨ Insert `Movie` objects into the table. Columns not specified in `data` will receive defaults (e.g. `null`). - """ - movie_insertMany( - """ - List of data objects to insert into the table. - """ - data: [Movie_Data!]! - ): [Movie_KeyOutput!]! @fdc_generated(from: "Movie", purpose: INSERT_MULTIPLE) - """ - ✨ Insert `MovieMetadata` objects into the table. Columns not specified in `data` will receive defaults (e.g. `null`). - """ - movieMetadata_insertMany( - """ - List of data objects to insert into the table. - """ - data: [MovieMetadata_Data!]! - ): [MovieMetadata_KeyOutput!]! @fdc_generated(from: "MovieMetadata", purpose: INSERT_MULTIPLE) - """ - ✨ Insert or update a single `Movie` into the table, based on the primary key. Returns the key of the newly inserted `Movie`. - """ - movie_upsert( - """ - Data object to insert or update if it already exists. - """ - data: Movie_Data! - ): Movie_KeyOutput! @fdc_generated(from: "Movie", purpose: UPSERT_SINGLE) - """ - ✨ Insert or update a single `MovieMetadata` into the table, based on the primary key. Returns the key of the newly inserted `MovieMetadata`. - """ - movieMetadata_upsert( - """ - Data object to insert or update if it already exists. - """ - data: MovieMetadata_Data! - ): MovieMetadata_KeyOutput! @fdc_generated(from: "MovieMetadata", purpose: UPSERT_SINGLE) - """ - ✨ Insert or update `Movie` objects into the table, based on the primary key. Returns the key of the newly inserted `Movie`. - """ - movie_upsertMany( - """ - List of data objects to insert or update if it already exists. - """ - data: [Movie_Data!]! - ): [Movie_KeyOutput!]! @fdc_generated(from: "Movie", purpose: UPSERT_MULTIPLE) - """ - ✨ Insert or update `MovieMetadata` objects into the table, based on the primary key. Returns the key of the newly inserted `MovieMetadata`. - """ - movieMetadata_upsertMany( - """ - List of data objects to insert or update if it already exists. - """ - data: [MovieMetadata_Data!]! - ): [MovieMetadata_KeyOutput!]! @fdc_generated(from: "MovieMetadata", purpose: UPSERT_MULTIPLE) - """ - ✨ Update a single `Movie` based on `id`, `key` or `first`, setting columns specified in `data`. Returns `null` if not found. - """ - movie_update( - """ - The unique ID of the object. - """ - id: UUID - - """ - The key used to identify the object. - """ - key: Movie_Key - - """ - Fetch the first row based on the filters and ordering. - """ - first: Movie_FirstRow - - """ - Data object containing fields to be updated. - """ - data: Movie_Data! - ): Movie_KeyOutput @fdc_generated(from: "Movie", purpose: UPDATE_SINGLE) - """ - ✨ Update a single `MovieMetadata` based on `id`, `key` or `first`, setting columns specified in `data`. Returns `null` if not found. - """ - movieMetadata_update( - """ - The unique ID of the object. - """ - id: UUID - - """ - The key used to identify the object. - """ - key: MovieMetadata_Key - - """ - Fetch the first row based on the filters and ordering. - """ - first: MovieMetadata_FirstRow - - """ - Data object containing fields to be updated. - """ - data: MovieMetadata_Data! - ): MovieMetadata_KeyOutput @fdc_generated(from: "MovieMetadata", purpose: UPDATE_SINGLE) - """ - ✨ Update `Movie` objects matching `where` conditions (or `all`, if true) according to `data`. Returns the number of rows updated. - """ - movie_updateMany( - """ - Filter condition to specify which rows to update. - """ - where: Movie_Filter - - """ - Set to true to update all rows. - """ - all: Boolean = false - - """ - Data object containing fields to update. - """ - data: Movie_Data! - ): Int! @fdc_generated(from: "Movie", purpose: UPDATE_MULTIPLE) - """ - ✨ Update `MovieMetadata` objects matching `where` conditions (or `all`, if true) according to `data`. Returns the number of rows updated. - """ - movieMetadata_updateMany( - """ - Filter condition to specify which rows to update. - """ - where: MovieMetadata_Filter - - """ - Set to true to update all rows. - """ - all: Boolean = false - - """ - Data object containing fields to update. - """ - data: MovieMetadata_Data! - ): Int! @fdc_generated(from: "MovieMetadata", purpose: UPDATE_MULTIPLE) - """ - ✨ Delete a single `Movie` based on `id`, `key` or `first` and return its key (or `null` if not found). - """ - movie_delete( - """ - The unique ID of the object. - """ - id: UUID - - """ - The key used to identify the object. - """ - key: Movie_Key - - """ - Fetch the first row based on the filters and ordering. - """ - first: Movie_FirstRow - ): Movie_KeyOutput @fdc_generated(from: "Movie", purpose: DELETE_SINGLE) - """ - ✨ Delete a single `MovieMetadata` based on `id`, `key` or `first` and return its key (or `null` if not found). - """ - movieMetadata_delete( - """ - The unique ID of the object. - """ - id: UUID - - """ - The key used to identify the object. - """ - key: MovieMetadata_Key - - """ - Fetch the first row based on the filters and ordering. - """ - first: MovieMetadata_FirstRow - ): MovieMetadata_KeyOutput @fdc_generated(from: "MovieMetadata", purpose: DELETE_SINGLE) - """ - ✨ Delete `Movie` objects matching `where` conditions (or `all`, if true). Returns the number of rows deleted. - """ - movie_deleteMany( - """ - Filter condition to specify which rows to delete. - """ - where: Movie_Filter - - """ - Set to true to delete all rows. - """ - all: Boolean = false - ): Int! @fdc_generated(from: "Movie", purpose: DELETE_MULTIPLE) - """ - ✨ Delete `MovieMetadata` objects matching `where` conditions (or `all`, if true). Returns the number of rows deleted. - """ - movieMetadata_deleteMany( - """ - Filter condition to specify which rows to delete. - """ - where: MovieMetadata_Filter - - """ - Set to true to delete all rows. - """ - all: Boolean = false - ): Int! @fdc_generated(from: "MovieMetadata", purpose: DELETE_MULTIPLE) -} diff --git a/dataconnect/.dataconnect/schema/main/query.gql b/dataconnect/.dataconnect/schema/main/query.gql deleted file mode 100644 index 899898d1..00000000 --- a/dataconnect/.dataconnect/schema/main/query.gql +++ /dev/null @@ -1,88 +0,0 @@ -extend type Query { - """ - ✨ Look up a single `Movie` based on `id`, `key` or `first` and return selected fields (or `null` if not found). - """ - movie( - """ - The unique ID of the object. - """ - id: UUID - - """ - The key used to identify the object. - """ - key: Movie_Key - - """ - Fetch the first row based on the filters and ordering. - """ - first: Movie_FirstRow - ): Movie @fdc_generated(from: "Movie", purpose: QUERY_SINGLE) - """ - ✨ Look up a single `MovieMetadata` based on `id`, `key` or `first` and return selected fields (or `null` if not found). - """ - movieMetadata( - """ - The unique ID of the object. - """ - id: UUID - - """ - The key used to identify the object. - """ - key: MovieMetadata_Key - - """ - Fetch the first row based on the filters and ordering. - """ - first: MovieMetadata_FirstRow - ): MovieMetadata @fdc_generated(from: "MovieMetadata", purpose: QUERY_SINGLE) - """ - ✨ List `Movie` objects in the table, optionally filtered by `where` conditions. - """ - movies( - """ - Filter condition to narrow down the query results. - """ - where: Movie_Filter - - """ - Order the query results by specific fields. - """ - orderBy: [Movie_Order!] - - """ - Number of rows to skip before starting to return the results. - """ - offset: Int - - """ - Maximum number of rows to return (defaults to 100 rows). - """ - limit: Int = 100 - ): [Movie!]! @fdc_generated(from: "Movie", purpose: QUERY_MULTIPLE) - """ - ✨ List `MovieMetadata` objects in the table, optionally filtered by `where` conditions. - """ - movieMetadatas( - """ - Filter condition to narrow down the query results. - """ - where: MovieMetadata_Filter - - """ - Order the query results by specific fields. - """ - orderBy: [MovieMetadata_Order!] - - """ - Number of rows to skip before starting to return the results. - """ - offset: Int - - """ - Maximum number of rows to return (defaults to 100 rows). - """ - limit: Int = 100 - ): [MovieMetadata!]! @fdc_generated(from: "MovieMetadata", purpose: QUERY_MULTIPLE) -} diff --git a/dataconnect/.dataconnect/schema/main/relation.gql b/dataconnect/.dataconnect/schema/main/relation.gql deleted file mode 100644 index c14ce6cc..00000000 --- a/dataconnect/.dataconnect/schema/main/relation.gql +++ /dev/null @@ -1,6 +0,0 @@ -extend type Movie { - """ - ✨ List `MovieMetadata` objects in a one-to-one relationship (where `MovieMetadata`.`movie` is this object). - """ - movieMetadata_on_movie: MovieMetadata @fdc_generated(from: "MovieMetadata.movie", purpose: QUERY_SINGLE_ONE_TO_ONE) -} diff --git a/dataconnect/.dataconnect/schema/prelude.gql b/dataconnect/.dataconnect/schema/prelude.gql deleted file mode 100644 index b38ec616..00000000 --- a/dataconnect/.dataconnect/schema/prelude.gql +++ /dev/null @@ -1,2009 +0,0 @@ -""" -Redact a part of the response from the client. - -Redacted fields are still evaluated for side effects (including data changes and -`@check`) and the results are still available to later steps in CEL expressions -(via `response.fieldName`). -""" -directive @redact on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT - -""" -Ensure this field is present and is not null or `[]`, or abort the request / transaction. - -A CEL expression, `expr` is used to test the field value. It defaults to -rejecting null and `[]` but a custom expression can be provided instead. - -If the field occurs multiple times (i.e. directly or indirectly nested under a -list), `expr` will be executed once for each occurrence and `@check` succeeds if -all values succeed. `@check` fails when the field is not present at all (i.e. -all ancestor paths contain `null` or `[]`), unless `optional` is true. - -If a `@check` fails in a mutation, the top-level field containing it will be -replaced with a partial error, whose message can be customzied via the `message` -argument. Each subsequent top-level fields will return an aborted error (i.e. -not executed). To rollback previous steps, see `@transaction`. -""" -directive @check( - """ - The CEL expression to test the field value (or values if nested under a list). - - Within the CEL expression, a special value `this` evaluates to the field that - this directive is attached to. If this field occurs multiple times because - any ancestor is a list, each occurrence is tested with `this` bound to each - value. When the field itself is a list or object, `this` follows the same - structure (including all decendants selected in case of objects). - - For any given path, if an ancestor is `null` or `[]`, the field will not be - reached and the CEL evaluation will be skipped for that path. In other words, - evaluation only takes place when `this` is `null` or non-null, but never - undefined. (See also the `optional` argument.) - """ - expr: Boolean_Expr! = "!(this in [null, []])" - """ - The error message to return to the client if the check fails. - - Defaults to "permission denied" if not specified. - """ - message: String! = "permission denied" - """ - Whether the check should pass or fail (default) when the field is not present. - - A field will not be reached at a given path if its parent or any ancestor is - `[]` or `null`. When this happens to all paths, the field will not be present - anywhere in the response tree. In other words, `expr` is evaluated 0 times. - By default, @check will automatically fail in this case. Set this argument to - `true` to make it pass even if no tests are run (a.k.a. "vacuously true"). - """ - optional: Boolean = false -) repeatable on QUERY | MUTATION | FIELD | FRAGMENT_DEFINITION | FRAGMENT_SPREAD | INLINE_FRAGMENT - -"AccessLevel specifies coarse access policies for common situations." -enum AccessLevel { - """ - This operation is accessible to anyone, with or without authentication. - Equivalent to: `@auth(expr: "true")` - """ - PUBLIC - - """ - This operation can be executed only with a valid Firebase Auth ID token. - **Note:** This access level allows anonymous and unverified accounts, - which may present security and abuse risks. - Equivalent to: `@auth(expr: "auth.uid != nil")` - """ - USER_ANON - - """ - This operation is restricted to non-anonymous Firebase Auth accounts. - Equivalent to: `@auth(expr: "auth.uid != nil && auth.token.firebase.sign_in_provider != 'anonymous'")` - """ - USER - - """ - This operation is restricted to Firebase Auth accounts with verified email addresses. - Equivalent to: `@auth(expr: "auth.uid != nil && auth.token.email_verified")` - """ - USER_EMAIL_VERIFIED - - """ - This operation cannot be executed by anyone. The operation can only be performed - by using the Admin SDK from a privileged environment. - Equivalent to: `@auth(expr: "false")` - """ - NO_ACCESS -} - -""" -The `@auth` directive defines the authentication policy for a query or mutation. - -It must be added to any operation that you wish to be accessible from a client -application. If not specified, the operation defaults to `@auth(level: NO_ACCESS)`. - -Refer to [Data Connect Auth Guide](https://firebase.google.com/docs/data-connect/authorization-and-security) for the best practices. -""" -directive @auth( - """ - The minimal level of access required to perform this operation. - Exactly one of `level` and `expr` should be specified. - """ - level: AccessLevel @fdc_oneOf(required: true) - """ - A CEL expression that grants access to this operation if the expression - evaluates to `true`. - Exactly one of `level` and `expr` should be specified. - """ - expr: Boolean_Expr @fdc_oneOf(required: true) -) on QUERY | MUTATION - - -""" -Require that this mutation always run in a DB transaction. - -Mutations with `@transaction` are guaranteed to either fully succeed or fully -fail. If any of the fields within the transaction fails, the entire transaction -is rolled back. From a client standpoint, any failure behaves as if the entire -request had failed with a request error and execution had not begun. - -Mutations without `@transaction` would execute each root field one after -another in sequence. It surfaces any errors as partial [field errors](https://spec.graphql.org/October2021/#sec-Errors.Field-errors), -but not impacts the subsequent executions. - -The `@transaction` directive cannot be added to queries for now. -Currently, queries cannot fail partially, the response data is not guaranteed -to be a consistent snapshot. -""" -directive @transaction on MUTATION - -"Query filter criteria for `String` scalar fields." -input String_Filter { - "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." - isNull: Boolean - "Match if field is exactly equal to provided value." - eq: String @fdc_oneOf(group: "eq") - """ - Match if field is exactly equal to the result of the provided server value - expression. Currently only `auth.uid` is supported as an expression. - """ - eq_expr: String_Expr @fdc_oneOf(group: "eq") - "Match if field is not equal to provided value." - ne: String @fdc_oneOf(group: "ne") - """ - Match if field is not equal to the result of the provided server value - expression. Currently only `auth.uid` is supported as an expression. - """ - ne_expr: String_Expr @fdc_oneOf(group: "ne") - "Match if field value is among the provided list of values." - in: [String!] - "Match if field value is not among the provided list of values." - nin: [String!] - "Match if field value is greater than the provided value." - gt: String - "Match if field value is greater than or equal to the provided value." - ge: String - "Match if field value is less than the provided value." - lt: String - "Match if field value is less than or equal to the provided value." - le: String - """ - Match if field value contains the provided value as a substring. Equivalent - to `LIKE '%value%'` - """ - contains: String - """ - Match if field value starts with the provided value. Equivalent to - `LIKE 'value%'` - """ - startsWith: String - """ - Match if field value ends with the provided value. Equivalent to - `LIKE '%value'` - """ - endsWith: String -} - -"Query filter criteris for `[String!]` scalar fields." -input String_ListFilter { - "Match if list field contains the provided value as a member." - includes: String - "Match if list field does not contain the provided value as a member." - excludes: String - "Match if list field contains all of the provided values as members." - includesAll: [String!] - "Match if list field does not contain any of the provided values as members." - excludesAll: [String!] -} - -"Query filter criteria for `UUID` scalar fields." -input UUID_Filter { - "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." - isNull: Boolean - "Match if field is exactly equal to provided value." - eq: UUID - "Match if field is not equal to provided value." - ne: UUID - "Match if field value is among the provided list of values." - in: [UUID!] - "Match if field value is not among the provided list of values." - nin: [UUID!] -} - -"Query filter criteris for `[UUID!]` scalar fields." -input UUID_ListFilter { - "Match if list field contains the provided value as a member." - includes: UUID - "Match if list field does not contain the provided value as a member." - excludes: UUID - "Match if list field contains all of the provided values as members." - includesAll: [UUID!] - "Match if list field does not contain any of the provided values as members." - excludesAll: [UUID!] -} - -"Query filter criteria for `Int` scalar fields." -input Int_Filter { - "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." - isNull: Boolean - "Match if field is exactly equal to provided value." - eq: Int - "Match if field is not equal to provided value." - ne: Int - "Match if field value is among the provided list of values." - in: [Int!] - "Match if field value is not among the provided list of values." - nin: [Int!] - "Match if field value is greater than the provided value." - gt: Int - "Match if field value is greater than or equal to the provided value." - ge: Int - "Match if field value is less than the provided value." - lt: Int - "Match if field value is less than or equal to the provided value." - le: Int -} - -"Query filter criteris for `[Int!]` scalar fields." -input Int_ListFilter { - "Match if list field contains the provided value as a member." - includes: Int - "Match if list field does not contain the provided value as a member." - excludes: Int - "Match if list field contains all of the provided values as members." - includesAll: [Int!] - "Match if list field does not contain any of the provided values as members." - excludesAll: [Int!] -} - -"Query filter criteria for `Int64` scalar fields." -input Int64_Filter { - "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." - isNull: Boolean - "Match if field is exactly equal to provided value." - eq: Int64 - "Match if field is not equal to provided value." - ne: Int64 - "Match if field value is among the provided list of values." - in: [Int64!] - "Match if field value is not among the provided list of values." - nin: [Int64!] - "Match if field value is greater than the provided value." - gt: Int64 - "Match if field value is greater than or equal to the provided value." - ge: Int64 - "Match if field value is less than the provided value." - lt: Int64 - "Match if field value is less than or equal to the provided value." - le: Int64 -} - -"Query filter criteria for `[Int64!]` scalar fields." -input Int64_ListFilter { - "Match if list field contains the provided value as a member." - includes: Int64 - "Match if list field does not contain the provided value as a member." - excludes: Int64 - "Match if list field contains all of the provided values as members." - includesAll: [Int64!] - "Match if list field does not contain any of the provided values as members." - excludesAll: [Int64!] -} - -"Query filter criteria for `Float` scalar fields." -input Float_Filter { - "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." - isNull: Boolean - "Match if field is exactly equal to provided value." - eq: Float - "Match if field is not equal to provided value." - ne: Float - "Match if field value is among the provided list of values." - in: [Float!] - "Match if field value is not among the provided list of values." - nin: [Float!] - "Match if field value is greater than the provided value." - gt: Float - "Match if field value is greater than or equal to the provided value." - ge: Float - "Match if field value is less than the provided value." - lt: Float - "Match if field value is less than or equal to the provided value." - le: Float -} - -"Query filter criteria for `[Float!]` scalar fields." -input Float_ListFilter { - "Match if list field contains the provided value as a member." - includes: Float - "Match if list field does not contain the provided value as a member." - excludes: Float - "Match if list field contains all of the provided values as members." - includesAll: [Float!] - "Match if list field does not contain any of the provided values as members." - excludesAll: [Float!] -} - -"Query filter criteria for `Boolean` scalar fields." -input Boolean_Filter { - "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." - isNull: Boolean - "Match if field is exactly equal to provided value." - eq: Boolean - "Match if field is not equal to provided value." - ne: Boolean - "Match if field value is among the provided list of values." - in: [Boolean!] - "Match if field value is not among the provided list of values." - nin: [Boolean!] -} - -"Query filter criteria for `[Boolean!]` scalar fields." -input Boolean_ListFilter { - "Match if list field contains the provided value as a member." - includes: Boolean - "Match if list field does not contain the provided value as a member." - excludes: Boolean - "Match if list field contains all of the provided values as members." - includesAll: [Boolean!] - "Match if list field does not contain any of the provided values as members." - excludesAll: [Boolean!] -} - -"Query filter criteria for `Any` scalar fields." -input Any_Filter { - "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." - isNull: Boolean - "Match if field is exactly equal to provided value." - eq: Any - "Match if field is not equal to provided value." - ne: Any - "Match if field value is among the provided list of values." - in: [Any!] - "Match if field value is not among the provided list of values." - nin: [Any!] -} - -"Query filter criteria for `[Any!]` scalar fields." -input Any_ListFilter { - "Match if list field contains the provided value as a member." - includes: Any - "Match if list field does not contain the provided value as a member." - excludes: Any - "Match if list field contains all of the provided values as members." - includesAll: [Any!] - "Match if list field does not contain any of the provided values as members." - excludesAll: [Any!] -} - -""" -(Internal) A string that uniquely identifies a type, field, and so on. - -The most common usage in FDC is `SomeType` or `SomeType.someField`. See the -linked page in the @specifiedBy directive for the GraphQL RFC with more details. -""" -scalar SchemaCoordinate - @specifiedBy(url: "https://github.com/graphql/graphql-wg/blob/6d02705dea034fb65ebc6799632adb7bd550d0aa/rfcs/SchemaCoordinates.md") - @fdc_forbiddenAsFieldType - @fdc_forbiddenAsVariableType - -"(Internal) The purpose of a generated type or field." -enum GeneratedPurpose { - # Implicit fields added to the table types as columns. - IMPLICIT_KEY_FIELD - IMPLICIT_REF_FIELD - - # Generated static fields extended to table types. - METADATA_FIELD - - # Relational non-column fields extended to table types. - QUERY_MULTIPLE_ONE_TO_MANY - QUERY_MULTIPLE_MANY_TO_MANY - - # Top-level Query fields. - QUERY_SINGLE - QUERY_MULTIPLE - QUERY_MULTIPLE_BY_SIMILARITY - - # Top-level Mutation fields. - INSERT_SINGLE - INSERT_MULTIPLE - UPSERT_SINGLE - UPSERT_MULTIPLE - UPDATE_SINGLE - UPDATE_MULTIPLE - DELETE_SINGLE - DELETE_MULTIPLE -} - -"(Internal) Added to definitions generated by FDC." -directive @fdc_generated( - "The source type or field that causes this definition to be generated." - from: SchemaCoordinate! - "The reason why this definition is generated, such as the intended use case." - purpose: GeneratedPurpose! -) on - | SCALAR - | OBJECT - | FIELD_DEFINITION - | ARGUMENT_DEFINITION - | INTERFACE - | UNION - | ENUM - | ENUM_VALUE - | INPUT_OBJECT - | INPUT_FIELD_DEFINITION - -type _Service { - "Full Service Definition Language of the Frebase Data Connect Schema, including normalized schema, predefined and generated types." - sdl( - """ - Whether or not to omit Data Connect builtin GraphQL preludes. - They are static GraphQL publically available in the docsite. - """ - omitBuiltin: Boolean = false - """ - Whether or not to omit GQL description in the SDL. - We generate description to document generated schema. - It may bloat the size of SDL. - """ - omitDescription: Boolean = false - ): String! - "Orignal Schema Sources in the service." - schema: String! - "Generated documentation from the schema of the Firebase Data Connect Service." - docs: [_Doc!]! -} - -type _Doc { - "Name of the Doc Page." - page: String! - "The markdown content of the doc page." - markdown: String! -} - -"(Internal) Added to things that may be removed from FDC and will soon be no longer usable in schema or operations." -directive @fdc_deprecated(reason: String = "No longer supported") on - | SCHEMA - | SCALAR - | OBJECT - | FIELD_DEFINITION - | ARGUMENT_DEFINITION - | INTERFACE - | UNION - | ENUM - | ENUM_VALUE - | INPUT_OBJECT - | INPUT_FIELD_DEFINITION - -"(Internal) Added to scalars representing quoted CEL expressions." -directive @fdc_celExpression( - "The expected CEL type that the expression should evaluate to." - returnType: String -) on SCALAR - -"(Internal) Added to scalars representing quoted SQL expressions." -directive @fdc_sqlExpression( - "The expected SQL type that the expression should evaluate to." - dataType: String -) on SCALAR - -"(Internal) Added to types that may not be used as variables." -directive @fdc_forbiddenAsVariableType on SCALAR | OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT - -"(Internal) Added to types that may not be used as fields in schema." -directive @fdc_forbiddenAsFieldType on SCALAR | OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT - -"Provides a frequently used example for this type / field / argument." -directive @fdc_example( - "A GraphQL literal value (verbatim) whose type matches the target." - value: Any - "A human-readable text description of what `value` means in this context." - description: String -) repeatable on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | INPUT_OBJECT | INPUT_FIELD_DEFINITION - -"(Internal) Marks this field / argument as conflicting with others in the same group." -directive @fdc_oneOf( - "The group name where fields / arguments conflict with each other." - group: String! = "" - "If true, exactly one field / argument in the group must be specified." - required: Boolean! = false -) repeatable on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION - -type Mutation { - """ - Run a query during the mutation and add fields into the response. - - Example: foo: query { users { id } } will add a field foo: {users: [{id: "..."}, …]} into the response JSON. - - Note: Data fetched this way can be handy for permission checks. See @check. - """ - query: Query -} - -""" -`UUID` is a string of hexadecimal digits representing an RFC4122-compliant UUID. - -UUIDs are always output as 32 lowercase hexadecimal digits without delimiters or -curly braces. -Inputs in the following formats are also accepted (case insensitive): - -- `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` -- `urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` -- `{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}` - -In the PostgreSQL table, it's stored as [`uuid`](https://www.postgresql.org/docs/current/datatype-uuid.html). -""" -scalar UUID @specifiedBy(url: "https://tools.ietf.org/html/rfc4122") - -""" -`Int64` is a scalar that represents a 64-bit signed integer. - -In the PostgreSQL table, it's stored as [`bigint`](https://www.postgresql.org/docs/current/datatype-numeric.html). - -On the wire, it's encoded as string because 64-bit integer exceeds the range of JSON number. -""" -scalar Int64 - -""" -The `Any` scalar type accommodates any valid [JSON value](https://www.json.org/json-en.html) -(e.g., numbers, strings, booleans, arrays, objects). PostgreSQL efficiently -stores this data as jsonb, providing flexibility for schemas with evolving structures. - -Caution: JSON doesn't distinguish Int and Float. - -##### Example: - -#### Schema - -```graphql -type Movie @table { - name: String! - metadata: Any! -} -``` - -#### Mutation - -Insert a movie with name and metadata from JSON literal. - -```graphql -mutation InsertMovie { - movie_insert( - data: { - name: "The Dark Knight" - metadata: { - release_year: 2008 - genre: ["Action", "Adventure", "Superhero"] - cast: [ - { name: "Christopher Bale", age: 31 } - { name: "Heath Ledger", age: 28 } - ] - director: "Christopher Nolan" - } - } - ) -} -``` - -Insert a movie with name and metadata that's constructed from a few GQL variables. - -```graphql -mutation InsertMovie($name: String!, $releaseDate: Date!, $genre: [String], $cast: [Any], $director: String!, $boxOfficeInUSD: Int) { - movie_insert(data: { - name: $name, - release_date: $releaseDate, - genre: $genre, - cast: $cast, - director: $director, - box_office: $boxOfficeInUSD - }) -} -``` -**Note**: - - - A mix of non-null and nullable variables can be provided. - - - `Date!` can be passed into scalar `Any` as well! It's stored as string. - - - `$cast` is a nested array. `[Any]` can represent an array of arbitrary types, but it won't enforce the input shape. - -#### Query - -Since `metadata` field has scalar `Any` type, it would return the full JSON in the response. - -**Note**: You can't define selection set to scalar based on [GraphQL spec](https://spec.graphql.org/October2021/#sec-Field-Selections). - -```graphql -query GetAllMovies { - movies { - name - metadata - } -} -``` - -""" -scalar Any @specifiedBy(url: "https://www.json.org/json-en.html") - -""" -The `Void` scalar type represents the absence of any value. It is typically used -in operations where no value is expected in return. -""" -scalar Void - -""" -The `True` scalar type only accepts the boolean value `true`. - -An optional field/argument typed as `True` may either be set -to `true` or omitted (not provided at all). The values `false` or `null` are not -accepted. -""" -scalar True - @fdc_forbiddenAsFieldType - @fdc_forbiddenAsVariableType - @fdc_example(value: true, description: "The only allowed value.") - -""" -A Common Expression Language (CEL) expression that returns a boolean at runtime. - -This expression can reference the `auth` variable, which is null when Firebase -Auth is not used. When Firebase Auth is used, the following fields are available: - - - `auth.uid`: The current user ID. - - `auth.token`: A map containing all token fields (e.g., claims). - -""" -scalar Boolean_Expr - @specifiedBy(url: "https://github.com/google/cel-spec") - @fdc_celExpression(returnType: "bool") - @fdc_forbiddenAsVariableType - @fdc_forbiddenAsFieldType - @fdc_example(value: "auth != null", description: "Allow only if a Firebase Auth user is present.") - -""" -A Common Expression Language (CEL) expression that returns a string at runtime. - -**Limitation**: Currently, only a limited set of expressions are supported. -""" -scalar String_Expr - @specifiedBy(url: "https://github.com/google/cel-spec") - @fdc_celExpression(returnType: "string") - @fdc_forbiddenAsVariableType - @fdc_forbiddenAsFieldType - @fdc_example(value: "auth.uid", description: "The ID of the currently logged in user in Firebase Auth. (Errors if not logged in.)") - @fdc_example(value: "uuidV4()", description: "Generates a new random UUID (version 4) string, formatted as 32 lower-case hex digits without delimiters.") - -""" -A Common Expression Language (CEL) expression that returns a UUID string at runtime. - -**Limitation**: Currently, only a limited set of expressions are supported. -""" -scalar UUID_Expr - @specifiedBy(url: "https://github.com/google/cel-spec") - @fdc_celExpression(returnType: "string") - @fdc_forbiddenAsVariableType - @fdc_forbiddenAsFieldType - @fdc_example(value: "uuidV4()", description: "Generates a new random UUID (version 4) every time.") - -""" -A Common Expression Language (CEL) expression whose return type is unspecified. - -**Limitation**: Only a limited set of expressions are currently supported for each -type. -""" -scalar Any_Expr - @specifiedBy(url: "https://github.com/google/cel-spec") - @fdc_celExpression - @fdc_forbiddenAsVariableType - @fdc_forbiddenAsFieldType - @fdc_example(value: "auth.uid", description: "The ID of the currently logged in user in Firebase Auth. (Errors if not logged in.)") - @fdc_example(value: "uuidV4()", description: "Generates a new random UUID version 4 (formatted as 32 lower-case hex digits without delimiters if result type is String).") - @fdc_example(value: "request.time", description: "The timestamp when the request is received (with microseconds precision).") - -""" -A PostgreSQL value expression whose return type is unspecified. -""" -scalar Any_SQL - @specifiedBy(url: "https://www.postgresql.org/docs/current/sql-expressions.html") - @fdc_sqlExpression - @fdc_forbiddenAsVariableType - @fdc_forbiddenAsFieldType - -""" -Defines a relational database table. - -In this example, we defined one table with a field named `myField`. - -```graphql -type TableName @table { - myField: String -} -``` -Data Connect adds an implicit `id` primary key column. So the above schema is equivalent to: - -```graphql -type TableName @table(key: "id") { - id: String @default(expr: "uuidV4()") - myField: String -} -``` - -Data Connect generates the following SQL table and CRUD operations to use it. - -```sql -CREATE TABLE "public"."table_name" ( - "id" uuid NOT NULL DEFAULT uuid_generate_v4(), - "my_field" text NULL, - PRIMARY KEY ("id") -) -``` - - * You can lookup a row: `query ($id: UUID!) { tableName(id: $id) { myField } } ` - * You can find rows using: `query tableNames(limit: 20) { myField }` - * You can insert a row: `mutation { tableName_insert(data: {myField: "foo"}) }` - * You can update a row: `mutation ($id: UUID!) { tableName_update(id: $id, data: {myField: "bar"}) }` - * You can delete a row: `mutation ($id: UUID!) { tableName_delete(id: $id) }` - -##### Customizations - -- `@table(singular)` and `@table(plural)` can customize the singular and plural name. -- `@table(name)` can customize the Postgres table name. -- `@table(key)` can customize the primary key field name and type. - -For example, the `User` table often has a `uid` as its primary key. - -```graphql -type User @table(key: "uid") { - uid: String! - name: String -} -``` - - * You can securely lookup a row: `query { user(key: {uid_expr: "auth.uid"}) { name } } ` - * You can securely insert a row: `mutation { user_insert(data: {uid_expr: "auth.uid" name: "Fred"}) }` - * You can securely update a row: `mutation { user_update(key: {uid_expr: "auth.uid"}, data: {name: "New Name"}) }` - * You can securely delete a row: `mutation { user_delete(key: {uid_expr: "auth.uid"}) }` - -`@table` type can be configured further with: - - - Custom SQL data types for columns. See `@col`. - - Add SQL indexes. See `@index`. - - Add SQL unique constraints. See `@unique`. - - Add foreign key constraints to define relations. See `@ref`. - -""" -directive @table( - """ - Configures the SQL database table name. Defaults to snake_case like `table_name`. - """ - name: String - """ - Configures the singular name. Defaults to the camelCase like `tableName`. - """ - singular: String - """ - Configures the plural name. Defaults to infer based on English plural pattern like `tableNames`. - """ - plural: String - """ - Defines the primary key of the table. Defaults to a single field named `id`. - If not present already, Data Connect adds an implicit field `id: UUID! @default(expr: "uuidV4()")`. - """ - key: [String!] -) on OBJECT - -""" -Defines a relational database Raw SQLview. - -Data Connect generates GraphQL queries with WHERE and ORDER BY clauses. -However, not all SQL features has native GraphQL equivalent. - -You can write **an arbitrary SQL SELECT statement**. Data Connect -would map Graphql fields on `@view` type to columns in your SELECT statement. - -* Scalar GQL fields (camelCase) should match a SQL column (snake_case) - in the SQL SELECT statement. -* Reference GQL field can point to another `@table` type. Similar to foreign key - defined with `@ref` on a `@table` type, a `@view` type establishes a relation - when `@ref(fields)` match `@ref(references)` on the target table. - -In this example, you can use `@view(sql)` to define an aggregation view on existing -table. - -```graphql -type User @table { - name: String - score: Int -} -type UserAggregation @view(sql: ''' - SELECT - COUNT(*) as count, - SUM(score) as sum, - AVG(score) as average, - PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY score) AS median, - (SELECT id FROM "user" LIMIT 1) as example_id - FROM "user" -''') { - count: Int - sum: Int - average: Float - median: Float - example: User - exampleId: UUID -} -``` - -###### Example: Query Raw SQL View - -```graphql -query { - userAggregations { - count sum average median - exampleId example { id } - } -} -``` - -##### One-to-One View - -An one-to-one companion `@view` can be handy if you want to argument a `@table` -with additional implied content. - -```graphql -type Restaurant @table { - name: String! -} -type Review @table { - restaurant: Restaurant! - rating: Int! -} -type RestaurantStats @view(sql: ''' - SELECT - restaurant_id, - COUNT(*) AS review_count, - AVG(rating) AS average_rating - FROM review - GROUP BY restaurant_id -''') { - restaurant: Restaurant @unique - reviewCount: Int - averageRating: Float -} -``` - -In this example, `@unique` convey the assumption that each `Restaurant` should -have only one `RestaurantStats` object. - -###### Example: Query One-to-One View - -```graphql -query ListRestaurants { - restaurants { - name - stats: restaurantStats_on_restaurant { - reviewCount - averageRating - } - } -} -``` - -###### Example: Filter based on One-to-One View - -```graphql -query BestRestaurants($minAvgRating: Float, $minReviewCount: Int) { - restaurants(where: { - restaurantStats_on_restaurant: { - averageRating: {ge: $minAvgRating} - reviewCount: {ge: $minReviewCount} - } - }) { name } -} -``` - -##### Customizations - -- One of `@view(sql)` or `@view(name)` should be defined. - `@view(name)` can refer to a persisted SQL view in the Postgres schema. -- `@view(singular)` and `@view(plural)` can customize the singular and plural name. - -`@view` type can be configured further: - - - `@unique` lets you define one-to-one relation. - - `@col` lets you customize SQL column mapping. For example, `@col(name: "column_in_select")`. - -##### Limitations - -Raw SQL view doesn't have a primary key, so it doesn't support lookup. Other -`@table` or `@view` cannot have `@ref` to a view either. - -View cannot be mutated. You can perform CRUD operations on the underlying -table to alter its content. - -**Important: Data Connect doesn't parse and validate SQL** - -- If the SQL view is invalid or undefined, related requests may fail. -- If the SQL view return incompatible types. Firebase Data Connect may surface - errors. -- If a field doesn't have a corresponding column in the SQL SELECT statement, - it will always be `null`. -- There is no way to ensure VIEW to TABLE `@ref` constraint. -- All fields must be nullable in case they aren't found in the SELECT statement - or in the referenced table. - -**Important: You should always test `@view`!** - -""" -directive @view( - """ - The SQL view name. If neither `name` nor `sql` are provided, defaults to the - snake_case of the singular type name. - `name` and `sql` cannot be specified at the same time. - """ - name: String @fdc_oneOf - """ - SQL `SELECT` statement used as the basis for this type. - SQL SELECT columns should use snake_case. GraphQL fields should use camelCase. - `name` and `sql` cannot be specified at the same time. - """ - sql: String @fdc_oneOf - """ - Configures the singular name. Defaults to the camelCase like `viewName`. - """ - singular: String - """ - Configures the plural name. Defaults to infer based on English plural pattern like `viewNames`. - """ - plural: String -) on OBJECT - -""" -Customizes a field that represents a SQL database table column. - -Data Connect maps scalar Fields on `@table` type to a SQL column of -corresponding data type. - -- scalar `UUID` maps to [`uuid`](https://www.postgresql.org/docs/current/datatype-uuid.html). -- scalar `String` maps to [`text`](https://www.postgresql.org/docs/current/datatype-character.html). -- scalar `Int` maps to [`int`](https://www.postgresql.org/docs/current/datatype-numeric.html). -- scalar `Int64` maps to [`bigint`](https://www.postgresql.org/docs/current/datatype-numeric.html). -- scalar `Float` maps to [`double precision`](https://www.postgresql.org/docs/current/datatype-numeric.html). -- scalar `Boolean` maps to [`boolean`](https://www.postgresql.org/docs/current/datatype-boolean.html). -- scalar `Date` maps to [`date`](https://www.postgresql.org/docs/current/datatype-datetime.html). -- scalar `Timestamp` maps to [`timestamptz`](https://www.postgresql.org/docs/current/datatype-datetime.html). -- scalar `Any` maps to [`jsonb`](https://www.postgresql.org/docs/current/datatype-json.html). -- scalar `Vector` maps to [`pgvector`](https://github.com/pgvector/pgvector). - -Array scalar fields are mapped to [Postgres arrays](https://www.postgresql.org/docs/current/arrays.html). - -###### Example: Serial Primary Key - -For example, you can define auto-increment primary key. - -```graphql -type Post @table { - id: Int! @col(name: "post_id", dataType: "serial") -} -``` - -Data Connect converts it to the following SQL table schema. - -```sql -CREATE TABLE "public"."post" ( - "post_id" serial NOT NULL, - PRIMARY KEY ("id") -) -``` - -###### Example: Vector - -```graphql -type Post @table { - content: String! @col(name: "post_content") - contentEmbedding: Vector! @col(size:768) -} -``` - -""" -directive @col( - """ - The SQL database column name. Defaults to snake_case of the field name. - """ - name: String - """ - Configures the custom SQL data type. - - Each GraphQL type can map to multiple SQL data types. - Refer to [Postgres supported data types](https://www.postgresql.org/docs/current/datatype.html). - - Incompatible SQL data type will lead to undefined behavior. - """ - dataType: String - """ - Required on `Vector` columns. It specifies the length of the Vector. - `textembedding-gecko@003` model generates `Vector` of `@col(size:768)`. - """ - size: Int -) on FIELD_DEFINITION - - -""" -Defines a foreign key reference to another table. - -For example, we can define a many-to-one relation. - -```graphql -type ManyTable @table { - refField: OneTable! -} -type OneTable @table { - someField: String! -} -``` -Data Connect adds implicit foreign key column and relation query field. So the -above schema is equivalent to the following schema. - -```graphql -type ManyTable @table { - id: UUID! @default(expr: "uuidV4()") - refField: OneTable! @ref(fields: "refFieldId", references: "id") - refFieldId: UUID! -} -type OneTable @table { - id: UUID! @default(expr: "uuidV4()") - someField: UUID! - # Generated Fields: - # manyTables_on_refField: [ManyTable!]! -} -``` -Data Connect generates the necessary foreign key constraint. - -```sql -CREATE TABLE "public"."many_table" ( - "id" uuid NOT NULL DEFAULT uuid_generate_v4(), - "ref_field_id" uuid NOT NULL, - PRIMARY KEY ("id"), - CONSTRAINT "many_table_ref_field_id_fkey" FOREIGN KEY ("ref_field_id") REFERENCES "public"."one_table" ("id") ON DELETE CASCADE -) -``` - -###### Example: Traverse the Reference Field - -```graphql -query ($id: UUID!) { - manyTable(id: $id) { - refField { id } - } -} -``` - -###### Example: Reverse Traverse the Reference field - -```graphql -query ($id: UUID!) { - oneTable(id: $id) { - manyTables_on_refField { id } - } -} -``` - -##### Optional Many-to-One Relation - -An optional foreign key reference will be set to null if the referenced row is deleted. - -In this example, if a `User` is deleted, the `assignee` and `reporter` -references will be set to null. - -```graphql -type Bug @table { - title: String! - assignee: User - reproter: User -} - -type User @table { name: String! } -``` - -##### Required Many-to-One Relation - -A required foreign key reference will cascade delete if the referenced row is -deleted. - -In this example, if a `Post` is deleted, associated comments will also be -deleted. - -```graphql -type Comment @table { - post: Post! - content: String! -} - -type Post @table { title: String! } -``` - -##### Many To Many Relation - -You can define a many-to-many relation with a join table. - -```graphql -type Membership @table(key: ["group", "user"]) { - group: Group! - user: User! - role: String! @default(value: "member") -} - -type Group @table { name: String! } -type User @table { name: String! } -``` - -When Data Connect sees a table with two reference field as its primary key, it -knows this is a join table, so expands the many-to-many query field. - -```graphql -type Group @table { - name: String! - # Generated Fields: - # users_via_Membership: [User!]! - # memberships_on_group: [Membership!]! -} -type User @table { - name: String! - # Generated Fields: - # groups_via_Membership: [Group!]! - # memberships_on_user: [Membership!]! -} -``` - -###### Example: Traverse the Many-To-Many Relation - -```graphql -query ($id: UUID!) { - group(id: $id) { - users: users_via_Membership { - name - } - } -} -``` - -###### Example: Traverse to the Join Table - -```graphql -query ($id: UUID!) { - group(id: $id) { - memberships: memberships_on_group { - user { name } - role - } - } -} -``` - -##### One To One Relation - -You can even define a one-to-one relation with the help of `@unique` or `@table(key)`. - -```graphql -type User @table { - name: String -} -type Account @table { - user: User! @unique -} -# Alternatively, use primary key constraint. -# type Account @table(key: "user") { -# user: User! -# } -``` - -###### Example: Transerse the Reference Field - -```graphql -query ($id: UUID!) { - account(id: $id) { - user { id } - } -} -``` - -###### Example: Reverse Traverse the Reference field - -```graphql -query ($id: UUID!) { - user(id: $id) { - account_on_user { id } - } -} -``` - -##### Customizations - -- `@ref(constraintName)` can customize the SQL foreign key constraint name (`table_name_ref_field_fkey` above). -- `@ref(fields)` can customize the foreign key field names. -- `@ref(references)` can customize the constraint to reference other columns. - By default, `@ref(references)` is the primary key of the `@ref` table. - Other fields with `@unique` may also be referred in the foreign key constraint. - -""" -directive @ref( - "The SQL database foreign key constraint name. Defaults to snake_case `{table_name}_{field_name}_fkey`." - constraintName: String - """ - Foreign key fields. Defaults to `{tableName}{PrimaryIdName}`. - """ - fields: [String!] - "The fields that the foreign key references in the other table. Defaults to its primary key." - references: [String!] -) on FIELD_DEFINITION - -"Defines the orderBy direction in a query." -enum OrderDirection { -"Results are ordered in ascending order." - ASC -"Results are ordered in descending order." - DESC -} - -""" -Specifies the default value for a column field. - -For example: - -```graphql -type User @table(key: "uid") { - uid: String! @default(expr: "auth.uid") - number: Int! @col(dataType: "serial") - createdAt: Date! @default(expr: "request.time") - role: String! @default(value: "Member") - credit: Int! @default(value: 100) -} -``` - -The supported arguments vary based on the field type. -""" -directive @default( - "A constant value validated against the field's GraphQL type during compilation." - value: Any @fdc_oneOf(required: true) - "A CEL expression whose return value must match the field's data type." - expr: Any_Expr @fdc_oneOf(required: true) - """ - A raw SQL expression, whose SQL data type must match the underlying column. - - The value is any variable-free expression (in particular, cross-references to - other columns in the current table are not allowed). Subqueries are not allowed either. - See [PostgreSQL defaults](https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-DEFAULT) - for more details. - """ - sql: Any_SQL @fdc_oneOf(required: true) -) on FIELD_DEFINITION - -""" -Defines a database index to optimize query performance. - -```graphql -type User @table @index(fields: ["name", "phoneNumber"], order: [ASC, DESC]) { - name: String @index - phoneNumber: Int64 @index - tags: [String] @index # GIN Index -} -``` - -##### Single Field Index - -You can put `@index` on a `@col` field to create a SQL index. - -`@index(order)` matters little for single field indexes, as they can be scanned -in both directions. - -##### Composite Index - -You can put `@index(fields: [...])` on `@table` type to define composite indexes. - -`@index(order: [...])` can customize the index order to satisfy particular -filter and order requirement. - -""" -directive @index( - """ - Configure the SQL database index id. - - If not overridden, Data Connect generates the index name: - - `{table_name}_{first_field}_{second_field}_aa_idx` - - `{table_name}_{field_name}_idx` - """ - name: String - """ - Only allowed and required when used on a `@table` type. - Specifies the fields to create the index on. - """ - fields: [String!] - """ - Only allowed for `BTREE` `@index` on `@table` type. - Specifies the order for each indexed column. Defaults to all `ASC`. - """ - order: [IndexFieldOrder!] - """ - Customize the index type. - - For most index, it defaults to `BTREE`. - For array fields, only allowed `IndexType` is `GIN`. - For `Vector` fields, defaults to `HNSW`, may configure to `IVFFLAT`. - """ - type: IndexType - """ - Only allowed when used on vector field. - Defines the vector similarity method. Defaults to `INNER_PRODUCT`. - """ - vector_method: VectorSimilarityMethod -) repeatable on FIELD_DEFINITION | OBJECT - -"Specifies the sorting order for database indexes." -enum IndexFieldOrder { - "Sorts the field in ascending order (from lowest to highest)." - ASC - "Sorts the field in descending order (from highest to lowest)." - DESC -} - -"Defines the type of index to be used in the database." -enum IndexType { - "A general-purpose index type commonly used for sorting and searching." - BTREE - "Generalized Inverted Index, optimized for indexing composite values such as arrays." - GIN - "Hierarchical Navigable Small World graph, used for nearest-neighbor searches on vector fields." - HNSW - "Inverted File Index, optimized for approximate nearest-neighbor searches in vector databases." - IVFFLAT -} - -""" -Defines unique constraints on `@table`. - -For example, - -```graphql -type User @table { - phoneNumber: Int64 @unique -} -type UserProfile @table { - user: User! @unique - address: String @unique -} -``` - -- `@unique` on a `@col` field adds a single-column unique constraint. -- `@unique` on a `@table` type adds a composite unique constraint. -- `@unique` on a `@ref` defines a one-to-one relation. It adds unique constraint - on `@ref(fields)`. - -`@unique` ensures those fields can uniquely identify a row, so other `@table` -type may define `@ref(references)` to refer to fields that has a unique constraint. - -""" -directive @unique( - """ - Configures the SQL database unique constraint name. - - If not overridden, Data Connect generates the unique constraint name: - - `table_name_first_field_second_field_uidx` - - `table_name_only_field_name_uidx` - """ - indexName: String - """ - Only allowed and required when used on OBJECT, - this specifies the fields to create a unique constraint on. - """ - fields: [String!] -) repeatable on FIELD_DEFINITION | OBJECT - -""" -Date is a string in the YYYY-MM-DD format representing a local-only date. - -See the description for Timestamp for range and limitations. - -As a FDC-specific extension, inputs that includes time portions (as specified by -the Timestamp scalar) are accepted but only the date portion is used. In other -words, only the part before "T" is used and the rest discarded. This effectively -truncates it to the local date in the specified time-zone. - -Outputs will always be in the canonical YYYY-MM-DD format. - -In the PostgreSQL table, it's stored as [`date`](https://www.postgresql.org/docs/current/datatype-datetime.html). -""" -scalar Date @specifiedBy(url: "https://scalars.graphql.org/andimarek/local-date.html") - -""" -Timestamp is a RFC 3339 string that represents an exact point in time. - -The serialization format follows https://scalars.graphql.org/andimarek/date-time -except the "Non-optional exact milliseconds" Section. As a FDC-specific -extension, inputs and outputs may contain 0, 3, 6, or 9 fractional digits. - -Specifically, output precision varies by server-side factors such as data source -support and clients must not rely on an exact number of digits. Clients may -truncate extra digits as fit, with the caveat that there may be information loss -if the truncated value is subsequently sent back to the server. - -FDC only supports year 1583 to 9999 (inclusive) and uses the ISO-8601 calendar -system for all date-time calculations. Notably, the expanded year representation -(+/-YYYYY) is rejected and Year 1582 and before may either be rejected or cause -undefined behavior. - -In the PostgreSQL table, it's stored as [`timestamptz`](https://www.postgresql.org/docs/current/datatype-datetime.html). -""" -scalar Timestamp @specifiedBy(url: "https://scalars.graphql.org/andimarek/date-time") - -""" -A Common Expression Language (CEL) expression that returns a Timestamp at runtime. - -Limitation: Right now, only a few expressions are supported. -""" -scalar Timestamp_Expr - @specifiedBy(url: "https://github.com/google/cel-spec") - @fdc_celExpression(returnType: "google.protobuf.Timestamp") - @fdc_forbiddenAsVariableType - @fdc_forbiddenAsFieldType - @fdc_example(value: "request.time", description: "The timestamp when the request is received (with microseconds precision).") - -""" -A Common Expression Language (CEL) expression that returns a Timestamp at runtime, -which is then truncated to UTC date only. The time-of-day parts are discarded. - -Limitation: Right now, only a few expressions are supported. -""" -scalar Date_Expr - @specifiedBy(url: "https://github.com/google/cel-spec") - @fdc_celExpression(returnType: "google.protobuf.Timestamp") - @fdc_forbiddenAsVariableType - @fdc_forbiddenAsFieldType - @fdc_example(value: "request.time", description: "The UTC date on which the request is received.") - -"Conditions on a `Date` value." -input Date_Filter { - "Match if the field `IS NULL`." - isNull: Boolean - "Match if the field is exactly equal to the provided value." - eq: Date @fdc_oneOf(group: "eq") - "Match if the field equals the provided CEL expression." - eq_expr: Date_Expr @fdc_oneOf(group: "eq") - "Match if the field equals the provided relative date." - eq_date: Date_Relative @fdc_oneOf(group: "eq") - "Match if the field is not equal to the provided value." - ne: Date @fdc_oneOf(group: "ne") - "Match if the field is not equal to the provided CEL expression." - ne_expr: Date_Expr @fdc_oneOf(group: "ne") - "Match if the field is not equal to the provided relative date." - ne_date: Date_Relative @fdc_oneOf(group: "ne") - "Match if the field value is among the provided list of values." - in: [Date!] - "Match if the field value is not among the provided list of values." - nin: [Date!] - "Match if the field value is greater than the provided value." - gt: Date @fdc_oneOf(group: "gt") - "Match if the field value is greater than the provided CEL expression." - gt_expr: Date_Expr @fdc_oneOf(group: "gt") - "Match if the field value is greater than the provided relative date." - gt_date: Date_Relative @fdc_oneOf(group: "gt") - "Match if the field value is greater than or equal to the provided value." - ge: Date @fdc_oneOf(group: "ge") - "Match if the field value is greater than or equal to the provided CEL expression." - ge_expr: Date_Expr @fdc_oneOf(group: "ge") - "Match if the field value is greater than or equal to the provided relative date." - ge_date: Date_Relative @fdc_oneOf(group: "ge") - "Match if the field value is less than the provided value." - lt: Date @fdc_oneOf(group: "lt") - "Match if the field value is less than the provided CEL expression." - lt_expr: Date_Expr @fdc_oneOf(group: "lt") - "Match if the field value is less than the provided relative date." - lt_date: Date_Relative @fdc_oneOf(group: "lt") - "Match if the field value is less than or equal to the provided value." - le: Date @fdc_oneOf(group: "le") - "Match if the field value is less than or equal to the provided CEL expression." - le_expr: Date_Expr @fdc_oneOf(group: "le") - "Match if the field value is less than or equal to the provided relative date." - le_date: Date_Relative @fdc_oneOf(group: "le") -} - -"Conditions on a`Date` list." -input Date_ListFilter { - "Match if the list contains the provided date." - includes: Date @fdc_oneOf(group: "includes") - "Match if the list contains the provided date CEL expression." - includes_expr: Date_Expr @fdc_oneOf(group: "includes") - "Match if the list contains the provided relative date." - includes_date: Date_Relative @fdc_oneOf(group: "includes") - "Match if the list does not contain the provided date." - excludes: Date @fdc_oneOf(group: "excludes") - "Match if the list does not contain the provided date CEL expression." - excludes_expr: Date_Expr @fdc_oneOf(group: "excludes") - "Match if the list does not contain the provided relative date." - excludes_date: Date_Relative @fdc_oneOf(group: "excludes") - "Match if the list contains all the provided dates." - includesAll: [Date!] - "Match if the list contains none of the provided dates." - excludesAll: [Date!] -} - -"Conditions on a `Timestamp` value." -input Timestamp_Filter { - "Match if the field `IS NULL`." - isNull: Boolean - "Match if the field is exactly equal to the provided value." - eq: Timestamp @fdc_oneOf(group: "eq") - "Match if the field equals the provided CEL expression." - eq_expr: Timestamp_Expr @fdc_oneOf(group: "eq") - "Match if the field equals the provided relative time." - eq_time: Timestamp_Relative @fdc_oneOf(group: "eq") - "Match if the field is not equal to the provided value." - ne: Timestamp @fdc_oneOf(group: "ne") - "Match if the field is not equal to the provided CEL expression." - ne_expr: Timestamp_Expr @fdc_oneOf(group: "ne") - "Match if the field is not equal to the provided relative time." - ne_time: Timestamp_Relative @fdc_oneOf(group: "ne") - "Match if the field value is among the provided list of values." - in: [Timestamp!] - "Match if the field value is not among the provided list of values." - nin: [Timestamp!] - "Match if the field value is greater than the provided value." - gt: Timestamp @fdc_oneOf(group: "gt") - "Match if the field value is greater than the provided CEL expression." - gt_expr: Timestamp_Expr @fdc_oneOf(group: "gt") - "Match if the field value is greater than the provided relative time." - gt_time: Timestamp_Relative @fdc_oneOf(group: "gt") - "Match if the field value is greater than or equal to the provided value." - ge: Timestamp @fdc_oneOf(group: "ge") - "Match if the field value is greater than or equal to the provided CEL expression." - ge_expr: Timestamp_Expr @fdc_oneOf(group: "ge") - "Match if the field value is greater than or equal to the provided relative time." - ge_time: Timestamp_Relative @fdc_oneOf(group: "ge") - "Match if the field value is less than the provided value." - lt: Timestamp @fdc_oneOf(group: "lt") - "Match if the field value is less than the provided CEL expression." - lt_expr: Timestamp_Expr @fdc_oneOf(group: "lt") - "Match if the field value is less than the provided relative time." - lt_time: Timestamp_Relative @fdc_oneOf(group: "lt") - "Match if the field value is less than or equal to the provided value." - le: Timestamp @fdc_oneOf(group: "le") - "Match if the field value is less than or equal to the provided CEL expression." - le_expr: Timestamp_Expr @fdc_oneOf(group: "le") - "Match if the field value is less than or equal to the provided relative time." - le_time: Timestamp_Relative @fdc_oneOf(group: "le") -} - -"Conditions on a `Timestamp` list." -input Timestamp_ListFilter { - "Match if the list contains the provided timestamp." - includes: Timestamp @fdc_oneOf(group: "includes") - "Match if the list contains the provided timestamp CEL expression." - includes_expr: Timestamp_Expr @fdc_oneOf(group: "includes") - "Match if the list contains the provided relative timestamp." - includes_time: Timestamp_Relative @fdc_oneOf(group: "includes") - "Match if the list does not contain the provided timestamp." - excludes: Timestamp @fdc_oneOf(group: "excludes") - "Match if the list does not contain the provided timestamp CEL expression." - excludes_expr: Timestamp_Expr @fdc_oneOf(group: "excludes") - "Match if the list does not contain the provided relative timestamp." - excludes_time: Timestamp_Relative @fdc_oneOf(group: "excludes") - "Match if the list contains all the provided timestamps." - includesAll: [Timestamp!] - "Match if the list contains none of the provided timestamps." - excludesAll: [Timestamp!] -} - -"Update input of a `Date` value." -input Date_Update { - "Set the field to the provided date." - set: Date @fdc_oneOf(group: "set") - "Set the field to the provided date CEL expression." - set_expr: Date_Expr @fdc_oneOf(group: "set") - "Set the field to the provided relative date." - set_date: Date_Relative @fdc_oneOf(group: "set") -} - -"Update input of a `Date` list value." -input Date_ListUpdate { - "Replace the current list with the provided list of `Date` values." - set: [Date!] - "Append the provided `Date` values to the existing list." - append: [Date!] - "Prepend the provided `Date` values to the existing list." - prepend: [Date!] - "Remove the date value at the specified index." - delete: Int - "The index of the list to perform updates." - i: Int - "Update the date value at the specified index." - update: Date -} - -"Update input of a `Timestamp` value." -input Timestamp_Update { - "Set the field to the provided timestamp." - set: Timestamp @fdc_oneOf(group: "set") - "Set the field to the provided timestamp CEL expression." - set_expr: Timestamp_Expr @fdc_oneOf(group: "set") - "Set the field to the provided relative timestamp." - set_time: Timestamp_Relative @fdc_oneOf(group: "set") -} - -"Update input of an `Timestamp` list value." -input Timestamp_ListUpdate { - "Replace the current list with the provided list of `Timestamp` values." - set: [Timestamp!] - "Append the provided `Timestamp` values to the existing list." - append: [Timestamp!] - "Prepend the provided `Timestamp` values to the existing list." - prepend: [Timestamp!] - "Remove the timestamp value at the specified index." - delete: Int - "The index of the list to perform updates." - i: Int - "Update the timestamp value at the specified index." - update: Timestamp -} - - -"A runtime-calculated `Timestamp` value relative to `now` or `at`." -input Timestamp_Relative @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { - "Match for the current time." - now: True @fdc_oneOf(group: "from", required: true) - "A specific timestamp for matching." - at: Timestamp @fdc_oneOf(group: "from", required: true) - "Add the provided duration to the base timestamp." - add: Timestamp_Duration - "Subtract the provided duration from the base timestamp." - sub: Timestamp_Duration - "Truncate the timestamp to the provided interval." - truncateTo: Timestamp_Interval -} - -input Timestamp_Duration @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { - "The number of milliseconds for the duration." - milliseconds: Int! = 0 - "The number of seconds for the duration." - seconds: Int! = 0 - "The number of minutes for the duration." - minutes: Int! = 0 - "The number of hours for the duration." - hours: Int! = 0 - "The number of days for the duration." - days: Int! = 0 - "The number of weeks for the duration." - weeks: Int! = 0 - "The number of months for the duration." - months: Int! = 0 - "The number of years for the duration." - years: Int! = 0 -} - -enum Timestamp_Interval @fdc_forbiddenAsFieldType { - "Represents a time interval of one second." - SECOND - "Represents a time interval of one minute." - MINUTE - "Represents a time interval of one hour." - HOUR - "Represents a time interval of one day." - DAY - "Represents a time interval of one week." - WEEK - "Represents a time interval of one month." - MONTH - "Represents a time interval of one year." - YEAR -} - -"A runtime-calculated Date value relative to `today` or `on`." -input Date_Relative @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { - "Match for today’s date." - today: True @fdc_oneOf(group: "from", required: true) - "A specific date for matching." - on: Date @fdc_oneOf(group: "from", required: true) - "Add the provided duration to the base date." - add: Date_Duration - "Subtract the provided duration from the base date." - sub: Date_Duration - "Truncate the date to the provided interval." - truncateTo: Date_Interval -} - -input Date_Duration @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { - "The number of days for the duration." - days: Int! = 0 - "The number of weeks for the duration." - weeks: Int! = 0 - "The number of months for the duration." - months: Int! = 0 - "The number of years for the duration." - years: Int! = 0 -} - -enum Date_Interval @fdc_forbiddenAsFieldType { - "Represents a time interval of one week." - WEEK - "Represents a time interval of one month." - MONTH - "Represents a time interval of one year." - YEAR -} - -"Update input of a `String` value." -input String_Update { - "Set the field to a provided value." - set: String @fdc_oneOf(group: "set") - "Set the field to a provided server value expression." - set_expr: String_Expr @fdc_oneOf(group: "set") -} - -"Update input of a `String` list value." -input String_ListUpdate { - "Set the list with the provided values." - set: [String!] - "Append the provided values to the existing list." - append: [String!] - "Prepend the provided values to the existing list." - prepend: [String!] -} - -"Update input of a `UUID` value." -input UUID_Update { - "Set the field to a provided UUID." - set: UUID @fdc_oneOf(group: "set") - "Set the field to a provided UUID expression." - set_expr: UUID_Expr @fdc_oneOf(group: "set") -} - -"Update input of an `ID` list value." -input UUID_ListUpdate { - "Set the list with the provided list of UUIDs." - set: [UUID!] - "Append the provided UUIDs to the existing list." - append: [UUID!] - "Prepend the provided UUIDs to the existing list." - prepend: [UUID!] -} - -"Update input of an `Int` value." -input Int_Update { - "Set the field to a provided value." - set: Int - "Increment the field by a provided value." - inc: Int - "Decrement the field by a provided value." - dec: Int -} - -"Update input of an `Int` list value." -input Int_ListUpdate { - "Set the list with the provided values." - set: [Int!] - "Append the provided list of values to the existing list." - append: [Int!] - "Prepend the provided list of values to the existing list." - prepend: [Int!] -} - -"Update input of an `Int64` value." -input Int64_Update { - "Set the field to a provided value." - set: Int64 - "Increment the field by a provided value." - inc: Int64 - "Decrement the field by a provided value." - dec: Int64 -} - -"Update input of an `Int64` list value." -input Int64_ListUpdate { - "Replace the list with the provided values." - set: [Int64!] - "Append the provided list of values to the existing list." - append: [Int64!] - "Prepend the provided list of values to the existing list." - prepend: [Int64!] -} - -"Update input of a `Float` value." -input Float_Update { - "Set the field to a provided value." - set: Float - "Increment the field by a provided value." - inc: Float - "Decrement the field by a provided value." - dec: Float -} - -"Update input of a `Float` list value." -input Float_ListUpdate { - "Set the list with the provided values." - set: [Float!] - "Append the provided list of values to the existing list." - append: [Float!] - "Prepend the provided list of values to the existing list." - prepend: [Float!] -} - -"Update input of a `Boolean` value." -input Boolean_Update { - "Set the field to a provided value." - set: Boolean -} - -"Update input of a `Boolean` list value." -input Boolean_ListUpdate { - "Set the list with the provided values." - set: [Boolean!] - "Append the provided list of values to the existing list." - append: [Boolean!] - "Prepend the provided list of values to the existing list." - prepend: [Boolean!] -} - -"Update input of an `Any` value." -input Any_Update { - "Set the field to a provided value." - set: Any -} - -"Update input of an `Any` list value." -input Any_ListUpdate { - "Set the list with the provided values." - set: [Any!] - "Append the provided list of values to the existing list." - append: [Any!] - "Prepend the provided list of values to the existing list." - prepend: [Any!] -} - -type Query { - """ - _service provides customized introspection on Firebase Data Connect Sevice. - """ - _service: _Service! -} - -""" -Vector is an array of single-precision floating-point numbers, serialized -as a JSON array. All elements must be finite (no NaN, Infinity or -Infinity). - -Example: [1.1, 2, 3.3] - -In the PostgreSQL table, it's stored as [`pgvector`](https://github.com/pgvector/pgvector). - -See `Vector_Embed` for how to generate text embeddings in query and mutations. -""" -scalar Vector - -""" -Defines the similarity function to use when comparing vectors in queries. - -Defaults to `INNER_PRODUCT`. - -View [all vector functions](https://github.com/pgvector/pgvector?tab=readme-ov-file#vector-functions). -""" -enum VectorSimilarityMethod { - "Measures the Euclidean (L2) distance between two vectors." - L2 - "Measures the cosine similarity between two vectors." - COSINE - "Measures the inner product(dot product) between two vectors." - INNER_PRODUCT -} - -"Conditions on a Vector value." -input Vector_Filter { - "Match if the field is exactly equal to the provided vector." - eq: Vector - "Match if the field is not equal to the provided vector." - ne: Vector - "Match if the field value is among the provided list of vectors." - in: [Vector!] - "Match if the field value is not among the provided list of vectors." - nin: [Vector!] - "Match if the field is `NULL`." - isNull: Boolean -} - -input Vector_ListFilter { - "Match if the list includes the supplied vector." - includes: Vector - "Match if the list does not include the supplied vector." - excludes: Vector - "Match if the list contains all the provided vectors." - includesAll: [Vector!] - "Match if the list contains none of the provided vectors." - excludesAll: [Vector!] -} - -"Update input of a Vector value." -input Vector_Update { - "Set the field to the provided vector value." - set: Vector @fdc_oneOf(group: "set") - "Set the field to the vector embedding result from a text input." - set_embed: Vector_Embed @fdc_oneOf(group: "set") -} - - -"Update input of a Vector list value." -input Vector_ListUpdate { - "Replace the current list with the provided list of Vector values." - set: [Vector] - "Append the provided Vector values to the existing list." - append: [Vector] - "Prepend the provided Vector values to the existing list." - prepend: [Vector] - "Delete the vector at the specified index." - delete: Int - "The index of the vector to be updated." - i: Int - "Update the vector at the specified index." - update: Vector -} - -""" -Create a vector embedding of text using the given model on Vertex AI. - -Cloud SQL for Postgresql natively integrates with [Vertex AI Text embeddings API](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/text-embeddings-api) -to effectively generate text embeddings. - -If you uses [`Vector`](scalar.md#Vector) in your schema, Firebase Data Connect automatically installs -[`pgvector`](https://github.com/pgvector/pgvector) and [`google_ml_integration`](https://cloud.google.com/sql/docs/postgres/integrate-cloud-sql-with-vertex-ai) -Postgres extensions in your Cloud SQL database. - -Given a Post table with a `Vector` embedding field. - -```graphql -type Post @table { - content: String! - contentEmbedding: Vector @col(size:768) -} -``` - -NOTE: All natively supported `Vector_Embed_Model` generates vector of length `768`. - -###### Example: Insert embedding - -```graphql -mutation CreatePost($content: String!) { - post_insert(data: { - content: $content, - contentEmbedding_embed: {model: "textembedding-gecko@003", text: $content}, - }) -} -``` - -###### Example: Vector similarity Search - -```graphql -query SearchPost($query: String!) { - posts_contentEmbedding_similarity(compare_embed: {model: "textembedding-gecko@003", text: $query}) { - id - content - } -} -``` -""" -input Vector_Embed @fdc_forbiddenAsVariableType { - """ - The model to use for vector embedding. - Recommend the latest stable model: `textembedding-gecko@003`. - """ - model: Vector_Embed_Model! - "The text to generate the vector embedding from." - text: String! -} - -""" -The Vertex AI model version that is required in input `Vector_Embed`. - -It is recommended to use the latest stable model version: `textembedding-gecko@003`. - -View all supported [Vertex AI Text embeddings APIs](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/text-embeddings-api). -""" -scalar Vector_Embed_Model - @specifiedBy(url: "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versioning") - @fdc_forbiddenAsVariableType - @fdc_forbiddenAsFieldType - @fdc_example(value: "textembedding-gecko@003", description: "A stable version of the textembedding-gecko model") - @fdc_example(value: "textembedding-gecko@001", description: "An older version of the textembedding-gecko model") - @fdc_example(value: "text-embedding-004", description: "Another text embedding model") - diff --git a/dataconnect/connector/connector.yaml b/dataconnect/connector/connector.yaml deleted file mode 100644 index 933ef4c6..00000000 --- a/dataconnect/connector/connector.yaml +++ /dev/null @@ -1,8 +0,0 @@ -connectorId: default -generate: - javascriptSdk: - outputDir: ../../dataconnect-sdk/js/default-connector - package: "@dataconnect/default-connector" - packageJsonDir: ../.. - react: true - angular: true diff --git a/dataconnect/connector/mutations.gql b/dataconnect/connector/mutations.gql deleted file mode 100644 index 6ccbe32d..00000000 --- a/dataconnect/connector/mutations.gql +++ /dev/null @@ -1,52 +0,0 @@ -# # Example mutations for a simple movie app - -# Create a movie based on user input -mutation CreateMovie($title: String!, $genre: String!, $imageUrl: String!) -@auth(level: PUBLIC) { - movie_insert(data: { title: $title, genre: $genre, imageUrl: $imageUrl }) -} - -# Upsert a movie -mutation UpsertMovie($id: UUID!, $title: String!, $imageUrl: String!) -@auth(level: PUBLIC) { - movie_upsert(data: { id: $id, title: $title, imageUrl: $imageUrl }) -} - -# Delete a movie -mutation DeleteMovie($id: UUID!) @auth(level: PUBLIC) { - movie_delete(id: $id) -} - -# # Upsert (update or insert) a user's username based on their auth.uid -# mutation UpsertUser($username: String!) @auth(level: USER) { -# user_upsert( -# data: { -# id_expr: "auth.uid" -# username: $username -# } -# ) -# } - -# # Add a review for a movie -# mutation AddReview( -# $movieId: UUID! -# $rating: Int! -# $reviewText: String! -# ) @auth(level: USER) { -# review_upsert( -# data: { -# userId_expr: "auth.uid" -# movieId: $movieId -# rating: $rating -# reviewText: $reviewText -# # reviewDate defaults to today in the schema. No need to set it manually. -# } -# ) -# } - -# # Logged in user can delete their review for a movie -# mutation DeleteReview( -# $movieId: UUID! -# ) @auth(level: USER) { -# review_delete(key: { userId_expr: "auth.uid", movieId: $movieId }) -# } diff --git a/dataconnect/connector/queries.gql b/dataconnect/connector/queries.gql deleted file mode 100644 index 24e8c94c..00000000 --- a/dataconnect/connector/queries.gql +++ /dev/null @@ -1,68 +0,0 @@ -# # Example queries for a simple movie app. - -# @auth() directives control who can call each operation. -# Anyone should be able to list all movies, so the auth level is set to PUBLIC -query ListMovies @auth(level: PUBLIC) { - movies { - id - title - imageUrl - genre - } -} - -# Get movie by id -query GetMovieById($id: UUID!) @auth(level: PUBLIC) { - movie(id: $id) { - id - title - imageUrl - genre - } -} - -# # List all users, only admins should be able to list all users, so we use NO_ACCESS -# query ListUsers @auth(level: NO_ACCESS) { -# users { id, username } -# } - -# # Logged in user can list all their reviews and movie titles associated with the review -# # Since the query requires the uid of the current authenticated user, the auth level is set to USER -# query ListUserReviews @auth(level: USER) { -# user(key: {id_expr: "auth.uid"}) { -# id -# username -# # _on_ makes it easy to grab info from another table -# # Here, we use it to grab all the reviews written by the user. -# reviews: reviews_on_user { -# id -# rating -# reviewDate -# reviewText -# movie { -# id -# title -# } -# } -# } -# } - -# # Search for movies, actors, and reviews -# query SearchMovie( -# $titleInput: String -# $genre: String -# ) @auth(level: PUBLIC) { -# movies( -# where: { -# _and: [ -# { genre: { eq: $genre } } -# { title: { contains: $titleInput } } -# ] -# } -# ) { -# id -# title -# genre -# imageUrl -# } -# } diff --git a/dataconnect/dataconnect.yaml b/dataconnect/dataconnect.yaml deleted file mode 100644 index 074f3f5d..00000000 --- a/dataconnect/dataconnect.yaml +++ /dev/null @@ -1,12 +0,0 @@ -specVersion: "v1beta" -serviceId: "tanstack-query-firebase" -location: "us-central1" -schema: - source: "./schema" - datasource: - postgresql: - database: "fdcdb" - cloudSql: - instanceId: "tanstack-query-firebase-fdc" - # schemaValidation: "COMPATIBLE" -connectorDirs: ["./connector"] diff --git a/dataconnect/schema/schema.gql b/dataconnect/schema/schema.gql deleted file mode 100644 index 3a7b73ce..00000000 --- a/dataconnect/schema/schema.gql +++ /dev/null @@ -1,45 +0,0 @@ -# # Example schema for simple movie review app - -# # Users -# # Suppose a user can leave reviews for movies -# # user -> reviews is a one to many relationship, -# # movie -> reviews is a one to many relationship -# # movie <-> user is a many to many relationship -# type User @table { -# id: String! @col(name: "user_auth") -# username: String! @col(name: "username", dataType: "varchar(50)") -# # The following are generated by the user: User! field in the Review table -# # reviews_on_user -# # movies_via_Review -# } - -# Movies -type Movie @table { - # The below parameter values are generated by default with @table, and can be edited manually. - # implies directive `@col(name: "movie_id")`, generating a column name - id: UUID! @default(expr: "uuidV4()") - title: String! - imageUrl: String! - genre: String -} - -# Movie Metadata -# Movie - MovieMetadata is a one-to-one relationship -type MovieMetadata @table { - # @unique indicates a 1-1 relationship - movie: Movie! @unique - # movieId: UUID <- this is created by the above reference - rating: Float - releaseYear: Int - description: String -} - -# # Reviews -# type Review @table(name: "Reviews", key: ["movie", "user"]) { -# id: UUID! @default(expr: "uuidV4()") -# user: User! -# movie: Movie! -# rating: Int -# reviewText: String -# reviewDate: Date! @default(expr: "request.time") -# } diff --git a/firebase.json b/firebase.json deleted file mode 100644 index 93a77ec3..00000000 --- a/firebase.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "emulators": { - "firestore": { - "port": 8080 - }, - "auth": { - "port": 9099 - }, - "functions": { - "port": 5001 - }, - "database": { - "port": 9000 - }, - "ui": { - "enabled": true - } - }, - "functions": { - "predeploy": "npm --prefix \"$RESOURCE_DIR\" run build", - "source": "functions" - }, - "firestore": { - "rules": "./firestore.rules" - }, - "dataconnect": { - "source": "dataconnect" - } -} diff --git a/packages/angular/package.json b/packages/angular/package.json index 26bdee24..49bfc62c 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -31,7 +31,7 @@ "license": "ISC", "dependencies": { "@angular/fire": "^19.0.0-rc.5", - "@tanstack/angular-query-experimental": "^5.66.4", + "@tanstack/angular-query-experimental": "5.66.4", "firebase": "^11.1.0" }, "devDependencies": { diff --git a/packages/angular/src/data-connect/index.ts b/packages/angular/src/data-connect/index.ts index d5646a4e..c7ca91cd 100644 --- a/packages/angular/src/data-connect/index.ts +++ b/packages/angular/src/data-connect/index.ts @@ -12,13 +12,7 @@ import { import { FirebaseError } from "firebase/app"; import { - assertInInjectionContext, - computed, inject, - InjectionToken, - Injector, - isSignal, - runInInjectionContext, signal, } from "@angular/core"; import { @@ -30,9 +24,6 @@ import { QueryRef, QueryResult, } from "@angular/fire/data-connect"; -import { createMovieRef } from "../../dataconnect-sdk/js/default-connector/angular"; -import { mutationRef } from "firebase/data-connect"; -import { SIGNAL } from "@angular/core/primitives/signals"; function getQueryKey(queryRef: QueryRef) { const key: (string | Record)[] = [queryRef.name]; if ("variables" in queryRef && queryRef.variables !== undefined) { @@ -66,7 +57,7 @@ interface CreateDataConnectQueryOptions export function injectDataConnectQuery( queryRefOrOptionsFn: | QueryRef - | (QueryRef ) + | QueryRef | (() => CreateDataConnectQueryOptions) ): CreateQueryResult, FirebaseError> { const queryKey = signal([]); @@ -98,10 +89,10 @@ export function injectDataConnectQuery( return injectQuery(fdcOptionsFn); } -export type GeneratedSignature = (( +export type GeneratedSignature = ( dc: DataConnect, vars: Variables -) => MutationRef); // TODO(mtewani): Add __angular: true +) => MutationRef; // TODO(mtewani): Add __angular: true export type DataConnectMutationOptionsFn = () => Omit, "mutationFn"> & { invalidate?: QueryKey | QueryRef[]; @@ -142,7 +133,11 @@ export function injectDataConnectMutation< Arguments = void | undefined >( factoryFn: EmptyFactoryFn, - options?: DataConnectMutationOptionsUndefinedMutationFn + options?: DataConnectMutationOptionsUndefinedMutationFn< + Data, + FirebaseError, + Variables + > ): CreateMutationResult< FlattenedMutationResult, FirebaseError, @@ -155,7 +150,11 @@ export function injectDataConnectMutation< Arguments = void | undefined >( factoryFn: EmptyFactoryFn, - options?: DataConnectMutationOptionsUndefinedMutationFn + options?: DataConnectMutationOptionsUndefinedMutationFn< + Data, + FirebaseError, + Variables + > ): CreateMutationResult< FlattenedMutationResult, FirebaseError, @@ -206,7 +205,11 @@ export function injectDataConnectMutation< Variables, Arguments extends Variables >( - factoryFn: GeneratedSignature | EmptyFactoryFn | undefined | null, + factoryFn: + | GeneratedSignature + | EmptyFactoryFn + | undefined + | null, optionsFn?: | DataConnectMutationOptionsFn | DataConnectMutationOptionsUndefinedMutationFn< @@ -219,17 +222,10 @@ export function injectDataConnectMutation< FirebaseError, Arguments > { - /** - * Hypothesis: - * It seems like optionsSignal is causing observerSignal to get called again - * - */ const dataConnect = inject(DataConnect); const queryClient = inject(QueryClient); - - const injectCb = () => { - + const injectCb = () => { const providedOptions = optionsFn && optionsFn(); const modifiedFn = (args: Arguments) => { const ref = @@ -249,10 +245,8 @@ export function injectDataConnectMutation< .then((ret) => { if (providedOptions?.invalidate) { for (const qk of providedOptions.invalidate) { - // @ts-ignore let key = qk; if ("name" in (key as Object)) { - // @ts-ignore const queryKey = getQueryKey(key as QueryRef); key = queryKey; if ( @@ -281,6 +275,6 @@ export function injectDataConnectMutation< mutationFn: modifiedFn, }; }; - + return injectMutation(injectCb); } diff --git a/packages/angular/src/data-connect/injectDataConnectMutation.test.ts b/packages/angular/src/data-connect/injectDataConnectMutation.test.ts index 8b8cedfa..37c27c22 100644 --- a/packages/angular/src/data-connect/injectDataConnectMutation.test.ts +++ b/packages/angular/src/data-connect/injectDataConnectMutation.test.ts @@ -1,10 +1,6 @@ import { TestBed } from "@angular/core/testing"; import { provideHttpClient } from '@angular/common/http'; -import { - connectorConfig, - createMovie, - -} from "../../dataconnect-sdk/js/default-connector"; + import { createMovieRef, upsertMovieRef, @@ -12,7 +8,9 @@ import { getMovieByIdRef, UpsertMovieVariables, listMoviesRef, -} from "../../dataconnect-sdk/js/default-connector/angular"; + connectorConfig, + createMovie, +} from "@/dataconnect/default-connector/angular"; import { waitFor } from '@testing-library/angular'; import { beforeEach, afterEach, describe, expect, test, vi } from "vitest"; import { injectDataConnectMutation } from "./index"; diff --git a/packages/angular/src/data-connect/injectDataConnectQuery.test.ts b/packages/angular/src/data-connect/injectDataConnectQuery.test.ts index 0663117c..890c0487 100644 --- a/packages/angular/src/data-connect/injectDataConnectQuery.test.ts +++ b/packages/angular/src/data-connect/injectDataConnectQuery.test.ts @@ -3,7 +3,7 @@ import { createMovie, getMovieByIdRef, listMoviesRef, -} from "../../dataconnect-sdk/js/default-connector/angular"; +} from "@/dataconnect/default-connector/angular"; import { provideHttpClient } from '@angular/common/http'; import { waitFor } from "@testing-library/angular"; import { connectDataConnectEmulator, DataConnect, getDataConnect, provideDataConnect } from "@angular/fire/data-connect"; diff --git a/packages/angular/tsconfig.json b/packages/angular/tsconfig.json index c17ccc04..ce32cdaa 100644 --- a/packages/angular/tsconfig.json +++ b/packages/angular/tsconfig.json @@ -12,8 +12,8 @@ "forceConsistentCasingInFileNames": true, "types": ["vitest/globals"], "paths": { - "~/testing-utils": ["../../vitest/utils.ts"], - "@/dataconnect/*": ["../../dataconnect-sdk/js/*"] + "~/testing-utils": ["../react/vitest/utils.ts"], + "@/dataconnect/*": ["./dataconnect-sdk/js/*"] } }, "include": ["src", "utils.tsx", "./package.json"] diff --git a/packages/react/package.json b/packages/react/package.json index 7123ce02..9c1877d4 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -36,7 +36,7 @@ ], "license": "Apache-2.0", "devDependencies": { - "@dataconnect/default-connector": "file:../../dataconnect-sdk/js/default-connector", + "@dataconnect/default-connector": "file:dataconnect-sdk/js/default-connector", "@testing-library/react": "^16.0.1", "@types/react": "^19.0.1", "react": "^19.0.0" diff --git a/packages/react/src/data-connect/useDataConnectMutation.ts b/packages/react/src/data-connect/useDataConnectMutation.ts index c32fa335..864f545b 100644 --- a/packages/react/src/data-connect/useDataConnectMutation.ts +++ b/packages/react/src/data-connect/useDataConnectMutation.ts @@ -92,4 +92,3 @@ export function useDataConnectMutation< }, }); } -const res = useDataConnectMutation((abc: string) => abc === 'a' ? mutationRef(getDataConnect({} as ConnectorConfig), '', { abc: 1 }) : mutationRef(getDataConnect({} as ConnectorConfig), '', { abc: 2})) diff --git a/packages/react/src/data-connect/useDataConnectQuery.test.tsx b/packages/react/src/data-connect/useDataConnectQuery.test.tsx index dcb37ac0..71e9f3a6 100644 --- a/packages/react/src/data-connect/useDataConnectQuery.test.tsx +++ b/packages/react/src/data-connect/useDataConnectQuery.test.tsx @@ -1,16 +1,12 @@ -import { - createMovie, - getMovieByIdRef, - listMoviesRef, -} from "@/dataconnect/default-connector"; import { dehydrate } from "@tanstack/react-query"; import { act, renderHook, waitFor } from "@testing-library/react"; -import { executeQuery } from "firebase/data-connect"; +import { DataConnect, executeQuery, queryRef, QueryRef } from "firebase/data-connect"; import { beforeEach, describe, expect, test } from "vitest"; import { firebaseApp } from "~/testing-utils"; import { queryClient, wrapper } from "../../utils"; import { DataConnectQueryClient } from "./query-client"; import { useDataConnectQuery } from "./useDataConnectQuery"; +import { createMovie, createMovieRef, getMovieByIdRef, ListMoviesData, listMoviesRef } from "@/dataconnect/default-connector"; // initialize firebase app firebaseApp; @@ -34,7 +30,7 @@ describe("useDataConnectQuery", () => { }); test("fetches data successfully", async () => { - const { result } = renderHook(() => useDataConnectQuery(listMoviesRef()), { + const { result } = renderHook(() => useListMoviesRef(), { wrapper, }); @@ -84,7 +80,9 @@ describe("useDataConnectQuery", () => { }); test("returns correct data", async () => { - const { result } = renderHook(() => useDataConnectQuery(listMoviesRef()), { + const abc = listMoviesRef(); + useDataConnectQuery(getMovieByIdRef({ id: 'a'})) + const { result } = renderHook(() => useDataConnectQuery(abc), { wrapper, }); @@ -111,6 +109,9 @@ describe("useDataConnectQuery", () => { }); test("returns the correct data properties", async () => { + const qc = queryRef({} as DataConnect, ''); + const newQc = Object.assign(qc, {__angular: false}) + const { result } = renderHook(() => useDataConnectQuery(listMoviesRef()), { wrapper, }); @@ -251,3 +252,7 @@ describe("useDataConnectQuery", () => { ]); }); }); +function useListMoviesRef(): any { + throw new Error("Function not implemented."); +} + diff --git a/packages/react/src/data-connect/useDataConnectQuery.ts b/packages/react/src/data-connect/useDataConnectQuery.ts index 31ca7bb1..99c2f7db 100644 --- a/packages/react/src/data-connect/useDataConnectQuery.ts +++ b/packages/react/src/data-connect/useDataConnectQuery.ts @@ -7,18 +7,29 @@ import { } from "firebase/data-connect"; import type { PartialBy } from "../../utils"; import type { FlattenedQueryResult } from "./types"; +import { listMoviesRef } from "@/dataconnect/default-connector"; export type useDataConnectQueryOptions< TData = unknown, TError = FirebaseError, > = PartialBy, "queryFn">, "queryKey">; - +useDataConnectQuery(listMoviesRef()).data!.movies +export function useDataConnectQuery2 = QueryRef>( + refOrResult: Ref + | QueryResult, + options?: useDataConnectQueryOptions< + FlattenedQueryResult, + FirebaseError + > +) { +} export function useDataConnectQuery( - refOrResult: QueryRef | QueryResult, + refOrResult: QueryRef + | QueryResult, options?: useDataConnectQueryOptions< FlattenedQueryResult, FirebaseError - >, + > ) { let queryRef: QueryRef; let initialData: FlattenedQueryResult | undefined; diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json index cb0abdf9..883a7ff4 100644 --- a/packages/react/tsconfig.json +++ b/packages/react/tsconfig.json @@ -11,8 +11,8 @@ "forceConsistentCasingInFileNames": true, "types": ["vitest/globals"], "paths": { - "~/testing-utils": ["../../vitest/utils.ts"], - "@/dataconnect/*": ["../../dataconnect-sdk/js/*"] + "~/testing-utils": ["./vitest/utils.ts"], + "@/dataconnect/*": ["./dataconnect-sdk/js/*"] } }, "include": ["src", "utils.tsx"] diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a8ee674a..10516737 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,3 @@ packages: - 'examples/*' - - 'packages/*' - - 'dataconnect-sdk/js/*' \ No newline at end of file + - 'packages/*' \ No newline at end of file diff --git a/vitest.config.ts b/vitest.config.ts deleted file mode 100644 index af98851c..00000000 --- a/vitest.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { defineConfig } from "vitest/config"; -import path from "path"; - -export default defineConfig({ - test: { - fileParallelism: false, - coverage: { - provider: "istanbul", - }, - alias: { - "~/testing-utils": path.resolve(__dirname, "./vitest/utils"), - "@/dataconnect/default-connector": path.resolve( - __dirname, - "./dataconnect-sdk/js/default-connector" - ), - }, - }, -}); diff --git a/vitest/utils.ts b/vitest/utils.ts deleted file mode 100644 index 30c4c58f..00000000 --- a/vitest/utils.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { type FirebaseApp, FirebaseError, initializeApp } from "firebase/app"; -import { getAuth, connectAuthEmulator, type Auth } from "firebase/auth"; -import { - getFirestore, - connectFirestoreEmulator, - type Firestore, -} from "firebase/firestore"; -import { expect } from "vitest"; -import { - connectDataConnectEmulator, - getDataConnect, -} from "firebase/data-connect"; -import { connectorConfig } from "@/dataconnect/default-connector"; - -const firebaseTestingOptions = { - projectId: "test-project", - apiKey: "test-api-key", - authDomain: "test-auth-domain", -}; - -let firebaseApp: FirebaseApp | undefined; -let firestore: Firestore; -let auth: Auth; - -if (!firebaseApp) { - firebaseApp = initializeApp(firebaseTestingOptions); - firestore = getFirestore(firebaseApp); - auth = getAuth(firebaseApp); - - connectFirestoreEmulator(firestore, "localhost", 8080); - connectAuthEmulator(auth, "http://localhost:9099"); - connectDataConnectEmulator( - getDataConnect(connectorConfig), - "localhost", - 9399 - ); -} - -async function wipeFirestore() { - const response = await fetch( - "http://localhost:8080/emulator/v1/projects/test-project/databases/(default)/documents", - { - method: "DELETE", - } - ); - - if (!response.ok) { - throw new Error("Failed to wipe firestore"); - } -} - -async function wipeAuth() { - const response = await fetch( - "http://localhost:9099/emulator/v1/projects/test-project/accounts", - { - method: "DELETE", - } - ); - - if (!response.ok) { - throw new Error("Failed to wipe auth"); - } -} - -function expectFirestoreError(error: unknown, expectedCode: string) { - if (error instanceof FirebaseError) { - expect(error).toBeDefined(); - expect(error.code).toBeDefined(); - expect(error.code).toBe(expectedCode); - } else { - throw new Error( - "Expected a Firestore error, but received a different type." - ); - } -} - -function expectFirebaseError(error: unknown, expectedCode: string) { - if (error instanceof FirebaseError) { - expect(error).toBeDefined(); - expect(error.code).toBeDefined(); - expect(error.code).toBe(expectedCode); - } else { - console.error("Expected a Firebase error, but received a different type.", { - receivedType: typeof error, - errorDetails: - error instanceof Error - ? { message: error.message, stack: error.stack } - : error, - }); - throw new Error( - "Expected a Firebase error, but received a different type." - ); - } -} - -export { - firestore, - wipeFirestore, - expectFirestoreError, - firebaseTestingOptions, - auth, - wipeAuth, - firebaseApp, - expectFirebaseError, -};