configuration makefile and dataconnect init
This commit is contained in:
25
Makefile
25
Makefile
@@ -283,3 +283,28 @@ prepare-export:
|
|||||||
@echo "--> Preparing fresh Base44 export for local development..."
|
@echo "--> Preparing fresh Base44 export for local development..."
|
||||||
@node scripts/prepare-export.js
|
@node scripts/prepare-export.js
|
||||||
@echo "--> Preparation complete. You can now run 'make dev'."
|
@echo "--> Preparation complete. You can now run 'make dev'."
|
||||||
|
|
||||||
|
# --- Data Connect / Backend ---
|
||||||
|
|
||||||
|
# Enable all required APIs for Firebase Data Connect + Cloud SQL
|
||||||
|
dataconnect-enable-apis:
|
||||||
|
@echo "--> Enabling Firebase & Data Connect APIs on project [$(GCP_PROJECT_ID)]..."
|
||||||
|
@gcloud services enable firebase.googleapis.com --project=$(GCP_PROJECT_ID)
|
||||||
|
@gcloud services enable firebasedataconnect.googleapis.com --project=$(GCP_PROJECT_ID)
|
||||||
|
@gcloud services enable sqladmin.googleapis.com --project=$(GCP_PROJECT_ID)
|
||||||
|
@gcloud services enable iam.googleapis.com --project=$(GCP_PROJECT_ID)
|
||||||
|
@gcloud services enable cloudresourcemanager.googleapis.com --project=$(GCP_PROJECT_ID)
|
||||||
|
@echo "✅ APIs enabled for project [$(GCP_PROJECT_ID)]."
|
||||||
|
|
||||||
|
# Initialize Firebase Data Connect (interactive wizard).
|
||||||
|
# This wraps the command so we remember how to run it for dev/staging/prod.
|
||||||
|
dataconnect-init:
|
||||||
|
@echo "--> Initializing Firebase Data Connect for alias [$(FIREBASE_ALIAS)] (project: $(GCP_PROJECT_ID))..."
|
||||||
|
@firebase init dataconnect --project $(FIREBASE_ALIAS)
|
||||||
|
@echo "✅ Data Connect initialization command executed. Follow the interactive steps in the CLI."
|
||||||
|
|
||||||
|
# Deploy Data Connect schemas (GraphQL → Cloud SQL)
|
||||||
|
dataconnect-deploy:
|
||||||
|
@echo "--> Deploying Firebase Data Connect schemas to [$(ENV)] (project: $(FIREBASE_ALIAS))..."
|
||||||
|
@firebase deploy --only dataconnect --project=$(FIREBASE_ALIAS)
|
||||||
|
@echo "✅ Data Connect deployment completed for [$(ENV)]."
|
||||||
13
dataconnect/dataconnect.yaml
Normal file
13
dataconnect/dataconnect.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
specVersion: "v1"
|
||||||
|
serviceId: "krow-workforce"
|
||||||
|
location: "us-central1"
|
||||||
|
schema:
|
||||||
|
source: "./schema"
|
||||||
|
datasource:
|
||||||
|
postgresql:
|
||||||
|
database: "fdcdb"
|
||||||
|
cloudSql:
|
||||||
|
instanceId: "krow-workforce-fdc"
|
||||||
|
# schemaValidation: "STRICT" # STRICT mode makes Postgres schema match Data Connect exactly.
|
||||||
|
# schemaValidation: "COMPATIBLE" # COMPATIBLE mode makes Postgres schema compatible with Data Connect.
|
||||||
|
connectorDirs: ["./example"]
|
||||||
8
dataconnect/example/connector.yaml
Normal file
8
dataconnect/example/connector.yaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
connectorId: example
|
||||||
|
generate:
|
||||||
|
javascriptSdk:
|
||||||
|
- outputDir: ../../frontend-web/src/dataconnect-generated
|
||||||
|
package: "@dataconnect/generated"
|
||||||
|
packageJsonDir: ../../frontend-web
|
||||||
|
react: true
|
||||||
|
angular: false
|
||||||
33
dataconnect/example/mutations.gql
Normal file
33
dataconnect/example/mutations.gql
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Example mutations for a simple movie app
|
||||||
|
|
||||||
|
# Create a movie based on user input
|
||||||
|
mutation CreateMovie($title: String!, $genre: String!, $imageUrl: String!)
|
||||||
|
@auth(level: USER_EMAIL_VERIFIED, insecureReason: "Any email verified users can create a new movie.") {
|
||||||
|
movie_insert(data: { title: $title, genre: $genre, imageUrl: $imageUrl })
|
||||||
|
}
|
||||||
|
|
||||||
|
# Upsert (update or insert) a user's username based on their auth.uid
|
||||||
|
mutation UpsertUser($username: String!) @auth(level: USER) {
|
||||||
|
# The "auth.uid" server value ensures that users can only register their own user.
|
||||||
|
user_upsert(data: { id_expr: "auth.uid", username: $username })
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add a review for a movie
|
||||||
|
mutation AddReview($movieId: UUID!, $rating: Int!, $reviewText: String!)
|
||||||
|
@auth(level: USER) {
|
||||||
|
review_upsert(
|
||||||
|
data: {
|
||||||
|
userId_expr: "auth.uid"
|
||||||
|
movieId: $movieId
|
||||||
|
rating: $rating
|
||||||
|
reviewText: $reviewText
|
||||||
|
# reviewDate defaults to today in the schema. No need to set it manually.
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Logged in user can delete their review for a movie
|
||||||
|
mutation DeleteReview($movieId: UUID!) @auth(level: USER) {
|
||||||
|
# The "auth.uid" server value ensures that users can only delete their own reviews.
|
||||||
|
review_delete(key: { userId_expr: "auth.uid", movieId: $movieId })
|
||||||
|
}
|
||||||
78
dataconnect/example/queries.gql
Normal file
78
dataconnect/example/queries.gql
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# Example queries for a simple movie app.
|
||||||
|
|
||||||
|
# @auth() directives control who can call each operation.
|
||||||
|
# Anyone should be able to list all movies, so the auth level is set to PUBLIC
|
||||||
|
query ListMovies @auth(level: PUBLIC, insecureReason: "Anyone can list all movies.") {
|
||||||
|
movies {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
imageUrl
|
||||||
|
genre
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# List all users, only admins should be able to list all users, so we use NO_ACCESS
|
||||||
|
query ListUsers @auth(level: NO_ACCESS) {
|
||||||
|
users {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Logged in users can list all their reviews and movie titles associated with the review
|
||||||
|
# Since the query uses the uid of the current authenticated user, we set auth level to USER
|
||||||
|
query ListUserReviews @auth(level: USER) {
|
||||||
|
user(key: { id_expr: "auth.uid" }) {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
# <field>_on_<foreign_key_field> makes it easy to grab info from another table
|
||||||
|
# Here, we use it to grab all the reviews written by the user.
|
||||||
|
reviews: reviews_on_user {
|
||||||
|
rating
|
||||||
|
reviewDate
|
||||||
|
reviewText
|
||||||
|
movie {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get movie by id
|
||||||
|
query GetMovieById($id: UUID!) @auth(level: PUBLIC, insecureReason: "Anyone can get a movie by id.") {
|
||||||
|
movie(id: $id) {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
imageUrl
|
||||||
|
genre
|
||||||
|
metadata: movieMetadata_on_movie {
|
||||||
|
rating
|
||||||
|
releaseYear
|
||||||
|
description
|
||||||
|
}
|
||||||
|
reviews: reviews_on_movie {
|
||||||
|
reviewText
|
||||||
|
reviewDate
|
||||||
|
rating
|
||||||
|
user {
|
||||||
|
id
|
||||||
|
username
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Search for movies, actors, and reviews
|
||||||
|
query SearchMovie($titleInput: String, $genre: String) @auth(level: PUBLIC, insecureReason: "Anyone can search for movies.") {
|
||||||
|
movies(
|
||||||
|
where: {
|
||||||
|
_and: [{ genre: { eq: $genre } }, { title: { contains: $titleInput } }]
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
genre
|
||||||
|
imageUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
52
dataconnect/schema/schema.gql
Normal file
52
dataconnect/schema/schema.gql
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Example schema for simple movie review app
|
||||||
|
|
||||||
|
# User table is keyed by Firebase Auth UID.
|
||||||
|
type User @table {
|
||||||
|
# `@default(expr: "auth.uid")` sets it to Firebase Auth UID during insert and upsert.
|
||||||
|
id: String! @default(expr: "auth.uid")
|
||||||
|
username: String! @col(dataType: "varchar(50)")
|
||||||
|
# The `user: User!` field in the Review table generates the following one-to-many query field.
|
||||||
|
# reviews_on_user: [Review!]!
|
||||||
|
# The `Review` join table the following many-to-many query field.
|
||||||
|
# movies_via_Review: [Movie!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
# Movie is keyed by a randomly generated UUID.
|
||||||
|
type Movie @table {
|
||||||
|
# If you do not pass a 'key' to `@table`, Data Connect automatically adds the following 'id' column.
|
||||||
|
# Feel free to uncomment and customize it.
|
||||||
|
# id: UUID! @default(expr: "uuidV4()")
|
||||||
|
title: String!
|
||||||
|
imageUrl: String!
|
||||||
|
genre: String
|
||||||
|
}
|
||||||
|
|
||||||
|
# MovieMetadata is a metadata attached to a Movie.
|
||||||
|
# Movie <-> MovieMetadata is a one-to-one relationship
|
||||||
|
type MovieMetadata @table {
|
||||||
|
# @unique ensures each Movie can only one MovieMetadata.
|
||||||
|
movie: Movie! @unique
|
||||||
|
# The movie field adds the following foreign key field. Feel free to uncomment and customize it.
|
||||||
|
# movieId: UUID!
|
||||||
|
rating: Float
|
||||||
|
releaseYear: Int
|
||||||
|
description: String
|
||||||
|
}
|
||||||
|
|
||||||
|
# Reviews is a join table between User and Movie.
|
||||||
|
# It has a composite primary keys `userUid` and `movieId`.
|
||||||
|
# A user can leave reviews for many movies. A movie can have reviews from many users.
|
||||||
|
# User <-> Review is a one-to-many relationship
|
||||||
|
# Movie <-> Review is a one-to-many relationship
|
||||||
|
# Movie <-> User is a many-to-many relationship
|
||||||
|
type Review @table(name: "Reviews", key: ["movie", "user"]) {
|
||||||
|
user: User!
|
||||||
|
# The user field adds the following foreign key field. Feel free to uncomment and customize it.
|
||||||
|
# userUid: String!
|
||||||
|
movie: Movie!
|
||||||
|
# The movie field adds the following foreign key field. Feel free to uncomment and customize it.
|
||||||
|
# movieId: UUID!
|
||||||
|
rating: Int
|
||||||
|
reviewText: String
|
||||||
|
reviewDate: Date! @default(expr: "request.time")
|
||||||
|
}
|
||||||
279
dataconnect/seed_data.gql
Normal file
279
dataconnect/seed_data.gql
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
mutation @transaction {
|
||||||
|
movie_insertMany(
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
title: "Quantum Paradox",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fquantum_paradox.jpeg?alt=media&token=4142e2a1-bf43-43b5-b7cf-6616be3fd4e3",
|
||||||
|
genre: "sci-fi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440001",
|
||||||
|
title: "The Lone Outlaw",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Flone_outlaw.jpeg?alt=media&token=15525ffc-208f-4b59-b506-ae8348e06e85",
|
||||||
|
genre: "western"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440002",
|
||||||
|
title: "Celestial Harmony",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fcelestial_harmony.jpeg?alt=media&token=3edf1cf9-c2f5-4c75-9819-36ff6a734c9a",
|
||||||
|
genre: "romance"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440003",
|
||||||
|
title: "Noir Mystique",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fnoir_mystique.jpeg?alt=media&token=3299adba-cb98-4302-8b23-aeb679a4f913",
|
||||||
|
genre: "mystery"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440004",
|
||||||
|
title: "The Forgotten Island",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fforgotten_island.jpeg?alt=media&token=bc2b16e1-caed-4649-952c-73b6113f205c",
|
||||||
|
genre: "adventure"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440005",
|
||||||
|
title: "Digital Nightmare",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fdigital_nightmare.jpeg?alt=media&token=335ec842-1ca4-4b09-abd1-e96d9f5c0c2f",
|
||||||
|
genre: "horror"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440006",
|
||||||
|
title: "Eclipse of Destiny",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Feclipse_destiny.jpeg?alt=media&token=346649b3-cb5c-4d7e-b0d4-6f02e3df5959",
|
||||||
|
genre: "fantasy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440007",
|
||||||
|
title: "Heart of Steel",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fheart_steel.jpeg?alt=media&token=17883d71-329b-415a-86f8-dd4d9e941d7f",
|
||||||
|
genre: "sci-fi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440008",
|
||||||
|
title: "Rise of the Crimson Empire",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Frise_crimson_empire.jpeg?alt=media&token=6faa73ad-7504-4146-8f3a-50b90f607f33",
|
||||||
|
genre: "action"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440009",
|
||||||
|
title: "Silent Waves",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fsilent_waves.jpeg?alt=media&token=bd626bf1-ec60-4e57-aa07-87ba14e35bb7",
|
||||||
|
genre: "drama"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440010",
|
||||||
|
title: "Echoes of the Past",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fecho_of_past.jpeg?alt=media&token=d866aa27-8534-4d72-8988-9da4a1b9e452",
|
||||||
|
genre: "historical"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440011",
|
||||||
|
title: "Beyond the Horizon",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fbeyond_horizon.jpeg?alt=media&token=31493973-0692-4e6e-8b88-afb1aaea17ee",
|
||||||
|
genre: "sci-fi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440012",
|
||||||
|
title: "Shadows and Lies",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fshadows_lies.jpeg?alt=media&token=01afb80d-caee-47f8-a00e-aea8b9e459a2",
|
||||||
|
genre: "crime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440013",
|
||||||
|
title: "The Last Symphony",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Flast_symphony.jpeg?alt=media&token=f9bf80cd-3d8e-4e24-8503-7feb11f4e397",
|
||||||
|
genre: "drama"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440014",
|
||||||
|
title: "Moonlit Crusade",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fmoonlit_crusade.jpeg?alt=media&token=b13241f5-d7d0-4370-b651-07847ad99dc2",
|
||||||
|
genre: "fantasy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440015",
|
||||||
|
title: "Abyss of the Deep",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fabyss_deep.jpeg?alt=media&token=2417321d-2451-4ec0-9ed6-6297042170e6",
|
||||||
|
genre: "horror"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440017",
|
||||||
|
title: "The Infinite Knot",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Finfinite_knot.jpeg?alt=media&token=93d54d93-d933-4663-a6fe-26b707ef823e",
|
||||||
|
genre: "romance"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "550e8400-e29b-41d4-a716-446655440019",
|
||||||
|
title: "Veil of Illusion",
|
||||||
|
imageUrl: "https://firebasestorage.googleapis.com/v0/b/fdc-web-quickstart.appspot.com/o/movie%2Fveil_illusion.jpeg?alt=media&token=7bf09a3c-c531-478a-9d02-5d99fca9393b",
|
||||||
|
genre: "mystery"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
movieMetadata_insertMany(
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
rating: 7.9,
|
||||||
|
releaseYear: 2025,
|
||||||
|
description: "A group of scientists accidentally open a portal to a parallel universe, causing a rift in time. As the team races to close the portal, they encounter alternate versions of themselves, leading to shocking revelations."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440001",
|
||||||
|
rating: 8.2,
|
||||||
|
releaseYear: 2023,
|
||||||
|
description: "In the lawless Wild West, a mysterious gunslinger with a hidden past takes on a corrupt sheriff and his band of outlaws to bring justice to a small town."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440002",
|
||||||
|
rating: 7.5,
|
||||||
|
releaseYear: 2024,
|
||||||
|
description: "Two astronauts, stationed on a remote space station, fall in love amidst the isolation of deep space. But when a mysterious signal disrupts their communication, they must find a way to reconnect and survive."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440003",
|
||||||
|
rating: 8.0,
|
||||||
|
releaseYear: 2022,
|
||||||
|
description: "A private detective gets caught up in a web of lies, deception, and betrayal while investigating the disappearance of a famous actress in 1940s Hollywood."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440004",
|
||||||
|
rating: 7.6,
|
||||||
|
releaseYear: 2025,
|
||||||
|
description: "An explorer leads an expedition to a remote island rumored to be home to mythical creatures. As the team ventures deeper into the island, they uncover secrets that change the course of history."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440005",
|
||||||
|
rating: 6.9,
|
||||||
|
releaseYear: 2024,
|
||||||
|
description: "A tech-savvy teenager discovers a cursed app that brings nightmares to life. As the horrors of the digital world cross into reality, she must find a way to break the curse before it's too late."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440006",
|
||||||
|
rating: 8.1,
|
||||||
|
releaseYear: 2026,
|
||||||
|
description: "In a kingdom on the brink of war, a prophecy speaks of an eclipse that will grant power to the rightful ruler. As factions vie for control, a young warrior must decide where his true loyalty lies."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440007",
|
||||||
|
rating: 7.7,
|
||||||
|
releaseYear: 2023,
|
||||||
|
description: "A brilliant scientist creates a robot with a human heart. As the robot struggles to understand emotions, it becomes entangled in a plot that could change the fate of humanity."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440008",
|
||||||
|
rating: 8.4,
|
||||||
|
releaseYear: 2025,
|
||||||
|
description: "A legendary warrior rises to challenge the tyrannical rule of a powerful empire. As rebellion brews, the warrior must unite different factions to lead an uprising."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440009",
|
||||||
|
rating: 8.2,
|
||||||
|
releaseYear: 2024,
|
||||||
|
description: "A talented pianist, who loses his hearing in a tragic accident, must rediscover his passion for music with the help of a young music teacher who believes in him."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440010",
|
||||||
|
rating: 7.8,
|
||||||
|
releaseYear: 2023,
|
||||||
|
description: "A historian stumbles upon an ancient artifact that reveals hidden truths about an empire long forgotten. As she deciphers the clues, a shadowy organization tries to stop her from unearthing the past."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440011",
|
||||||
|
rating: 8.5,
|
||||||
|
releaseYear: 2026,
|
||||||
|
description: "In the future, Earth's best pilots are sent on a mission to explore a mysterious planet beyond the solar system. What they find changes humanity's understanding of the universe forever."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440012",
|
||||||
|
rating: 7.9,
|
||||||
|
releaseYear: 2022,
|
||||||
|
description: "A young detective with a dark past investigates a series of mysterious murders in a city plagued by corruption. As she digs deeper, she realizes nothing is as it seems."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440013",
|
||||||
|
rating: 8.0,
|
||||||
|
releaseYear: 2024,
|
||||||
|
description: "An aging composer struggling with memory loss attempts to complete his final symphony. With the help of a young prodigy, he embarks on an emotional journey through his memories and legacy."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440014",
|
||||||
|
rating: 8.3,
|
||||||
|
releaseYear: 2025,
|
||||||
|
description: "A knight is chosen by an ancient order to embark on a quest under the light of the full moon. Facing mythical beasts and treacherous landscapes, he seeks a relic that could save his kingdom."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440015",
|
||||||
|
rating: 7.2,
|
||||||
|
releaseYear: 2023,
|
||||||
|
description: "When a group of marine biologists descends into the unexplored depths of the ocean, they encounter a terrifying and ancient force. Now, they must survive as the abyss comes alive."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440017",
|
||||||
|
rating: 7.4,
|
||||||
|
releaseYear: 2026,
|
||||||
|
description: "Two souls destined to meet across multiple lifetimes struggle to find each other in a chaotic world. With each incarnation, they get closer, but time itself becomes their greatest obstacle."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440019",
|
||||||
|
rating: 7.8,
|
||||||
|
releaseYear: 2022,
|
||||||
|
description: "A magician-turned-detective uses his skills in illusion to solve crimes. When a series of murders leaves the city in fear, he must reveal the truth hidden behind a veil of deceit."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
user_insertMany(
|
||||||
|
data: [
|
||||||
|
{ id: "SnLgOC3lN4hcIl69s53cW0Q8R1T2", username: "sherlock_h" },
|
||||||
|
{ id: "fep4fXpGWsaRpuphq9CIrBIXQ0S2", username: "hercule_p" },
|
||||||
|
{ id: "TBedjwCX0Jf955Uuoxk6k74sY0l1", username: "jane_d" }
|
||||||
|
]
|
||||||
|
)
|
||||||
|
review_insertMany(
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
userId: "SnLgOC3lN4hcIl69s53cW0Q8R1T2",
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
rating: 5,
|
||||||
|
reviewText: "An incredible movie with a mind-blowing plot!",
|
||||||
|
reviewDate: "2025-10-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
userId: "fep4fXpGWsaRpuphq9CIrBIXQ0S2",
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440001",
|
||||||
|
rating: 5,
|
||||||
|
reviewText: "A revolutionary film that changed cinema forever.",
|
||||||
|
reviewDate: "2025-10-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
userId: "TBedjwCX0Jf955Uuoxk6k74sY0l1",
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440002",
|
||||||
|
rating: 5,
|
||||||
|
reviewText: "A visually stunning and emotionally impactful movie.",
|
||||||
|
reviewDate: "2025-10-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
userId: "SnLgOC3lN4hcIl69s53cW0Q8R1T2",
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440003",
|
||||||
|
rating: 4,
|
||||||
|
reviewText: "A fantastic superhero film with great performances.",
|
||||||
|
reviewDate: "2025-10-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
userId: "fep4fXpGWsaRpuphq9CIrBIXQ0S2",
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440004",
|
||||||
|
rating: 5,
|
||||||
|
reviewText: "An amazing film that keeps you on the edge of your seat.",
|
||||||
|
reviewDate: "2025-10-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
userId: "TBedjwCX0Jf955Uuoxk6k74sY0l1",
|
||||||
|
movieId: "550e8400-e29b-41d4-a716-446655440005",
|
||||||
|
rating: 5,
|
||||||
|
reviewText: "An absolute classic with unforgettable dialogue.",
|
||||||
|
reviewDate: "2025-10-01"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -45,5 +45,13 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"emulators": {
|
||||||
|
"dataconnect": {
|
||||||
|
"dataDir": "dataconnect/.dataconnect/pgliteData"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dataconnect": {
|
||||||
|
"source": "dataconnect"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
986
frontend-web/package-lock.json
generated
986
frontend-web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@base44/sdk": "^0.1.2",
|
"@base44/sdk": "^0.1.2",
|
||||||
|
"@dataconnect/generated": "file:src/dataconnect-generated",
|
||||||
"@hookform/resolvers": "^4.1.2",
|
"@hookform/resolvers": "^4.1.2",
|
||||||
"@radix-ui/react-accordion": "^1.2.3",
|
"@radix-ui/react-accordion": "^1.2.3",
|
||||||
"@radix-ui/react-alert-dialog": "^1.1.6",
|
"@radix-ui/react-alert-dialog": "^1.1.6",
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"description": "A set of guides for interacting with the generated firebase dataconnect sdk",
|
||||||
|
"mcpServers": {
|
||||||
|
"firebase": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": ["-y", "firebase-tools@latest", "experimental:mcp"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
frontend-web/src/dataconnect-generated/.guides/setup.md
Normal file
62
frontend-web/src/dataconnect-generated/.guides/setup.md
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Setup
|
||||||
|
|
||||||
|
If the user hasn't already installed the SDK, always run the user's node package manager of choice, and install the package in the directory ../package.json.
|
||||||
|
For more information on where the library is located, look at the connector.yaml file.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { initializeApp } from 'firebase/app';
|
||||||
|
|
||||||
|
initializeApp({
|
||||||
|
// fill in your project config here using the values from your Firebase project or from the `firebase_get_sdk_config` tool from the Firebase MCP server.
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, you can run the SDK as needed.
|
||||||
|
```ts
|
||||||
|
import { ... } from '@dataconnect/generated';
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## React
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
The user should make sure to install the `@tanstack/react-query` package, along with `@tanstack-query-firebase/react` and `firebase`.
|
||||||
|
|
||||||
|
Then, they should initialize Firebase:
|
||||||
|
```ts
|
||||||
|
import { initializeApp } from 'firebase/app';
|
||||||
|
initializeApp(firebaseConfig); /* your config here. To generate this, you can use the `firebase_sdk_config` MCP tool */
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, they should add a `QueryClientProvider` to their root of their application.
|
||||||
|
|
||||||
|
Here's an example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { initializeApp } from 'firebase/app';
|
||||||
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
const firebaseConfig = {
|
||||||
|
/* your config here. To generate this, you can use the `firebase_sdk_config` MCP tool */
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize Firebase
|
||||||
|
const app = initializeApp(firebaseConfig);
|
||||||
|
|
||||||
|
// Create a TanStack Query client instance
|
||||||
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
// Provide the client to your App
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<MyApplication />
|
||||||
|
</QueryClientProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
render(<App />, document.getElementById('root'));
|
||||||
|
```
|
||||||
|
|
||||||
104
frontend-web/src/dataconnect-generated/.guides/usage.md
Normal file
104
frontend-web/src/dataconnect-generated/.guides/usage.md
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# Basic Usage
|
||||||
|
|
||||||
|
Always prioritize using a supported framework over using the generated SDK
|
||||||
|
directly. Supported frameworks simplify the developer experience and help ensure
|
||||||
|
best practices are followed.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### React
|
||||||
|
For each operation, there is a wrapper hook that can be used to call the operation.
|
||||||
|
|
||||||
|
Here are all of the hooks that get generated:
|
||||||
|
```ts
|
||||||
|
import { useCreateMovie, useUpsertUser, useAddReview, useDeleteReview, useListMovies, useListUsers, useListUserReviews, useGetMovieById, useSearchMovie } from '@dataconnect/generated/react';
|
||||||
|
// The types of these hooks are available in react/index.d.ts
|
||||||
|
|
||||||
|
const { data, isPending, isSuccess, isError, error } = useCreateMovie(createMovieVars);
|
||||||
|
|
||||||
|
const { data, isPending, isSuccess, isError, error } = useUpsertUser(upsertUserVars);
|
||||||
|
|
||||||
|
const { data, isPending, isSuccess, isError, error } = useAddReview(addReviewVars);
|
||||||
|
|
||||||
|
const { data, isPending, isSuccess, isError, error } = useDeleteReview(deleteReviewVars);
|
||||||
|
|
||||||
|
const { data, isPending, isSuccess, isError, error } = useListMovies();
|
||||||
|
|
||||||
|
const { data, isPending, isSuccess, isError, error } = useListUsers();
|
||||||
|
|
||||||
|
const { data, isPending, isSuccess, isError, error } = useListUserReviews();
|
||||||
|
|
||||||
|
const { data, isPending, isSuccess, isError, error } = useGetMovieById(getMovieByIdVars);
|
||||||
|
|
||||||
|
const { data, isPending, isSuccess, isError, error } = useSearchMovie(searchMovieVars);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Here's an example from a different generated SDK:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { useListAllMovies } from '@dataconnect/generated/react';
|
||||||
|
|
||||||
|
function MyComponent() {
|
||||||
|
const { isLoading, data, error } = useListAllMovies();
|
||||||
|
if(isLoading) {
|
||||||
|
return <div>Loading...</div>
|
||||||
|
}
|
||||||
|
if(error) {
|
||||||
|
return <div> An Error Occurred: {error} </div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// App.tsx
|
||||||
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
import MyComponent from './my-component';
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
const queryClient = new QueryClient();
|
||||||
|
return <QueryClientProvider client={queryClient}>
|
||||||
|
<MyComponent />
|
||||||
|
</QueryClientProvider>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Advanced Usage
|
||||||
|
If a user is not using a supported framework, they can use the generated SDK directly.
|
||||||
|
|
||||||
|
Here's an example of how to use it with the first 5 operations:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createMovie, upsertUser, addReview, deleteReview, listMovies, listUsers, listUserReviews, getMovieById, searchMovie } from '@dataconnect/generated';
|
||||||
|
|
||||||
|
|
||||||
|
// Operation CreateMovie: For variables, look at type CreateMovieVars in ../index.d.ts
|
||||||
|
const { data } = await CreateMovie(dataConnect, createMovieVars);
|
||||||
|
|
||||||
|
// Operation UpsertUser: For variables, look at type UpsertUserVars in ../index.d.ts
|
||||||
|
const { data } = await UpsertUser(dataConnect, upsertUserVars);
|
||||||
|
|
||||||
|
// Operation AddReview: For variables, look at type AddReviewVars in ../index.d.ts
|
||||||
|
const { data } = await AddReview(dataConnect, addReviewVars);
|
||||||
|
|
||||||
|
// Operation DeleteReview: For variables, look at type DeleteReviewVars in ../index.d.ts
|
||||||
|
const { data } = await DeleteReview(dataConnect, deleteReviewVars);
|
||||||
|
|
||||||
|
// Operation ListMovies:
|
||||||
|
const { data } = await ListMovies(dataConnect);
|
||||||
|
|
||||||
|
// Operation ListUsers:
|
||||||
|
const { data } = await ListUsers(dataConnect);
|
||||||
|
|
||||||
|
// Operation ListUserReviews:
|
||||||
|
const { data } = await ListUserReviews(dataConnect);
|
||||||
|
|
||||||
|
// Operation GetMovieById: For variables, look at type GetMovieByIdVars in ../index.d.ts
|
||||||
|
const { data } = await GetMovieById(dataConnect, getMovieByIdVars);
|
||||||
|
|
||||||
|
// Operation SearchMovie: For variables, look at type SearchMovieVars in ../index.d.ts
|
||||||
|
const { data } = await SearchMovie(dataConnect, searchMovieVars);
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
1073
frontend-web/src/dataconnect-generated/README.md
Normal file
1073
frontend-web/src/dataconnect-generated/README.md
Normal file
File diff suppressed because it is too large
Load Diff
107
frontend-web/src/dataconnect-generated/esm/index.esm.js
Normal file
107
frontend-web/src/dataconnect-generated/esm/index.esm.js
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } from 'firebase/data-connect';
|
||||||
|
|
||||||
|
export const connectorConfig = {
|
||||||
|
connector: 'example',
|
||||||
|
service: 'krow-workforce',
|
||||||
|
location: 'us-central1'
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createMovieRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return mutationRef(dcInstance, 'CreateMovie', inputVars);
|
||||||
|
}
|
||||||
|
createMovieRef.operationName = 'CreateMovie';
|
||||||
|
|
||||||
|
export function createMovie(dcOrVars, vars) {
|
||||||
|
return executeMutation(createMovieRef(dcOrVars, vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const upsertUserRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return mutationRef(dcInstance, 'UpsertUser', inputVars);
|
||||||
|
}
|
||||||
|
upsertUserRef.operationName = 'UpsertUser';
|
||||||
|
|
||||||
|
export function upsertUser(dcOrVars, vars) {
|
||||||
|
return executeMutation(upsertUserRef(dcOrVars, vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const addReviewRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return mutationRef(dcInstance, 'AddReview', inputVars);
|
||||||
|
}
|
||||||
|
addReviewRef.operationName = 'AddReview';
|
||||||
|
|
||||||
|
export function addReview(dcOrVars, vars) {
|
||||||
|
return executeMutation(addReviewRef(dcOrVars, vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deleteReviewRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return mutationRef(dcInstance, 'DeleteReview', inputVars);
|
||||||
|
}
|
||||||
|
deleteReviewRef.operationName = 'DeleteReview';
|
||||||
|
|
||||||
|
export function deleteReview(dcOrVars, vars) {
|
||||||
|
return executeMutation(deleteReviewRef(dcOrVars, vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const listMoviesRef = (dc) => {
|
||||||
|
const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return queryRef(dcInstance, 'ListMovies');
|
||||||
|
}
|
||||||
|
listMoviesRef.operationName = 'ListMovies';
|
||||||
|
|
||||||
|
export function listMovies(dc) {
|
||||||
|
return executeQuery(listMoviesRef(dc));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const listUsersRef = (dc) => {
|
||||||
|
const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return queryRef(dcInstance, 'ListUsers');
|
||||||
|
}
|
||||||
|
listUsersRef.operationName = 'ListUsers';
|
||||||
|
|
||||||
|
export function listUsers(dc) {
|
||||||
|
return executeQuery(listUsersRef(dc));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const listUserReviewsRef = (dc) => {
|
||||||
|
const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return queryRef(dcInstance, 'ListUserReviews');
|
||||||
|
}
|
||||||
|
listUserReviewsRef.operationName = 'ListUserReviews';
|
||||||
|
|
||||||
|
export function listUserReviews(dc) {
|
||||||
|
return executeQuery(listUserReviewsRef(dc));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getMovieByIdRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return queryRef(dcInstance, 'GetMovieById', inputVars);
|
||||||
|
}
|
||||||
|
getMovieByIdRef.operationName = 'GetMovieById';
|
||||||
|
|
||||||
|
export function getMovieById(dcOrVars, vars) {
|
||||||
|
return executeQuery(getMovieByIdRef(dcOrVars, vars));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const searchMovieRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return queryRef(dcInstance, 'SearchMovie', inputVars);
|
||||||
|
}
|
||||||
|
searchMovieRef.operationName = 'SearchMovie';
|
||||||
|
|
||||||
|
export function searchMovie(dcOrVars, vars) {
|
||||||
|
return executeQuery(searchMovieRef(dcOrVars, vars));
|
||||||
|
}
|
||||||
|
|
||||||
1
frontend-web/src/dataconnect-generated/esm/package.json
Normal file
1
frontend-web/src/dataconnect-generated/esm/package.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"type":"module"}
|
||||||
116
frontend-web/src/dataconnect-generated/index.cjs.js
Normal file
116
frontend-web/src/dataconnect-generated/index.cjs.js
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
const { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } = require('firebase/data-connect');
|
||||||
|
|
||||||
|
const connectorConfig = {
|
||||||
|
connector: 'example',
|
||||||
|
service: 'krow-workforce',
|
||||||
|
location: 'us-central1'
|
||||||
|
};
|
||||||
|
exports.connectorConfig = connectorConfig;
|
||||||
|
|
||||||
|
const createMovieRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return mutationRef(dcInstance, 'CreateMovie', inputVars);
|
||||||
|
}
|
||||||
|
createMovieRef.operationName = 'CreateMovie';
|
||||||
|
exports.createMovieRef = createMovieRef;
|
||||||
|
|
||||||
|
exports.createMovie = function createMovie(dcOrVars, vars) {
|
||||||
|
return executeMutation(createMovieRef(dcOrVars, vars));
|
||||||
|
};
|
||||||
|
|
||||||
|
const upsertUserRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return mutationRef(dcInstance, 'UpsertUser', inputVars);
|
||||||
|
}
|
||||||
|
upsertUserRef.operationName = 'UpsertUser';
|
||||||
|
exports.upsertUserRef = upsertUserRef;
|
||||||
|
|
||||||
|
exports.upsertUser = function upsertUser(dcOrVars, vars) {
|
||||||
|
return executeMutation(upsertUserRef(dcOrVars, vars));
|
||||||
|
};
|
||||||
|
|
||||||
|
const addReviewRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return mutationRef(dcInstance, 'AddReview', inputVars);
|
||||||
|
}
|
||||||
|
addReviewRef.operationName = 'AddReview';
|
||||||
|
exports.addReviewRef = addReviewRef;
|
||||||
|
|
||||||
|
exports.addReview = function addReview(dcOrVars, vars) {
|
||||||
|
return executeMutation(addReviewRef(dcOrVars, vars));
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteReviewRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return mutationRef(dcInstance, 'DeleteReview', inputVars);
|
||||||
|
}
|
||||||
|
deleteReviewRef.operationName = 'DeleteReview';
|
||||||
|
exports.deleteReviewRef = deleteReviewRef;
|
||||||
|
|
||||||
|
exports.deleteReview = function deleteReview(dcOrVars, vars) {
|
||||||
|
return executeMutation(deleteReviewRef(dcOrVars, vars));
|
||||||
|
};
|
||||||
|
|
||||||
|
const listMoviesRef = (dc) => {
|
||||||
|
const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return queryRef(dcInstance, 'ListMovies');
|
||||||
|
}
|
||||||
|
listMoviesRef.operationName = 'ListMovies';
|
||||||
|
exports.listMoviesRef = listMoviesRef;
|
||||||
|
|
||||||
|
exports.listMovies = function listMovies(dc) {
|
||||||
|
return executeQuery(listMoviesRef(dc));
|
||||||
|
};
|
||||||
|
|
||||||
|
const listUsersRef = (dc) => {
|
||||||
|
const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return queryRef(dcInstance, 'ListUsers');
|
||||||
|
}
|
||||||
|
listUsersRef.operationName = 'ListUsers';
|
||||||
|
exports.listUsersRef = listUsersRef;
|
||||||
|
|
||||||
|
exports.listUsers = function listUsers(dc) {
|
||||||
|
return executeQuery(listUsersRef(dc));
|
||||||
|
};
|
||||||
|
|
||||||
|
const listUserReviewsRef = (dc) => {
|
||||||
|
const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return queryRef(dcInstance, 'ListUserReviews');
|
||||||
|
}
|
||||||
|
listUserReviewsRef.operationName = 'ListUserReviews';
|
||||||
|
exports.listUserReviewsRef = listUserReviewsRef;
|
||||||
|
|
||||||
|
exports.listUserReviews = function listUserReviews(dc) {
|
||||||
|
return executeQuery(listUserReviewsRef(dc));
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMovieByIdRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return queryRef(dcInstance, 'GetMovieById', inputVars);
|
||||||
|
}
|
||||||
|
getMovieByIdRef.operationName = 'GetMovieById';
|
||||||
|
exports.getMovieByIdRef = getMovieByIdRef;
|
||||||
|
|
||||||
|
exports.getMovieById = function getMovieById(dcOrVars, vars) {
|
||||||
|
return executeQuery(getMovieByIdRef(dcOrVars, vars));
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchMovieRef = (dcOrVars, vars) => {
|
||||||
|
const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars);
|
||||||
|
dcInstance._useGeneratedSdk();
|
||||||
|
return queryRef(dcInstance, 'SearchMovie', inputVars);
|
||||||
|
}
|
||||||
|
searchMovieRef.operationName = 'SearchMovie';
|
||||||
|
exports.searchMovieRef = searchMovieRef;
|
||||||
|
|
||||||
|
exports.searchMovie = function searchMovie(dcOrVars, vars) {
|
||||||
|
return executeQuery(searchMovieRef(dcOrVars, vars));
|
||||||
|
};
|
||||||
250
frontend-web/src/dataconnect-generated/index.d.ts
vendored
Normal file
250
frontend-web/src/dataconnect-generated/index.d.ts
vendored
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
import { ConnectorConfig, DataConnect, QueryRef, QueryPromise, MutationRef, MutationPromise } from 'firebase/data-connect';
|
||||||
|
|
||||||
|
export const connectorConfig: ConnectorConfig;
|
||||||
|
|
||||||
|
export type TimestampString = string;
|
||||||
|
export type UUIDString = string;
|
||||||
|
export type Int64String = string;
|
||||||
|
export type DateString = string;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export interface AddReviewData {
|
||||||
|
review_upsert: Review_Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AddReviewVariables {
|
||||||
|
movieId: UUIDString;
|
||||||
|
rating: number;
|
||||||
|
reviewText: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateMovieData {
|
||||||
|
movie_insert: Movie_Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateMovieVariables {
|
||||||
|
title: string;
|
||||||
|
genre: string;
|
||||||
|
imageUrl: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeleteReviewData {
|
||||||
|
review_delete?: Review_Key | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeleteReviewVariables {
|
||||||
|
movieId: UUIDString;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetMovieByIdData {
|
||||||
|
movie?: {
|
||||||
|
id: UUIDString;
|
||||||
|
title: string;
|
||||||
|
imageUrl: string;
|
||||||
|
genre?: string | null;
|
||||||
|
metadata?: {
|
||||||
|
rating?: number | null;
|
||||||
|
releaseYear?: number | null;
|
||||||
|
description?: string | null;
|
||||||
|
};
|
||||||
|
reviews: ({
|
||||||
|
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;
|
||||||
|
genre?: string | null;
|
||||||
|
} & Movie_Key)[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ListUserReviewsData {
|
||||||
|
user?: {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
reviews: ({
|
||||||
|
rating?: number | null;
|
||||||
|
reviewDate: DateString;
|
||||||
|
reviewText?: string | null;
|
||||||
|
movie: {
|
||||||
|
id: UUIDString;
|
||||||
|
title: string;
|
||||||
|
} & Movie_Key;
|
||||||
|
})[];
|
||||||
|
} & User_Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ListUsersData {
|
||||||
|
users: ({
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
} & User_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 SearchMovieData {
|
||||||
|
movies: ({
|
||||||
|
id: UUIDString;
|
||||||
|
title: string;
|
||||||
|
genre?: string | null;
|
||||||
|
imageUrl: string;
|
||||||
|
} & Movie_Key)[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchMovieVariables {
|
||||||
|
titleInput?: string | null;
|
||||||
|
genre?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpsertUserData {
|
||||||
|
user_upsert: User_Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpsertUserVariables {
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface User_Key {
|
||||||
|
id: string;
|
||||||
|
__typename?: 'User_Key';
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CreateMovieRef {
|
||||||
|
/* Allow users to create refs without passing in DataConnect */
|
||||||
|
(vars: CreateMovieVariables): MutationRef<CreateMovieData, CreateMovieVariables>;
|
||||||
|
/* Allow users to pass in custom DataConnect instances */
|
||||||
|
(dc: DataConnect, vars: CreateMovieVariables): MutationRef<CreateMovieData, CreateMovieVariables>;
|
||||||
|
operationName: string;
|
||||||
|
}
|
||||||
|
export const createMovieRef: CreateMovieRef;
|
||||||
|
|
||||||
|
export function createMovie(vars: CreateMovieVariables): MutationPromise<CreateMovieData, CreateMovieVariables>;
|
||||||
|
export function createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise<CreateMovieData, CreateMovieVariables>;
|
||||||
|
|
||||||
|
interface UpsertUserRef {
|
||||||
|
/* Allow users to create refs without passing in DataConnect */
|
||||||
|
(vars: UpsertUserVariables): MutationRef<UpsertUserData, UpsertUserVariables>;
|
||||||
|
/* Allow users to pass in custom DataConnect instances */
|
||||||
|
(dc: DataConnect, vars: UpsertUserVariables): MutationRef<UpsertUserData, UpsertUserVariables>;
|
||||||
|
operationName: string;
|
||||||
|
}
|
||||||
|
export const upsertUserRef: UpsertUserRef;
|
||||||
|
|
||||||
|
export function upsertUser(vars: UpsertUserVariables): MutationPromise<UpsertUserData, UpsertUserVariables>;
|
||||||
|
export function upsertUser(dc: DataConnect, vars: UpsertUserVariables): MutationPromise<UpsertUserData, UpsertUserVariables>;
|
||||||
|
|
||||||
|
interface AddReviewRef {
|
||||||
|
/* Allow users to create refs without passing in DataConnect */
|
||||||
|
(vars: AddReviewVariables): MutationRef<AddReviewData, AddReviewVariables>;
|
||||||
|
/* Allow users to pass in custom DataConnect instances */
|
||||||
|
(dc: DataConnect, vars: AddReviewVariables): MutationRef<AddReviewData, AddReviewVariables>;
|
||||||
|
operationName: string;
|
||||||
|
}
|
||||||
|
export const addReviewRef: AddReviewRef;
|
||||||
|
|
||||||
|
export function addReview(vars: AddReviewVariables): MutationPromise<AddReviewData, AddReviewVariables>;
|
||||||
|
export function addReview(dc: DataConnect, vars: AddReviewVariables): MutationPromise<AddReviewData, AddReviewVariables>;
|
||||||
|
|
||||||
|
interface DeleteReviewRef {
|
||||||
|
/* Allow users to create refs without passing in DataConnect */
|
||||||
|
(vars: DeleteReviewVariables): MutationRef<DeleteReviewData, DeleteReviewVariables>;
|
||||||
|
/* Allow users to pass in custom DataConnect instances */
|
||||||
|
(dc: DataConnect, vars: DeleteReviewVariables): MutationRef<DeleteReviewData, DeleteReviewVariables>;
|
||||||
|
operationName: string;
|
||||||
|
}
|
||||||
|
export const deleteReviewRef: DeleteReviewRef;
|
||||||
|
|
||||||
|
export function deleteReview(vars: DeleteReviewVariables): MutationPromise<DeleteReviewData, DeleteReviewVariables>;
|
||||||
|
export function deleteReview(dc: DataConnect, vars: DeleteReviewVariables): MutationPromise<DeleteReviewData, DeleteReviewVariables>;
|
||||||
|
|
||||||
|
interface ListMoviesRef {
|
||||||
|
/* Allow users to create refs without passing in DataConnect */
|
||||||
|
(): QueryRef<ListMoviesData, undefined>;
|
||||||
|
/* Allow users to pass in custom DataConnect instances */
|
||||||
|
(dc: DataConnect): QueryRef<ListMoviesData, undefined>;
|
||||||
|
operationName: string;
|
||||||
|
}
|
||||||
|
export const listMoviesRef: ListMoviesRef;
|
||||||
|
|
||||||
|
export function listMovies(): QueryPromise<ListMoviesData, undefined>;
|
||||||
|
export function listMovies(dc: DataConnect): QueryPromise<ListMoviesData, undefined>;
|
||||||
|
|
||||||
|
interface ListUsersRef {
|
||||||
|
/* Allow users to create refs without passing in DataConnect */
|
||||||
|
(): QueryRef<ListUsersData, undefined>;
|
||||||
|
/* Allow users to pass in custom DataConnect instances */
|
||||||
|
(dc: DataConnect): QueryRef<ListUsersData, undefined>;
|
||||||
|
operationName: string;
|
||||||
|
}
|
||||||
|
export const listUsersRef: ListUsersRef;
|
||||||
|
|
||||||
|
export function listUsers(): QueryPromise<ListUsersData, undefined>;
|
||||||
|
export function listUsers(dc: DataConnect): QueryPromise<ListUsersData, undefined>;
|
||||||
|
|
||||||
|
interface ListUserReviewsRef {
|
||||||
|
/* Allow users to create refs without passing in DataConnect */
|
||||||
|
(): QueryRef<ListUserReviewsData, undefined>;
|
||||||
|
/* Allow users to pass in custom DataConnect instances */
|
||||||
|
(dc: DataConnect): QueryRef<ListUserReviewsData, undefined>;
|
||||||
|
operationName: string;
|
||||||
|
}
|
||||||
|
export const listUserReviewsRef: ListUserReviewsRef;
|
||||||
|
|
||||||
|
export function listUserReviews(): QueryPromise<ListUserReviewsData, undefined>;
|
||||||
|
export function listUserReviews(dc: DataConnect): QueryPromise<ListUserReviewsData, undefined>;
|
||||||
|
|
||||||
|
interface GetMovieByIdRef {
|
||||||
|
/* Allow users to create refs without passing in DataConnect */
|
||||||
|
(vars: GetMovieByIdVariables): QueryRef<GetMovieByIdData, GetMovieByIdVariables>;
|
||||||
|
/* Allow users to pass in custom DataConnect instances */
|
||||||
|
(dc: DataConnect, vars: GetMovieByIdVariables): QueryRef<GetMovieByIdData, GetMovieByIdVariables>;
|
||||||
|
operationName: string;
|
||||||
|
}
|
||||||
|
export const getMovieByIdRef: GetMovieByIdRef;
|
||||||
|
|
||||||
|
export function getMovieById(vars: GetMovieByIdVariables): QueryPromise<GetMovieByIdData, GetMovieByIdVariables>;
|
||||||
|
export function getMovieById(dc: DataConnect, vars: GetMovieByIdVariables): QueryPromise<GetMovieByIdData, GetMovieByIdVariables>;
|
||||||
|
|
||||||
|
interface SearchMovieRef {
|
||||||
|
/* Allow users to create refs without passing in DataConnect */
|
||||||
|
(vars?: SearchMovieVariables): QueryRef<SearchMovieData, SearchMovieVariables>;
|
||||||
|
/* Allow users to pass in custom DataConnect instances */
|
||||||
|
(dc: DataConnect, vars?: SearchMovieVariables): QueryRef<SearchMovieData, SearchMovieVariables>;
|
||||||
|
operationName: string;
|
||||||
|
}
|
||||||
|
export const searchMovieRef: SearchMovieRef;
|
||||||
|
|
||||||
|
export function searchMovie(vars?: SearchMovieVariables): QueryPromise<SearchMovieData, SearchMovieVariables>;
|
||||||
|
export function searchMovie(dc: DataConnect, vars?: SearchMovieVariables): QueryPromise<SearchMovieData, SearchMovieVariables>;
|
||||||
|
|
||||||
32
frontend-web/src/dataconnect-generated/package.json
Normal file
32
frontend-web/src/dataconnect-generated/package.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "@dataconnect/generated",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": "Firebase <firebase-support@google.com> (https://firebase.google.com/)",
|
||||||
|
"description": "Generated SDK For example",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": " >=18.0"
|
||||||
|
},
|
||||||
|
"typings": "index.d.ts",
|
||||||
|
"module": "esm/index.esm.js",
|
||||||
|
"main": "index.cjs.js",
|
||||||
|
"browser": "esm/index.esm.js",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./index.d.ts",
|
||||||
|
"require": "./index.cjs.js",
|
||||||
|
"default": "./esm/index.esm.js"
|
||||||
|
},
|
||||||
|
"./react": {
|
||||||
|
"types": "./react/index.d.ts",
|
||||||
|
"require": "./react/index.cjs.js",
|
||||||
|
"import": "./react/esm/index.esm.js",
|
||||||
|
"default": "./react/esm/index.esm.js"
|
||||||
|
},
|
||||||
|
"./package.json": "./package.json"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"firebase": "^11.3.0 || ^12.0.0",
|
||||||
|
"@tanstack-query-firebase/react": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
952
frontend-web/src/dataconnect-generated/react/README.md
Normal file
952
frontend-web/src/dataconnect-generated/react/README.md
Normal file
@@ -0,0 +1,952 @@
|
|||||||
|
# Generated React README
|
||||||
|
This README will guide you through the process of using the generated React SDK package for the connector `example`. It will also provide examples on how to use your generated SDK to call your Data Connect queries and mutations.
|
||||||
|
|
||||||
|
**If you're looking for the `JavaScript README`, you can find it at [`dataconnect-generated/README.md`](../README.md)**
|
||||||
|
|
||||||
|
***NOTE:** This README is generated alongside the generated SDK. If you make changes to this file, they will be overwritten when the SDK is regenerated.*
|
||||||
|
|
||||||
|
You can use this generated SDK by importing from the package `@dataconnect/generated/react` as shown below. Both CommonJS and ESM imports are supported.
|
||||||
|
|
||||||
|
You can also follow the instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#react).
|
||||||
|
|
||||||
|
# Table of Contents
|
||||||
|
- [**Overview**](#generated-react-readme)
|
||||||
|
- [**TanStack Query Firebase & TanStack React Query**](#tanstack-query-firebase-tanstack-react-query)
|
||||||
|
- [*Package Installation*](#installing-tanstack-query-firebase-and-tanstack-react-query-packages)
|
||||||
|
- [*Configuring TanStack Query*](#configuring-tanstack-query)
|
||||||
|
- [**Accessing the connector**](#accessing-the-connector)
|
||||||
|
- [*Connecting to the local Emulator*](#connecting-to-the-local-emulator)
|
||||||
|
- [**Queries**](#queries)
|
||||||
|
- [*ListMovies*](#listmovies)
|
||||||
|
- [*ListUsers*](#listusers)
|
||||||
|
- [*ListUserReviews*](#listuserreviews)
|
||||||
|
- [*GetMovieById*](#getmoviebyid)
|
||||||
|
- [*SearchMovie*](#searchmovie)
|
||||||
|
- [**Mutations**](#mutations)
|
||||||
|
- [*CreateMovie*](#createmovie)
|
||||||
|
- [*UpsertUser*](#upsertuser)
|
||||||
|
- [*AddReview*](#addreview)
|
||||||
|
- [*DeleteReview*](#deletereview)
|
||||||
|
|
||||||
|
# TanStack Query Firebase & TanStack React Query
|
||||||
|
This SDK provides [React](https://react.dev/) hooks generated specific to your application, for the operations found in the connector `example`. These hooks are generated using [TanStack Query Firebase](https://react-query-firebase.invertase.dev/) by our partners at Invertase, a library built on top of [TanStack React Query v5](https://tanstack.com/query/v5/docs/framework/react/overview).
|
||||||
|
|
||||||
|
***You do not need to be familiar with Tanstack Query or Tanstack Query Firebase to use this SDK.*** However, you may find it useful to learn more about them, as they will empower you as a user of this Generated React SDK.
|
||||||
|
|
||||||
|
## Installing TanStack Query Firebase and TanStack React Query Packages
|
||||||
|
In order to use the React generated SDK, you must install the `TanStack React Query` and `TanStack Query Firebase` packages.
|
||||||
|
```bash
|
||||||
|
npm i --save @tanstack/react-query @tanstack-query-firebase/react
|
||||||
|
```
|
||||||
|
```bash
|
||||||
|
npm i --save firebase@latest # Note: React has a peer dependency on ^11.3.0
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also follow the installation instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#tanstack-install), or the [TanStack Query Firebase documentation](https://react-query-firebase.invertase.dev/react) and [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/installation).
|
||||||
|
|
||||||
|
## Configuring TanStack Query
|
||||||
|
In order to use the React generated SDK in your application, you must wrap your application's component tree in a `QueryClientProvider` component from TanStack React Query. None of your generated React SDK hooks will work without this provider.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
// Create a TanStack Query client instance
|
||||||
|
const queryClient = new QueryClient()
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
// Provide the client to your App
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<MyApplication />
|
||||||
|
</QueryClientProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about `QueryClientProvider`, see the [TanStack React Query documentation](https://tanstack.com/query/latest/docs/framework/react/quick-start) and the [TanStack Query Firebase documentation](https://invertase.docs.page/tanstack-query-firebase/react#usage).
|
||||||
|
|
||||||
|
# Accessing the connector
|
||||||
|
A connector is a collection of Queries and Mutations. One SDK is generated for each connector - this SDK is generated for the connector `example`.
|
||||||
|
|
||||||
|
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 { connectorConfig } from '@dataconnect/generated';
|
||||||
|
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Connecting to the local Emulator
|
||||||
|
By default, the connector will connect to the production service.
|
||||||
|
|
||||||
|
To connect to the emulator, you can use the following code.
|
||||||
|
You can also follow the emulator instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#emulator-react-angular).
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { connectDataConnectEmulator, getDataConnect } from 'firebase/data-connect';
|
||||||
|
import { connectorConfig } from '@dataconnect/generated';
|
||||||
|
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
connectDataConnectEmulator(dataConnect, 'localhost', 9399);
|
||||||
|
```
|
||||||
|
|
||||||
|
After it's initialized, you can call your Data Connect [queries](#queries) and [mutations](#mutations) using the hooks provided from your generated React SDK.
|
||||||
|
|
||||||
|
# Queries
|
||||||
|
|
||||||
|
The React generated SDK provides Query hook functions that call and return [`useDataConnectQuery`](https://react-query-firebase.invertase.dev/react/data-connect/querying) hooks from TanStack Query Firebase.
|
||||||
|
|
||||||
|
Calling these hook functions will return a `UseQueryResult` object. This object holds the state of your Query, including whether the Query is loading, has completed, or has succeeded/failed, and the most recent data returned by the Query, among other things. To learn more about these hooks and how to use them, see the [TanStack Query Firebase documentation](https://react-query-firebase.invertase.dev/react/data-connect/querying).
|
||||||
|
|
||||||
|
TanStack React Query caches the results of your Queries, so using the same Query hook function in multiple places in your application allows the entire application to automatically see updates to that Query's data.
|
||||||
|
|
||||||
|
Query hooks execute their Queries automatically when called, and periodically refresh, unless you change the `queryOptions` for the Query. To learn how to stop a Query from automatically executing, including how to make a query "lazy", see the [TanStack React Query documentation](https://tanstack.com/query/latest/docs/framework/react/guides/disabling-queries).
|
||||||
|
|
||||||
|
To learn more about TanStack React Query's Queries, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/guides/queries).
|
||||||
|
|
||||||
|
## Using Query Hooks
|
||||||
|
Here's a general overview of how to use the generated Query hooks in your code:
|
||||||
|
|
||||||
|
- If the Query has no variables, the Query hook function does not require arguments.
|
||||||
|
- If the Query has any required variables, the Query hook function will require at least one argument: an object that contains all the required variables for the Query.
|
||||||
|
- If the Query has some required and some optional variables, only required variables are necessary in the variables argument object, and optional variables may be provided as well.
|
||||||
|
- If all of the Query's variables are optional, the Query hook function does not require any arguments.
|
||||||
|
- Query hook functions can be called with or without passing in a `DataConnect` instance as an argument. If no `DataConnect` argument is passed in, then the generated SDK will call `getDataConnect(connectorConfig)` behind the scenes for you.
|
||||||
|
- Query hooks functions can be called with or without passing in an `options` argument of type `useDataConnectQueryOptions`. To learn more about the `options` argument, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/guides/query-options).
|
||||||
|
- ***Special case:*** If the Query has all optional variables and you would like to provide an `options` argument to the Query hook function without providing any variables, you must pass `undefined` where you would normally pass the Query's variables, and then may provide the `options` argument.
|
||||||
|
|
||||||
|
Below are examples of how to use the `example` connector's generated Query hook 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#operations-react-angular).
|
||||||
|
|
||||||
|
## ListMovies
|
||||||
|
You can execute the `ListMovies` Query using the following Query hook function, which is defined in [dataconnect-generated/react/index.d.ts](./index.d.ts):
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
useListMovies(dc: DataConnect, options?: useDataConnectQueryOptions<ListMoviesData>): UseDataConnectQueryResult<ListMoviesData, undefined>;
|
||||||
|
```
|
||||||
|
You can also pass in a `DataConnect` instance to the Query hook function.
|
||||||
|
```javascript
|
||||||
|
useListMovies(options?: useDataConnectQueryOptions<ListMoviesData>): UseDataConnectQueryResult<ListMoviesData, undefined>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
The `ListMovies` Query has no variables.
|
||||||
|
### Return Type
|
||||||
|
Recall that calling the `ListMovies` Query hook function returns a `UseQueryResult` object. This object holds the state of your Query, including whether the Query is loading, has completed, or has succeeded/failed, and any data returned by the Query, among other things.
|
||||||
|
|
||||||
|
To check the status of a Query, use the `UseQueryResult.status` field. You can also check for pending / success / error status using the `UseQueryResult.isPending`, `UseQueryResult.isSuccess`, and `UseQueryResult.isError` fields.
|
||||||
|
|
||||||
|
To access the data returned by a Query, use the `UseQueryResult.data` field. The data for the `ListMovies` Query is of type `ListMoviesData`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
```javascript
|
||||||
|
export interface ListMoviesData {
|
||||||
|
movies: ({
|
||||||
|
id: UUIDString;
|
||||||
|
title: string;
|
||||||
|
imageUrl: string;
|
||||||
|
genre?: string | null;
|
||||||
|
} & Movie_Key)[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about the `UseQueryResult` object, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/reference/useQuery).
|
||||||
|
|
||||||
|
### Using `ListMovies`'s Query hook function
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { getDataConnect } from 'firebase/data-connect';
|
||||||
|
import { connectorConfig } from '@dataconnect/generated';
|
||||||
|
import { useListMovies } from '@dataconnect/generated/react'
|
||||||
|
|
||||||
|
export default function ListMoviesComponent() {
|
||||||
|
// You don't have to do anything to "execute" the Query.
|
||||||
|
// Call the Query hook function to get a `UseQueryResult` object which holds the state of your Query.
|
||||||
|
const query = useListMovies();
|
||||||
|
|
||||||
|
// You can also pass in a `DataConnect` instance to the Query hook function.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const query = useListMovies(dataConnect);
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectQueryOptions` object to the Query hook function.
|
||||||
|
const options = { staleTime: 5 * 1000 };
|
||||||
|
const query = useListMovies(options);
|
||||||
|
|
||||||
|
// You can also pass both a `DataConnect` instance and a `useDataConnectQueryOptions` object.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const options = { staleTime: 5 * 1000 };
|
||||||
|
const query = useListMovies(dataConnect, options);
|
||||||
|
|
||||||
|
// Then, you can render your component dynamically based on the status of the Query.
|
||||||
|
if (query.isPending) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.isError) {
|
||||||
|
return <div>Error: {query.error.message}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Query is successful, you can access the data returned using the `UseQueryResult.data` field.
|
||||||
|
if (query.isSuccess) {
|
||||||
|
console.log(query.data.movies);
|
||||||
|
}
|
||||||
|
return <div>Query execution {query.isSuccess ? 'successful' : 'failed'}!</div>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ListUsers
|
||||||
|
You can execute the `ListUsers` Query using the following Query hook function, which is defined in [dataconnect-generated/react/index.d.ts](./index.d.ts):
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
useListUsers(dc: DataConnect, options?: useDataConnectQueryOptions<ListUsersData>): UseDataConnectQueryResult<ListUsersData, undefined>;
|
||||||
|
```
|
||||||
|
You can also pass in a `DataConnect` instance to the Query hook function.
|
||||||
|
```javascript
|
||||||
|
useListUsers(options?: useDataConnectQueryOptions<ListUsersData>): UseDataConnectQueryResult<ListUsersData, undefined>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
The `ListUsers` Query has no variables.
|
||||||
|
### Return Type
|
||||||
|
Recall that calling the `ListUsers` Query hook function returns a `UseQueryResult` object. This object holds the state of your Query, including whether the Query is loading, has completed, or has succeeded/failed, and any data returned by the Query, among other things.
|
||||||
|
|
||||||
|
To check the status of a Query, use the `UseQueryResult.status` field. You can also check for pending / success / error status using the `UseQueryResult.isPending`, `UseQueryResult.isSuccess`, and `UseQueryResult.isError` fields.
|
||||||
|
|
||||||
|
To access the data returned by a Query, use the `UseQueryResult.data` field. The data for the `ListUsers` Query is of type `ListUsersData`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
```javascript
|
||||||
|
export interface ListUsersData {
|
||||||
|
users: ({
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
} & User_Key)[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about the `UseQueryResult` object, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/reference/useQuery).
|
||||||
|
|
||||||
|
### Using `ListUsers`'s Query hook function
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { getDataConnect } from 'firebase/data-connect';
|
||||||
|
import { connectorConfig } from '@dataconnect/generated';
|
||||||
|
import { useListUsers } from '@dataconnect/generated/react'
|
||||||
|
|
||||||
|
export default function ListUsersComponent() {
|
||||||
|
// You don't have to do anything to "execute" the Query.
|
||||||
|
// Call the Query hook function to get a `UseQueryResult` object which holds the state of your Query.
|
||||||
|
const query = useListUsers();
|
||||||
|
|
||||||
|
// You can also pass in a `DataConnect` instance to the Query hook function.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const query = useListUsers(dataConnect);
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectQueryOptions` object to the Query hook function.
|
||||||
|
const options = { staleTime: 5 * 1000 };
|
||||||
|
const query = useListUsers(options);
|
||||||
|
|
||||||
|
// You can also pass both a `DataConnect` instance and a `useDataConnectQueryOptions` object.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const options = { staleTime: 5 * 1000 };
|
||||||
|
const query = useListUsers(dataConnect, options);
|
||||||
|
|
||||||
|
// Then, you can render your component dynamically based on the status of the Query.
|
||||||
|
if (query.isPending) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.isError) {
|
||||||
|
return <div>Error: {query.error.message}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Query is successful, you can access the data returned using the `UseQueryResult.data` field.
|
||||||
|
if (query.isSuccess) {
|
||||||
|
console.log(query.data.users);
|
||||||
|
}
|
||||||
|
return <div>Query execution {query.isSuccess ? 'successful' : 'failed'}!</div>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ListUserReviews
|
||||||
|
You can execute the `ListUserReviews` Query using the following Query hook function, which is defined in [dataconnect-generated/react/index.d.ts](./index.d.ts):
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
useListUserReviews(dc: DataConnect, options?: useDataConnectQueryOptions<ListUserReviewsData>): UseDataConnectQueryResult<ListUserReviewsData, undefined>;
|
||||||
|
```
|
||||||
|
You can also pass in a `DataConnect` instance to the Query hook function.
|
||||||
|
```javascript
|
||||||
|
useListUserReviews(options?: useDataConnectQueryOptions<ListUserReviewsData>): UseDataConnectQueryResult<ListUserReviewsData, undefined>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
The `ListUserReviews` Query has no variables.
|
||||||
|
### Return Type
|
||||||
|
Recall that calling the `ListUserReviews` Query hook function returns a `UseQueryResult` object. This object holds the state of your Query, including whether the Query is loading, has completed, or has succeeded/failed, and any data returned by the Query, among other things.
|
||||||
|
|
||||||
|
To check the status of a Query, use the `UseQueryResult.status` field. You can also check for pending / success / error status using the `UseQueryResult.isPending`, `UseQueryResult.isSuccess`, and `UseQueryResult.isError` fields.
|
||||||
|
|
||||||
|
To access the data returned by a Query, use the `UseQueryResult.data` field. The data for the `ListUserReviews` Query is of type `ListUserReviewsData`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
```javascript
|
||||||
|
export interface ListUserReviewsData {
|
||||||
|
user?: {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
reviews: ({
|
||||||
|
rating?: number | null;
|
||||||
|
reviewDate: DateString;
|
||||||
|
reviewText?: string | null;
|
||||||
|
movie: {
|
||||||
|
id: UUIDString;
|
||||||
|
title: string;
|
||||||
|
} & Movie_Key;
|
||||||
|
})[];
|
||||||
|
} & User_Key;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about the `UseQueryResult` object, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/reference/useQuery).
|
||||||
|
|
||||||
|
### Using `ListUserReviews`'s Query hook function
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { getDataConnect } from 'firebase/data-connect';
|
||||||
|
import { connectorConfig } from '@dataconnect/generated';
|
||||||
|
import { useListUserReviews } from '@dataconnect/generated/react'
|
||||||
|
|
||||||
|
export default function ListUserReviewsComponent() {
|
||||||
|
// You don't have to do anything to "execute" the Query.
|
||||||
|
// Call the Query hook function to get a `UseQueryResult` object which holds the state of your Query.
|
||||||
|
const query = useListUserReviews();
|
||||||
|
|
||||||
|
// You can also pass in a `DataConnect` instance to the Query hook function.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const query = useListUserReviews(dataConnect);
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectQueryOptions` object to the Query hook function.
|
||||||
|
const options = { staleTime: 5 * 1000 };
|
||||||
|
const query = useListUserReviews(options);
|
||||||
|
|
||||||
|
// You can also pass both a `DataConnect` instance and a `useDataConnectQueryOptions` object.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const options = { staleTime: 5 * 1000 };
|
||||||
|
const query = useListUserReviews(dataConnect, options);
|
||||||
|
|
||||||
|
// Then, you can render your component dynamically based on the status of the Query.
|
||||||
|
if (query.isPending) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.isError) {
|
||||||
|
return <div>Error: {query.error.message}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Query is successful, you can access the data returned using the `UseQueryResult.data` field.
|
||||||
|
if (query.isSuccess) {
|
||||||
|
console.log(query.data.user);
|
||||||
|
}
|
||||||
|
return <div>Query execution {query.isSuccess ? 'successful' : 'failed'}!</div>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## GetMovieById
|
||||||
|
You can execute the `GetMovieById` Query using the following Query hook function, which is defined in [dataconnect-generated/react/index.d.ts](./index.d.ts):
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
useGetMovieById(dc: DataConnect, vars: GetMovieByIdVariables, options?: useDataConnectQueryOptions<GetMovieByIdData>): UseDataConnectQueryResult<GetMovieByIdData, GetMovieByIdVariables>;
|
||||||
|
```
|
||||||
|
You can also pass in a `DataConnect` instance to the Query hook function.
|
||||||
|
```javascript
|
||||||
|
useGetMovieById(vars: GetMovieByIdVariables, options?: useDataConnectQueryOptions<GetMovieByIdData>): UseDataConnectQueryResult<GetMovieByIdData, GetMovieByIdVariables>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
The `GetMovieById` Query requires an argument of type `GetMovieByIdVariables`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export interface GetMovieByIdVariables {
|
||||||
|
id: UUIDString;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Return Type
|
||||||
|
Recall that calling the `GetMovieById` Query hook function returns a `UseQueryResult` object. This object holds the state of your Query, including whether the Query is loading, has completed, or has succeeded/failed, and any data returned by the Query, among other things.
|
||||||
|
|
||||||
|
To check the status of a Query, use the `UseQueryResult.status` field. You can also check for pending / success / error status using the `UseQueryResult.isPending`, `UseQueryResult.isSuccess`, and `UseQueryResult.isError` fields.
|
||||||
|
|
||||||
|
To access the data returned by a Query, use the `UseQueryResult.data` field. The data for the `GetMovieById` Query is of type `GetMovieByIdData`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
```javascript
|
||||||
|
export interface GetMovieByIdData {
|
||||||
|
movie?: {
|
||||||
|
id: UUIDString;
|
||||||
|
title: string;
|
||||||
|
imageUrl: string;
|
||||||
|
genre?: string | null;
|
||||||
|
metadata?: {
|
||||||
|
rating?: number | null;
|
||||||
|
releaseYear?: number | null;
|
||||||
|
description?: string | null;
|
||||||
|
};
|
||||||
|
reviews: ({
|
||||||
|
reviewText?: string | null;
|
||||||
|
reviewDate: DateString;
|
||||||
|
rating?: number | null;
|
||||||
|
user: {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
} & User_Key;
|
||||||
|
})[];
|
||||||
|
} & Movie_Key;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about the `UseQueryResult` object, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/reference/useQuery).
|
||||||
|
|
||||||
|
### Using `GetMovieById`'s Query hook function
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { getDataConnect } from 'firebase/data-connect';
|
||||||
|
import { connectorConfig, GetMovieByIdVariables } from '@dataconnect/generated';
|
||||||
|
import { useGetMovieById } from '@dataconnect/generated/react'
|
||||||
|
|
||||||
|
export default function GetMovieByIdComponent() {
|
||||||
|
// The `useGetMovieById` Query hook requires an argument of type `GetMovieByIdVariables`:
|
||||||
|
const getMovieByIdVars: GetMovieByIdVariables = {
|
||||||
|
id: ...,
|
||||||
|
};
|
||||||
|
|
||||||
|
// You don't have to do anything to "execute" the Query.
|
||||||
|
// Call the Query hook function to get a `UseQueryResult` object which holds the state of your Query.
|
||||||
|
const query = useGetMovieById(getMovieByIdVars);
|
||||||
|
// Variables can be defined inline as well.
|
||||||
|
const query = useGetMovieById({ id: ..., });
|
||||||
|
|
||||||
|
// You can also pass in a `DataConnect` instance to the Query hook function.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const query = useGetMovieById(dataConnect, getMovieByIdVars);
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectQueryOptions` object to the Query hook function.
|
||||||
|
const options = { staleTime: 5 * 1000 };
|
||||||
|
const query = useGetMovieById(getMovieByIdVars, options);
|
||||||
|
|
||||||
|
// You can also pass both a `DataConnect` instance and a `useDataConnectQueryOptions` object.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const options = { staleTime: 5 * 1000 };
|
||||||
|
const query = useGetMovieById(dataConnect, getMovieByIdVars, options);
|
||||||
|
|
||||||
|
// Then, you can render your component dynamically based on the status of the Query.
|
||||||
|
if (query.isPending) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.isError) {
|
||||||
|
return <div>Error: {query.error.message}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Query is successful, you can access the data returned using the `UseQueryResult.data` field.
|
||||||
|
if (query.isSuccess) {
|
||||||
|
console.log(query.data.movie);
|
||||||
|
}
|
||||||
|
return <div>Query execution {query.isSuccess ? 'successful' : 'failed'}!</div>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## SearchMovie
|
||||||
|
You can execute the `SearchMovie` Query using the following Query hook function, which is defined in [dataconnect-generated/react/index.d.ts](./index.d.ts):
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
useSearchMovie(dc: DataConnect, vars?: SearchMovieVariables, options?: useDataConnectQueryOptions<SearchMovieData>): UseDataConnectQueryResult<SearchMovieData, SearchMovieVariables>;
|
||||||
|
```
|
||||||
|
You can also pass in a `DataConnect` instance to the Query hook function.
|
||||||
|
```javascript
|
||||||
|
useSearchMovie(vars?: SearchMovieVariables, options?: useDataConnectQueryOptions<SearchMovieData>): UseDataConnectQueryResult<SearchMovieData, SearchMovieVariables>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
The `SearchMovie` Query has an optional argument of type `SearchMovieVariables`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export interface SearchMovieVariables {
|
||||||
|
titleInput?: string | null;
|
||||||
|
genre?: string | null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Return Type
|
||||||
|
Recall that calling the `SearchMovie` Query hook function returns a `UseQueryResult` object. This object holds the state of your Query, including whether the Query is loading, has completed, or has succeeded/failed, and any data returned by the Query, among other things.
|
||||||
|
|
||||||
|
To check the status of a Query, use the `UseQueryResult.status` field. You can also check for pending / success / error status using the `UseQueryResult.isPending`, `UseQueryResult.isSuccess`, and `UseQueryResult.isError` fields.
|
||||||
|
|
||||||
|
To access the data returned by a Query, use the `UseQueryResult.data` field. The data for the `SearchMovie` Query is of type `SearchMovieData`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
```javascript
|
||||||
|
export interface SearchMovieData {
|
||||||
|
movies: ({
|
||||||
|
id: UUIDString;
|
||||||
|
title: string;
|
||||||
|
genre?: string | null;
|
||||||
|
imageUrl: string;
|
||||||
|
} & Movie_Key)[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about the `UseQueryResult` object, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/reference/useQuery).
|
||||||
|
|
||||||
|
### Using `SearchMovie`'s Query hook function
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { getDataConnect } from 'firebase/data-connect';
|
||||||
|
import { connectorConfig, SearchMovieVariables } from '@dataconnect/generated';
|
||||||
|
import { useSearchMovie } from '@dataconnect/generated/react'
|
||||||
|
|
||||||
|
export default function SearchMovieComponent() {
|
||||||
|
// The `useSearchMovie` Query hook has an optional argument of type `SearchMovieVariables`:
|
||||||
|
const searchMovieVars: SearchMovieVariables = {
|
||||||
|
titleInput: ..., // optional
|
||||||
|
genre: ..., // optional
|
||||||
|
};
|
||||||
|
|
||||||
|
// You don't have to do anything to "execute" the Query.
|
||||||
|
// Call the Query hook function to get a `UseQueryResult` object which holds the state of your Query.
|
||||||
|
const query = useSearchMovie(searchMovieVars);
|
||||||
|
// Variables can be defined inline as well.
|
||||||
|
const query = useSearchMovie({ titleInput: ..., genre: ..., });
|
||||||
|
// Since all variables are optional for this Query, you can omit the `SearchMovieVariables` argument.
|
||||||
|
// (as long as you don't want to provide any `options`!)
|
||||||
|
const query = useSearchMovie();
|
||||||
|
|
||||||
|
// You can also pass in a `DataConnect` instance to the Query hook function.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const query = useSearchMovie(dataConnect, searchMovieVars);
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectQueryOptions` object to the Query hook function.
|
||||||
|
const options = { staleTime: 5 * 1000 };
|
||||||
|
const query = useSearchMovie(searchMovieVars, options);
|
||||||
|
// If you'd like to provide options without providing any variables, you must
|
||||||
|
// pass `undefined` where you would normally pass the variables.
|
||||||
|
const query = useSearchMovie(undefined, options);
|
||||||
|
|
||||||
|
// You can also pass both a `DataConnect` instance and a `useDataConnectQueryOptions` object.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const options = { staleTime: 5 * 1000 };
|
||||||
|
const query = useSearchMovie(dataConnect, searchMovieVars /** or undefined */, options);
|
||||||
|
|
||||||
|
// Then, you can render your component dynamically based on the status of the Query.
|
||||||
|
if (query.isPending) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.isError) {
|
||||||
|
return <div>Error: {query.error.message}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Query is successful, you can access the data returned using the `UseQueryResult.data` field.
|
||||||
|
if (query.isSuccess) {
|
||||||
|
console.log(query.data.movies);
|
||||||
|
}
|
||||||
|
return <div>Query execution {query.isSuccess ? 'successful' : 'failed'}!</div>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Mutations
|
||||||
|
|
||||||
|
The React generated SDK provides Mutations hook functions that call and return [`useDataConnectMutation`](https://react-query-firebase.invertase.dev/react/data-connect/mutations) hooks from TanStack Query Firebase.
|
||||||
|
|
||||||
|
Calling these hook functions will return a `UseMutationResult` object. This object holds the state of your Mutation, including whether the Mutation is loading, has completed, or has succeeded/failed, and the most recent data returned by the Mutation, among other things. To learn more about these hooks and how to use them, see the [TanStack Query Firebase documentation](https://react-query-firebase.invertase.dev/react/data-connect/mutations).
|
||||||
|
|
||||||
|
Mutation hooks do not execute their Mutations automatically when called. Rather, after calling the Mutation hook function and getting a `UseMutationResult` object, you must call the `UseMutationResult.mutate()` function to execute the Mutation.
|
||||||
|
|
||||||
|
To learn more about TanStack React Query's Mutations, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/guides/mutations).
|
||||||
|
|
||||||
|
## Using Mutation Hooks
|
||||||
|
Here's a general overview of how to use the generated Mutation hooks in your code:
|
||||||
|
|
||||||
|
- Mutation hook functions are not called with the arguments to the Mutation. Instead, arguments are passed to `UseMutationResult.mutate()`.
|
||||||
|
- If the Mutation has no variables, the `mutate()` function does not require arguments.
|
||||||
|
- If the Mutation has any required variables, the `mutate()` function will require at least one argument: an object that contains all the required variables for the Mutation.
|
||||||
|
- If the Mutation has some required and some optional variables, only required variables are necessary in the variables argument object, and optional variables may be provided as well.
|
||||||
|
- If all of the Mutation's variables are optional, the Mutation hook function does not require any arguments.
|
||||||
|
- Mutation hook functions can be called with or without passing in a `DataConnect` instance as an argument. If no `DataConnect` argument is passed in, then the generated SDK will call `getDataConnect(connectorConfig)` behind the scenes for you.
|
||||||
|
- Mutation hooks also accept an `options` argument of type `useDataConnectMutationOptions`. To learn more about the `options` argument, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/guides/mutations#mutation-side-effects).
|
||||||
|
- `UseMutationResult.mutate()` also accepts an `options` argument of type `useDataConnectMutationOptions`.
|
||||||
|
- ***Special case:*** If the Mutation has no arguments (or all optional arguments and you wish to provide none), and you want to pass `options` to `UseMutationResult.mutate()`, you must pass `undefined` where you would normally pass the Mutation's arguments, and then may provide the options argument.
|
||||||
|
|
||||||
|
Below are examples of how to use the `example` connector's generated Mutation hook 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#operations-react-angular).
|
||||||
|
|
||||||
|
## CreateMovie
|
||||||
|
You can execute the `CreateMovie` Mutation using the `UseMutationResult` object returned by the following Mutation hook function (which is defined in [dataconnect-generated/react/index.d.ts](./index.d.ts)):
|
||||||
|
```javascript
|
||||||
|
useCreateMovie(options?: useDataConnectMutationOptions<CreateMovieData, FirebaseError, CreateMovieVariables>): UseDataConnectMutationResult<CreateMovieData, CreateMovieVariables>;
|
||||||
|
```
|
||||||
|
You can also pass in a `DataConnect` instance to the Mutation hook function.
|
||||||
|
```javascript
|
||||||
|
useCreateMovie(dc: DataConnect, options?: useDataConnectMutationOptions<CreateMovieData, FirebaseError, CreateMovieVariables>): UseDataConnectMutationResult<CreateMovieData, CreateMovieVariables>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
The `CreateMovie` Mutation requires an argument of type `CreateMovieVariables`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export interface CreateMovieVariables {
|
||||||
|
title: string;
|
||||||
|
genre: string;
|
||||||
|
imageUrl: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Return Type
|
||||||
|
Recall that calling the `CreateMovie` Mutation hook function returns a `UseMutationResult` object. This object holds the state of your Mutation, including whether the Mutation is loading, has completed, or has succeeded/failed, among other things.
|
||||||
|
|
||||||
|
To check the status of a Mutation, use the `UseMutationResult.status` field. You can also check for pending / success / error status using the `UseMutationResult.isPending`, `UseMutationResult.isSuccess`, and `UseMutationResult.isError` fields.
|
||||||
|
|
||||||
|
To execute the Mutation, call `UseMutationResult.mutate()`. This function executes the Mutation, but does not return the data from the Mutation.
|
||||||
|
|
||||||
|
To access the data returned by a Mutation, use the `UseMutationResult.data` field. The data for the `CreateMovie` Mutation is of type `CreateMovieData`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
```javascript
|
||||||
|
export interface CreateMovieData {
|
||||||
|
movie_insert: Movie_Key;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about the `UseMutationResult` object, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/reference/useMutation).
|
||||||
|
|
||||||
|
### Using `CreateMovie`'s Mutation hook function
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { getDataConnect } from 'firebase/data-connect';
|
||||||
|
import { connectorConfig, CreateMovieVariables } from '@dataconnect/generated';
|
||||||
|
import { useCreateMovie } from '@dataconnect/generated/react'
|
||||||
|
|
||||||
|
export default function CreateMovieComponent() {
|
||||||
|
// Call the Mutation hook function to get a `UseMutationResult` object which holds the state of your Mutation.
|
||||||
|
const mutation = useCreateMovie();
|
||||||
|
|
||||||
|
// You can also pass in a `DataConnect` instance to the Mutation hook function.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const mutation = useCreateMovie(dataConnect);
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectMutationOptions` object to the Mutation hook function.
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
const mutation = useCreateMovie(options);
|
||||||
|
|
||||||
|
// You can also pass both a `DataConnect` instance and a `useDataConnectMutationOptions` object.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
const mutation = useCreateMovie(dataConnect, options);
|
||||||
|
|
||||||
|
// After calling the Mutation hook function, you must call `UseMutationResult.mutate()` to execute the Mutation.
|
||||||
|
// The `useCreateMovie` Mutation requires an argument of type `CreateMovieVariables`:
|
||||||
|
const createMovieVars: CreateMovieVariables = {
|
||||||
|
title: ...,
|
||||||
|
genre: ...,
|
||||||
|
imageUrl: ...,
|
||||||
|
};
|
||||||
|
mutation.mutate(createMovieVars);
|
||||||
|
// Variables can be defined inline as well.
|
||||||
|
mutation.mutate({ title: ..., genre: ..., imageUrl: ..., });
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectMutationOptions` object to `UseMutationResult.mutate()`.
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
mutation.mutate(createMovieVars, options);
|
||||||
|
|
||||||
|
// Then, you can render your component dynamically based on the status of the Mutation.
|
||||||
|
if (mutation.isPending) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mutation.isError) {
|
||||||
|
return <div>Error: {mutation.error.message}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Mutation is successful, you can access the data returned using the `UseMutationResult.data` field.
|
||||||
|
if (mutation.isSuccess) {
|
||||||
|
console.log(mutation.data.movie_insert);
|
||||||
|
}
|
||||||
|
return <div>Mutation execution {mutation.isSuccess ? 'successful' : 'failed'}!</div>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## UpsertUser
|
||||||
|
You can execute the `UpsertUser` Mutation using the `UseMutationResult` object returned by the following Mutation hook function (which is defined in [dataconnect-generated/react/index.d.ts](./index.d.ts)):
|
||||||
|
```javascript
|
||||||
|
useUpsertUser(options?: useDataConnectMutationOptions<UpsertUserData, FirebaseError, UpsertUserVariables>): UseDataConnectMutationResult<UpsertUserData, UpsertUserVariables>;
|
||||||
|
```
|
||||||
|
You can also pass in a `DataConnect` instance to the Mutation hook function.
|
||||||
|
```javascript
|
||||||
|
useUpsertUser(dc: DataConnect, options?: useDataConnectMutationOptions<UpsertUserData, FirebaseError, UpsertUserVariables>): UseDataConnectMutationResult<UpsertUserData, UpsertUserVariables>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
The `UpsertUser` Mutation requires an argument of type `UpsertUserVariables`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export interface UpsertUserVariables {
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Return Type
|
||||||
|
Recall that calling the `UpsertUser` Mutation hook function returns a `UseMutationResult` object. This object holds the state of your Mutation, including whether the Mutation is loading, has completed, or has succeeded/failed, among other things.
|
||||||
|
|
||||||
|
To check the status of a Mutation, use the `UseMutationResult.status` field. You can also check for pending / success / error status using the `UseMutationResult.isPending`, `UseMutationResult.isSuccess`, and `UseMutationResult.isError` fields.
|
||||||
|
|
||||||
|
To execute the Mutation, call `UseMutationResult.mutate()`. This function executes the Mutation, but does not return the data from the Mutation.
|
||||||
|
|
||||||
|
To access the data returned by a Mutation, use the `UseMutationResult.data` field. The data for the `UpsertUser` Mutation is of type `UpsertUserData`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
```javascript
|
||||||
|
export interface UpsertUserData {
|
||||||
|
user_upsert: User_Key;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about the `UseMutationResult` object, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/reference/useMutation).
|
||||||
|
|
||||||
|
### Using `UpsertUser`'s Mutation hook function
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { getDataConnect } from 'firebase/data-connect';
|
||||||
|
import { connectorConfig, UpsertUserVariables } from '@dataconnect/generated';
|
||||||
|
import { useUpsertUser } from '@dataconnect/generated/react'
|
||||||
|
|
||||||
|
export default function UpsertUserComponent() {
|
||||||
|
// Call the Mutation hook function to get a `UseMutationResult` object which holds the state of your Mutation.
|
||||||
|
const mutation = useUpsertUser();
|
||||||
|
|
||||||
|
// You can also pass in a `DataConnect` instance to the Mutation hook function.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const mutation = useUpsertUser(dataConnect);
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectMutationOptions` object to the Mutation hook function.
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
const mutation = useUpsertUser(options);
|
||||||
|
|
||||||
|
// You can also pass both a `DataConnect` instance and a `useDataConnectMutationOptions` object.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
const mutation = useUpsertUser(dataConnect, options);
|
||||||
|
|
||||||
|
// After calling the Mutation hook function, you must call `UseMutationResult.mutate()` to execute the Mutation.
|
||||||
|
// The `useUpsertUser` Mutation requires an argument of type `UpsertUserVariables`:
|
||||||
|
const upsertUserVars: UpsertUserVariables = {
|
||||||
|
username: ...,
|
||||||
|
};
|
||||||
|
mutation.mutate(upsertUserVars);
|
||||||
|
// Variables can be defined inline as well.
|
||||||
|
mutation.mutate({ username: ..., });
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectMutationOptions` object to `UseMutationResult.mutate()`.
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
mutation.mutate(upsertUserVars, options);
|
||||||
|
|
||||||
|
// Then, you can render your component dynamically based on the status of the Mutation.
|
||||||
|
if (mutation.isPending) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mutation.isError) {
|
||||||
|
return <div>Error: {mutation.error.message}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Mutation is successful, you can access the data returned using the `UseMutationResult.data` field.
|
||||||
|
if (mutation.isSuccess) {
|
||||||
|
console.log(mutation.data.user_upsert);
|
||||||
|
}
|
||||||
|
return <div>Mutation execution {mutation.isSuccess ? 'successful' : 'failed'}!</div>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## AddReview
|
||||||
|
You can execute the `AddReview` Mutation using the `UseMutationResult` object returned by the following Mutation hook function (which is defined in [dataconnect-generated/react/index.d.ts](./index.d.ts)):
|
||||||
|
```javascript
|
||||||
|
useAddReview(options?: useDataConnectMutationOptions<AddReviewData, FirebaseError, AddReviewVariables>): UseDataConnectMutationResult<AddReviewData, AddReviewVariables>;
|
||||||
|
```
|
||||||
|
You can also pass in a `DataConnect` instance to the Mutation hook function.
|
||||||
|
```javascript
|
||||||
|
useAddReview(dc: DataConnect, options?: useDataConnectMutationOptions<AddReviewData, FirebaseError, AddReviewVariables>): UseDataConnectMutationResult<AddReviewData, AddReviewVariables>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
The `AddReview` Mutation requires an argument of type `AddReviewVariables`, which is defined in [dataconnect-generated/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 calling the `AddReview` Mutation hook function returns a `UseMutationResult` object. This object holds the state of your Mutation, including whether the Mutation is loading, has completed, or has succeeded/failed, among other things.
|
||||||
|
|
||||||
|
To check the status of a Mutation, use the `UseMutationResult.status` field. You can also check for pending / success / error status using the `UseMutationResult.isPending`, `UseMutationResult.isSuccess`, and `UseMutationResult.isError` fields.
|
||||||
|
|
||||||
|
To execute the Mutation, call `UseMutationResult.mutate()`. This function executes the Mutation, but does not return the data from the Mutation.
|
||||||
|
|
||||||
|
To access the data returned by a Mutation, use the `UseMutationResult.data` field. The data for the `AddReview` Mutation is of type `AddReviewData`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
```javascript
|
||||||
|
export interface AddReviewData {
|
||||||
|
review_upsert: Review_Key;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about the `UseMutationResult` object, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/reference/useMutation).
|
||||||
|
|
||||||
|
### Using `AddReview`'s Mutation hook function
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { getDataConnect } from 'firebase/data-connect';
|
||||||
|
import { connectorConfig, AddReviewVariables } from '@dataconnect/generated';
|
||||||
|
import { useAddReview } from '@dataconnect/generated/react'
|
||||||
|
|
||||||
|
export default function AddReviewComponent() {
|
||||||
|
// Call the Mutation hook function to get a `UseMutationResult` object which holds the state of your Mutation.
|
||||||
|
const mutation = useAddReview();
|
||||||
|
|
||||||
|
// You can also pass in a `DataConnect` instance to the Mutation hook function.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const mutation = useAddReview(dataConnect);
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectMutationOptions` object to the Mutation hook function.
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
const mutation = useAddReview(options);
|
||||||
|
|
||||||
|
// You can also pass both a `DataConnect` instance and a `useDataConnectMutationOptions` object.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
const mutation = useAddReview(dataConnect, options);
|
||||||
|
|
||||||
|
// After calling the Mutation hook function, you must call `UseMutationResult.mutate()` to execute the Mutation.
|
||||||
|
// The `useAddReview` Mutation requires an argument of type `AddReviewVariables`:
|
||||||
|
const addReviewVars: AddReviewVariables = {
|
||||||
|
movieId: ...,
|
||||||
|
rating: ...,
|
||||||
|
reviewText: ...,
|
||||||
|
};
|
||||||
|
mutation.mutate(addReviewVars);
|
||||||
|
// Variables can be defined inline as well.
|
||||||
|
mutation.mutate({ movieId: ..., rating: ..., reviewText: ..., });
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectMutationOptions` object to `UseMutationResult.mutate()`.
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
mutation.mutate(addReviewVars, options);
|
||||||
|
|
||||||
|
// Then, you can render your component dynamically based on the status of the Mutation.
|
||||||
|
if (mutation.isPending) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mutation.isError) {
|
||||||
|
return <div>Error: {mutation.error.message}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Mutation is successful, you can access the data returned using the `UseMutationResult.data` field.
|
||||||
|
if (mutation.isSuccess) {
|
||||||
|
console.log(mutation.data.review_upsert);
|
||||||
|
}
|
||||||
|
return <div>Mutation execution {mutation.isSuccess ? 'successful' : 'failed'}!</div>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## DeleteReview
|
||||||
|
You can execute the `DeleteReview` Mutation using the `UseMutationResult` object returned by the following Mutation hook function (which is defined in [dataconnect-generated/react/index.d.ts](./index.d.ts)):
|
||||||
|
```javascript
|
||||||
|
useDeleteReview(options?: useDataConnectMutationOptions<DeleteReviewData, FirebaseError, DeleteReviewVariables>): UseDataConnectMutationResult<DeleteReviewData, DeleteReviewVariables>;
|
||||||
|
```
|
||||||
|
You can also pass in a `DataConnect` instance to the Mutation hook function.
|
||||||
|
```javascript
|
||||||
|
useDeleteReview(dc: DataConnect, options?: useDataConnectMutationOptions<DeleteReviewData, FirebaseError, DeleteReviewVariables>): UseDataConnectMutationResult<DeleteReviewData, DeleteReviewVariables>;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variables
|
||||||
|
The `DeleteReview` Mutation requires an argument of type `DeleteReviewVariables`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export interface DeleteReviewVariables {
|
||||||
|
movieId: UUIDString;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### Return Type
|
||||||
|
Recall that calling the `DeleteReview` Mutation hook function returns a `UseMutationResult` object. This object holds the state of your Mutation, including whether the Mutation is loading, has completed, or has succeeded/failed, among other things.
|
||||||
|
|
||||||
|
To check the status of a Mutation, use the `UseMutationResult.status` field. You can also check for pending / success / error status using the `UseMutationResult.isPending`, `UseMutationResult.isSuccess`, and `UseMutationResult.isError` fields.
|
||||||
|
|
||||||
|
To execute the Mutation, call `UseMutationResult.mutate()`. This function executes the Mutation, but does not return the data from the Mutation.
|
||||||
|
|
||||||
|
To access the data returned by a Mutation, use the `UseMutationResult.data` field. The data for the `DeleteReview` Mutation is of type `DeleteReviewData`, which is defined in [dataconnect-generated/index.d.ts](../index.d.ts). It has the following fields:
|
||||||
|
```javascript
|
||||||
|
export interface DeleteReviewData {
|
||||||
|
review_delete?: Review_Key | null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about the `UseMutationResult` object, see the [TanStack React Query documentation](https://tanstack.com/query/v5/docs/framework/react/reference/useMutation).
|
||||||
|
|
||||||
|
### Using `DeleteReview`'s Mutation hook function
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { getDataConnect } from 'firebase/data-connect';
|
||||||
|
import { connectorConfig, DeleteReviewVariables } from '@dataconnect/generated';
|
||||||
|
import { useDeleteReview } from '@dataconnect/generated/react'
|
||||||
|
|
||||||
|
export default function DeleteReviewComponent() {
|
||||||
|
// Call the Mutation hook function to get a `UseMutationResult` object which holds the state of your Mutation.
|
||||||
|
const mutation = useDeleteReview();
|
||||||
|
|
||||||
|
// You can also pass in a `DataConnect` instance to the Mutation hook function.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const mutation = useDeleteReview(dataConnect);
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectMutationOptions` object to the Mutation hook function.
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
const mutation = useDeleteReview(options);
|
||||||
|
|
||||||
|
// You can also pass both a `DataConnect` instance and a `useDataConnectMutationOptions` object.
|
||||||
|
const dataConnect = getDataConnect(connectorConfig);
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
const mutation = useDeleteReview(dataConnect, options);
|
||||||
|
|
||||||
|
// After calling the Mutation hook function, you must call `UseMutationResult.mutate()` to execute the Mutation.
|
||||||
|
// The `useDeleteReview` Mutation requires an argument of type `DeleteReviewVariables`:
|
||||||
|
const deleteReviewVars: DeleteReviewVariables = {
|
||||||
|
movieId: ...,
|
||||||
|
};
|
||||||
|
mutation.mutate(deleteReviewVars);
|
||||||
|
// Variables can be defined inline as well.
|
||||||
|
mutation.mutate({ movieId: ..., });
|
||||||
|
|
||||||
|
// You can also pass in a `useDataConnectMutationOptions` object to `UseMutationResult.mutate()`.
|
||||||
|
const options = {
|
||||||
|
onSuccess: () => { console.log('Mutation succeeded!'); }
|
||||||
|
};
|
||||||
|
mutation.mutate(deleteReviewVars, options);
|
||||||
|
|
||||||
|
// Then, you can render your component dynamically based on the status of the Mutation.
|
||||||
|
if (mutation.isPending) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mutation.isError) {
|
||||||
|
return <div>Error: {mutation.error.message}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the Mutation is successful, you can access the data returned using the `UseMutationResult.data` field.
|
||||||
|
if (mutation.isSuccess) {
|
||||||
|
console.log(mutation.data.review_delete);
|
||||||
|
}
|
||||||
|
return <div>Mutation execution {mutation.isSuccess ? 'successful' : 'failed'}!</div>;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import { createMovieRef, upsertUserRef, addReviewRef, deleteReviewRef, listMoviesRef, listUsersRef, listUserReviewsRef, getMovieByIdRef, searchMovieRef, connectorConfig } from '../../esm/index.esm.js';
|
||||||
|
import { validateArgs, CallerSdkTypeEnum } from 'firebase/data-connect';
|
||||||
|
import { useDataConnectQuery, useDataConnectMutation, validateReactArgs } from '@tanstack-query-firebase/react/data-connect';
|
||||||
|
|
||||||
|
export function useCreateMovie(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
function refFactory(vars) {
|
||||||
|
return createMovieRef(dcInstance, vars);
|
||||||
|
}
|
||||||
|
return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useUpsertUser(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
function refFactory(vars) {
|
||||||
|
return upsertUserRef(dcInstance, vars);
|
||||||
|
}
|
||||||
|
return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAddReview(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
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);
|
||||||
|
function refFactory(vars) {
|
||||||
|
return deleteReviewRef(dcInstance, vars);
|
||||||
|
}
|
||||||
|
return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function useListMovies(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, options: inputOpts } = validateReactArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
const ref = listMoviesRef(dcInstance);
|
||||||
|
return useDataConnectQuery(ref, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useListUsers(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, options: inputOpts } = validateReactArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
const ref = listUsersRef(dcInstance);
|
||||||
|
return useDataConnectQuery(ref, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useListUserReviews(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, options: inputOpts } = validateReactArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
const ref = listUserReviewsRef(dcInstance);
|
||||||
|
return useDataConnectQuery(ref, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useGetMovieById(dcOrVars, varsOrOptions, options) {
|
||||||
|
const { dc: dcInstance, vars: inputVars, options: inputOpts } = validateReactArgs(connectorConfig, dcOrVars, varsOrOptions, options, true, true);
|
||||||
|
const ref = getMovieByIdRef(dcInstance, inputVars);
|
||||||
|
return useDataConnectQuery(ref, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useSearchMovie(dcOrVars, varsOrOptions, options) {
|
||||||
|
const { dc: dcInstance, vars: inputVars, options: inputOpts } = validateReactArgs(connectorConfig, dcOrVars, varsOrOptions, options, true, false);
|
||||||
|
const ref = searchMovieRef(dcInstance, inputVars);
|
||||||
|
return useDataConnectQuery(ref, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"type":"module"}
|
||||||
66
frontend-web/src/dataconnect-generated/react/index.cjs.js
Normal file
66
frontend-web/src/dataconnect-generated/react/index.cjs.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
const { createMovieRef, upsertUserRef, addReviewRef, deleteReviewRef, listMoviesRef, listUsersRef, listUserReviewsRef, getMovieByIdRef, searchMovieRef, connectorConfig } = require('../index.cjs.js');
|
||||||
|
const { validateArgs, CallerSdkTypeEnum } = require('firebase/data-connect');
|
||||||
|
const { useDataConnectQuery, useDataConnectMutation, validateReactArgs } = require('@tanstack-query-firebase/react/data-connect');
|
||||||
|
|
||||||
|
exports.useCreateMovie = function useCreateMovie(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
function refFactory(vars) {
|
||||||
|
return createMovieRef(dcInstance, vars);
|
||||||
|
}
|
||||||
|
return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.useUpsertUser = function useUpsertUser(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
function refFactory(vars) {
|
||||||
|
return upsertUserRef(dcInstance, vars);
|
||||||
|
}
|
||||||
|
return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.useAddReview = function useAddReview(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, vars: inputOpts } = validateArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
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);
|
||||||
|
function refFactory(vars) {
|
||||||
|
return deleteReviewRef(dcInstance, vars);
|
||||||
|
}
|
||||||
|
return useDataConnectMutation(refFactory, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
exports.useListMovies = function useListMovies(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, options: inputOpts } = validateReactArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
const ref = listMoviesRef(dcInstance);
|
||||||
|
return useDataConnectQuery(ref, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.useListUsers = function useListUsers(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, options: inputOpts } = validateReactArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
const ref = listUsersRef(dcInstance);
|
||||||
|
return useDataConnectQuery(ref, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.useListUserReviews = function useListUserReviews(dcOrOptions, options) {
|
||||||
|
const { dc: dcInstance, options: inputOpts } = validateReactArgs(connectorConfig, dcOrOptions, options);
|
||||||
|
const ref = listUserReviewsRef(dcInstance);
|
||||||
|
return useDataConnectQuery(ref, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.useGetMovieById = function useGetMovieById(dcOrVars, varsOrOptions, options) {
|
||||||
|
const { dc: dcInstance, vars: inputVars, options: inputOpts } = validateReactArgs(connectorConfig, dcOrVars, varsOrOptions, options, true, true);
|
||||||
|
const ref = getMovieByIdRef(dcInstance, inputVars);
|
||||||
|
return useDataConnectQuery(ref, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.useSearchMovie = function useSearchMovie(dcOrVars, varsOrOptions, options) {
|
||||||
|
const { dc: dcInstance, vars: inputVars, options: inputOpts } = validateReactArgs(connectorConfig, dcOrVars, varsOrOptions, options, true, false);
|
||||||
|
const ref = searchMovieRef(dcInstance, inputVars);
|
||||||
|
return useDataConnectQuery(ref, inputOpts, CallerSdkTypeEnum.GeneratedReact);
|
||||||
|
}
|
||||||
33
frontend-web/src/dataconnect-generated/react/index.d.ts
vendored
Normal file
33
frontend-web/src/dataconnect-generated/react/index.d.ts
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { CreateMovieData, CreateMovieVariables, UpsertUserData, UpsertUserVariables, AddReviewData, AddReviewVariables, DeleteReviewData, DeleteReviewVariables, ListMoviesData, ListUsersData, ListUserReviewsData, GetMovieByIdData, GetMovieByIdVariables, SearchMovieData, SearchMovieVariables } from '../';
|
||||||
|
import { UseDataConnectQueryResult, useDataConnectQueryOptions, UseDataConnectMutationResult, useDataConnectMutationOptions} 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 useCreateMovie(options?: useDataConnectMutationOptions<CreateMovieData, FirebaseError, CreateMovieVariables>): UseDataConnectMutationResult<CreateMovieData, CreateMovieVariables>;
|
||||||
|
export function useCreateMovie(dc: DataConnect, options?: useDataConnectMutationOptions<CreateMovieData, FirebaseError, CreateMovieVariables>): UseDataConnectMutationResult<CreateMovieData, CreateMovieVariables>;
|
||||||
|
|
||||||
|
export function useUpsertUser(options?: useDataConnectMutationOptions<UpsertUserData, FirebaseError, UpsertUserVariables>): UseDataConnectMutationResult<UpsertUserData, UpsertUserVariables>;
|
||||||
|
export function useUpsertUser(dc: DataConnect, options?: useDataConnectMutationOptions<UpsertUserData, FirebaseError, UpsertUserVariables>): UseDataConnectMutationResult<UpsertUserData, UpsertUserVariables>;
|
||||||
|
|
||||||
|
export function useAddReview(options?: useDataConnectMutationOptions<AddReviewData, FirebaseError, AddReviewVariables>): UseDataConnectMutationResult<AddReviewData, AddReviewVariables>;
|
||||||
|
export function useAddReview(dc: DataConnect, options?: useDataConnectMutationOptions<AddReviewData, FirebaseError, AddReviewVariables>): UseDataConnectMutationResult<AddReviewData, AddReviewVariables>;
|
||||||
|
|
||||||
|
export function useDeleteReview(options?: useDataConnectMutationOptions<DeleteReviewData, FirebaseError, DeleteReviewVariables>): UseDataConnectMutationResult<DeleteReviewData, DeleteReviewVariables>;
|
||||||
|
export function useDeleteReview(dc: DataConnect, options?: useDataConnectMutationOptions<DeleteReviewData, FirebaseError, DeleteReviewVariables>): UseDataConnectMutationResult<DeleteReviewData, DeleteReviewVariables>;
|
||||||
|
|
||||||
|
export function useListMovies(options?: useDataConnectQueryOptions<ListMoviesData>): UseDataConnectQueryResult<ListMoviesData, undefined>;
|
||||||
|
export function useListMovies(dc: DataConnect, options?: useDataConnectQueryOptions<ListMoviesData>): UseDataConnectQueryResult<ListMoviesData, undefined>;
|
||||||
|
|
||||||
|
export function useListUsers(options?: useDataConnectQueryOptions<ListUsersData>): UseDataConnectQueryResult<ListUsersData, undefined>;
|
||||||
|
export function useListUsers(dc: DataConnect, options?: useDataConnectQueryOptions<ListUsersData>): UseDataConnectQueryResult<ListUsersData, undefined>;
|
||||||
|
|
||||||
|
export function useListUserReviews(options?: useDataConnectQueryOptions<ListUserReviewsData>): UseDataConnectQueryResult<ListUserReviewsData, undefined>;
|
||||||
|
export function useListUserReviews(dc: DataConnect, options?: useDataConnectQueryOptions<ListUserReviewsData>): UseDataConnectQueryResult<ListUserReviewsData, undefined>;
|
||||||
|
|
||||||
|
export function useGetMovieById(vars: GetMovieByIdVariables, options?: useDataConnectQueryOptions<GetMovieByIdData>): UseDataConnectQueryResult<GetMovieByIdData, GetMovieByIdVariables>;
|
||||||
|
export function useGetMovieById(dc: DataConnect, vars: GetMovieByIdVariables, options?: useDataConnectQueryOptions<GetMovieByIdData>): UseDataConnectQueryResult<GetMovieByIdData, GetMovieByIdVariables>;
|
||||||
|
|
||||||
|
export function useSearchMovie(vars?: SearchMovieVariables, options?: useDataConnectQueryOptions<SearchMovieData>): UseDataConnectQueryResult<SearchMovieData, SearchMovieVariables>;
|
||||||
|
export function useSearchMovie(dc: DataConnect, vars?: SearchMovieVariables, options?: useDataConnectQueryOptions<SearchMovieData>): UseDataConnectQueryResult<SearchMovieData, SearchMovieVariables>;
|
||||||
17
frontend-web/src/dataconnect-generated/react/package.json
Normal file
17
frontend-web/src/dataconnect-generated/react/package.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "@dataconnect/generated-react",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": "Firebase <firebase-support@google.com> (https://firebase.google.com/)",
|
||||||
|
"description": "Generated SDK For example",
|
||||||
|
"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": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user