From 47cab3fd69a77f95cb791cf16fbbea2c6b0d1bda Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 28 Mar 2025 12:38:10 -0700 Subject: [PATCH 01/10] Fixed issue where updated variables weren't getting picked up --- .../js/default-connector/README.md | 36 ++++----- .../js/default-connector/index.cjs.js | 15 ++++ packages/react/package.json | 4 + .../data-connect/useDataConnectQuery.test.tsx | 40 ++++++++++ .../src/data-connect/useDataConnectQuery.ts | 33 +++++--- pnpm-lock.yaml | 78 +++++++++++++++++++ 6 files changed, 178 insertions(+), 28 deletions(-) diff --git a/dataconnect-sdk/js/default-connector/README.md b/dataconnect-sdk/js/default-connector/README.md index c3d1ddb..0c66142 100644 --- a/dataconnect-sdk/js/default-connector/README.md +++ b/dataconnect-sdk/js/default-connector/README.md @@ -28,7 +28,7 @@ A connector is a collection of Queries and Mutations. One SDK is generated for e You can find more information about connectors in the [Data Connect documentation](https://firebase.google.com/docs/data-connect#how-does). ```javascript -import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig } from '@dataconnect/default-connector'; const dataConnect = getDataConnect(connectorConfig); @@ -41,7 +41,7 @@ To connect to the emulator, you can use the following code. You can also follow the emulator instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#instrument-clients). ```javascript -import { connectDataConnectEmulator, getDataConnect, DataConnect } from 'firebase/data-connect'; +import { connectDataConnectEmulator, getDataConnect } from 'firebase/data-connect'; import { connectorConfig } from '@dataconnect/default-connector'; const dataConnect = getDataConnect(connectorConfig); @@ -98,7 +98,7 @@ export interface ListMoviesData { ### Using `ListMovies`'s action shortcut function ```javascript -import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig, listMovies } from '@dataconnect/default-connector'; @@ -122,7 +122,7 @@ listMovies().then((response) => { ### Using `ListMovies`'s `QueryRef` function ```javascript -import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; +import { getDataConnect, executeQuery } from 'firebase/data-connect'; import { connectorConfig, listMoviesRef } from '@dataconnect/default-connector'; @@ -185,7 +185,7 @@ export interface GetMovieByIdData { ### Using `GetMovieById`'s action shortcut function ```javascript -import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig, getMovieById, GetMovieByIdVariables } from '@dataconnect/default-connector'; // The `GetMovieById` query requires an argument of type `GetMovieByIdVariables`: @@ -215,7 +215,7 @@ getMovieById(getMovieByIdVars).then((response) => { ### Using `GetMovieById`'s `QueryRef` function ```javascript -import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; +import { getDataConnect, executeQuery } from 'firebase/data-connect'; import { connectorConfig, getMovieByIdRef, GetMovieByIdVariables } from '@dataconnect/default-connector'; // The `GetMovieById` query requires an argument of type `GetMovieByIdVariables`: @@ -275,7 +275,7 @@ export interface GetMetaData { ### Using `GetMeta`'s action shortcut function ```javascript -import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig, getMeta } from '@dataconnect/default-connector'; @@ -299,7 +299,7 @@ getMeta().then((response) => { ### Using `GetMeta`'s `QueryRef` function ```javascript -import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; +import { getDataConnect, executeQuery } from 'firebase/data-connect'; import { connectorConfig, getMetaRef } from '@dataconnect/default-connector'; @@ -374,7 +374,7 @@ export interface CreateMovieData { ### Using `CreateMovie`'s action shortcut function ```javascript -import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig, createMovie, CreateMovieVariables } from '@dataconnect/default-connector'; // The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: @@ -406,7 +406,7 @@ createMovie(createMovieVars).then((response) => { ### Using `CreateMovie`'s `MutationRef` function ```javascript -import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { getDataConnect, executeMutation } from 'firebase/data-connect'; import { connectorConfig, createMovieRef, CreateMovieVariables } from '@dataconnect/default-connector'; // The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: @@ -474,7 +474,7 @@ export interface UpsertMovieData { ### Using `UpsertMovie`'s action shortcut function ```javascript -import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig, upsertMovie, UpsertMovieVariables } from '@dataconnect/default-connector'; // The `UpsertMovie` mutation requires an argument of type `UpsertMovieVariables`: @@ -506,7 +506,7 @@ upsertMovie(upsertMovieVars).then((response) => { ### Using `UpsertMovie`'s `MutationRef` function ```javascript -import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { getDataConnect, executeMutation } from 'firebase/data-connect'; import { connectorConfig, upsertMovieRef, UpsertMovieVariables } from '@dataconnect/default-connector'; // The `UpsertMovie` mutation requires an argument of type `UpsertMovieVariables`: @@ -572,7 +572,7 @@ export interface DeleteMovieData { ### Using `DeleteMovie`'s action shortcut function ```javascript -import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig, deleteMovie, DeleteMovieVariables } from '@dataconnect/default-connector'; // The `DeleteMovie` mutation requires an argument of type `DeleteMovieVariables`: @@ -602,7 +602,7 @@ deleteMovie(deleteMovieVars).then((response) => { ### Using `DeleteMovie`'s `MutationRef` function ```javascript -import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { getDataConnect, executeMutation } from 'firebase/data-connect'; import { connectorConfig, deleteMovieRef, DeleteMovieVariables } from '@dataconnect/default-connector'; // The `DeleteMovie` mutation requires an argument of type `DeleteMovieVariables`: @@ -660,7 +660,7 @@ export interface AddMetaData { ### Using `AddMeta`'s action shortcut function ```javascript -import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig, addMeta } from '@dataconnect/default-connector'; @@ -684,7 +684,7 @@ addMeta().then((response) => { ### Using `AddMeta`'s `MutationRef` function ```javascript -import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { getDataConnect, executeMutation } from 'firebase/data-connect'; import { connectorConfig, addMetaRef } from '@dataconnect/default-connector'; @@ -742,7 +742,7 @@ export interface DeleteMetaData { ### Using `DeleteMeta`'s action shortcut function ```javascript -import { getDataConnect, DataConnect } from 'firebase/data-connect'; +import { getDataConnect } from 'firebase/data-connect'; import { connectorConfig, deleteMeta, DeleteMetaVariables } from '@dataconnect/default-connector'; // The `DeleteMeta` mutation requires an argument of type `DeleteMetaVariables`: @@ -772,7 +772,7 @@ deleteMeta(deleteMetaVars).then((response) => { ### Using `DeleteMeta`'s `MutationRef` function ```javascript -import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; +import { getDataConnect, executeMutation } from 'firebase/data-connect'; import { connectorConfig, deleteMetaRef, DeleteMetaVariables } from '@dataconnect/default-connector'; // The `DeleteMeta` mutation requires an argument of type `DeleteMetaVariables`: diff --git a/dataconnect-sdk/js/default-connector/index.cjs.js b/dataconnect-sdk/js/default-connector/index.cjs.js index 6fa0628..84b7ed0 100644 --- a/dataconnect-sdk/js/default-connector/index.cjs.js +++ b/dataconnect-sdk/js/default-connector/index.cjs.js @@ -12,62 +12,77 @@ exports.createMovieRef = function createMovieRef(dcOrVars, vars) { dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'CreateMovie', inputVars); } + exports.createMovie = function createMovie(dcOrVars, vars) { return executeMutation(createMovieRef(dcOrVars, vars)); }; + exports.upsertMovieRef = function upsertMovieRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'UpsertMovie', inputVars); } + exports.upsertMovie = function upsertMovie(dcOrVars, vars) { return executeMutation(upsertMovieRef(dcOrVars, vars)); }; + exports.deleteMovieRef = function deleteMovieRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'DeleteMovie', inputVars); } + exports.deleteMovie = function deleteMovie(dcOrVars, vars) { return executeMutation(deleteMovieRef(dcOrVars, vars)); }; + exports.addMetaRef = function addMetaRef(dc) { const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'AddMeta'); } + exports.addMeta = function addMeta(dc) { return executeMutation(addMetaRef(dc)); }; + exports.deleteMetaRef = function deleteMetaRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'DeleteMeta', inputVars); } + exports.deleteMeta = function deleteMeta(dcOrVars, vars) { return executeMutation(deleteMetaRef(dcOrVars, vars)); }; + exports.listMoviesRef = function listMoviesRef(dc) { const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'ListMovies'); } + exports.listMovies = function listMovies(dc) { return executeQuery(listMoviesRef(dc)); }; + 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.getMetaRef = function getMetaRef(dc) { const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'GetMeta'); } + exports.getMeta = function getMeta(dc) { return executeQuery(getMetaRef(dc)); }; diff --git a/packages/react/package.json b/packages/react/package.json index cdbc12f..a1c11e2 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -46,5 +46,9 @@ "peerDependencies": { "@tanstack/react-query": "^5", "firebase": "^11.3.0" + }, + "dependencies": { + "@types/deep-equal": "^1.0.4", + "deep-equal": "^2.2.3" } } diff --git a/packages/react/src/data-connect/useDataConnectQuery.test.tsx b/packages/react/src/data-connect/useDataConnectQuery.test.tsx index 3054bb1..dfe7c92 100644 --- a/packages/react/src/data-connect/useDataConnectQuery.test.tsx +++ b/packages/react/src/data-connect/useDataConnectQuery.test.tsx @@ -269,4 +269,44 @@ describe("useDataConnectQuery", () => { { id: movieId }, ]); }); + + test("fetches new data when variables change", async () => { + const movieData1 = { + title: "tanstack query firebase 1", + genre: "library 1", + imageUrl: "https://invertase.io/1", + }; + const createdMovie = await createMovie(movieData1); + const movieData2 = { + title: "tanstack query firebase 2", + genre: "library 2", + imageUrl: "https://invertase.io/2", + }; + const createdMovie2 = await createMovie(movieData2); + + const movieId = createdMovie?.data?.movie_insert?.id; + const movieId2 = createdMovie2?.data?.movie_insert?.id; + getMovieByIdRef({ id: movieId2 }); + const ref = getMovieByIdRef({ id: movieId }); + const { result } = renderHook(() => useDataConnectQuery(ref), { + wrapper, + }); + + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + expect(result.current.data?.movie?.title).toBe(movieData1?.title); + expect(result.current.data?.movie?.genre).toBe(movieData1?.genre); + expect(result.current.data?.movie?.imageUrl).toBe(movieData1?.imageUrl); + }); + await act(async () => { + ref.variables.id = createdMovie2.data.movie_insert.id; + result.current.refetch(); + }); + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + expect(result.current.data?.movie?.title).toBe(movieData2?.title); + expect(result.current.data?.movie?.genre).toBe(movieData2?.genre); + expect(result.current.data?.movie?.imageUrl).toBe(movieData2?.imageUrl); + }); + }); }); diff --git a/packages/react/src/data-connect/useDataConnectQuery.ts b/packages/react/src/data-connect/useDataConnectQuery.ts index de0198e..5cc4324 100644 --- a/packages/react/src/data-connect/useDataConnectQuery.ts +++ b/packages/react/src/data-connect/useDataConnectQuery.ts @@ -3,6 +3,7 @@ import { type UseQueryOptions, useQuery, } from "@tanstack/react-query"; +import deepEqual from "deep-equal"; import type { FirebaseError } from "firebase/app"; import { type CallerSdkType, @@ -11,7 +12,7 @@ import { type QueryResult, executeQuery, } from "firebase/data-connect"; -import { useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import type { PartialBy } from "../../utils"; import type { QueryResultRequiredRef, @@ -22,6 +23,11 @@ export type useDataConnectQueryOptions< TData = object, TError = FirebaseError, > = PartialBy, "queryFn">, "queryKey">; +function getRef( + refOrResult: QueryRef | QueryResult, +): QueryRef { + return "ref" in refOrResult ? refOrResult.ref : refOrResult; +} export function useDataConnectQuery( refOrResult: QueryRef | QueryResult, @@ -31,17 +37,24 @@ export function useDataConnectQuery( const [dataConnectResult, setDataConnectResult] = useState< QueryResultRequiredRef >("ref" in refOrResult ? refOrResult : { ref: refOrResult }); + const [ref, setRef] = useState(dataConnectResult.ref); // TODO(mtewani): in the future we should allow for users to pass in `QueryResult` objects into `initialData`. - let initialData: Data | InitialDataFunction | undefined; - const { ref } = dataConnectResult; + const [initialData] = useState( + dataConnectResult.data || options?.initialData, + ); - if ("ref" in refOrResult) { - initialData = { - ...refOrResult.data, - }; - } else { - initialData = options?.initialData; - } + useEffect(() => { + setRef((oldRef) => { + const newRef = getRef(refOrResult); + if ( + newRef.name !== oldRef.name || + !deepEqual(oldRef, newRef, { strict: true }) + ) { + return newRef; + } + return oldRef; + }); + }, [refOrResult]); // @ts-expect-error function is hidden under `DataConnect`. ref.dataConnect._setCallerSdkType(_callerSdkType); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f74bb3a..6596518 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -152,6 +152,12 @@ importers: '@tanstack/react-query': specifier: ^5 version: 5.66.9(react@19.0.0) + '@types/deep-equal': + specifier: ^1.0.4 + version: 1.0.4 + deep-equal: + specifier: ^2.2.3 + version: 2.2.3 firebase: specifier: ^11.3.0 version: 11.3.1 @@ -1358,6 +1364,9 @@ packages: '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + '@types/deep-equal@1.0.4': + resolution: {integrity: sha512-tqdiS4otQP4KmY0PR3u6KbZ5EWvhNdUoS/jc93UuK23C220lOZ/9TvjfxdPcKvqwwDVtmtSCrnr0p/2dirAxkA==} + '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -1776,6 +1785,10 @@ packages: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} + deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -1850,6 +1863,9 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + es-iterator-helpers@1.2.1: resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} engines: {node: '>= 0.4'} @@ -2213,6 +2229,10 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} @@ -2604,6 +2624,10 @@ packages: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -2987,6 +3011,10 @@ packages: std-env@3.8.0: resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} @@ -4436,6 +4464,8 @@ snapshots: '@types/aria-query@5.0.4': {} + '@types/deep-equal@1.0.4': {} + '@types/estree@1.0.6': {} '@types/json-schema@7.0.15': {} @@ -4915,6 +4945,27 @@ snapshots: deep-eql@5.0.2: {} + deep-equal@2.2.3: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + es-get-iterator: 1.1.3 + get-intrinsic: 1.3.0 + is-arguments: 1.2.0 + is-array-buffer: 3.0.5 + is-date-object: 1.1.0 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + isarray: 2.0.5 + object-is: 1.1.6 + object-keys: 1.1.1 + object.assign: 4.1.7 + regexp.prototype.flags: 1.5.4 + side-channel: 1.1.0 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.18 + deep-is@0.1.4: {} defaults@1.0.4: @@ -5031,6 +5082,18 @@ snapshots: es-errors@1.3.0: {} + es-get-iterator@1.1.3: + dependencies: + call-bind: 1.0.8 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + is-arguments: 1.2.0 + is-map: 2.0.3 + is-set: 2.0.3 + is-string: 1.1.1 + isarray: 2.0.5 + stop-iteration-iterator: 1.1.0 + es-iterator-helpers@1.2.1: dependencies: call-bind: 1.0.8 @@ -5564,6 +5627,11 @@ snapshots: hasown: 2.0.2 side-channel: 1.1.0 + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.3 + has-tostringtag: 1.0.2 + is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 @@ -5947,6 +6015,11 @@ snapshots: object-inspect@1.13.4: {} + object-is@1.1.6: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + object-keys@1.1.1: {} object.assign@4.1.7: @@ -6393,6 +6466,11 @@ snapshots: std-env@3.8.0: {} + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + streamsearch@1.1.0: {} string-width@4.2.3: From 5f83600026f452639f47c289c06007c7d63642cd Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 7 Apr 2025 15:32:52 -0700 Subject: [PATCH 02/10] Completed docs site for angular --- biome.json | 1 + .../js/default-connector/index.cjs.js | 24 ++-- docs.json | 36 ++++++ .../functions/injectDataConnectMutation.mdx | 42 +++++++ .../functions/injectDataConnectQuery.mdx | 43 +++++++ docs/angular/data-connect/index.mdx | 117 ++++++++++++++++++ docs/angular/data-connect/mutations.mdx | 102 +++++++++++++++ docs/angular/data-connect/querying.mdx | 81 ++++++++++++ docs/angular/index.mdx | 92 ++++++++++++++ docs/react/data-connect/querying.mdx | 2 +- 10 files changed, 531 insertions(+), 9 deletions(-) create mode 100644 docs/angular/data-connect/functions/injectDataConnectMutation.mdx create mode 100644 docs/angular/data-connect/functions/injectDataConnectQuery.mdx create mode 100644 docs/angular/data-connect/index.mdx create mode 100644 docs/angular/data-connect/mutations.mdx create mode 100644 docs/angular/data-connect/querying.mdx create mode 100644 docs/angular/index.mdx diff --git a/biome.json b/biome.json index 64c9952..6a9ce33 100644 --- a/biome.json +++ b/biome.json @@ -18,6 +18,7 @@ }, "linter": { "enabled": true, + "ignore": ["node_modules/**"], "rules": { "recommended": true, "style": { diff --git a/dataconnect-sdk/js/default-connector/index.cjs.js b/dataconnect-sdk/js/default-connector/index.cjs.js index 84b7ed0..eeb404a 100644 --- a/dataconnect-sdk/js/default-connector/index.cjs.js +++ b/dataconnect-sdk/js/default-connector/index.cjs.js @@ -7,81 +7,89 @@ const connectorConfig = { }; exports.connectorConfig = connectorConfig; -exports.createMovieRef = function createMovieRef(dcOrVars, vars) { +function createMovieRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'CreateMovie', inputVars); } +exports.createMovieRef = createMovieRef; exports.createMovie = function createMovie(dcOrVars, vars) { return executeMutation(createMovieRef(dcOrVars, vars)); }; -exports.upsertMovieRef = function upsertMovieRef(dcOrVars, vars) { +function upsertMovieRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'UpsertMovie', inputVars); } +exports.upsertMovieRef = upsertMovieRef; exports.upsertMovie = function upsertMovie(dcOrVars, vars) { return executeMutation(upsertMovieRef(dcOrVars, vars)); }; -exports.deleteMovieRef = function deleteMovieRef(dcOrVars, vars) { +function deleteMovieRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'DeleteMovie', inputVars); } +exports.deleteMovieRef = deleteMovieRef; exports.deleteMovie = function deleteMovie(dcOrVars, vars) { return executeMutation(deleteMovieRef(dcOrVars, vars)); }; -exports.addMetaRef = function addMetaRef(dc) { +function addMetaRef(dc) { const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'AddMeta'); } +exports.addMetaRef = addMetaRef; exports.addMeta = function addMeta(dc) { return executeMutation(addMetaRef(dc)); }; -exports.deleteMetaRef = function deleteMetaRef(dcOrVars, vars) { +function deleteMetaRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'DeleteMeta', inputVars); } +exports.deleteMetaRef = deleteMetaRef; exports.deleteMeta = function deleteMeta(dcOrVars, vars) { return executeMutation(deleteMetaRef(dcOrVars, vars)); }; -exports.listMoviesRef = function listMoviesRef(dc) { +function listMoviesRef(dc) { const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'ListMovies'); } +exports.listMoviesRef = listMoviesRef; exports.listMovies = function listMovies(dc) { return executeQuery(listMoviesRef(dc)); }; -exports.getMovieByIdRef = function getMovieByIdRef(dcOrVars, vars) { +function getMovieByIdRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'GetMovieById', inputVars); } +exports.getMovieByIdRef = getMovieByIdRef; exports.getMovieById = function getMovieById(dcOrVars, vars) { return executeQuery(getMovieByIdRef(dcOrVars, vars)); }; -exports.getMetaRef = function getMetaRef(dc) { +function getMetaRef(dc) { const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'GetMeta'); } +exports.getMetaRef = getMetaRef; exports.getMeta = function getMeta(dc) { return executeQuery(getMetaRef(dc)); diff --git a/docs.json b/docs.json index 43f4d40..25aa215 100644 --- a/docs.json +++ b/docs.json @@ -15,6 +15,11 @@ "id": "react", "title": "React", "href": "/react" + }, + { + "id": "angular", + "title": "Angular", + "href": "/angular" } ], "sidebar": [ @@ -42,6 +47,37 @@ } ] }, + { + "tab": "angular", + "group": "Data Connect", + "pages": [ + { + "title": "Getting Started", + "href": "/angular/data-connect" + }, + { + "title": "Querying", + "href": "/angular/data-connect/querying" + }, + { + "title": "Mutations", + "href": "/angular/data-connect/mutations" + }, + { + "group": "functions", + "pages": [ + { + "title": "injectDataConnectQuery", + "href": "/angular/data-connect/functions/injectDataConnectQuery" + }, + { + "title": "injectDataConnectMutation", + "href": "/angular/data-connect/functions/injectDataConnectMutation" + } + ] + } + ] + }, { "tab": "react", "group": "Authentication", diff --git a/docs/angular/data-connect/functions/injectDataConnectMutation.mdx b/docs/angular/data-connect/functions/injectDataConnectMutation.mdx new file mode 100644 index 0000000..eaa6292 --- /dev/null +++ b/docs/angular/data-connect/functions/injectDataConnectMutation.mdx @@ -0,0 +1,42 @@ +--- +title: injectDataConnectMutation +--- + +`injectDataConnectMutation` is a hook designed to simplify handling mutations (creating, updating, deleting) with Firebase Data Connect. + +See [mutations](/react/data-connect/mutations) for more information. + +## Features + +- Simplifies mutation handling for create, update, and delete operations using Firebase Data Connect. +- Provides type-safe handling of mutations based on your Firebase Data Connect schema. +- Automatically manages pending, success, and error states for mutations. +- Supports optimistic updates and caching to improve user experience and performance. + +## Usage + +```ts +import { injectDataConnectMutation } from "@tanstack-query-firebase/angular/data-connect"; +import { createMovieRef } from "@your-package-name/your-connector"; + +class AddMovieComponent() { + createMovie = injectDataConnectMutation( + createMovieRef + ); + addMovie() { + createMovie.mutate({ + title: 'John Wick', + genre: "Action", + imageUrl: "https://example.com/image.jpg", + }); + } + return ( + + ); +} +``` diff --git a/docs/angular/data-connect/functions/injectDataConnectQuery.mdx b/docs/angular/data-connect/functions/injectDataConnectQuery.mdx new file mode 100644 index 0000000..07ee933 --- /dev/null +++ b/docs/angular/data-connect/functions/injectDataConnectQuery.mdx @@ -0,0 +1,43 @@ +--- +title: injectDataConnectQuery +--- + +`injectDataConnectQuery` is a hook designed to simplify data fetching and state management with Firebase Data Connect. + +See [querying](/angular/data-connect/querying) for more information. + +## Features + +- Provides type-safe handling of queries based on the Firebase Data Connect schema. +- Simplifies data fetching using Firebase Data Connect. +- Automatically manages loading, success, and error states. +- Supports refetching data with integrated caching. + +## Usage + +```ts +import { injectDataConnectQuery } from '@tanstack-query-firebase/angular/data-connect'; +import { listMoviesRef } from "@your-package-name/your-connector"; + +// class +export class MovieListComponent { + movies = injectDataConnectQuery(listMoviesRef()); +} + +// template +@if (movies.isPending()) { + Loading... +} +@if (movies.error()) { + An error has occurred: {{ movies.error() }} +} +@if (movies.data(); as data) { + @for (movie of data.movies; track movie.id) { + + {{movie.description}} + + } @empty { +

No items!

+ } +} +``` diff --git a/docs/angular/data-connect/index.mdx b/docs/angular/data-connect/index.mdx new file mode 100644 index 0000000..a3edc19 --- /dev/null +++ b/docs/angular/data-connect/index.mdx @@ -0,0 +1,117 @@ +--- +title: Firebase Data Connect +--- + +Firebase Data Connect is a relational database service for mobile and web apps that lets you build and scale using a fully-managed PostgreSQL database powered by Cloud SQL. It provides secure schema, query and mutation management using GraphQL technology that integrates well with Firebase Authentication. + +To get started, ensure you have setup your Firebase project and have the Data Connect setup in your project. To learn more, +follow the [Firebase Data Connect documentation](https://firebase.google.com/docs/data-connect/quickstart). + +## Setup + +Before using the Tanstack Query Firebase hooks for Data Connect, ensure you have configured your application using your chosen connector: + +```ts +// app.config.ts +export const appConfig: ApplicationConfig = { + providers: [ + ... + provideFirebaseApp(() => + initializeApp(/*Replace with your firebase config*/) + ), + provideDataConnect(() => getDataConnect(connectorConfig)), + provideTanStackQuery(new QueryClient()), + ], +}; +``` + +## Importing + +The package exports are available via the `@tanstack-query-firebase/angular` package under the `data-connect` namespace: + +```ts +import { injectDataConnectQuery } from "@tanstack-query-firebase/angular/data-connect"; +``` + +## Basic Usage + +To use the Tanstack Query Firebase injectors, you can either use the generated SDKs, or the `injectDataConnectQuery` injector to fetch data from the database: + +### Using the Generated SDK + +The generated SDK reduces the boilerplate required to use Tanstack Query Firebase's injectors. Instead of having to provide a ref to `injectDataConnectQuery`, you simply need to call the generated +injector function like so: + +```ts +import { injectListMyPosts } from '@firebasegen/posts/angular' + +@Component({ + ... + template: ` + @if (posts.isPending()) { + Loading... + } + @if (posts.error()) { + An error has occurred: {{ posts.error() }} + } + @if (posts.data(); as data) { + @for (post of data.posts; track post.id) { + + {{post.description}} + + } @empty { +

No items!

+ } + } + `, +}) +export class PostListComponent { + // Calls `injectDataConnectQuery` with the corresponding types. + posts = injectListMyPosts(); +} +``` + +### Using `injectDataConnectQuery` + +Alternatively, you can use the `injectDataConnectQuery` injector. To use this, you need to pass the Response and Data generics: + +```ts +import { injectDataConnectQuery } from "@tanstack-query-firebase/angular"; +import { listMoviesRef } from "@firebasegen/posts"; + +@Component({ + ... + template: ` + @if (posts.isPending()) { + Loading... + } + @if (posts.error()) { + An error has occurred: {{ posts.error() }} + } + @if (posts.data(); as data) { + @for (post of data.posts; track post.id) { + + {{post.description}} + + } @empty { +

No items!

+ } + } + `, +}) +export class PostListComponent { + // Calls `injectDataConnectQuery` with the corresponding types. + // Alternatively: + // injectDataConnectQuery(queryRef(dc, 'ListMovies')) + posts = injectDataConnectQuery(listMoviesRef()); +} +``` + +The hooks will automatically infer the data type from the connector and the query and automtically create a [query key](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for the query. + +## Learning more + +To learn more about the Data Connect hooks, check out the following pages: + +- [Querying](/angular/data-connect/querying) +- [Mutations](/angular/data-connect/mutations) diff --git a/docs/angular/data-connect/mutations.mdx b/docs/angular/data-connect/mutations.mdx new file mode 100644 index 0000000..b760854 --- /dev/null +++ b/docs/angular/data-connect/mutations.mdx @@ -0,0 +1,102 @@ +--- +title: Mutations +description: Learn how to mutate data in Firebase Data Connect using the Tanstack Query Firebase hooks. +--- + +## Mutating Data + +To mutate data in Firebase Data Connect, you can either use the generated injectors, or use the `injectDataConnectMutation` injector. + +```ts +import { injectCreateMovie } from "@firebasegen/movies/angular"; + +@Component({ + ... + template: ` + + ` +}) +class AddMovieComponent() { + // Calls `injectDataConnectMutation` with the respective types. + // Alternatively: + // import { injectDataConnectMutation } from '@tanstack-query-firebase/angular/data-connect'; + // ... + // createMovie = injectDataConnectMutation(createMovieRef); + createMovie = injectCreateMovie(); + addMovie() { + createMovie.mutate({ + title: 'John Wick', + genre: "Action", + imageUrl: "https://example.com/image.jpg", + }); + } +} +``` + +Additionally, you can provide a factory function to the mutation, which will be called with the mutation variables: + +```ts +createMovie = injectDataConnectMutation(undefined, () => ({ + mutationFn: (title: string) => createMovieRef({ title, reviewDate: Date.now() }) +})); + +// ... +createMovie.mutate("John Wick"); +``` + +## Invalidating Queries + +The hook provides an additional [mutation option](https://tanstack.com/query/latest/docs/framework/angular/reference/functions/injectMutation) called `invalidate`. This option accepts a list of query references which will be automatically invalidated when the mutation is successful. + +```ts +const createMovie = injectDataConnectMutation(createMovieRef, { + invalidate: [getMovieRef], +}); +``` + +### Implicit references + +// TODO(mtewani): Check this for Angular +The above example provides a `getMovieRef` instance to the invalidate array. By default this will invalidate all queries that cached via the `getMovieRef` reference, for example the following query references will be invalidated: + +```ts +getMovieRef({ id: "1"}); +getMovieRef({ id: "2"}); +``` + +### Explicit references + +You can also provide explicit references to the invalidate array, for example: + +```ts +const createMovie = injectDataConnectMutation(createMovieRef, { + invalidate: [getMovieRef({ id: "1" })], +}); +``` + +In this case only the query reference `getMovieRef({ id: "1" })` will be invalidated. + +## Overriding the mutation key + +### Metadata + +Along with the data, the hook will also return the `ref`, `source`, and `fetchTime` metadata from the mutation. + +```ts +const createMovie = injectDataConnectMutation(createMovieRef); + +await createMovie.mutateAsync({ + title: 'John Wick', + genre: "Action", + imageUrl: "https://example.com/image.jpg", +}); + +console.log(createMovie.dataConnectResult().ref); +console.log(createMovie.dataConnectResult().source); +console.log(createMovie.dataConnectResult().fetchTime); +``` diff --git a/docs/angular/data-connect/querying.mdx b/docs/angular/data-connect/querying.mdx new file mode 100644 index 0000000..d9f96e1 --- /dev/null +++ b/docs/angular/data-connect/querying.mdx @@ -0,0 +1,81 @@ +--- +title: Querying +description: Learn how to query data from Firebase Data Connect using the Tanstack Query Firebase injectors. +--- + +## Querying Data + +To query data from Firebase Data Connect, you can either use the generated injectors, or the `injectDataConnect` injector. This will automatically create a query key and infer the data type and variables associated with the query. + +```ts +import { injectListMyPosts } from '@firebasegen/posts/angular' + +@Component({ + ... + template: ` + @if (movies.isPending()) { + Loading... + } + @if (movies.error()) { + An error has occurred: {{ movies.error() }} + } + @if (movies.data(); as data) { + @for (movie of data.movies; track movie.id) { + + {{movie.description}} + + } @empty { +

No items!

+ } + } + `, +}) +export class PostListComponent { + // Calls `injectDataConnectQuery` with the respective types. + // Alternatively: + // import { injectDataConnectQuery } from '@tanstack-query-firebase/angular/data-connect'; + // ... + // injectDataConnectQuery(listMoviesRef()) + movies = injectListMovies(); +} +``` + +### Query Options + +To leverage the full power of Tanstack Query, you can pass in query options to the `injectDataConnectQuery` injector, for example to refetch the query on a interval: + +```ts +movies = injectListMovies( + { + refetchInterval: 1000, + } +); +``` +The hook extends the [`injectQuery`](https://tanstack.com/query/latest/docs/framework/angular/reference/functions/injectquery) hook, so you can learn more about the available options by reading the [Tanstack Query documentation](https://tanstack.com/query/latest/docs/framework/react/reference/useQuery). + +### Overriding the query key + +To override the query key, you can pass in a custom query key to the `injectDataConnectQuery` injector: + +```ts +movies = injectListMovies( + listMoviesRef(), + { + queryKey: ['movies', '1'] + } +); +``` +Note that overriding the query key could mean your query is no longer synchronized with mutation invalidations or server side rendering pre-fetching. + +### Metadata + +Along with the data, the hook will also return the `ref`, `source`, and `fetchTime` metadata from the query. + +```ts +const movies = injectListMovies(); + +console.log(movies.dataConnectResult()?.ref); +console.log(movies.dataConnectResult()?.source); +console.log(movies.dataConnectResult()?.fetchTime); +``` + diff --git a/docs/angular/index.mdx b/docs/angular/index.mdx new file mode 100644 index 0000000..a1d5dc8 --- /dev/null +++ b/docs/angular/index.mdx @@ -0,0 +1,92 @@ +--- +title: Angular +description: Using TanStack Query Firebase with Angular +--- + +To get started using TanStack Query Firebase with Angular, you will need to install the following packages: + +```bash +npm i --save firebase @tanstack/angular-query-experimental @tanstack-query-firebase/angular +``` + +Both `@angular/fire` and `@tanstack/angular-query-experimental` are peer dependencies of `@tanstack-query-firebase/angular`. + +## Usage + +TanStack Query Firebase provides a hands-off approach to integrate with TanStack Query - you are +still responsible for both setting up Firebase in your application and configuring TanStack Query. + +If you haven't already done so, [initialize your Firebase project](https://firebase.google.com/docs/web/setup) +and [configure TanStack Query](https://tanstack.com/query/latest/docs/framework/angular/quick-start): + +### Automatic Setup +To automatically set up AngularFire, just run: +```shell +ng add @angular/fire +``` + +### Manual Setup + +```ts +// app.config.ts +import { initializeApp, provideFirebaseApp } from '@angular/fire/app'; +import { getDataConnect, provideDataConnect } from '@angular/fire/data-connect'; +import { connectorConfig } from '@firebasegen/movies'; +import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query-experimental'; + + +export const appConfig: ApplicationConfig = { + providers: [ + ... + provideFirebaseApp(() => + initializeApp(/*Replace with your firebase config*/) + ), + provideDataConnect(() => getDataConnect(connectorConfig)), + provideTanStackQuery(new QueryClient()), + ], +}; +``` + +And be sure to add `angular: true` to your `connector.yaml`: + +```yaml +generate: + javascriptSdk: + angular: true + outputDir: "../movies-generated" + package: "@movie-app/movies" + packageJsonDir: "../../" +``` + +## Example Usage + +Next, you can start to use injectors provided by `@tanstack-query-firebase/angular`. For example, to +fetch a query from Data Connect: + +```ts +import { injectListMovies } from '@firebasegen/movies/angular' + +// class +export class MovieListComponent { + movies = injectListMovies(); +} + +// template +@if (movies.isPending()) { + Loading... +} +@if (movies.error()) { + An error has occurred: {{ movies.error() }} +} +@if (movies.data(); as data) { + @for (movie of data.movies; track movie.id) { + + {{movie.description}} + + } @empty { +

No items!

+ } +} +``` + +TanStack Query Firebase provides hooks for all Firebase services, supporting both mutations and queries \ No newline at end of file diff --git a/docs/react/data-connect/querying.mdx b/docs/react/data-connect/querying.mdx index 52a7ecc..6f9faa5 100644 --- a/docs/react/data-connect/querying.mdx +++ b/docs/react/data-connect/querying.mdx @@ -5,7 +5,7 @@ description: Learn how to query data from Firebase Data Connect using the Tansta ## Querying Data -To query data from Firebase Data Connect, you can use the `useDataConnectQuery` hook. This hook will automatically infer the data type from the connector and the query and automtically create a [query key](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for the query. +To query data from Firebase Data Connect, you can use the `useDataConnectQuery` hook. This hook will automatically infer the data type from the connector and the query and automatically create a [query key](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for the query. ```tsx import { useDataConnectQuery } from "@tanstack-query-firebase/react/data-connect"; From 210063f5174388cacdeb84e14085ce7b3caeba46 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 7 Apr 2025 15:35:14 -0700 Subject: [PATCH 03/10] Undid changes --- .../data-connect/useDataConnectQuery.test.tsx | 40 ------------------- .../src/data-connect/useDataConnectQuery.ts | 33 +++++---------- 2 files changed, 10 insertions(+), 63 deletions(-) diff --git a/packages/react/src/data-connect/useDataConnectQuery.test.tsx b/packages/react/src/data-connect/useDataConnectQuery.test.tsx index dfe7c92..3054bb1 100644 --- a/packages/react/src/data-connect/useDataConnectQuery.test.tsx +++ b/packages/react/src/data-connect/useDataConnectQuery.test.tsx @@ -269,44 +269,4 @@ describe("useDataConnectQuery", () => { { id: movieId }, ]); }); - - test("fetches new data when variables change", async () => { - const movieData1 = { - title: "tanstack query firebase 1", - genre: "library 1", - imageUrl: "https://invertase.io/1", - }; - const createdMovie = await createMovie(movieData1); - const movieData2 = { - title: "tanstack query firebase 2", - genre: "library 2", - imageUrl: "https://invertase.io/2", - }; - const createdMovie2 = await createMovie(movieData2); - - const movieId = createdMovie?.data?.movie_insert?.id; - const movieId2 = createdMovie2?.data?.movie_insert?.id; - getMovieByIdRef({ id: movieId2 }); - const ref = getMovieByIdRef({ id: movieId }); - const { result } = renderHook(() => useDataConnectQuery(ref), { - wrapper, - }); - - await waitFor(() => { - expect(result.current.isSuccess).toBe(true); - expect(result.current.data?.movie?.title).toBe(movieData1?.title); - expect(result.current.data?.movie?.genre).toBe(movieData1?.genre); - expect(result.current.data?.movie?.imageUrl).toBe(movieData1?.imageUrl); - }); - await act(async () => { - ref.variables.id = createdMovie2.data.movie_insert.id; - result.current.refetch(); - }); - await waitFor(() => { - expect(result.current.isSuccess).toBe(true); - expect(result.current.data?.movie?.title).toBe(movieData2?.title); - expect(result.current.data?.movie?.genre).toBe(movieData2?.genre); - expect(result.current.data?.movie?.imageUrl).toBe(movieData2?.imageUrl); - }); - }); }); diff --git a/packages/react/src/data-connect/useDataConnectQuery.ts b/packages/react/src/data-connect/useDataConnectQuery.ts index 5cc4324..de0198e 100644 --- a/packages/react/src/data-connect/useDataConnectQuery.ts +++ b/packages/react/src/data-connect/useDataConnectQuery.ts @@ -3,7 +3,6 @@ import { type UseQueryOptions, useQuery, } from "@tanstack/react-query"; -import deepEqual from "deep-equal"; import type { FirebaseError } from "firebase/app"; import { type CallerSdkType, @@ -12,7 +11,7 @@ import { type QueryResult, executeQuery, } from "firebase/data-connect"; -import { useEffect, useMemo, useState } from "react"; +import { useState } from "react"; import type { PartialBy } from "../../utils"; import type { QueryResultRequiredRef, @@ -23,11 +22,6 @@ export type useDataConnectQueryOptions< TData = object, TError = FirebaseError, > = PartialBy, "queryFn">, "queryKey">; -function getRef( - refOrResult: QueryRef | QueryResult, -): QueryRef { - return "ref" in refOrResult ? refOrResult.ref : refOrResult; -} export function useDataConnectQuery( refOrResult: QueryRef | QueryResult, @@ -37,24 +31,17 @@ export function useDataConnectQuery( const [dataConnectResult, setDataConnectResult] = useState< QueryResultRequiredRef >("ref" in refOrResult ? refOrResult : { ref: refOrResult }); - const [ref, setRef] = useState(dataConnectResult.ref); // TODO(mtewani): in the future we should allow for users to pass in `QueryResult` objects into `initialData`. - const [initialData] = useState( - dataConnectResult.data || options?.initialData, - ); + let initialData: Data | InitialDataFunction | undefined; + const { ref } = dataConnectResult; - useEffect(() => { - setRef((oldRef) => { - const newRef = getRef(refOrResult); - if ( - newRef.name !== oldRef.name || - !deepEqual(oldRef, newRef, { strict: true }) - ) { - return newRef; - } - return oldRef; - }); - }, [refOrResult]); + if ("ref" in refOrResult) { + initialData = { + ...refOrResult.data, + }; + } else { + initialData = options?.initialData; + } // @ts-expect-error function is hidden under `DataConnect`. ref.dataConnect._setCallerSdkType(_callerSdkType); From 3407c1ca0f9baa2e08a0ee036c7123aef60fff36 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 7 Apr 2025 15:35:59 -0700 Subject: [PATCH 04/10] Undid package.json changes --- packages/react/package.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/react/package.json b/packages/react/package.json index a1c11e2..cdbc12f 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -46,9 +46,5 @@ "peerDependencies": { "@tanstack/react-query": "^5", "firebase": "^11.3.0" - }, - "dependencies": { - "@types/deep-equal": "^1.0.4", - "deep-equal": "^2.2.3" } } From 4611d07046735afa5e78341dcae916ec019782b6 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 7 Apr 2025 15:36:05 -0700 Subject: [PATCH 05/10] Undid package.json changes --- pnpm-lock.yaml | 78 -------------------------------------------------- 1 file changed, 78 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6596518..f74bb3a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -152,12 +152,6 @@ importers: '@tanstack/react-query': specifier: ^5 version: 5.66.9(react@19.0.0) - '@types/deep-equal': - specifier: ^1.0.4 - version: 1.0.4 - deep-equal: - specifier: ^2.2.3 - version: 2.2.3 firebase: specifier: ^11.3.0 version: 11.3.1 @@ -1364,9 +1358,6 @@ packages: '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} - '@types/deep-equal@1.0.4': - resolution: {integrity: sha512-tqdiS4otQP4KmY0PR3u6KbZ5EWvhNdUoS/jc93UuK23C220lOZ/9TvjfxdPcKvqwwDVtmtSCrnr0p/2dirAxkA==} - '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -1785,10 +1776,6 @@ packages: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} - deep-equal@2.2.3: - resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} - engines: {node: '>= 0.4'} - deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -1863,9 +1850,6 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-get-iterator@1.1.3: - resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} - es-iterator-helpers@1.2.1: resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} engines: {node: '>= 0.4'} @@ -2229,10 +2213,6 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - is-arguments@1.2.0: - resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} - engines: {node: '>= 0.4'} - is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} @@ -2624,10 +2604,6 @@ packages: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} - object-is@1.1.6: - resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} - engines: {node: '>= 0.4'} - object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -3011,10 +2987,6 @@ packages: std-env@3.8.0: resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} - stop-iteration-iterator@1.1.0: - resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} - engines: {node: '>= 0.4'} - streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} @@ -4464,8 +4436,6 @@ snapshots: '@types/aria-query@5.0.4': {} - '@types/deep-equal@1.0.4': {} - '@types/estree@1.0.6': {} '@types/json-schema@7.0.15': {} @@ -4945,27 +4915,6 @@ snapshots: deep-eql@5.0.2: {} - deep-equal@2.2.3: - dependencies: - array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 - es-get-iterator: 1.1.3 - get-intrinsic: 1.3.0 - is-arguments: 1.2.0 - is-array-buffer: 3.0.5 - is-date-object: 1.1.0 - is-regex: 1.2.1 - is-shared-array-buffer: 1.0.4 - isarray: 2.0.5 - object-is: 1.1.6 - object-keys: 1.1.1 - object.assign: 4.1.7 - regexp.prototype.flags: 1.5.4 - side-channel: 1.1.0 - which-boxed-primitive: 1.1.1 - which-collection: 1.0.2 - which-typed-array: 1.1.18 - deep-is@0.1.4: {} defaults@1.0.4: @@ -5082,18 +5031,6 @@ snapshots: es-errors@1.3.0: {} - es-get-iterator@1.1.3: - dependencies: - call-bind: 1.0.8 - get-intrinsic: 1.3.0 - has-symbols: 1.1.0 - is-arguments: 1.2.0 - is-map: 2.0.3 - is-set: 2.0.3 - is-string: 1.1.1 - isarray: 2.0.5 - stop-iteration-iterator: 1.1.0 - es-iterator-helpers@1.2.1: dependencies: call-bind: 1.0.8 @@ -5627,11 +5564,6 @@ snapshots: hasown: 2.0.2 side-channel: 1.1.0 - is-arguments@1.2.0: - dependencies: - call-bound: 1.0.3 - has-tostringtag: 1.0.2 - is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 @@ -6015,11 +5947,6 @@ snapshots: object-inspect@1.13.4: {} - object-is@1.1.6: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - object-keys@1.1.1: {} object.assign@4.1.7: @@ -6466,11 +6393,6 @@ snapshots: std-env@3.8.0: {} - stop-iteration-iterator@1.1.0: - dependencies: - es-errors: 1.3.0 - internal-slot: 1.1.0 - streamsearch@1.1.0: {} string-width@4.2.3: From eede42c5a924b28f1f2f8a9df38de404e6a32d75 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 7 Apr 2025 15:36:33 -0700 Subject: [PATCH 06/10] Removed unnecessary changes --- .../js/default-connector/README.md | 36 ++++++++--------- .../js/default-connector/index.cjs.js | 39 ++++--------------- 2 files changed, 26 insertions(+), 49 deletions(-) diff --git a/dataconnect-sdk/js/default-connector/README.md b/dataconnect-sdk/js/default-connector/README.md index 0c66142..c3d1ddb 100644 --- a/dataconnect-sdk/js/default-connector/README.md +++ b/dataconnect-sdk/js/default-connector/README.md @@ -28,7 +28,7 @@ A connector is a collection of Queries and Mutations. One SDK is generated for e You can find more information about connectors in the [Data Connect documentation](https://firebase.google.com/docs/data-connect#how-does). ```javascript -import { getDataConnect } from 'firebase/data-connect'; +import { getDataConnect, DataConnect } from 'firebase/data-connect'; import { connectorConfig } from '@dataconnect/default-connector'; const dataConnect = getDataConnect(connectorConfig); @@ -41,7 +41,7 @@ To connect to the emulator, you can use the following code. You can also follow the emulator instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#instrument-clients). ```javascript -import { connectDataConnectEmulator, getDataConnect } from 'firebase/data-connect'; +import { connectDataConnectEmulator, getDataConnect, DataConnect } from 'firebase/data-connect'; import { connectorConfig } from '@dataconnect/default-connector'; const dataConnect = getDataConnect(connectorConfig); @@ -98,7 +98,7 @@ export interface ListMoviesData { ### Using `ListMovies`'s action shortcut function ```javascript -import { getDataConnect } from 'firebase/data-connect'; +import { getDataConnect, DataConnect } from 'firebase/data-connect'; import { connectorConfig, listMovies } from '@dataconnect/default-connector'; @@ -122,7 +122,7 @@ listMovies().then((response) => { ### Using `ListMovies`'s `QueryRef` function ```javascript -import { getDataConnect, executeQuery } from 'firebase/data-connect'; +import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; import { connectorConfig, listMoviesRef } from '@dataconnect/default-connector'; @@ -185,7 +185,7 @@ export interface GetMovieByIdData { ### Using `GetMovieById`'s action shortcut function ```javascript -import { getDataConnect } from 'firebase/data-connect'; +import { getDataConnect, DataConnect } from 'firebase/data-connect'; import { connectorConfig, getMovieById, GetMovieByIdVariables } from '@dataconnect/default-connector'; // The `GetMovieById` query requires an argument of type `GetMovieByIdVariables`: @@ -215,7 +215,7 @@ getMovieById(getMovieByIdVars).then((response) => { ### Using `GetMovieById`'s `QueryRef` function ```javascript -import { getDataConnect, executeQuery } from 'firebase/data-connect'; +import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; import { connectorConfig, getMovieByIdRef, GetMovieByIdVariables } from '@dataconnect/default-connector'; // The `GetMovieById` query requires an argument of type `GetMovieByIdVariables`: @@ -275,7 +275,7 @@ export interface GetMetaData { ### Using `GetMeta`'s action shortcut function ```javascript -import { getDataConnect } from 'firebase/data-connect'; +import { getDataConnect, DataConnect } from 'firebase/data-connect'; import { connectorConfig, getMeta } from '@dataconnect/default-connector'; @@ -299,7 +299,7 @@ getMeta().then((response) => { ### Using `GetMeta`'s `QueryRef` function ```javascript -import { getDataConnect, executeQuery } from 'firebase/data-connect'; +import { getDataConnect, DataConnect, executeQuery } from 'firebase/data-connect'; import { connectorConfig, getMetaRef } from '@dataconnect/default-connector'; @@ -374,7 +374,7 @@ export interface CreateMovieData { ### Using `CreateMovie`'s action shortcut function ```javascript -import { getDataConnect } from 'firebase/data-connect'; +import { getDataConnect, DataConnect } from 'firebase/data-connect'; import { connectorConfig, createMovie, CreateMovieVariables } from '@dataconnect/default-connector'; // The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: @@ -406,7 +406,7 @@ createMovie(createMovieVars).then((response) => { ### Using `CreateMovie`'s `MutationRef` function ```javascript -import { getDataConnect, executeMutation } from 'firebase/data-connect'; +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; import { connectorConfig, createMovieRef, CreateMovieVariables } from '@dataconnect/default-connector'; // The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: @@ -474,7 +474,7 @@ export interface UpsertMovieData { ### Using `UpsertMovie`'s action shortcut function ```javascript -import { getDataConnect } from 'firebase/data-connect'; +import { getDataConnect, DataConnect } from 'firebase/data-connect'; import { connectorConfig, upsertMovie, UpsertMovieVariables } from '@dataconnect/default-connector'; // The `UpsertMovie` mutation requires an argument of type `UpsertMovieVariables`: @@ -506,7 +506,7 @@ upsertMovie(upsertMovieVars).then((response) => { ### Using `UpsertMovie`'s `MutationRef` function ```javascript -import { getDataConnect, executeMutation } from 'firebase/data-connect'; +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; import { connectorConfig, upsertMovieRef, UpsertMovieVariables } from '@dataconnect/default-connector'; // The `UpsertMovie` mutation requires an argument of type `UpsertMovieVariables`: @@ -572,7 +572,7 @@ export interface DeleteMovieData { ### Using `DeleteMovie`'s action shortcut function ```javascript -import { getDataConnect } from 'firebase/data-connect'; +import { getDataConnect, DataConnect } from 'firebase/data-connect'; import { connectorConfig, deleteMovie, DeleteMovieVariables } from '@dataconnect/default-connector'; // The `DeleteMovie` mutation requires an argument of type `DeleteMovieVariables`: @@ -602,7 +602,7 @@ deleteMovie(deleteMovieVars).then((response) => { ### Using `DeleteMovie`'s `MutationRef` function ```javascript -import { getDataConnect, executeMutation } from 'firebase/data-connect'; +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; import { connectorConfig, deleteMovieRef, DeleteMovieVariables } from '@dataconnect/default-connector'; // The `DeleteMovie` mutation requires an argument of type `DeleteMovieVariables`: @@ -660,7 +660,7 @@ export interface AddMetaData { ### Using `AddMeta`'s action shortcut function ```javascript -import { getDataConnect } from 'firebase/data-connect'; +import { getDataConnect, DataConnect } from 'firebase/data-connect'; import { connectorConfig, addMeta } from '@dataconnect/default-connector'; @@ -684,7 +684,7 @@ addMeta().then((response) => { ### Using `AddMeta`'s `MutationRef` function ```javascript -import { getDataConnect, executeMutation } from 'firebase/data-connect'; +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; import { connectorConfig, addMetaRef } from '@dataconnect/default-connector'; @@ -742,7 +742,7 @@ export interface DeleteMetaData { ### Using `DeleteMeta`'s action shortcut function ```javascript -import { getDataConnect } from 'firebase/data-connect'; +import { getDataConnect, DataConnect } from 'firebase/data-connect'; import { connectorConfig, deleteMeta, DeleteMetaVariables } from '@dataconnect/default-connector'; // The `DeleteMeta` mutation requires an argument of type `DeleteMetaVariables`: @@ -772,7 +772,7 @@ deleteMeta(deleteMetaVars).then((response) => { ### Using `DeleteMeta`'s `MutationRef` function ```javascript -import { getDataConnect, executeMutation } from 'firebase/data-connect'; +import { getDataConnect, DataConnect, executeMutation } from 'firebase/data-connect'; import { connectorConfig, deleteMetaRef, DeleteMetaVariables } from '@dataconnect/default-connector'; // The `DeleteMeta` mutation requires an argument of type `DeleteMetaVariables`: diff --git a/dataconnect-sdk/js/default-connector/index.cjs.js b/dataconnect-sdk/js/default-connector/index.cjs.js index eeb404a..6fa0628 100644 --- a/dataconnect-sdk/js/default-connector/index.cjs.js +++ b/dataconnect-sdk/js/default-connector/index.cjs.js @@ -7,90 +7,67 @@ const connectorConfig = { }; exports.connectorConfig = connectorConfig; -function createMovieRef(dcOrVars, vars) { +exports.createMovieRef = function createMovieRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'CreateMovie', inputVars); } -exports.createMovieRef = createMovieRef; - exports.createMovie = function createMovie(dcOrVars, vars) { return executeMutation(createMovieRef(dcOrVars, vars)); }; - -function upsertMovieRef(dcOrVars, vars) { +exports.upsertMovieRef = function upsertMovieRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'UpsertMovie', inputVars); } -exports.upsertMovieRef = upsertMovieRef; - exports.upsertMovie = function upsertMovie(dcOrVars, vars) { return executeMutation(upsertMovieRef(dcOrVars, vars)); }; - -function deleteMovieRef(dcOrVars, vars) { +exports.deleteMovieRef = function deleteMovieRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'DeleteMovie', inputVars); } -exports.deleteMovieRef = deleteMovieRef; - exports.deleteMovie = function deleteMovie(dcOrVars, vars) { return executeMutation(deleteMovieRef(dcOrVars, vars)); }; - -function addMetaRef(dc) { +exports.addMetaRef = function addMetaRef(dc) { const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'AddMeta'); } -exports.addMetaRef = addMetaRef; - exports.addMeta = function addMeta(dc) { return executeMutation(addMetaRef(dc)); }; - -function deleteMetaRef(dcOrVars, vars) { +exports.deleteMetaRef = function deleteMetaRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'DeleteMeta', inputVars); } -exports.deleteMetaRef = deleteMetaRef; - exports.deleteMeta = function deleteMeta(dcOrVars, vars) { return executeMutation(deleteMetaRef(dcOrVars, vars)); }; - -function listMoviesRef(dc) { +exports.listMoviesRef = function listMoviesRef(dc) { const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'ListMovies'); } -exports.listMoviesRef = listMoviesRef; - exports.listMovies = function listMovies(dc) { return executeQuery(listMoviesRef(dc)); }; - -function getMovieByIdRef(dcOrVars, vars) { +exports.getMovieByIdRef = function getMovieByIdRef(dcOrVars, vars) { const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'GetMovieById', inputVars); } -exports.getMovieByIdRef = getMovieByIdRef; - exports.getMovieById = function getMovieById(dcOrVars, vars) { return executeQuery(getMovieByIdRef(dcOrVars, vars)); }; - -function getMetaRef(dc) { +exports.getMetaRef = function getMetaRef(dc) { const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'GetMeta'); } -exports.getMetaRef = getMetaRef; - exports.getMeta = function getMeta(dc) { return executeQuery(getMetaRef(dc)); }; From 189b42719210b7190f0fcacf8d3c117643d8bfdd Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 7 Apr 2025 15:36:38 -0700 Subject: [PATCH 07/10] Removed unnecessary changes --- biome.json | 1 - 1 file changed, 1 deletion(-) diff --git a/biome.json b/biome.json index 6a9ce33..64c9952 100644 --- a/biome.json +++ b/biome.json @@ -18,7 +18,6 @@ }, "linter": { "enabled": true, - "ignore": ["node_modules/**"], "rules": { "recommended": true, "style": { From 5f258c5b19f46c8d5fadcd6d794fe50a08673b08 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 7 Apr 2025 15:37:46 -0700 Subject: [PATCH 08/10] s/functions/Functions --- docs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs.json b/docs.json index 25aa215..35baeb3 100644 --- a/docs.json +++ b/docs.json @@ -64,7 +64,7 @@ "href": "/angular/data-connect/mutations" }, { - "group": "functions", + "group": "Functions", "pages": [ { "title": "injectDataConnectQuery", From 3bf9158732f4a274a54807c9228b0d41bd273511 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 7 Apr 2025 15:41:57 -0700 Subject: [PATCH 09/10] Cleaned up docs a bit more --- docs/angular/data-connect/mutations.mdx | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/docs/angular/data-connect/mutations.mdx b/docs/angular/data-connect/mutations.mdx index b760854..2daacb5 100644 --- a/docs/angular/data-connect/mutations.mdx +++ b/docs/angular/data-connect/mutations.mdx @@ -1,6 +1,6 @@ --- title: Mutations -description: Learn how to mutate data in Firebase Data Connect using the Tanstack Query Firebase hooks. +description: Learn how to mutate data in Firebase Data Connect using the Tanstack Query Firebase injectors. --- ## Mutating Data @@ -51,25 +51,7 @@ createMovie.mutate("John Wick"); ## Invalidating Queries -The hook provides an additional [mutation option](https://tanstack.com/query/latest/docs/framework/angular/reference/functions/injectMutation) called `invalidate`. This option accepts a list of query references which will be automatically invalidated when the mutation is successful. - -```ts -const createMovie = injectDataConnectMutation(createMovieRef, { - invalidate: [getMovieRef], -}); -``` - -### Implicit references - -// TODO(mtewani): Check this for Angular -The above example provides a `getMovieRef` instance to the invalidate array. By default this will invalidate all queries that cached via the `getMovieRef` reference, for example the following query references will be invalidated: - -```ts -getMovieRef({ id: "1"}); -getMovieRef({ id: "2"}); -``` - -### Explicit references +The function provides an additional [mutation option](https://tanstack.com/query/latest/docs/framework/angular/reference/functions/injectMutation) called `invalidate`. This option accepts a list of query references which will be automatically invalidated when the mutation is successful. You can also provide explicit references to the invalidate array, for example: @@ -85,7 +67,7 @@ In this case only the query reference `getMovieRef({ id: "1" })` will be invalid ### Metadata -Along with the data, the hook will also return the `ref`, `source`, and `fetchTime` metadata from the mutation. +Along with the data, the function will also return the `ref`, `source`, and `fetchTime` metadata from the mutation. ```ts const createMovie = injectDataConnectMutation(createMovieRef); From e553d49bd84510ef293e04800af3026878a805ce Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 7 Apr 2025 15:47:05 -0700 Subject: [PATCH 10/10] Removed all hook references --- .../data-connect/functions/injectDataConnectMutation.mdx | 4 ++-- .../data-connect/functions/injectDataConnectQuery.mdx | 2 +- docs/angular/data-connect/index.mdx | 6 +++--- docs/angular/data-connect/querying.mdx | 4 ++-- docs/angular/index.mdx | 2 -- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/angular/data-connect/functions/injectDataConnectMutation.mdx b/docs/angular/data-connect/functions/injectDataConnectMutation.mdx index eaa6292..f1d5aec 100644 --- a/docs/angular/data-connect/functions/injectDataConnectMutation.mdx +++ b/docs/angular/data-connect/functions/injectDataConnectMutation.mdx @@ -2,9 +2,9 @@ title: injectDataConnectMutation --- -`injectDataConnectMutation` is a hook designed to simplify handling mutations (creating, updating, deleting) with Firebase Data Connect. +`injectDataConnectMutation` is an injector designed to simplify handling mutations (creating, updating, deleting) with Firebase Data Connect. -See [mutations](/react/data-connect/mutations) for more information. +See [mutations](/angular/data-connect/mutations) for more information. ## Features diff --git a/docs/angular/data-connect/functions/injectDataConnectQuery.mdx b/docs/angular/data-connect/functions/injectDataConnectQuery.mdx index 07ee933..10b5b46 100644 --- a/docs/angular/data-connect/functions/injectDataConnectQuery.mdx +++ b/docs/angular/data-connect/functions/injectDataConnectQuery.mdx @@ -2,7 +2,7 @@ title: injectDataConnectQuery --- -`injectDataConnectQuery` is a hook designed to simplify data fetching and state management with Firebase Data Connect. +`injectDataConnectQuery` is an injector designed to simplify data fetching and state management with Firebase Data Connect. See [querying](/angular/data-connect/querying) for more information. diff --git a/docs/angular/data-connect/index.mdx b/docs/angular/data-connect/index.mdx index a3edc19..78554b9 100644 --- a/docs/angular/data-connect/index.mdx +++ b/docs/angular/data-connect/index.mdx @@ -9,7 +9,7 @@ follow the [Firebase Data Connect documentation](https://firebase.google.com/doc ## Setup -Before using the Tanstack Query Firebase hooks for Data Connect, ensure you have configured your application using your chosen connector: +Before using the Tanstack Query Firebase injectors for Data Connect, ensure you have configured your application using your chosen connector: ```ts // app.config.ts @@ -107,11 +107,11 @@ export class PostListComponent { } ``` -The hooks will automatically infer the data type from the connector and the query and automtically create a [query key](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) for the query. +The injectors will automatically infer the data type from the connector and the query and automtically create a [query key](https://tanstack.com/query/latest/docs/framework/angular/guides/query-keys) for the query. ## Learning more -To learn more about the Data Connect hooks, check out the following pages: +To learn more about the Data Connect functions, check out the following pages: - [Querying](/angular/data-connect/querying) - [Mutations](/angular/data-connect/mutations) diff --git a/docs/angular/data-connect/querying.mdx b/docs/angular/data-connect/querying.mdx index d9f96e1..e46eb56 100644 --- a/docs/angular/data-connect/querying.mdx +++ b/docs/angular/data-connect/querying.mdx @@ -51,7 +51,7 @@ movies = injectListMovies( } ); ``` -The hook extends the [`injectQuery`](https://tanstack.com/query/latest/docs/framework/angular/reference/functions/injectquery) hook, so you can learn more about the available options by reading the [Tanstack Query documentation](https://tanstack.com/query/latest/docs/framework/react/reference/useQuery). +The injector extends the [`injectQuery`](https://tanstack.com/query/latest/docs/framework/angular/reference/functions/injectquery) injector, so you can learn more about the available options by reading the [Tanstack Query documentation](https://tanstack.com/query/latest/docs/framework/angular/reference/functions/injectquery). ### Overriding the query key @@ -69,7 +69,7 @@ Note that overriding the query key could mean your query is no longer synchroniz ### Metadata -Along with the data, the hook will also return the `ref`, `source`, and `fetchTime` metadata from the query. +Along with the data, the injector will also return the `ref`, `source`, and `fetchTime` metadata from the query. ```ts const movies = injectListMovies(); diff --git a/docs/angular/index.mdx b/docs/angular/index.mdx index a1d5dc8..d9e7554 100644 --- a/docs/angular/index.mdx +++ b/docs/angular/index.mdx @@ -88,5 +88,3 @@ export class MovieListComponent { } } ``` - -TanStack Query Firebase provides hooks for all Firebase services, supporting both mutations and queries \ No newline at end of file