diff --git a/.gitignore b/.gitignore index 032d69a..7b51885 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ app/node_modules .log app/dist/ dataconnect/.dataconnect +.firebaserc diff --git a/app/package-lock.json b/app/package-lock.json index 6c8cae7..16e382e 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -9,8 +9,10 @@ "version": "0.0.0", "dependencies": { "@movie/dataconnect": "file:src/lib/dataconnect-sdk", + "@tanstack-query-firebase/react": "^1.0.6", + "@tanstack/react-query": "^5.67.1", "dotenv": "^16.4.5", - "firebase": "^10.12.4-dataconnect-preview.d986d4bf2", + "firebase": "^11.4.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-icons": "^5.2.1", @@ -939,14 +941,14 @@ } }, "node_modules/@firebase/analytics": { - "version": "0.10.8", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.8.tgz", - "integrity": "sha512-CVnHcS4iRJPqtIDc411+UmFldk0ShSK3OB+D0bKD8Ck5Vro6dbK5+APZpkuWpbfdL359DIQUnAaMLE+zs/PVyA==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "version": "0.10.12", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.12.tgz", + "integrity": "sha512-iDCGnw6qdFqwI5ywkgece99WADJNoymu+nLIQI4fZM/vCZ3bEo4wlpEetW71s1HqGpI0hQStiPhqVjFxDb2yyw==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/installations": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -954,14 +956,14 @@ } }, "node_modules/@firebase/analytics-compat": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.14.tgz", - "integrity": "sha512-unRVY6SvRqfNFIAA/kwl4vK+lvQAL2HVcgu9zTrUtTyYDmtIt/lOuHJynBMYEgLnKm39YKBDhtqdapP2e++ASw==", - "dependencies": { - "@firebase/analytics": "0.10.8", - "@firebase/analytics-types": "0.8.2", - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", + "version": "0.2.18", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.18.tgz", + "integrity": "sha512-Hw9mzsSMZaQu6wrTbi3kYYwGw9nBqOHr47pVLxfr5v8CalsdrG5gfs9XUlPOZjHRVISp3oQrh1j7d3E+ulHPjQ==", + "dependencies": { + "@firebase/analytics": "0.10.12", + "@firebase/analytics-types": "0.8.3", + "@firebase/component": "0.6.13", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -969,89 +971,121 @@ } }, "node_modules/@firebase/analytics-types": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.2.tgz", - "integrity": "sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==" + "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.12", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.12.tgz", - "integrity": "sha512-fgBqe5j7GKv7/eMfyU4N1FdiW6O1EyrrVbMa8rJOT5MYNpCXqdL/5NNcLDStS1l6CN7h65a7jUNXmMnMSWo0sw==", + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.11.2.tgz", + "integrity": "sha512-bFee0hPJZBzNtiizRxdgsu8C9DW3mn1y0OJJ4zHQsccjDYzGOfvN0G3CMGyBIiwNctsFpQa8orbp2IKywoUeqA==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", "idb": "7.1.1", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@firebase/app-check": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.8.tgz", - "integrity": "sha512-O49RGF1xj7k6BuhxGpHmqOW5hqBIAEbt2q6POW0lIywx7emYtzPDeQI+ryQpC4zbKX646SoVZ711TN1DBLNSOQ==", + "version": "0.8.12", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.12.tgz", + "integrity": "sha512-LxjcoIFOU4sgK07ZWb8XDHxuVB+UKs41vPK+Sg9PeZMvEoz84fndFAx8Nz2nipiya2EmyxBgVhff8Hi6GBt+XA==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, + "engines": { + "node": ">=18.0.0" + }, "peerDependencies": { "@firebase/app": "0.x" } }, "node_modules/@firebase/app-check-compat": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.15.tgz", - "integrity": "sha512-zFIvIFFNqDXpOT2huorz9cwf56VT3oJYRFjSFYdSbGYEJYEaXjLJbfC79lx/zjx4Fh+yuN8pry3TtvwaevrGbg==", - "dependencies": { - "@firebase/app-check": "0.8.8", - "@firebase/app-check-types": "0.5.2", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.19.tgz", + "integrity": "sha512-G8FMiqhrKc4gEEujrBDBBrbRav8MGqoLObWj1hy/riCSg4XlRYhpnq3ev8E9HTirqU1tAGH6oJl7vr+jfM7YNA==", + "dependencies": { + "@firebase/app-check": "0.8.12", + "@firebase/app-check-types": "0.5.3", + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", "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.2", - "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz", - "integrity": "sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==" + "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.2", - "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.2.tgz", - "integrity": "sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==" + "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.42", - "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.42.tgz", - "integrity": "sha512-vPI0Aksk8ZuHywigyTxrx/oWbuD41kHxajfxRly7urHOFRiXKxf/q2ftgmcMVPfIeg0K02LzYNBmoh2PWzERpg==", - "dependencies": { - "@firebase/app": "0.10.12", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "version": "0.2.51", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.51.tgz", + "integrity": "sha512-pxF1+coABt+ugqNI0YXDlmkKv4kh3pjI5BqIJJ1VXBo42OZbKMsQbFeos14YBrWwiqqSjUvQ70FBNsv5E2wuxg==", + "dependencies": { + "@firebase/app": "0.11.2", + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@firebase/app-types": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz", - "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==" - }, - "node_modules/@firebase/auth": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.7.9.tgz", - "integrity": "sha512-yLD5095kVgDw965jepMyUrIgDklD6qH/BZNHeKOgvu7pchOKNjVM+zQoOVYJIKWMWOWBq8IRNVU6NXzBbozaJg==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" + "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-compat": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.19.tgz", + "integrity": "sha512-v898POphOIBJliKF76SiGOXh4EdhO5fM6S9a2ZKf/8wHdBea/qwxwZoVVya4DW6Mi7vWyp1lIzHbFgwRz8G9TA==", + "dependencies": { + "@firebase/auth": "1.9.1", + "@firebase/auth-types": "0.13.0", + "@firebase/component": "0.6.13", + "@firebase/util": "1.11.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/auth-compat/node_modules/@firebase/auth": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.9.1.tgz", + "integrity": "sha512-9KKo5SNVkyJzftsW+daS+PGDbeJ+MFJWXQFHDqqPPH3acWHtiNnGHH5HGpIJErEELrsm9xMPie5zfZ0XpGU8+w==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" }, "peerDependencies": { "@firebase/app": "0.x", @@ -1063,54 +1097,41 @@ } } }, - "node_modules/@firebase/auth-compat": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.14.tgz", - "integrity": "sha512-2eczCSqBl1KUPJacZlFpQayvpilg3dxXLy9cSMTKtQMTQSmondUtPI47P3ikH3bQAXhzKLOE+qVxJ3/IRtu9pw==", - "dependencies": { - "@firebase/auth": "1.7.9", - "@firebase/auth-types": "0.12.2", - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, "node_modules/@firebase/auth-interop-types": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz", - "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==" + "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.2", - "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.2.tgz", - "integrity": "sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w==", + "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.9", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.9.tgz", - "integrity": "sha512-gm8EUEJE/fEac86AvHn8Z/QW8BvR56TBw3hMW0O838J/1mThYQXAIQBgUv75EqlCZfdawpWLrKt1uXvp9ciK3Q==", + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.13.tgz", + "integrity": "sha512-I/Eg1NpAtZ8AAfq8mpdfXnuUpcLxIDdCDtTzWSh+FXnp/9eCKJ3SNbOCKrUCyhLzNa2SiPJYruei0sxVjaOTeg==", "dependencies": { - "@firebase/util": "1.10.0", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@firebase/data-connect": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.0.tgz", - "integrity": "sha512-vSe5s8dY13ilhLnfY0eYRmQsdTbH7PUFZtBbqU6JVX/j8Qp9A6G5gG6//ulbX9/1JFOF1IWNOne9c8S/DOCJaQ==", - "dependencies": { - "@firebase/auth-interop-types": "0.2.3", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.3.1.tgz", + "integrity": "sha512-PNlfAJ2mcbyRlWfm41nfk8EksTuvMFTFIX+puNzeUa6OTIDtyp1IX1NJVc7n6WpfbErN7tNqcOEMe6BMtpcjVA==", + "dependencies": { + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1118,130 +1139,143 @@ } }, "node_modules/@firebase/database": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.8.tgz", - "integrity": "sha512-dzXALZeBI1U5TXt6619cv0+tgEhJiwlUtQ55WNZY7vGAjv7Q1QioV969iYwt1AQQ0ovHnEW0YW9TiBfefLvErg==", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.2", - "@firebase/auth-interop-types": "0.2.3", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.13.tgz", + "integrity": "sha512-cdc+LuseKdJXzlrCx8ePMXyctSWtYS9SsP3y7EeA85GzNh/IL0b7HOq0eShridL935iQ0KScZCj5qJtKkGE53g==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", "faye-websocket": "0.11.4", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@firebase/database-compat": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.8.tgz", - "integrity": "sha512-OpeWZoPE3sGIRPBKYnW9wLad25RaWbGyk7fFQe4xnJQKRzlynWeFBSRRAoLE2Old01WXwskUiucNqUUVlFsceg==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/database": "1.0.8", - "@firebase/database-types": "1.0.5", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.4.tgz", + "integrity": "sha512-4qsptwZ3DTGNBje56ETItZQyA/HMalOelnLmkC3eR0M6+zkzOHjNHyWUWodW2mqxRKAM0sGkn+aIwYHKZFJXug==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/database": "1.0.13", + "@firebase/database-types": "1.0.9", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@firebase/database-types": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.5.tgz", - "integrity": "sha512-fTlqCNwFYyq/C6W7AJ5OCuq5CeZuBEsEwptnVxlNPkWCo5cTTyukzAHRSO/jaQcItz33FfYrrFk1SJofcu2AaQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.9.tgz", + "integrity": "sha512-uCntrxPbJHhZsNRpMhxNCm7GzhYWX+7J2e57wq1ZZ4NJrQw5DORgkAzJMByYZcVAjgADnCxxhK/GkoypH+XpvQ==", "dependencies": { - "@firebase/app-types": "0.9.2", - "@firebase/util": "1.10.0" + "@firebase/app-types": "0.9.3", + "@firebase/util": "1.11.0" } }, "node_modules/@firebase/firestore": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.3.tgz", - "integrity": "sha512-NwVU+JPZ/3bhvNSJMCSzfcBZZg8SUGyzZ2T0EW3/bkUeefCyzMISSt/TTIfEHc8cdyXGlMqfGe3/62u9s74UEg==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", - "@firebase/webchannel-wrapper": "1.0.1", + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.9.tgz", + "integrity": "sha512-uq/bUtHDqJ5ZqPHAJIlNzHpXUtcVYcASz2V6y7UmP1WLlRKEt1yf1OcQW5u8pY2yq7162OnCl5J5mkOdMTMLZw==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", + "@firebase/webchannel-wrapper": "1.0.3", "@grpc/grpc-js": "~1.9.0", "@grpc/proto-loader": "^0.7.8", - "tslib": "^2.1.0", - "undici": "6.19.7" + "tslib": "^2.1.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.0.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "node_modules/@firebase/firestore-compat": { - "version": "0.3.38", - "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.38.tgz", - "integrity": "sha512-GoS0bIMMkjpLni6StSwRJarpu2+S5m346Na7gr9YZ/BZ/W3/8iHGNr9PxC+f0rNZXqS4fGRn88pICjrZEgbkqQ==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/firestore": "4.7.3", - "@firebase/firestore-types": "3.0.2", - "@firebase/util": "1.10.0", + "version": "0.3.44", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.44.tgz", + "integrity": "sha512-4Lv2TyHEW+FugXPgmQ0ZylSbh9uFuKDP0lCL1hX9cbxXaafhC/Nww+DWokUQ2zZcynjc8fxFunw6Xbd3QHAlgA==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/firestore": "4.7.9", + "@firebase/firestore-types": "3.0.3", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, + "engines": { + "node": ">=18.0.0" + }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "node_modules/@firebase/firestore-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.2.tgz", - "integrity": "sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg==", + "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.11.8", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.8.tgz", - "integrity": "sha512-Lo2rTPDn96naFIlSZKVd1yvRRqqqwiJk7cf9TZhUerwnPKgBzXy+aHE22ry+6EjCaQusUoNai6mU6p+G8QZT1g==", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.2", - "@firebase/auth-interop-types": "0.2.3", - "@firebase/component": "0.6.9", - "@firebase/messaging-interop-types": "0.2.2", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.12.3.tgz", + "integrity": "sha512-Wv7JZMUkKLb1goOWRtsu3t7m97uK6XQvjQLPvn8rncY91+VgdU72crqnaYCDI/ophNuBEmuK8mn0/pAnjUeA6A==", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.6.13", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.11.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "node_modules/@firebase/functions-compat": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.14.tgz", - "integrity": "sha512-dZ0PKOKQFnOlMfcim39XzaXonSuPPAVuzpqA4ONTIdyaJK/OnBaIEVs/+BH4faa1a2tLeR+Jy15PKqDRQoNIJw==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/functions": "0.11.8", - "@firebase/functions-types": "0.6.2", - "@firebase/util": "1.10.0", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.20.tgz", + "integrity": "sha512-iIudmYDAML6n3c7uXO2YTlzra2/J6lnMzmJTXNthvrKVMgNMaseNoQP1wKfchK84hMuSF8EkM4AvufwbJ+Juew==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/functions": "0.12.3", + "@firebase/functions-types": "0.6.3", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, + "engines": { + "node": ">=18.0.0" + }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "node_modules/@firebase/functions-types": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.2.tgz", - "integrity": "sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w==" + "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.9", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.9.tgz", - "integrity": "sha512-hlT7AwCiKghOX3XizLxXOsTFiFCQnp/oj86zp1UxwDGmyzsyoxtX+UIZyVyH/oBF5+XtblFG9KZzZQ/h+dpy+Q==", + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.13.tgz", + "integrity": "sha512-6ZpkUiaygPFwgVneYxuuOuHnSPnTA4KefLEaw/sKk/rNYgC7X6twaGfYb0sYLpbi9xV4i5jXsqZ3WO+yaguNgg==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", + "@firebase/component": "0.6.13", + "@firebase/util": "1.11.0", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -1250,14 +1284,14 @@ } }, "node_modules/@firebase/installations-compat": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.9.tgz", - "integrity": "sha512-2lfdc6kPXR7WaL4FCQSQUhXcPbI7ol3wF+vkgtU25r77OxPf8F/VmswQ7sgIkBBWtymn5ZF20TIKtnOj9rjb6w==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/installations-types": "0.5.2", - "@firebase/util": "1.10.0", + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.13.tgz", + "integrity": "sha512-f/o6MqCI7LD/ulY9gvgkv6w5k6diaReD8BFHd/y/fEdpsXmFWYS/g28GXCB72bRVBOgPpkOUNl+VsMvDwlRKmw==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/installations": "0.6.13", + "@firebase/installations-types": "0.5.3", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1265,30 +1299,33 @@ } }, "node_modules/@firebase/installations-types": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.2.tgz", - "integrity": "sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA==", + "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.2", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz", - "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==", + "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.11", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.11.tgz", - "integrity": "sha512-zn5zGhF46BmiZ7W9yAUoHlqzJGakmWn1FNp//roXHN62dgdEFIKfXY7IODA2iQiXpmUO3sBdI/Tf+Hsft1mVkw==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/messaging-interop-types": "0.2.2", - "@firebase/util": "1.10.0", + "version": "0.12.17", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.17.tgz", + "integrity": "sha512-W3CnGhTm6Nx8XGb6E5/+jZTuxX/EK8Vur4QXvO1DwZta/t0xqWMRgO9vNsZFMYBqFV4o3j4F9qK/iddGYwWS6g==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/installations": "0.6.13", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.11.0", "idb": "7.1.1", "tslib": "^2.1.0" }, @@ -1297,13 +1334,13 @@ } }, "node_modules/@firebase/messaging-compat": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.11.tgz", - "integrity": "sha512-2NCkfE1L9jSn5OC+2n5rGAz5BEAQreK2lQGdPYQEJlAbKB2efoF+2FdiQ+LD8SlioSXz66REfeaEdesoLPFQcw==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.17.tgz", + "integrity": "sha512-5Q+9IG7FuedusdWHVQRjpA3OVD9KUWp/IPegcv0s5qSqRLBjib7FlAeWxN+VL0Ew43tuPJBY2HKhEecuizmO1Q==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/messaging": "0.12.11", - "@firebase/util": "1.10.0", + "@firebase/component": "0.6.13", + "@firebase/messaging": "0.12.17", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1311,35 +1348,36 @@ } }, "node_modules/@firebase/messaging-interop-types": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz", - "integrity": "sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA==" + "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.9", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.9.tgz", - "integrity": "sha512-PnVaak5sqfz5ivhua+HserxTJHtCar/7zM0flCX6NkzBNzJzyzlH4Hs94h2Il0LQB99roBqoE5QT1JqWqcLJHQ==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0" + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.1.tgz", + "integrity": "sha512-SkEUurawojCjav2V2AXo6BQLDtv02NxgXPLCiAvrkn95IAKI4W/UbLKYQvMbEez/nqvmnucLyklcMlB0Q5a1iw==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/installations": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", + "tslib": "^2.1.0", + "web-vitals": "^4.2.4" }, "peerDependencies": { "@firebase/app": "0.x" } }, "node_modules/@firebase/performance-compat": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.9.tgz", - "integrity": "sha512-dNl95IUnpsu3fAfYBZDCVhXNkASE0uo4HYaEPd2/PKscfTvsgqFAOxfAXzBEDOnynDWiaGUnb5M1O00JQ+3FXA==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/performance": "0.6.9", - "@firebase/performance-types": "0.2.2", - "@firebase/util": "1.10.0", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.14.tgz", + "integrity": "sha512-/crPg0fDqHIx+FjFoEqWxNp+lJSF40ZG7x43AAJGRaUaWLJDncQm3UJB5/mABaRZb7obs1CQAcRtd4phZFkmZg==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/performance": "0.7.1", + "@firebase/performance-types": "0.2.3", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1347,19 +1385,19 @@ } }, "node_modules/@firebase/performance-types": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.2.tgz", - "integrity": "sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA==" + "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.9", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.9.tgz", - "integrity": "sha512-EO1NLCWSPMHdDSRGwZ73kxEEcTopAxX1naqLJFNApp4hO8WfKfmEpmjxmP5TrrnypjIf2tUkYaKsfbEA7+AMmA==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/installations": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.6.0.tgz", + "integrity": "sha512-Yrk4l5+6FJLPHC6irNHMzgTtJ3NfHXlAXVChCBdNFtgmzyGmufNs/sr8oA0auEfIJ5VpXCaThRh3P4OdQxiAlQ==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/installations": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1367,15 +1405,15 @@ } }, "node_modules/@firebase/remote-config-compat": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.9.tgz", - "integrity": "sha512-AxzGpWfWFYejH2twxfdOJt5Cfh/ATHONegTd/a0p5flEzsD5JsxXgfkFToop+mypEL3gNwawxrxlZddmDoNxyA==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/remote-config": "0.4.9", - "@firebase/remote-config-types": "0.3.2", - "@firebase/util": "1.10.0", + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.13.tgz", + "integrity": "sha512-UmHoO7TxAEJPIZf8e1Hy6CeFGMeyjqSCpgoBkQZYXFI2JHhzxIyDpr8jVKJJN1dmAePKZ5EX7dC13CmcdTOl7Q==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/remote-config": "0.6.0", + "@firebase/remote-config-types": "0.4.0", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -1383,65 +1421,74 @@ } }, "node_modules/@firebase/remote-config-types": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz", - "integrity": "sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==" + "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.2", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.2.tgz", - "integrity": "sha512-fxuJnHshbhVwuJ4FuISLu+/76Aby2sh+44ztjF2ppoe0TELIDxPW6/r1KGlWYt//AD0IodDYYA8ZTN89q8YqUw==", + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.7.tgz", + "integrity": "sha512-FkRyc24rK+Y6EaQ1tYFm3TevBnnfSNA0VyTfew2hrYyL/aYfatBg7HOgktUdB4kWMHNA9VoTotzZTGoLuK92wg==", "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/util": "1.10.0", - "tslib": "^2.1.0", - "undici": "6.19.7" + "@firebase/component": "0.6.13", + "@firebase/util": "1.11.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" }, "peerDependencies": { "@firebase/app": "0.x" } }, "node_modules/@firebase/storage-compat": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.12.tgz", - "integrity": "sha512-hA4VWKyGU5bWOll+uwzzhEMMYGu9PlKQc1w4DWxB3aIErWYzonrZjF0icqNQZbwKNIdh8SHjZlFeB2w6OSsjfg==", - "dependencies": { - "@firebase/component": "0.6.9", - "@firebase/storage": "0.13.2", - "@firebase/storage-types": "0.8.2", - "@firebase/util": "1.10.0", + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.17.tgz", + "integrity": "sha512-CBlODWEZ5b6MJWVh21VZioxwxNwVfPA9CAdsk+ZgVocJQQbE2oDW1XJoRcgthRY1HOitgbn4cVrM+NlQtuUYhw==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/storage": "0.13.7", + "@firebase/storage-types": "0.8.3", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, + "engines": { + "node": ">=18.0.0" + }, "peerDependencies": { "@firebase/app-compat": "0.x" } }, "node_modules/@firebase/storage-types": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.2.tgz", - "integrity": "sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g==", + "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.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.0.tgz", - "integrity": "sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.11.0.tgz", + "integrity": "sha512-PzSrhIr++KI6y4P6C/IdgBNMkEx0Ex6554/cYd0Hm+ovyFSJtJXqb/3OSIdnBoa2cpwZT1/GW56EmRc5qEc5fQ==", + "hasInstallScript": true, "dependencies": { "tslib": "^2.1.0" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@firebase/vertexai-preview": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@firebase/vertexai-preview/-/vertexai-preview-0.0.4.tgz", - "integrity": "sha512-EBSqyu9eg8frQlVU9/HjKtHN7odqbh9MtAcVz3WwHj4gLCLOoN9F/o+oxlq3CxvFrd3CNTZwu6d2mZtVlEInng==", + "node_modules/@firebase/vertexai": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.1.0.tgz", + "integrity": "sha512-K8CgIFKJrfrf5lYhKnDXOu08FEmIzVExK+ApUZx4Bw2GAmLEA3wDVrsjuupuvpXZSp8QlzvEiXwqshqqc4v0pA==", "dependencies": { - "@firebase/app-check-interop-types": "0.3.2", - "@firebase/component": "0.6.9", - "@firebase/logger": "0.4.2", - "@firebase/util": "1.10.0", + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", "tslib": "^2.1.0" }, "engines": { @@ -1453,9 +1500,9 @@ } }, "node_modules/@firebase/webchannel-wrapper": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.1.tgz", - "integrity": "sha512-jmEnr/pk0yVkA7mIlHNnxCi+wWzOFUg0WyIotgkKAb2u1J7fAeDBcVNSTjTihbAYNusCLQdW5s9IJ5qwnEufcQ==" + "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", @@ -1972,6 +2019,39 @@ "win32" ] }, + "node_modules/@tanstack-query-firebase/react": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@tanstack-query-firebase/react/-/react-1.0.6.tgz", + "integrity": "sha512-/bj9QSnmu02XF2Cvy+OoClh2PWiETGeGk69BbXDO1bNdIHeW3dyc0Y/owSLBG/EAIZxDAKR6IZu0eYkBr3J4ug==", + "peerDependencies": { + "@tanstack/react-query": "^5", + "firebase": "^11.3.0" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.67.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.67.1.tgz", + "integrity": "sha512-AkFmuukVejyqVIjEQoFhLb3q+xHl7JG8G9cANWTMe3s8iKzD9j1VBSYXgCjy6vm6xM8cUCR9zP2yqWxY9pTWOA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.67.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.67.1.tgz", + "integrity": "sha512-fH5u4JLwB6A+wLFdi8wWBWAYoJV5deYif2OveJ26ktAWjU499uvVFS1wPWnyEyq5LvZX1MZInvv9QRaIZANRaQ==", + "dependencies": { + "@tanstack/query-core": "5.67.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -3322,38 +3402,61 @@ } }, "node_modules/firebase": { - "version": "10.14.0", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.14.0.tgz", - "integrity": "sha512-/yB/OE4bfBbmtfku0DCdW6nWMHYVayN6xWKw68ztedxqGevfYDoPoygBXiLmvBHdWdBa+IlhJDkdUUiEEpcAUw==", - "dependencies": { - "@firebase/analytics": "0.10.8", - "@firebase/analytics-compat": "0.2.14", - "@firebase/app": "0.10.12", - "@firebase/app-check": "0.8.8", - "@firebase/app-check-compat": "0.3.15", - "@firebase/app-compat": "0.2.42", - "@firebase/app-types": "0.9.2", - "@firebase/auth": "1.7.9", - "@firebase/auth-compat": "0.5.14", - "@firebase/data-connect": "0.1.0", - "@firebase/database": "1.0.8", - "@firebase/database-compat": "1.0.8", - "@firebase/firestore": "4.7.3", - "@firebase/firestore-compat": "0.3.38", - "@firebase/functions": "0.11.8", - "@firebase/functions-compat": "0.3.14", - "@firebase/installations": "0.6.9", - "@firebase/installations-compat": "0.2.9", - "@firebase/messaging": "0.12.11", - "@firebase/messaging-compat": "0.2.11", - "@firebase/performance": "0.6.9", - "@firebase/performance-compat": "0.2.9", - "@firebase/remote-config": "0.4.9", - "@firebase/remote-config-compat": "0.2.9", - "@firebase/storage": "0.13.2", - "@firebase/storage-compat": "0.3.12", - "@firebase/util": "1.10.0", - "@firebase/vertexai-preview": "0.0.4" + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-11.4.0.tgz", + "integrity": "sha512-Z6kwhWIPDgIm0+NUEQxwjH14hMP7t42WSFnf/78R0Vh59VovLYTOCTM3MIdY3jlSZ9uKz56FhXrvsNXNhAn/Xg==", + "dependencies": { + "@firebase/analytics": "0.10.12", + "@firebase/analytics-compat": "0.2.18", + "@firebase/app": "0.11.2", + "@firebase/app-check": "0.8.12", + "@firebase/app-check-compat": "0.3.19", + "@firebase/app-compat": "0.2.51", + "@firebase/app-types": "0.9.3", + "@firebase/auth": "1.9.1", + "@firebase/auth-compat": "0.5.19", + "@firebase/data-connect": "0.3.1", + "@firebase/database": "1.0.13", + "@firebase/database-compat": "2.0.4", + "@firebase/firestore": "4.7.9", + "@firebase/firestore-compat": "0.3.44", + "@firebase/functions": "0.12.3", + "@firebase/functions-compat": "0.3.20", + "@firebase/installations": "0.6.13", + "@firebase/installations-compat": "0.2.13", + "@firebase/messaging": "0.12.17", + "@firebase/messaging-compat": "0.2.17", + "@firebase/performance": "0.7.1", + "@firebase/performance-compat": "0.2.14", + "@firebase/remote-config": "0.6.0", + "@firebase/remote-config-compat": "0.2.13", + "@firebase/storage": "0.13.7", + "@firebase/storage-compat": "0.3.17", + "@firebase/util": "1.11.0", + "@firebase/vertexai": "1.1.0" + } + }, + "node_modules/firebase/node_modules/@firebase/auth": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.9.1.tgz", + "integrity": "sha512-9KKo5SNVkyJzftsW+daS+PGDbeJ+MFJWXQFHDqqPPH3acWHtiNnGHH5HGpIJErEELrsm9xMPie5zfZ0XpGU8+w==", + "dependencies": { + "@firebase/component": "0.6.13", + "@firebase/logger": "0.4.4", + "@firebase/util": "1.11.0", + "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/flat-cache": { @@ -3580,9 +3683,9 @@ } }, "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + "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", @@ -3895,9 +3998,9 @@ "license": "MIT" }, "node_modules/long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", + "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==" }, "node_modules/loose-envify": { "version": "1.4.0", @@ -5090,9 +5193,9 @@ "license": "Apache-2.0" }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/type-check": { "version": "0.4.0", @@ -5134,14 +5237,6 @@ "node": ">=14.17" } }, - "node_modules/undici": { - "version": "6.19.7", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.7.tgz", - "integrity": "sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A==", - "engines": { - "node": ">=18.17" - } - }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -5252,6 +5347,11 @@ } } }, + "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", @@ -5535,7 +5635,9 @@ "node": " >=18.0" }, "peerDependencies": { - "firebase": "^10.14.0 || ^11.0.0" + "@tanstack-query-firebase/react": "^1.0.5", + "@tanstack/react-query": "^5", + "firebase": "^11.3.0" } } } diff --git a/app/package.json b/app/package.json index 00e022c..6e2bd72 100644 --- a/app/package.json +++ b/app/package.json @@ -11,8 +11,10 @@ }, "dependencies": { "@movie/dataconnect": "file:src/lib/dataconnect-sdk", + "@tanstack-query-firebase/react": "^1.0.6", + "@tanstack/react-query": "^5.67.1", "dotenv": "^16.4.5", - "firebase": "^10.12.4-dataconnect-preview.d986d4bf2", + "firebase": "^11.4.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-icons": "^5.2.1", diff --git a/app/src/App.tsx b/app/src/App.tsx index e31f29c..1d932c7 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -24,21 +24,24 @@ import VectorSearchPage from "./pages/VectorSearch"; import AdvancedSearchPage from "./pages/AdvancedSearch"; import NotFound from "./pages/NotFound"; import RootLayout from "./layout/RootLayout"; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; export default function App() { return ( - - - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - + + + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + + ); } diff --git a/app/src/components/moviecard.tsx b/app/src/components/moviecard.tsx index 8d99312..73c28e8 100644 --- a/app/src/components/moviecard.tsx +++ b/app/src/components/moviecard.tsx @@ -19,11 +19,8 @@ import { Link, useNavigate } from "react-router-dom"; import { MdFavorite, MdFavoriteBorder, MdStar } from "react-icons/md"; import { onAuthStateChanged, User } from "firebase/auth"; import { AuthContext } from "@/lib/firebase"; -import { - handleAddFavoritedMovie, - handleDeleteFavoritedMovie, - handleGetIfFavoritedMovie, -} from "@/lib/MovieService"; +import { getIfFavoritedMovieRef } from "@/lib/dataconnect-sdk"; +import { useAddFavoritedMovie, useDeleteFavoritedMovie, useGetIfFavoritedMovie } from "@/lib/dataconnect-sdk/react"; interface MovieCardProps { id: string; @@ -43,25 +40,22 @@ export default function MovieCard({ tags, }: MovieCardProps) { const [user, setUser] = useState(null); - const [isFavorited, setIsFavorited] = useState(false); const auth = useContext(AuthContext); const navigate = useNavigate(); +const { mutate: handleAddFavoritedMovie } = useAddFavoritedMovie({ + invalidate: [getIfFavoritedMovieRef({ movieId: id })], + }); + const { mutate: handleDeleteFavoritedMovie } = useDeleteFavoritedMovie({ + invalidate: [getIfFavoritedMovieRef({ movieId: id })], + }); + const { data } = useGetIfFavoritedMovie({ movieId: id }); + const isFavorited = data?.favorite_movie; useEffect(() => { - async function checkIfFavorited() { - try { - const isFav = await handleGetIfFavoritedMovie(id); - setIsFavorited(isFav); - } catch (error) { - console.error("Error checking if movie is favorited:", error); - } - } + const unsubscribe = onAuthStateChanged(auth, (user) => { if (user) { setUser(user); - checkIfFavorited(); - } else { - setIsFavorited(false); } }); @@ -73,13 +67,11 @@ export default function MovieCard({ e.preventDefault(); if (!user) return; try { - const isFav = await handleGetIfFavoritedMovie(id); - if (isFav) { - await handleDeleteFavoritedMovie(id); + if (isFavorited) { + await handleDeleteFavoritedMovie({ movieId: id }); } else { - await handleAddFavoritedMovie(id); + await handleAddFavoritedMovie({ movieId: id }); } - setIsFavorited(!isFav); } catch (error) { console.error("Error updating favorite status:", error); } diff --git a/app/src/lib/MovieService.tsx b/app/src/lib/MovieService.tsx index 304b12d..52f5a20 100644 --- a/app/src/lib/MovieService.tsx +++ b/app/src/lib/MovieService.tsx @@ -14,53 +14,42 @@ * limitations under the License. */ -// import { listMovies, ListMoviesData, OrderDirection } from "@movie/dataconnect"; -// import { getMovieById, GetMovieByIdData } from "@movie/dataconnect"; -// import { GetActorByIdData, getActorById } from "@movie/dataconnect"; +// import { AddFavoritedMovieData, AddFavoritedMovieVariables, DeleteFavoritedMovieData, DeleteFavoritedMovieVariables, GetCurrentUserData, getCurrentUserRef, GetIfFavoritedMovieData, getIfFavoritedMovieRef, GetIfFavoritedMovieVariables, getMovieByIdRef, ListMoviesData, ListMoviesVariables, OrderDirection, searchAll, SearchAllData, upsertUser } from "@movie/dataconnect"; +// import { useAddFavoritedMovie, useAddReview, useDeleteFavoritedMovie, useDeleteReview, useGetActorById, useGetCurrentUser, useGetIfFavoritedMovie, useGetMovieById, useListMovies } from "@movie/dataconnect/react"; +// import { FlattenedMutationResult, FlattenedQueryResult } from "@tanstack-query-firebase/react/data-connect"; +// import { UseMutationResult, UseQueryResult } from "@tanstack/react-query"; +// import { FirebaseError } from "firebase/app"; -// import { upsertUser } from "@movie/dataconnect"; -// import { getCurrentUser, GetCurrentUserData } from "@movie/dataconnect"; - -// import { addFavoritedMovie, deleteFavoritedMovie, getIfFavoritedMovie } from "@movie/dataconnect"; -// import { addReview, deleteReview } from "@movie/dataconnect"; - -// import { searchAll, SearchAllData } from "@movie/dataconnect"; - -// import { -// searchMovieDescriptionUsingL2similarity, -// SearchMovieDescriptionUsingL2similarityData, -// } from "@movie/dataconnect"; - -import { onAuthStateChanged, User } from "firebase/auth"; +import { OrderDirection } from "@movie/dataconnect"; +import { User } from "firebase/auth"; // Fetch top-rated movies -export const handleGetTopMovies = async ( - limit: number -): Promise => { - return []; -}; +export const useHandleTopMovies = (limit: number, orderByRating: OrderDirection): { data: any; isLoading: any; } => { + return { data: { movies: [] }, isLoading: false }; +} // Fetch latest movies -export const handleGetLatestMovies = async ( - limit: number -): Promise => { - return []; -}; +export const useHandleLatestMovies = (limit: number, orderByReleaseYear: OrderDirection): { data: any; isLoading: any; } => { + return { data: { movies: [] }, isLoading: false }; +} // Fetch movie details by ID -export const handleGetMovieById = async ( - movieId: string -): Promise => { - return null; -}; - +export const useHandleGetMovieById = (id: string): { data: any; isLoading: any; error: any } => { + return { + error: new Error("Function not implemented."), + isLoading: false, + data: {}, + }; +} // Fetch actor details by ID -export const handleGetActorById = async ( - actorId: string -): Promise => { - return null; -}; +export const useHandleGetActorById = (id: string): { error: any; isLoading: any; data: any; } => { + return { + error: new Error("Function not implemented."), + isLoading: false, + data: {}, + }; +} // Updates user table when user signs in export const handleAuthStateChange = (auth: any, setUser: (user: User | null) => void) => { @@ -68,45 +57,44 @@ export const handleAuthStateChange = (auth: any, setUser: (user: User | null) => }; // Fetch current user profile -export const handleGetCurrentUser = async (): Promise => { - return null; +export const useHandleGetCurrentUser =(enabled: boolean): { data: any, isLoading: boolean, refetch: any} => { + return { data: {}, isLoading: false, refetch: () => {}}; }; - // Add a movie to user's favorites -export const handleAddFavoritedMovie = async ( - movieId: string -): Promise => { - return; -}; +export const useHandleAddFavoritedMovie = (id: string): {mutate: any} => { + return { + mutate: () => {} + } +} // Remove a movie from user's favorites -export const handleDeleteFavoritedMovie = async ( - movieId: string -): Promise => { - return; -}; +export const useHandleDeleteFavoritedMovie = (id: string): {mutate: any} => { +return { + mutate: () => {} + } +} // Check if the movie is favorited by the user -export const handleGetIfFavoritedMovie = async ( - movieId: string -): Promise => { - return false; -}; +export const useHandleGetIfFavoritedMovie = (movieId: string, enabled: boolean): {data: any} => { + return { + data: {}, + }; +} // Add a review to a movie -export const handleAddReview = async ( - movieId: string, - rating: number, - reviewText: string -): Promise => { - return; -}; +export const useHandleAddReview = (id: string): { mutate: any; } => { + return { + mutate: () => {} + } +} // Delete a review from a movie -export const handleDeleteReview = async (movieId: string): Promise => { - return; -}; +export const useHandleDeleteReview = (): { mutate: any; } => { + return { + mutate: () => {} + } +} // Function to perform the search using the query and filters export const handleSearchAll = async ( diff --git a/app/src/lib/dataconnect-sdk/README.md b/app/src/lib/dataconnect-sdk/README.md index 4a448f0..c470c69 100644 --- a/app/src/lib/dataconnect-sdk/README.md +++ b/app/src/lib/dataconnect-sdk/README.md @@ -38,12 +38,1190 @@ connectDataConnectEmulator(connector, 'localhost', 9399); After it's initialized, you can call your Data Connect [queries](#queries) and [mutations](#mutations) from your generated SDK. # Queries -No queries were generated for the `movie-connector` connector. +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` -If you want to learn more about how to use queries in Data Connect, you can follow the examples from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#using-queries). +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 `movie-connector` 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 [dataconnect-sdk/index.d.ts](./index.d.ts): +```javascript +listMovies(vars?: ListMoviesVariables): QueryPromise; + +listMoviesRef(vars?: ListMoviesVariables): QueryRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. +```javascript +listMovies(dc: DataConnect, vars?: ListMoviesVariables): QueryPromise; + +listMoviesRef(dc: DataConnect, vars?: ListMoviesVariables): QueryRef; +``` + +### Variables +The `ListMovies` query has an optional argument of type `ListMoviesVariables`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface ListMoviesVariables { + orderByRating?: OrderDirection | null; + orderByReleaseYear?: OrderDirection | null; + limit?: number | null; +} +``` +### 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 [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface ListMoviesData { + movies: ({ + id: UUIDString; + title: string; + imageUrl: string; + releaseYear?: number | null; + genre?: string | null; + rating?: number | null; + tags?: string[] | null; + description?: string | null; + } & Movie_Key)[]; +} +``` +### Using `ListMovies`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, listMovies, ListMoviesVariables } from '@movie/dataconnect'; +// The `ListMovies` query has an optional argument of type `ListMoviesVariables`: +const listMoviesVars: ListMoviesVariables = { + orderByRating: ..., // optional + orderByReleaseYear: ..., // optional + limit: ..., // optional +} + +// 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(listMoviesVars); +// Variables can be defined inline as well. +const { data } = await listMovies({ orderByRating: ..., orderByReleaseYear: ..., limit: ..., }); +// Since all variables are optional for this query, you can omit the `ListMoviesVariables` argument. +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, listMoviesVars); + +console.log(data.movies); + +// Or, you can use the `Promise` API. +listMovies(listMoviesVars).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, ListMoviesVariables } from '@movie/dataconnect'; +// The `ListMovies` query has an optional argument of type `ListMoviesVariables`: +const listMoviesVars: ListMoviesVariables = { + orderByRating: ..., // optional + orderByReleaseYear: ..., // optional + limit: ..., // optional +} + +// Call the `listMoviesRef()` function to get a reference to the query. +const ref = listMoviesRef(listMoviesVars); +// Variables can be defined inline as well. +const ref = listMoviesRef({ orderByRating: ..., orderByReleaseYear: ..., limit: ..., }); +// Since all variables are optional for this query, you can omit the `ListMoviesVariables` argument. +const ref = listMoviesRef(); + +// You can also pass in a `DataConnect` instance to the `QueryRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = listMoviesRef(connector, listMoviesVars); + +// 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 [dataconnect-sdk/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 [dataconnect-sdk/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 [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface GetMovieByIdData { + movie?: { + id: UUIDString; + title: string; + imageUrl: string; + releaseYear?: number | null; + genre?: string | null; + rating?: number | null; + description?: string | null; + tags?: string[] | null; + metadata: ({ + director?: string | null; + })[]; + mainActors: ({ + id: UUIDString; + name: string; + imageUrl: string; + } & Actor_Key)[]; + supportingActors: ({ + id: UUIDString; + name: string; + imageUrl: string; + } & Actor_Key)[]; + reviews: ({ + id: UUIDString; + reviewText?: string | null; + reviewDate: DateString; + rating?: number | null; + user: { + id: string; + username: string; + } & User_Key; + })[]; + } & Movie_Key; +} +``` +### Using `GetMovieById`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, getMovieById, GetMovieByIdVariables } from '@movie/dataconnect'; +// 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 '@movie/dataconnect'; +// 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); +}); +``` + +## GetActorById +You can execute the `GetActorById` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [dataconnect-sdk/index.d.ts](./index.d.ts): +```javascript +getActorById(vars: GetActorByIdVariables): QueryPromise; + +getActorByIdRef(vars: GetActorByIdVariables): QueryRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. +```javascript +getActorById(dc: DataConnect, vars: GetActorByIdVariables): QueryPromise; + +getActorByIdRef(dc: DataConnect, vars: GetActorByIdVariables): QueryRef; +``` + +### Variables +The `GetActorById` query requires an argument of type `GetActorByIdVariables`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface GetActorByIdVariables { + id: UUIDString; +} +``` +### Return Type +Recall that executing the `GetActorById` query returns a `QueryPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `GetActorByIdData`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface GetActorByIdData { + actor?: { + id: UUIDString; + name: string; + imageUrl: string; + mainActors: ({ + id: UUIDString; + title: string; + genre?: string | null; + tags?: string[] | null; + imageUrl: string; + } & Movie_Key)[]; + supportingActors: ({ + id: UUIDString; + title: string; + genre?: string | null; + tags?: string[] | null; + imageUrl: string; + } & Movie_Key)[]; + } & Actor_Key; +} +``` +### Using `GetActorById`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, getActorById, GetActorByIdVariables } from '@movie/dataconnect'; +// The `GetActorById` query requires an argument of type `GetActorByIdVariables`: +const getActorByIdVars: GetActorByIdVariables = { + id: ..., +} + +// Call the `getActorById()` function to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await getActorById(getActorByIdVars); +// Variables can be defined inline as well. +const { data } = await getActorById({ id: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await getActorById(connector, getActorByIdVars); + +console.log(data.actor); + +// Or, you can use the `Promise` API. +getActorById(getActorByIdVars).then((response) => { + const data = response.data; + console.log(data.actor); +}); +``` + +### Using `GetActorById`'s `QueryRef` function + +```javascript +import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; +import { connectorConfig, getActorByIdRef, GetActorByIdVariables } from '@movie/dataconnect'; +// The `GetActorById` query requires an argument of type `GetActorByIdVariables`: +const getActorByIdVars: GetActorByIdVariables = { + id: ..., +} + +// Call the `getActorByIdRef()` function to get a reference to the query. +const ref = getActorByIdRef(getActorByIdVars); +// Variables can be defined inline as well. +const ref = getActorByIdRef({ id: ..., }); + +// You can also pass in a `DataConnect` instance to the `QueryRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = getActorByIdRef(connector, getActorByIdVars); + +// 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.actor); + +// Or, you can use the `Promise` API. +executeQuery(ref).then((response) => { + const data = response.data; + console.log(data.actor); +}); +``` + +## GetCurrentUser +You can execute the `GetCurrentUser` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [dataconnect-sdk/index.d.ts](./index.d.ts): +```javascript +getCurrentUser(): QueryPromise; + +getCurrentUserRef(): QueryRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. +```javascript +getCurrentUser(dc: DataConnect): QueryPromise; + +getCurrentUserRef(dc: DataConnect): QueryRef; +``` + +### Variables +The `GetCurrentUser` query has no variables. +### Return Type +Recall that executing the `GetCurrentUser` query returns a `QueryPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `GetCurrentUserData`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface GetCurrentUserData { + user?: { + id: string; + username: string; + reviews: ({ + id: UUIDString; + rating?: number | null; + reviewDate: DateString; + reviewText?: string | null; + movie: { + id: UUIDString; + title: string; + } & Movie_Key; + })[]; + favoriteMovies: ({ + movie: { + id: UUIDString; + title: string; + genre?: string | null; + imageUrl: string; + releaseYear?: number | null; + rating?: number | null; + description?: string | null; + tags?: string[] | null; + metadata: ({ + director?: string | null; + })[]; + } & Movie_Key; + })[]; + } & User_Key; +} +``` +### Using `GetCurrentUser`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, getCurrentUser } from '@movie/dataconnect'; + +// Call the `getCurrentUser()` function to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await getCurrentUser(); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await getCurrentUser(connector); + +console.log(data.user); + +// Or, you can use the `Promise` API. +getCurrentUser().then((response) => { + const data = response.data; + console.log(data.user); +}); +``` + +### Using `GetCurrentUser`'s `QueryRef` function + +```javascript +import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; +import { connectorConfig, getCurrentUserRef } from '@movie/dataconnect'; + +// Call the `getCurrentUserRef()` function to get a reference to the query. +const ref = getCurrentUserRef(); + +// You can also pass in a `DataConnect` instance to the `QueryRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = getCurrentUserRef(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.user); + +// Or, you can use the `Promise` API. +executeQuery(ref).then((response) => { + const data = response.data; + console.log(data.user); +}); +``` + +## GetIfFavoritedMovie +You can execute the `GetIfFavoritedMovie` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [dataconnect-sdk/index.d.ts](./index.d.ts): +```javascript +getIfFavoritedMovie(vars: GetIfFavoritedMovieVariables): QueryPromise; + +getIfFavoritedMovieRef(vars: GetIfFavoritedMovieVariables): QueryRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. +```javascript +getIfFavoritedMovie(dc: DataConnect, vars: GetIfFavoritedMovieVariables): QueryPromise; + +getIfFavoritedMovieRef(dc: DataConnect, vars: GetIfFavoritedMovieVariables): QueryRef; +``` + +### Variables +The `GetIfFavoritedMovie` query requires an argument of type `GetIfFavoritedMovieVariables`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface GetIfFavoritedMovieVariables { + movieId: UUIDString; +} +``` +### Return Type +Recall that executing the `GetIfFavoritedMovie` query returns a `QueryPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `GetIfFavoritedMovieData`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface GetIfFavoritedMovieData { + favorite_movie?: { + movieId: UUIDString; + }; +} +``` +### Using `GetIfFavoritedMovie`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, getIfFavoritedMovie, GetIfFavoritedMovieVariables } from '@movie/dataconnect'; +// The `GetIfFavoritedMovie` query requires an argument of type `GetIfFavoritedMovieVariables`: +const getIfFavoritedMovieVars: GetIfFavoritedMovieVariables = { + movieId: ..., +} + +// Call the `getIfFavoritedMovie()` function to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await getIfFavoritedMovie(getIfFavoritedMovieVars); +// Variables can be defined inline as well. +const { data } = await getIfFavoritedMovie({ movieId: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await getIfFavoritedMovie(connector, getIfFavoritedMovieVars); + +console.log(data.favorite_movie); + +// Or, you can use the `Promise` API. +getIfFavoritedMovie(getIfFavoritedMovieVars).then((response) => { + const data = response.data; + console.log(data.favorite_movie); +}); +``` + +### Using `GetIfFavoritedMovie`'s `QueryRef` function + +```javascript +import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; +import { connectorConfig, getIfFavoritedMovieRef, GetIfFavoritedMovieVariables } from '@movie/dataconnect'; +// The `GetIfFavoritedMovie` query requires an argument of type `GetIfFavoritedMovieVariables`: +const getIfFavoritedMovieVars: GetIfFavoritedMovieVariables = { + movieId: ..., +} + +// Call the `getIfFavoritedMovieRef()` function to get a reference to the query. +const ref = getIfFavoritedMovieRef(getIfFavoritedMovieVars); +// Variables can be defined inline as well. +const ref = getIfFavoritedMovieRef({ movieId: ..., }); + +// You can also pass in a `DataConnect` instance to the `QueryRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = getIfFavoritedMovieRef(connector, getIfFavoritedMovieVars); + +// 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.favorite_movie); + +// Or, you can use the `Promise` API. +executeQuery(ref).then((response) => { + const data = response.data; + console.log(data.favorite_movie); +}); +``` + +## SearchAll +You can execute the `SearchAll` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [dataconnect-sdk/index.d.ts](./index.d.ts): +```javascript +searchAll(vars: SearchAllVariables): QueryPromise; + +searchAllRef(vars: SearchAllVariables): QueryRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. +```javascript +searchAll(dc: DataConnect, vars: SearchAllVariables): QueryPromise; + +searchAllRef(dc: DataConnect, vars: SearchAllVariables): QueryRef; +``` + +### Variables +The `SearchAll` query requires an argument of type `SearchAllVariables`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface SearchAllVariables { + input?: string | null; + minYear: number; + maxYear: number; + minRating: number; + maxRating: number; + genre: string; +} +``` +### Return Type +Recall that executing the `SearchAll` query returns a `QueryPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `SearchAllData`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface SearchAllData { + moviesMatchingTitle: ({ + id: UUIDString; + title: string; + genre?: string | null; + rating?: number | null; + imageUrl: string; + tags?: string[] | null; + } & Movie_Key)[]; + moviesMatchingDescription: ({ + id: UUIDString; + title: string; + genre?: string | null; + rating?: number | null; + imageUrl: string; + tags?: string[] | null; + } & Movie_Key)[]; + actorsMatchingName: ({ + id: UUIDString; + name: string; + imageUrl: string; + } & Actor_Key)[]; + reviewsMatchingText: ({ + id: UUIDString; + rating?: number | null; + reviewText?: string | null; + reviewDate: DateString; + movie: { + id: UUIDString; + title: string; + } & Movie_Key; + user: { + id: string; + username: string; + } & User_Key; + })[]; +} +``` +### Using `SearchAll`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, searchAll, SearchAllVariables } from '@movie/dataconnect'; +// The `SearchAll` query requires an argument of type `SearchAllVariables`: +const searchAllVars: SearchAllVariables = { + input: ..., // optional + minYear: ..., + maxYear: ..., + minRating: ..., + maxRating: ..., + genre: ..., +} + +// Call the `searchAll()` function to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await searchAll(searchAllVars); +// Variables can be defined inline as well. +const { data } = await searchAll({ input: ..., minYear: ..., maxYear: ..., minRating: ..., maxRating: ..., genre: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await searchAll(connector, searchAllVars); + +console.log(data.moviesMatchingTitle); +console.log(data.moviesMatchingDescription); +console.log(data.actorsMatchingName); +console.log(data.reviewsMatchingText); + +// Or, you can use the `Promise` API. +searchAll(searchAllVars).then((response) => { + const data = response.data; + console.log(data.moviesMatchingTitle); + console.log(data.moviesMatchingDescription); + console.log(data.actorsMatchingName); + console.log(data.reviewsMatchingText); +}); +``` + +### Using `SearchAll`'s `QueryRef` function + +```javascript +import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; +import { connectorConfig, searchAllRef, SearchAllVariables } from '@movie/dataconnect'; +// The `SearchAll` query requires an argument of type `SearchAllVariables`: +const searchAllVars: SearchAllVariables = { + input: ..., // optional + minYear: ..., + maxYear: ..., + minRating: ..., + maxRating: ..., + genre: ..., +} + +// Call the `searchAllRef()` function to get a reference to the query. +const ref = searchAllRef(searchAllVars); +// Variables can be defined inline as well. +const ref = searchAllRef({ input: ..., minYear: ..., maxYear: ..., minRating: ..., maxRating: ..., genre: ..., }); + +// You can also pass in a `DataConnect` instance to the `QueryRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = searchAllRef(connector, searchAllVars); + +// 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.moviesMatchingTitle); +console.log(data.moviesMatchingDescription); +console.log(data.actorsMatchingName); +console.log(data.reviewsMatchingText); + +// Or, you can use the `Promise` API. +executeQuery(ref).then((response) => { + const data = response.data; + console.log(data.moviesMatchingTitle); + console.log(data.moviesMatchingDescription); + console.log(data.actorsMatchingName); + console.log(data.reviewsMatchingText); +}); +``` # Mutations -No mutations were generated for the `movie-connector` connector. +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 `movie-connector` 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). + +## UpsertUser +You can execute the `UpsertUser` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [dataconnect-sdk/index.d.ts](./index.d.ts): +```javascript +upsertUser(vars: UpsertUserVariables): MutationPromise; + +upsertUserRef(vars: UpsertUserVariables): MutationRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +upsertUser(dc: DataConnect, vars: UpsertUserVariables): MutationPromise; + +upsertUserRef(dc: DataConnect, vars: UpsertUserVariables): MutationRef; +``` + +### Variables +The `UpsertUser` mutation requires an argument of type `UpsertUserVariables`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface UpsertUserVariables { + username: string; +} +``` +### Return Type +Recall that executing the `UpsertUser` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `UpsertUserData`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface UpsertUserData { + user_upsert: User_Key; +} +``` +### Using `UpsertUser`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, upsertUser, UpsertUserVariables } from '@movie/dataconnect'; +// The `UpsertUser` mutation requires an argument of type `UpsertUserVariables`: +const upsertUserVars: UpsertUserVariables = { + username: ..., +} + +// Call the `upsertUser()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await upsertUser(upsertUserVars); +// Variables can be defined inline as well. +const { data } = await upsertUser({ username: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await upsertUser(connector, upsertUserVars); + +console.log(data.user_upsert); + +// Or, you can use the `Promise` API. +upsertUser(upsertUserVars).then((response) => { + const data = response.data; + console.log(data.user_upsert); +}); +``` + +### Using `UpsertUser`'s `MutationRef` function + +```javascript +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, upsertUserRef, UpsertUserVariables } from '@movie/dataconnect'; +// The `UpsertUser` mutation requires an argument of type `UpsertUserVariables`: +const upsertUserVars: UpsertUserVariables = { + username: ..., +} + +// Call the `upsertUserRef()` function to get a reference to the mutation. +const ref = upsertUserRef(upsertUserVars); +// Variables can be defined inline as well. +const ref = upsertUserRef({ username: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = upsertUserRef(connector, upsertUserVars); + +// 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.user_upsert); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.user_upsert); +}); +``` + +## AddFavoritedMovie +You can execute the `AddFavoritedMovie` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [dataconnect-sdk/index.d.ts](./index.d.ts): +```javascript +addFavoritedMovie(vars: AddFavoritedMovieVariables): MutationPromise; + +addFavoritedMovieRef(vars: AddFavoritedMovieVariables): MutationRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +addFavoritedMovie(dc: DataConnect, vars: AddFavoritedMovieVariables): MutationPromise; + +addFavoritedMovieRef(dc: DataConnect, vars: AddFavoritedMovieVariables): MutationRef; +``` + +### Variables +The `AddFavoritedMovie` mutation requires an argument of type `AddFavoritedMovieVariables`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface AddFavoritedMovieVariables { + movieId: UUIDString; +} +``` +### Return Type +Recall that executing the `AddFavoritedMovie` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `AddFavoritedMovieData`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface AddFavoritedMovieData { + favorite_movie_upsert: FavoriteMovie_Key; +} +``` +### Using `AddFavoritedMovie`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, addFavoritedMovie, AddFavoritedMovieVariables } from '@movie/dataconnect'; +// The `AddFavoritedMovie` mutation requires an argument of type `AddFavoritedMovieVariables`: +const addFavoritedMovieVars: AddFavoritedMovieVariables = { + movieId: ..., +} + +// Call the `addFavoritedMovie()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await addFavoritedMovie(addFavoritedMovieVars); +// Variables can be defined inline as well. +const { data } = await addFavoritedMovie({ movieId: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await addFavoritedMovie(connector, addFavoritedMovieVars); + +console.log(data.favorite_movie_upsert); + +// Or, you can use the `Promise` API. +addFavoritedMovie(addFavoritedMovieVars).then((response) => { + const data = response.data; + console.log(data.favorite_movie_upsert); +}); +``` + +### Using `AddFavoritedMovie`'s `MutationRef` function + +```javascript +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, addFavoritedMovieRef, AddFavoritedMovieVariables } from '@movie/dataconnect'; +// The `AddFavoritedMovie` mutation requires an argument of type `AddFavoritedMovieVariables`: +const addFavoritedMovieVars: AddFavoritedMovieVariables = { + movieId: ..., +} + +// Call the `addFavoritedMovieRef()` function to get a reference to the mutation. +const ref = addFavoritedMovieRef(addFavoritedMovieVars); +// Variables can be defined inline as well. +const ref = addFavoritedMovieRef({ movieId: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = addFavoritedMovieRef(connector, addFavoritedMovieVars); + +// 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.favorite_movie_upsert); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.favorite_movie_upsert); +}); +``` + +## DeleteFavoritedMovie +You can execute the `DeleteFavoritedMovie` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [dataconnect-sdk/index.d.ts](./index.d.ts): +```javascript +deleteFavoritedMovie(vars: DeleteFavoritedMovieVariables): MutationPromise; + +deleteFavoritedMovieRef(vars: DeleteFavoritedMovieVariables): MutationRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +deleteFavoritedMovie(dc: DataConnect, vars: DeleteFavoritedMovieVariables): MutationPromise; + +deleteFavoritedMovieRef(dc: DataConnect, vars: DeleteFavoritedMovieVariables): MutationRef; +``` + +### Variables +The `DeleteFavoritedMovie` mutation requires an argument of type `DeleteFavoritedMovieVariables`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: -If you want to learn more about how to use mutations in Data Connect, you can follow the examples from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#using-mutations). +```javascript +export interface DeleteFavoritedMovieVariables { + movieId: UUIDString; +} +``` +### Return Type +Recall that executing the `DeleteFavoritedMovie` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `DeleteFavoritedMovieData`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface DeleteFavoritedMovieData { + favorite_movie_delete?: FavoriteMovie_Key | null; +} +``` +### Using `DeleteFavoritedMovie`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, deleteFavoritedMovie, DeleteFavoritedMovieVariables } from '@movie/dataconnect'; +// The `DeleteFavoritedMovie` mutation requires an argument of type `DeleteFavoritedMovieVariables`: +const deleteFavoritedMovieVars: DeleteFavoritedMovieVariables = { + movieId: ..., +} + +// Call the `deleteFavoritedMovie()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await deleteFavoritedMovie(deleteFavoritedMovieVars); +// Variables can be defined inline as well. +const { data } = await deleteFavoritedMovie({ movieId: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await deleteFavoritedMovie(connector, deleteFavoritedMovieVars); + +console.log(data.favorite_movie_delete); + +// Or, you can use the `Promise` API. +deleteFavoritedMovie(deleteFavoritedMovieVars).then((response) => { + const data = response.data; + console.log(data.favorite_movie_delete); +}); +``` + +### Using `DeleteFavoritedMovie`'s `MutationRef` function + +```javascript +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, deleteFavoritedMovieRef, DeleteFavoritedMovieVariables } from '@movie/dataconnect'; +// The `DeleteFavoritedMovie` mutation requires an argument of type `DeleteFavoritedMovieVariables`: +const deleteFavoritedMovieVars: DeleteFavoritedMovieVariables = { + movieId: ..., +} + +// Call the `deleteFavoritedMovieRef()` function to get a reference to the mutation. +const ref = deleteFavoritedMovieRef(deleteFavoritedMovieVars); +// Variables can be defined inline as well. +const ref = deleteFavoritedMovieRef({ movieId: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = deleteFavoritedMovieRef(connector, deleteFavoritedMovieVars); + +// 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.favorite_movie_delete); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.favorite_movie_delete); +}); +``` + +## AddReview +You can execute the `AddReview` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [dataconnect-sdk/index.d.ts](./index.d.ts): +```javascript +addReview(vars: AddReviewVariables): MutationPromise; + +addReviewRef(vars: AddReviewVariables): MutationRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +addReview(dc: DataConnect, vars: AddReviewVariables): MutationPromise; + +addReviewRef(dc: DataConnect, vars: AddReviewVariables): MutationRef; +``` + +### Variables +The `AddReview` mutation requires an argument of type `AddReviewVariables`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface AddReviewVariables { + movieId: UUIDString; + rating: number; + reviewText: string; +} +``` +### Return Type +Recall that executing the `AddReview` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `AddReviewData`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface AddReviewData { + review_insert: Review_Key; +} +``` +### Using `AddReview`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, addReview, AddReviewVariables } from '@movie/dataconnect'; +// The `AddReview` mutation requires an argument of type `AddReviewVariables`: +const addReviewVars: AddReviewVariables = { + movieId: ..., + rating: ..., + reviewText: ..., +} + +// Call the `addReview()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await addReview(addReviewVars); +// Variables can be defined inline as well. +const { data } = await addReview({ movieId: ..., rating: ..., reviewText: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await addReview(connector, addReviewVars); + +console.log(data.review_insert); + +// Or, you can use the `Promise` API. +addReview(addReviewVars).then((response) => { + const data = response.data; + console.log(data.review_insert); +}); +``` + +### Using `AddReview`'s `MutationRef` function + +```javascript +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, addReviewRef, AddReviewVariables } from '@movie/dataconnect'; +// The `AddReview` mutation requires an argument of type `AddReviewVariables`: +const addReviewVars: AddReviewVariables = { + movieId: ..., + rating: ..., + reviewText: ..., +} + +// Call the `addReviewRef()` function to get a reference to the mutation. +const ref = addReviewRef(addReviewVars); +// Variables can be defined inline as well. +const ref = addReviewRef({ movieId: ..., rating: ..., reviewText: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = addReviewRef(connector, addReviewVars); + +// 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.review_insert); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.review_insert); +}); +``` + +## DeleteReview +You can execute the `DeleteReview` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [dataconnect-sdk/index.d.ts](./index.d.ts): +```javascript +deleteReview(vars: DeleteReviewVariables): MutationPromise; + +deleteReviewRef(vars: DeleteReviewVariables): MutationRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +deleteReview(dc: DataConnect, vars: DeleteReviewVariables): MutationPromise; + +deleteReviewRef(dc: DataConnect, vars: DeleteReviewVariables): MutationRef; +``` + +### Variables +The `DeleteReview` mutation requires an argument of type `DeleteReviewVariables`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface DeleteReviewVariables { + movieId: UUIDString; +} +``` +### Return Type +Recall that executing the `DeleteReview` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `DeleteReviewData`, which is defined in [dataconnect-sdk/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface DeleteReviewData { + review_delete?: Review_Key | null; +} +``` +### Using `DeleteReview`'s action shortcut function + +```javascript +import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectorConfig, deleteReview, DeleteReviewVariables } from '@movie/dataconnect'; +// The `DeleteReview` mutation requires an argument of type `DeleteReviewVariables`: +const deleteReviewVars: DeleteReviewVariables = { + movieId: ..., +} + +// Call the `deleteReview()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await deleteReview(deleteReviewVars); +// Variables can be defined inline as well. +const { data } = await deleteReview({ movieId: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const connector: DataConnect = getDataConnect(connectorConfig); +const { data } = await deleteReview(connector, deleteReviewVars); + +console.log(data.review_delete); + +// Or, you can use the `Promise` API. +deleteReview(deleteReviewVars).then((response) => { + const data = response.data; + console.log(data.review_delete); +}); +``` + +### Using `DeleteReview`'s `MutationRef` function + +```javascript +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, deleteReviewRef, DeleteReviewVariables } from '@movie/dataconnect'; +// The `DeleteReview` mutation requires an argument of type `DeleteReviewVariables`: +const deleteReviewVars: DeleteReviewVariables = { + movieId: ..., +} + +// Call the `deleteReviewRef()` function to get a reference to the mutation. +const ref = deleteReviewRef(deleteReviewVars); +// Variables can be defined inline as well. +const ref = deleteReviewRef({ movieId: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const connector: DataConnect = getDataConnect(connectorConfig); +const ref = deleteReviewRef(connector, deleteReviewVars); + +// 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.review_delete); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.review_delete); +}); +``` diff --git a/app/src/lib/dataconnect-sdk/esm/index.esm.js b/app/src/lib/dataconnect-sdk/esm/index.esm.js index 0498b49..e735d97 100644 --- a/app/src/lib/dataconnect-sdk/esm/index.esm.js +++ b/app/src/lib/dataconnect-sdk/esm/index.esm.js @@ -1,6 +1,124 @@ +import { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } from 'firebase/data-connect'; +export const OrderDirection = { + + ASC: "ASC", + + DESC: "DESC", +} + export const connectorConfig = { connector: 'movie-connector', service: 'your-service-id', location: 'us-central1' }; +export function upsertUserRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'UpsertUser', inputVars); +} + +export function upsertUser(dcOrVars, vars) { + return executeMutation(upsertUserRef(dcOrVars, vars)); +} + +export function addFavoritedMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'AddFavoritedMovie', inputVars); +} + +export function addFavoritedMovie(dcOrVars, vars) { + return executeMutation(addFavoritedMovieRef(dcOrVars, vars)); +} + +export function deleteFavoritedMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'DeleteFavoritedMovie', inputVars); +} + +export function deleteFavoritedMovie(dcOrVars, vars) { + return executeMutation(deleteFavoritedMovieRef(dcOrVars, vars)); +} + +export function addReviewRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'AddReview', inputVars); +} + +export function addReview(dcOrVars, vars) { + return executeMutation(addReviewRef(dcOrVars, vars)); +} + +export function deleteReviewRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'DeleteReview', inputVars); +} + +export function deleteReview(dcOrVars, vars) { + return executeMutation(deleteReviewRef(dcOrVars, vars)); +} + +export function listMoviesRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'ListMovies', inputVars); +} + +export function listMovies(dcOrVars, vars) { + return executeQuery(listMoviesRef(dcOrVars, vars)); +} + +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)); +} + +export function getActorByIdRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'GetActorById', inputVars); +} + +export function getActorById(dcOrVars, vars) { + return executeQuery(getActorByIdRef(dcOrVars, vars)); +} + +export function getCurrentUserRef(dc) { + const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'GetCurrentUser'); +} + +export function getCurrentUser(dc) { + return executeQuery(getCurrentUserRef(dc)); +} + +export function getIfFavoritedMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'GetIfFavoritedMovie', inputVars); +} + +export function getIfFavoritedMovie(dcOrVars, vars) { + return executeQuery(getIfFavoritedMovieRef(dcOrVars, vars)); +} + +export function searchAllRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'SearchAll', inputVars); +} + +export function searchAll(dcOrVars, vars) { + return executeQuery(searchAllRef(dcOrVars, vars)); +} + diff --git a/app/src/lib/dataconnect-sdk/index.cjs.js b/app/src/lib/dataconnect-sdk/index.cjs.js index 763e7b5..0a63f07 100644 --- a/app/src/lib/dataconnect-sdk/index.cjs.js +++ b/app/src/lib/dataconnect-sdk/index.cjs.js @@ -1,4 +1,12 @@ -const { , validateArgs } = require('firebase/data-connect'); +const { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } = require('firebase/data-connect'); + +const OrderDirection = { + + ASC: "ASC", + + DESC: "DESC", +} +exports.OrderDirection = OrderDirection; const connectorConfig = { connector: 'movie-connector', @@ -7,3 +15,102 @@ const connectorConfig = { }; exports.connectorConfig = connectorConfig; +exports.upsertUserRef = function upsertUserRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'UpsertUser', inputVars); +} + +exports.upsertUser = function upsertUser(dcOrVars, vars) { + return executeMutation(upsertUserRef(dcOrVars, vars)); +}; +exports.addFavoritedMovieRef = function addFavoritedMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'AddFavoritedMovie', inputVars); +} + +exports.addFavoritedMovie = function addFavoritedMovie(dcOrVars, vars) { + return executeMutation(addFavoritedMovieRef(dcOrVars, vars)); +}; +exports.deleteFavoritedMovieRef = function deleteFavoritedMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'DeleteFavoritedMovie', inputVars); +} + +exports.deleteFavoritedMovie = function deleteFavoritedMovie(dcOrVars, vars) { + return executeMutation(deleteFavoritedMovieRef(dcOrVars, vars)); +}; +exports.addReviewRef = function addReviewRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'AddReview', inputVars); +} + +exports.addReview = function addReview(dcOrVars, vars) { + return executeMutation(addReviewRef(dcOrVars, vars)); +}; +exports.deleteReviewRef = function deleteReviewRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'DeleteReview', inputVars); +} + +exports.deleteReview = function deleteReview(dcOrVars, vars) { + return executeMutation(deleteReviewRef(dcOrVars, vars)); +}; +exports.listMoviesRef = function listMoviesRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'ListMovies', inputVars); +} + +exports.listMovies = function listMovies(dcOrVars, vars) { + return executeQuery(listMoviesRef(dcOrVars, vars)); +}; +exports.getMovieByIdRef = function getMovieByIdRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'GetMovieById', inputVars); +} + +exports.getMovieById = function getMovieById(dcOrVars, vars) { + return executeQuery(getMovieByIdRef(dcOrVars, vars)); +}; +exports.getActorByIdRef = function getActorByIdRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'GetActorById', inputVars); +} + +exports.getActorById = function getActorById(dcOrVars, vars) { + return executeQuery(getActorByIdRef(dcOrVars, vars)); +}; +exports.getCurrentUserRef = function getCurrentUserRef(dc) { + const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'GetCurrentUser'); +} + +exports.getCurrentUser = function getCurrentUser(dc) { + return executeQuery(getCurrentUserRef(dc)); +}; +exports.getIfFavoritedMovieRef = function getIfFavoritedMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'GetIfFavoritedMovie', inputVars); +} + +exports.getIfFavoritedMovie = function getIfFavoritedMovie(dcOrVars, vars) { + return executeQuery(getIfFavoritedMovieRef(dcOrVars, vars)); +}; +exports.searchAllRef = function searchAllRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'SearchAll', inputVars); +} + +exports.searchAll = function searchAll(dcOrVars, vars) { + return executeQuery(searchAllRef(dcOrVars, vars)); +}; diff --git a/app/src/lib/dataconnect-sdk/index.d.ts b/app/src/lib/dataconnect-sdk/index.d.ts index d8f37b0..2e16fd3 100644 --- a/app/src/lib/dataconnect-sdk/index.d.ts +++ b/app/src/lib/dataconnect-sdk/index.d.ts @@ -1,12 +1,369 @@ -import { ConnectorConfig, DataConnect } from 'firebase/data-connect'; +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 enum OrderDirection { + + ASC = "ASC", + + DESC = "DESC", + +} +export interface Actor_Key { + id: UUIDString; + __typename?: 'Actor_Key'; +} + +export interface AddFavoritedMovieData { + favorite_movie_upsert: FavoriteMovie_Key; +} + +export interface AddFavoritedMovieVariables { + movieId: UUIDString; +} + +export interface AddReviewData { + review_insert: Review_Key; +} + +export interface AddReviewVariables { + movieId: UUIDString; + rating: number; + reviewText: string; +} + +export interface DeleteFavoritedMovieData { + favorite_movie_delete?: FavoriteMovie_Key | null; +} + +export interface DeleteFavoritedMovieVariables { + movieId: UUIDString; +} + +export interface DeleteReviewData { + review_delete?: Review_Key | null; +} + +export interface DeleteReviewVariables { + movieId: UUIDString; +} + +export interface FavoriteMovie_Key { + userId: string; + movieId: UUIDString; + __typename?: 'FavoriteMovie_Key'; +} + +export interface GetActorByIdData { + actor?: { + id: UUIDString; + name: string; + imageUrl: string; + mainActors: ({ + id: UUIDString; + title: string; + genre?: string | null; + tags?: string[] | null; + imageUrl: string; + } & Movie_Key)[]; + supportingActors: ({ + id: UUIDString; + title: string; + genre?: string | null; + tags?: string[] | null; + imageUrl: string; + } & Movie_Key)[]; + } & Actor_Key; +} + +export interface GetActorByIdVariables { + id: UUIDString; +} + +export interface GetCurrentUserData { + user?: { + id: string; + username: string; + reviews: ({ + id: UUIDString; + rating?: number | null; + reviewDate: DateString; + reviewText?: string | null; + movie: { + id: UUIDString; + title: string; + } & Movie_Key; + })[]; + favoriteMovies: ({ + movie: { + id: UUIDString; + title: string; + genre?: string | null; + imageUrl: string; + releaseYear?: number | null; + rating?: number | null; + description?: string | null; + tags?: string[] | null; + metadata: ({ + director?: string | null; + })[]; + } & Movie_Key; + })[]; + } & User_Key; +} + +export interface GetIfFavoritedMovieData { + favorite_movie?: { + movieId: UUIDString; + }; +} + +export interface GetIfFavoritedMovieVariables { + movieId: UUIDString; +} + +export interface GetMovieByIdData { + movie?: { + id: UUIDString; + title: string; + imageUrl: string; + releaseYear?: number | null; + genre?: string | null; + rating?: number | null; + description?: string | null; + tags?: string[] | null; + metadata: ({ + director?: string | null; + })[]; + mainActors: ({ + id: UUIDString; + name: string; + imageUrl: string; + } & Actor_Key)[]; + supportingActors: ({ + id: UUIDString; + name: string; + imageUrl: string; + } & Actor_Key)[]; + reviews: ({ + id: UUIDString; + reviewText?: string | null; + reviewDate: DateString; + rating?: number | null; + user: { + id: string; + username: string; + } & User_Key; + })[]; + } & Movie_Key; +} + +export interface GetMovieByIdVariables { + id: UUIDString; +} + +export interface ListMoviesData { + movies: ({ + id: UUIDString; + title: string; + imageUrl: string; + releaseYear?: number | null; + genre?: string | null; + rating?: number | null; + tags?: string[] | null; + description?: string | null; + } & Movie_Key)[]; +} + +export interface ListMoviesVariables { + orderByRating?: OrderDirection | null; + orderByReleaseYear?: OrderDirection | null; + limit?: number | null; +} + +export interface MovieActor_Key { + movieId: UUIDString; + actorId: UUIDString; + __typename?: 'MovieActor_Key'; +} + +export interface MovieMetadata_Key { + id: UUIDString; + __typename?: 'MovieMetadata_Key'; +} + +export interface Movie_Key { + id: UUIDString; + __typename?: 'Movie_Key'; +} + +export interface Review_Key { + userId: string; + movieId: UUIDString; + __typename?: 'Review_Key'; +} + +export interface SearchAllData { + moviesMatchingTitle: ({ + id: UUIDString; + title: string; + genre?: string | null; + rating?: number | null; + imageUrl: string; + tags?: string[] | null; + } & Movie_Key)[]; + moviesMatchingDescription: ({ + id: UUIDString; + title: string; + genre?: string | null; + rating?: number | null; + imageUrl: string; + tags?: string[] | null; + } & Movie_Key)[]; + actorsMatchingName: ({ + id: UUIDString; + name: string; + imageUrl: string; + } & Actor_Key)[]; + reviewsMatchingText: ({ + id: UUIDString; + rating?: number | null; + reviewText?: string | null; + reviewDate: DateString; + movie: { + id: UUIDString; + title: string; + } & Movie_Key; + user: { + id: string; + username: string; + } & User_Key; + })[]; +} + +export interface SearchAllVariables { + input?: string | null; + minYear: number; + maxYear: number; + minRating: number; + maxRating: number; + genre: string; +} + +export interface UpsertUserData { + user_upsert: User_Key; +} + +export interface UpsertUserVariables { + username: string; +} + +export interface User_Key { + id: string; + __typename?: 'User_Key'; +} + + +/* Allow users to create refs without passing in DataConnect */ +export function upsertUserRef(vars: UpsertUserVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function upsertUserRef(dc: DataConnect, vars: UpsertUserVariables): MutationRef; + +export function upsertUser(vars: UpsertUserVariables): MutationPromise; +export function upsertUser(dc: DataConnect, vars: UpsertUserVariables): MutationPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function addFavoritedMovieRef(vars: AddFavoritedMovieVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function addFavoritedMovieRef(dc: DataConnect, vars: AddFavoritedMovieVariables): MutationRef; + +export function addFavoritedMovie(vars: AddFavoritedMovieVariables): MutationPromise; +export function addFavoritedMovie(dc: DataConnect, vars: AddFavoritedMovieVariables): MutationPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function deleteFavoritedMovieRef(vars: DeleteFavoritedMovieVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function deleteFavoritedMovieRef(dc: DataConnect, vars: DeleteFavoritedMovieVariables): MutationRef; + +export function deleteFavoritedMovie(vars: DeleteFavoritedMovieVariables): MutationPromise; +export function deleteFavoritedMovie(dc: DataConnect, vars: DeleteFavoritedMovieVariables): MutationPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function addReviewRef(vars: AddReviewVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function addReviewRef(dc: DataConnect, vars: AddReviewVariables): MutationRef; + +export function addReview(vars: AddReviewVariables): MutationPromise; +export function addReview(dc: DataConnect, vars: AddReviewVariables): MutationPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function deleteReviewRef(vars: DeleteReviewVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function deleteReviewRef(dc: DataConnect, vars: DeleteReviewVariables): MutationRef; + +export function deleteReview(vars: DeleteReviewVariables): MutationPromise; +export function deleteReview(dc: DataConnect, vars: DeleteReviewVariables): MutationPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function listMoviesRef(vars?: ListMoviesVariables): QueryRef; +/* Allow users to pass in custom DataConnect instances */ +export function listMoviesRef(dc: DataConnect, vars?: ListMoviesVariables): QueryRef; + +export function listMovies(vars?: ListMoviesVariables): QueryPromise; +export function listMovies(dc: DataConnect, vars?: ListMoviesVariables): 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 getActorByIdRef(vars: GetActorByIdVariables): QueryRef; +/* Allow users to pass in custom DataConnect instances */ +export function getActorByIdRef(dc: DataConnect, vars: GetActorByIdVariables): QueryRef; + +export function getActorById(vars: GetActorByIdVariables): QueryPromise; +export function getActorById(dc: DataConnect, vars: GetActorByIdVariables): QueryPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function getCurrentUserRef(): QueryRef; +/* Allow users to pass in custom DataConnect instances */ +export function getCurrentUserRef(dc: DataConnect): QueryRef; + +export function getCurrentUser(): QueryPromise; +export function getCurrentUser(dc: DataConnect): QueryPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function getIfFavoritedMovieRef(vars: GetIfFavoritedMovieVariables): QueryRef; +/* Allow users to pass in custom DataConnect instances */ +export function getIfFavoritedMovieRef(dc: DataConnect, vars: GetIfFavoritedMovieVariables): QueryRef; + +export function getIfFavoritedMovie(vars: GetIfFavoritedMovieVariables): QueryPromise; +export function getIfFavoritedMovie(dc: DataConnect, vars: GetIfFavoritedMovieVariables): QueryPromise; + + +/* Allow users to create refs without passing in DataConnect */ +export function searchAllRef(vars: SearchAllVariables): QueryRef; +/* Allow users to pass in custom DataConnect instances */ +export function searchAllRef(dc: DataConnect, vars: SearchAllVariables): QueryRef; + +export function searchAll(vars: SearchAllVariables): QueryPromise; +export function searchAll(dc: DataConnect, vars: SearchAllVariables): QueryPromise; diff --git a/app/src/lib/dataconnect-sdk/package.json b/app/src/lib/dataconnect-sdk/package.json index 8af069b..e9234a2 100644 --- a/app/src/lib/dataconnect-sdk/package.json +++ b/app/src/lib/dataconnect-sdk/package.json @@ -17,9 +17,17 @@ "require": "./index.cjs.js", "default": "./esm/index.esm.js" }, + "./react": { + "types": "./react/index.d.ts", + "require": "./react/index.cjs.js", + "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": "^11.3.0", + "@tanstack-query-firebase/react": "^1.0.5", + "@tanstack/react-query": "^5" } } \ No newline at end of file diff --git a/app/src/lib/dataconnect-sdk/react/esm/index.esm.js b/app/src/lib/dataconnect-sdk/react/esm/index.esm.js new file mode 100644 index 0000000..39b51bc --- /dev/null +++ b/app/src/lib/dataconnect-sdk/react/esm/index.esm.js @@ -0,0 +1,80 @@ +import { upsertUserRef, addFavoritedMovieRef, deleteFavoritedMovieRef, addReviewRef, deleteReviewRef, listMoviesRef, getMovieByIdRef, getActorByIdRef, getCurrentUserRef, getIfFavoritedMovieRef, searchAllRef, connectorConfig } from '../../'; +import { validateArgs, CallerSdkTypeEnum } from 'firebase/data-connect'; +import { useDataConnectQuery, useDataConnectMutation } from '@tanstack-query-firebase/react/data-connect'; + +export function useUpsertUser(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return upsertUserRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +export function useAddFavoritedMovie(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return addFavoritedMovieRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +export function useDeleteFavoritedMovie(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return deleteFavoritedMovieRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +export function useAddReview(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return addReviewRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +export function useDeleteReview(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return deleteReviewRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + + +export function useListMovies(dcOrVars, vars, options) { + const { dc: dcInstance, vars: inputVars } = validateArgs(connectorConfig, dcOrVars, vars, false); + const ref = listMoviesRef(dcInstance, inputVars); + 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); +} + +export function useGetActorById(dcOrVars, vars, options) { + const { dc: dcInstance, vars: inputVars } = validateArgs(connectorConfig, dcOrVars, vars, false); + const ref = getActorByIdRef(dcInstance, inputVars); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} + +export function useGetCurrentUser(dc, options) { + const { dc: dcInstance } = validateArgs(connectorConfig, dc, undefined, false); + const ref = getCurrentUserRef(dcInstance); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} + +export function useGetIfFavoritedMovie(dcOrVars, vars, options) { + const { dc: dcInstance, vars: inputVars } = validateArgs(connectorConfig, dcOrVars, vars, false); + const ref = getIfFavoritedMovieRef(dcInstance, inputVars); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} + +export function useSearchAll(dcOrVars, vars, options) { + const { dc: dcInstance, vars: inputVars } = validateArgs(connectorConfig, dcOrVars, vars, false); + const ref = searchAllRef(dcInstance, inputVars); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} \ No newline at end of file diff --git a/app/src/lib/dataconnect-sdk/react/esm/package.json b/app/src/lib/dataconnect-sdk/react/esm/package.json new file mode 100644 index 0000000..7c34deb --- /dev/null +++ b/app/src/lib/dataconnect-sdk/react/esm/package.json @@ -0,0 +1 @@ +{"type":"module"} \ No newline at end of file diff --git a/app/src/lib/dataconnect-sdk/react/index.cjs.js b/app/src/lib/dataconnect-sdk/react/index.cjs.js new file mode 100644 index 0000000..b9c166d --- /dev/null +++ b/app/src/lib/dataconnect-sdk/react/index.cjs.js @@ -0,0 +1,80 @@ +const { upsertUserRef, addFavoritedMovieRef, deleteFavoritedMovieRef, addReviewRef, deleteReviewRef, listMoviesRef, getMovieByIdRef, getActorByIdRef, getCurrentUserRef, getIfFavoritedMovieRef, searchAllRef, connectorConfig } = require('../'); +const { validateArgs, CallerSdkTypeEnum } = require('firebase/data-connect'); +const { useDataConnectQuery, useDataConnectMutation } = require('@tanstack-query-firebase/react/data-connect'); + +exports.useUpsertUser = function useUpsertUser(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return upsertUserRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +exports.useAddFavoritedMovie = function useAddFavoritedMovie(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return addFavoritedMovieRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +exports.useDeleteFavoritedMovie = function useDeleteFavoritedMovie(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return deleteFavoritedMovieRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +exports.useAddReview = function useAddReview(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return addReviewRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + +exports.useDeleteReview = function useDeleteReview(dcOrOptions, options) { + const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options, false); + function refFactory(vars) { + return deleteReviewRef(dcInstance, vars); + } + return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact); +} + + +exports.useListMovies = function useListMovies(dcOrVars, vars, options) { + const { dc: dcInstance, vars: inputVars } = validateArgs(connectorConfig, dcOrVars, vars, false); + const ref = listMoviesRef(dcInstance, inputVars); + 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); +} + +exports.useGetActorById = function useGetActorById(dcOrVars, vars, options) { + const { dc: dcInstance, vars: inputVars } = validateArgs(connectorConfig, dcOrVars, vars, false); + const ref = getActorByIdRef(dcInstance, inputVars); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} + +exports.useGetCurrentUser = function useGetCurrentUser(dc, options) { + const { dc: dcInstance } = validateArgs(connectorConfig, dc, undefined, false); + const ref = getCurrentUserRef(dcInstance); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} + +exports.useGetIfFavoritedMovie = function useGetIfFavoritedMovie(dcOrVars, vars, options) { + const { dc: dcInstance, vars: inputVars } = validateArgs(connectorConfig, dcOrVars, vars, false); + const ref = getIfFavoritedMovieRef(dcInstance, inputVars); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} + +exports.useSearchAll = function useSearchAll(dcOrVars, vars, options) { + const { dc: dcInstance, vars: inputVars } = validateArgs(connectorConfig, dcOrVars, vars, false); + const ref = searchAllRef(dcInstance, inputVars); + return useDataConnectQuery(ref, options, CallerSdkTypeEnum.GeneratedReact); +} \ No newline at end of file diff --git a/app/src/lib/dataconnect-sdk/react/index.d.ts b/app/src/lib/dataconnect-sdk/react/index.d.ts new file mode 100644 index 0000000..20e54f1 --- /dev/null +++ b/app/src/lib/dataconnect-sdk/react/index.d.ts @@ -0,0 +1,38 @@ +import { UpsertUserData, UpsertUserVariables, AddFavoritedMovieData, AddFavoritedMovieVariables, DeleteFavoritedMovieData, DeleteFavoritedMovieVariables, AddReviewData, AddReviewVariables, DeleteReviewData, DeleteReviewVariables, ListMoviesData, ListMoviesVariables, GetMovieByIdData, GetMovieByIdVariables, GetActorByIdData, GetActorByIdVariables, GetCurrentUserData, GetIfFavoritedMovieData, GetIfFavoritedMovieVariables, SearchAllData, SearchAllVariables } 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'; +import { FirebaseError } from 'firebase/app'; + +export function useUpsertUser(options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, UpsertUserVariables>; +export function useUpsertUser(dc: DataConnect, options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, UpsertUserVariables>; + +export function useAddFavoritedMovie(options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, AddFavoritedMovieVariables>; +export function useAddFavoritedMovie(dc: DataConnect, options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, AddFavoritedMovieVariables>; + +export function useDeleteFavoritedMovie(options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, DeleteFavoritedMovieVariables>; +export function useDeleteFavoritedMovie(dc: DataConnect, options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, DeleteFavoritedMovieVariables>; + +export function useAddReview(options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, AddReviewVariables>; +export function useAddReview(dc: DataConnect, options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, AddReviewVariables>; + +export function useDeleteReview(options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, DeleteReviewVariables>; +export function useDeleteReview(dc: DataConnect, options?: useDataConnectMutationOptions): UseMutationResult, FirebaseError, DeleteReviewVariables>; + +export function useListMovies(vars: ListMoviesVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; +export function useListMovies(dc: DataConnect, vars: ListMoviesVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; + +export function useGetMovieById(vars: GetMovieByIdVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; +export function useGetMovieById(dc: DataConnect, vars: GetMovieByIdVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; + +export function useGetActorById(vars: GetActorByIdVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; +export function useGetActorById(dc: DataConnect, vars: GetActorByIdVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; + +export function useGetCurrentUser(options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; +export function useGetCurrentUser(dc: DataConnect, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; + +export function useGetIfFavoritedMovie(vars: GetIfFavoritedMovieVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; +export function useGetIfFavoritedMovie(dc: DataConnect, vars: GetIfFavoritedMovieVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; + +export function useSearchAll(vars: SearchAllVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; +export function useSearchAll(dc: DataConnect, vars: SearchAllVariables, options?: useDataConnectQueryOptions): UseQueryResult, FirebaseError>; diff --git a/app/src/lib/dataconnect-sdk/react/package.json b/app/src/lib/dataconnect-sdk/react/package.json new file mode 100644 index 0000000..f22cba4 --- /dev/null +++ b/app/src/lib/dataconnect-sdk/react/package.json @@ -0,0 +1,17 @@ +{ + "name": "@movie/dataconnect-react", + "version": "1.0.0", + "author": "Firebase (https://firebase.google.com/)", + "description": "Generated SDK For movie-connector", + "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/app/src/pages/Actor.tsx b/app/src/pages/Actor.tsx index 55de87b..c5b4128 100644 --- a/app/src/pages/Actor.tsx +++ b/app/src/pages/Actor.tsx @@ -19,17 +19,17 @@ import { useParams, Link, useNavigate } from 'react-router-dom'; import { onAuthStateChanged, User } from 'firebase/auth'; import { AuthContext } from '@/lib/firebase'; import NotFound from './NotFound'; -import { handleGetActorById } from '@/lib/MovieService'; +import { useHandleGetActorById } from '@/lib/MovieService'; export default function ActorPage() { const navigate = useNavigate(); const auth = useContext(AuthContext); - const [loading, setLoading] = useState(true); const { id } = useParams<{ id: string }>(); const actorId = id || ''; const [, setAuthUser] = useState(null); - const [actor, setActor] = useState(null); + const { error, isLoading, data } = useHandleGetActorById(actorId); + const actor = data?.actor; useEffect(() => { const unsubscribe = onAuthStateChanged(auth, (user) => { @@ -41,23 +41,11 @@ export default function ActorPage() { return () => unsubscribe(); }, [auth, actorId]); - useEffect(() => { - if (actorId) { - const fetchActor = async () => { - const actorData = await handleGetActorById(actorId); - if (actorData) { - setActor(actorData); - } else { - navigate('/not-found'); - } - setLoading(false); - }; - - fetchActor(); - } - }, [actorId, navigate]); - if (loading) return

Loading...

; + if (isLoading) return

Loading...

; + if(error) { + navigate('/not-found'); + } return actor ? (
@@ -116,3 +104,5 @@ export default function ActorPage() { ); } + + diff --git a/app/src/pages/AdvancedSearch.tsx b/app/src/pages/AdvancedSearch.tsx index 880c3a3..7d9f73e 100644 --- a/app/src/pages/AdvancedSearch.tsx +++ b/app/src/pages/AdvancedSearch.tsx @@ -19,15 +19,22 @@ import { Link } from 'react-router-dom'; import { FaSearch } from 'react-icons/fa'; import { MdStar } from 'react-icons/md'; import { handleSearchAll } from '@/lib/MovieService'; +import { SearchAllData } from '@/lib/dataconnect-sdk'; const genres = ['', 'action', 'crime', 'drama', 'sci-fi', 'thriller', 'adventure']; +interface SearchResults { +moviesMatchingTitle?: SearchAllData['moviesMatchingTitle']; + moviesMatchingDescription?: SearchAllData['moviesMatchingDescription'] + actors?: SearchAllData['actorsMatchingName']; + reviews?: SearchAllData['reviewsMatchingText']; +} export default function AdvancedSearchPage() { const [searchQuery, setSearchQuery] = useState(''); const [releaseYearRange, setReleaseYearRange] = useState({ min: 1900, max: 2030 }); const [genre, setGenre] = useState(''); const [ratingRange, setRatingRange] = useState({ min: 1, max: 10 }); - const [results, setResults] = useState({ + const [results, setResults] = useState({ moviesMatchingTitle: [], moviesMatchingDescription: [], actors: [], diff --git a/app/src/pages/Home.tsx b/app/src/pages/Home.tsx index 0bb83e6..b13c2ed 100644 --- a/app/src/pages/Home.tsx +++ b/app/src/pages/Home.tsx @@ -14,30 +14,25 @@ * limitations under the License. */ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import Carousel from '@/components/carousel'; -import { handleGetTopMovies, handleGetLatestMovies } from '@/lib/MovieService'; +import { OrderDirection } from '@/lib/dataconnect-sdk'; +import { useHandleLatestMovies, useHandleTopMovies } from '@/lib/MovieService'; export default function HomePage() { - const [topMovies, setTopMovies] = useState([]); - const [latestMovies, setLatestMovies] = useState([]); + const { data: topMoviesData, isLoading: topMoviesLoading } = useHandleTopMovies(10, OrderDirection.DESC ); + const { data: latestMoviesData, isLoading: latestMoviesLoading } = useHandleLatestMovies(10, OrderDirection.DESC); - useEffect(() => { - async function fetchMovies() { - const topMoviesData = await handleGetTopMovies(10); - const latestMoviesData = await handleGetLatestMovies(10); - - if (topMoviesData) setTopMovies(topMoviesData); - if (latestMoviesData) setLatestMovies(latestMoviesData); - } - - fetchMovies(); - }, []); + if(topMoviesLoading || latestMoviesLoading) { + return
Loading...
+ } return (
- - + +
); } + + diff --git a/app/src/pages/Movie.tsx b/app/src/pages/Movie.tsx index c4186e2..7265726 100644 --- a/app/src/pages/Movie.tsx +++ b/app/src/pages/Movie.tsx @@ -21,36 +21,60 @@ import { onAuthStateChanged, User } from "firebase/auth"; import { AuthContext } from "@/lib/firebase"; import NotFound from "./NotFound"; import { - handleGetMovieById, - handleGetIfFavoritedMovie, - handleAddFavoritedMovie, - handleDeleteFavoritedMovie, - handleAddReview, - handleDeleteReview, fetchSimilarMovies, + useHandleAddFavoritedMovie, + useHandleAddReview, + useHandleDeleteFavoritedMovie, + useHandleDeleteReview, + useHandleGetIfFavoritedMovie, + useHandleGetMovieById, } from "@/lib/MovieService"; import MovieCard from "@/components/moviecard"; +import { + DateString, + User_Key, + UUIDString, +} from "@/lib/dataconnect-sdk"; + +interface UserReview { + id: UUIDString; + reviewText?: string | null; + reviewDate: DateString; + rating?: number | null; + user: { + id: string; + username: string; + } & User_Key; +} export default function MoviePage() { const { id } = useParams() as { id: string }; const auth = useContext(AuthContext); - const [loading, setLoading] = useState(true); const [authUser, setAuthUser] = useState(null); - const [isFavorited, setIsFavorited] = useState(false); const [reviewText, setReviewText] = useState(""); const [rating, setRating] = useState(0); - const [movie, setMovie] = useState(null); - const [userReview, setUserReview] = useState(null); - const [similarMovies, setSimilarMovies] = useState([]); + const [userReview, setUserReview] = useState(null); + const [similarMovies, setSimilarMovies] = useState([]); + + const { data, isLoading, error } = useHandleGetMovieById(id); + const movie = data?.movie; + const { mutate: handleAddFavoritedMovie } = useHandleAddFavoritedMovie(id); + const { mutate: handleDeleteFavoritedMovie } = useHandleDeleteFavoritedMovie(id); + const { mutate: handleAddReview } = useHandleAddReview(id); + const { mutate: handleDeleteReview } = useHandleDeleteReview(); + const { data: favoritedMovieData } = useHandleGetIfFavoritedMovie( + id , + !!authUser + ); + const isFavorited = !!favoritedMovieData?.favorite_movie; // Fetch the movie details and check if it's favorited when the user is authenticated useEffect(() => { const unsubscribe = onAuthStateChanged(auth, (user) => { if (user) { setAuthUser(user); - handleGetIfFavoritedMovie(id).then(setIsFavorited); } }); @@ -60,25 +84,22 @@ export default function MoviePage() { // Fetch movie details and the user's review useEffect(() => { if (id) { - handleGetMovieById(id).then((movieData) => { - setMovie(movieData); - if (movieData?.reviews) { - const userReview = movieData.reviews.find( + if (movie) { + if (movie.reviews) { + const userReview = movie.reviews.find( (review) => review.user.id === authUser?.uid ); - fetchSimilarMovies(movieData.description).then((similarMovies) => { + fetchSimilarMovies(movie.description!).then((similarMovies) => { const similarResults = similarMovies?.filter( - (movie) => movie.id !== movieData.id + (movie) => movie.id !== movie.id ); setSimilarMovies( similarResults && similarResults.length > 1 ? similarResults : [] ); - setMovie(movieData); }); setUserReview(userReview || null); } - setLoading(false); - }); + } } }, [id, authUser]); @@ -90,11 +111,10 @@ export default function MoviePage() { try { if (isFavorited) { - await handleDeleteFavoritedMovie(id); + await handleDeleteFavoritedMovie({ movieId: id }); } else { - await handleAddFavoritedMovie(id); + await handleAddFavoritedMovie({ movieId: id }); } - setIsFavorited(!isFavorited); } catch (error) { console.error("Error updating favorite status:", error); } @@ -106,11 +126,11 @@ export default function MoviePage() { if (!authUser) return; try { - await handleAddReview(id, rating, reviewText); + await handleAddReview({ movieId: id, rating, reviewText }); setReviewText(""); setRating(0); - const updatedMovie = await handleGetMovieById(id); - setMovie(updatedMovie); + // const updatedMovie = await handleGetMovieById(id); + // setMovie(updatedMovie); } catch (error) { console.error("Error submitting review:", error); } @@ -123,17 +143,15 @@ export default function MoviePage() { if (!authUser || !userReview) return; try { - await handleDeleteReview(id); + await handleDeleteReview({ movieId: id }); setUserReview(null); - const updatedMovie = await handleGetMovieById(id); - setMovie(updatedMovie); } catch (error) { console.error("Error deleting review:", error); } }; - if (loading) return

Loading...

; - if (!movie) return ; + if (isLoading) return

Loading...

; + if (error || !movie) return ; return (
@@ -301,3 +319,5 @@ export default function MoviePage() {
); } + + diff --git a/app/src/pages/MyProfile.tsx b/app/src/pages/MyProfile.tsx index ac9741c..0a6ccb6 100644 --- a/app/src/pages/MyProfile.tsx +++ b/app/src/pages/MyProfile.tsx @@ -17,7 +17,7 @@ import React, { useContext, useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { onAuthStateChanged, User } from "firebase/auth"; -import { handleGetCurrentUser, handleDeleteReview } from "@/lib/MovieService"; +import { useHandleDeleteReview, useHandleGetCurrentUser} from "@/lib/MovieService"; import { MdStar } from "react-icons/md"; import { AuthContext } from "@/lib/firebase"; import MovieCard from "@/components/moviecard"; @@ -25,16 +25,15 @@ import MovieCard from "@/components/moviecard"; export default function MyProfilePage() { const navigate = useNavigate(); const [authUser, setAuthUser] = useState(null); - const [loading, setLoading] = useState(true); const auth = useContext(AuthContext); - const [user, setUser] = useState(null); - + const {mutate: handleDeleteReview } = useHandleDeleteReview(); + const { data: userData, isLoading, refetch } = useHandleGetCurrentUser(!!authUser); + const user = userData?.user; useEffect(() => { const unsubscribe = onAuthStateChanged(auth, (user) => { if (user) { setAuthUser(user); - loadUserProfile(); } else { navigate("/"); } @@ -43,28 +42,18 @@ export default function MyProfilePage() { return () => unsubscribe(); }, [navigate, auth]); - async function loadUserProfile() { - try { - const userProfile = await handleGetCurrentUser(); - setUser(userProfile); - } catch (error) { - console.error("Error loading user profile:", error); - } finally { - setLoading(false); - } - } async function deleteReview(reviewMovieId: string) { if (!authUser) return; try { - await handleDeleteReview(reviewMovieId); - loadUserProfile(); + await handleDeleteReview({movieId: reviewMovieId}); + refetch(); } catch (error) { console.error("Error deleting review:", error); } } - if (loading) return

Loading...

; + if (isLoading) return

Loading...

; if (!user) return

User not found.

; return ( diff --git a/app/src/pages/VectorSearch.tsx b/app/src/pages/VectorSearch.tsx index 8a1a5c4..988e304 100644 --- a/app/src/pages/VectorSearch.tsx +++ b/app/src/pages/VectorSearch.tsx @@ -22,7 +22,7 @@ export default function VectorSearchPage() { const [query, setQuery] = useState(''); const [loading, setLoading] = useState(false); - const [results, setResults] = useState([]); + const [results, setResults] = useState([]); async function handleSearch(e: React.FormEvent) { e.preventDefault(); diff --git a/app/tsconfig.json b/app/tsconfig.json index 7c235bb..4ddeb3c 100644 --- a/app/tsconfig.json +++ b/app/tsconfig.json @@ -17,8 +17,9 @@ "noEmit": true, "esModuleInterop": true, "module": "esnext", - "moduleResolution": "node", + "moduleResolution": "bundler", "resolveJsonModule": true, + "strictNullChecks": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, diff --git a/dataconnect/movie-connector/connector.yaml b/dataconnect/movie-connector/connector.yaml index a214dfe..c8f74c1 100644 --- a/dataconnect/movie-connector/connector.yaml +++ b/dataconnect/movie-connector/connector.yaml @@ -18,3 +18,4 @@ generate: package: "@movie/dataconnect" outputDir: ../../app/src/lib/dataconnect-sdk packageJsonDir: "../../app" + react: true diff --git a/dataconnect/movie-connector/mutations.gql b/dataconnect/movie-connector/mutations.gql index e8c3e63..f4acd09 100644 --- a/dataconnect/movie-connector/mutations.gql +++ b/dataconnect/movie-connector/mutations.gql @@ -15,19 +15,44 @@ # Upsert (update or insert) a user based on their username # TODO: Complete UpsertUser +# Create or update the current authenticated user +mutation UpsertUser($username: String!) @auth(level: USER) { + user_upsert( + data: { + id_expr: "auth.uid" + username: $username + } + ) +} # Add a movie to the user's favorites list -# TODO: Complete AddFavoritedMovie +mutation AddFavoritedMovie($movieId: UUID!) @auth(level: USER) { + favorite_movie_upsert(data: { userId_expr: "auth.uid", movieId: $movieId }) +} # Remove a movie from the user's favorites list -# TODO: Complete DeleteFavoritedMovie +mutation DeleteFavoritedMovie($movieId: UUID!) @auth(level: USER) { + favorite_movie_delete(key: { userId_expr: "auth.uid", movieId: $movieId }) +} # Add a review for a movie -# TODO: Complete AddReview +mutation AddReview($movieId: UUID!, $rating: Int!, $reviewText: String!) +@auth(level: USER) { + review_insert( + data: { + userId_expr: "auth.uid" + movieId: $movieId + rating: $rating + reviewText: $reviewText + reviewDate_date: { today: true } + } + ) +} # Delete a user's review for a movie -# TODO: Complete DeleteReview - +mutation DeleteReview($movieId: UUID!) @auth(level: USER) { + review_delete(key: { userId_expr: "auth.uid", movieId: $movieId }) +} # The mutations below are unused by the application, but are useful examples for more complex cases diff --git a/dataconnect/movie-connector/queries.gql b/dataconnect/movie-connector/queries.gql index c05306d..b6c644a 100644 --- a/dataconnect/movie-connector/queries.gql +++ b/dataconnect/movie-connector/queries.gql @@ -15,33 +15,204 @@ # List subset of fields for movies # TODO: Update ListMovies -# query ListMovies @auth(level: PUBLIC) { -# movies{ -# id -# title -# imageUrl -# releaseYear -# genre -# rating -# tags -# description -# } -# } +# +# List subset of fields for movies +query ListMovies($orderByRating: OrderDirection, $orderByReleaseYear: OrderDirection, $limit: Int) @auth(level: PUBLIC) { + movies( + orderBy: [ + { rating: $orderByRating }, + { releaseYear: $orderByReleaseYear } + ] + limit: $limit + ) { + id + title + imageUrl + releaseYear + genre + rating + tags + description + } +} # Get movie by id # TODO: Complete GetMovieById +# Get movie by id +query GetMovieById($id: UUID!) @auth(level: PUBLIC) { +movie(id: $id) { + id + title + imageUrl + releaseYear + genre + rating + description + tags + metadata: movieMetadatas_on_movie { + director + } + mainActors: actors_via_MovieActor(where: { role: { eq: "main" } }) { + id + name + imageUrl + } + supportingActors: actors_via_MovieActor( + where: { role: { eq: "supporting" } } + ) { + id + name + imageUrl + } + reviews: reviews_on_movie { + id + reviewText + reviewDate + rating + user { + id + username + } + } + } +} # Get actor by id # TODO: Complete GetActorById +query GetActorById($id: UUID!) @auth(level: PUBLIC) { + actor(id: $id) { + id + name + imageUrl + mainActors: movies_via_MovieActor(where: { role: { eq: "main" } }) { + id + title + genre + tags + imageUrl + } + supportingActors: movies_via_MovieActor( + where: { role: { eq: "supporting" } } + ) { + id + title + genre + tags + imageUrl + } + } +} + + # Get current authenticated user -# TODO: Complete GetCurrentUser +query GetCurrentUser @auth(level: USER) { + user(key: { id_expr: "auth.uid" }) { + id + username + reviews: reviews_on_user { + id + rating + reviewDate + reviewText + movie { + id + title + } + } + favoriteMovies: favorite_movies_on_user { + movie { + id + title + genre + imageUrl + releaseYear + rating + description + tags + metadata: movieMetadatas_on_movie { + director + } + } + } + } +} -# Check if a movie is favorited by user -# TODO: Complete GetIfFavoritedMovie +query GetIfFavoritedMovie($movieId: UUID!) @auth(level: USER) { + favorite_movie(key: { userId_expr: "auth.uid", movieId: $movieId }) { + movieId + } +} # Search for movies, actors, and reviews # TODO: Complete SearchAll +# Search for movies, actors, and reviews +query SearchAll( + $input: String + $minYear: Int! + $maxYear: Int! + $minRating: Float! + $maxRating: Float! + $genre: String! +) @auth(level: PUBLIC) { + moviesMatchingTitle: movies( + where: { + _and: [ + { releaseYear: { ge: $minYear } } + { releaseYear: { le: $maxYear } } + { rating: { ge: $minRating } } + { rating: { le: $maxRating } } + { genre: { contains: $genre } } + { title: { contains: $input } } + ] + } + ) { + id + title + genre + rating + imageUrl + tags + } + moviesMatchingDescription: movies( + where: { + _and: [ + { releaseYear: { ge: $minYear } } + { releaseYear: { le: $maxYear } } + { rating: { ge: $minRating } } + { rating: { le: $maxRating } } + { genre: { contains: $genre } } + { description: { contains: $input } } + ] + } + ) { + id + title + genre + rating + imageUrl + tags + } + actorsMatchingName: actors(where: { name: { contains: $input } }) { + id + name + imageUrl + } + reviewsMatchingText: reviews(where: { reviewText: { contains: $input } }) { + id + rating + reviewText + reviewDate + movie { + id + title + } + user { + id + username + } + } +} # Search movie descriptions using L2 similarity with Vertex AI # TODO: Complete SearchMovieDescriptionUsingL2Similarity diff --git a/dataconnect/schema/schema.gql b/dataconnect/schema/schema.gql index 6dac321..7d8b594 100644 --- a/dataconnect/schema/schema.gql +++ b/dataconnect/schema/schema.gql @@ -14,29 +14,86 @@ # Movies # TODO: Fill out Movie table +type Movie + @table { + id: UUID! @default(expr: "uuidV4()") + title: String! + imageUrl: String! + releaseYear: Int + genre: String + rating: Float + description: String + tags: [String] +} # Movie Metadata # Movie - MovieMetadata is a one-to-one relationship # TODO: Fill out MovieMetadata table +type MovieMetadata + @table { + # @ref creates a field in the current table (MovieMetadata) + # It is a reference that holds the primary key of the referenced type + # In this case, @ref(fields: "movieId", references: "id") is implied + movie: Movie! @ref + # movieId: UUID <- this is created by the above @ref + director: String +} # Actors # Suppose an actor can participate in multiple movies and movies can have multiple actors # Movie - Actors (or vice versa) is a many to many relationship # TODO: Fill out Actor table +type Actor @table { + id: UUID! + imageUrl: String! + name: String! @col(name: "name", dataType: "varchar(30)") +} # Join table for many-to-many relationship for movies and actors # The 'key' param signifies the primary key(s) of this table # In this case, the keys are [movieId, actorId], the generated fields of the reference types [movie, actor] # TODO: Fill out MovieActor table +type MovieActor @table(key: ["movie", "actor"]) { + # @ref creates a field in the current table (MovieActor) that holds the primary key of the referenced type + # In this case, @ref(fields: "id") is implied + movie: Movie! + # movieId: UUID! <- this is created by the implied @ref, see: implicit.gql + + actor: Actor! + # actorId: UUID! <- this is created by the implied @ref, see: implicit.gql + + role: String! # "main" or "supporting" +} # 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 # TODO: Fill out User table +type User + @table { + id: String! @col(name: "auth_uid") + username: String! @col(dataType: "varchar(50)") + # The following are generated from the @ref in the Review table + # reviews_on_user + # movies_via_Review +} # Join table for many-to-many relationship for users and favorite movies # TODO: Fill out FavoriteMovie table +type FavoriteMovie + @table(name: "FavoriteMovies", singular: "favorite_movie", plural: "favorite_movies", key: ["user", "movie"]) { + # @ref is implicit + user: User! + movie: Movie! +} # Reviews # TODO: Fill out Review table - +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") +}