From 02c52c6035d59b1ecc83e39e02f4d78a9ca42a00 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 11 Apr 2025 14:30:44 -0700 Subject: [PATCH 01/63] Added test project to fdc --- .../js/default-connector/README.md | 257 ++++++ .../js/default-connector/esm/index.esm.js | 28 + .../js/default-connector/esm/package.json | 1 + .../js/default-connector/index.cjs.js | 28 + .../js/default-connector/index.d.ts | 50 ++ .../js/default-connector/package.json | 25 + .../dataconnect/connector/connector.yaml | 6 + .../dataconnect/connector/mutations.gql | 33 + .../dataconnect/connector/queries.gql | 78 ++ .../dataconnect/dataconnect.yaml | 12 + .../dataconnect/schema/schema.gql | 52 ++ .../example-integration/dataconnect/test | 0 .../firebase-js-config.json | 3 + .../example-integration/firebase.json | 10 + .../example-integration/package.json | 22 + .../data-connect/example-integration/test.ts | 7 + .../example-integration/testscript.sh | 11 + .../example-integration/tsconfig.json | 10 + .../example-integration/yarn.lock | 802 ++++++++++++++++++ 19 files changed, 1435 insertions(+) create mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/README.md create mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js create mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/package.json create mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js create mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts create mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/package.json create mode 100644 packages/data-connect/example-integration/dataconnect/connector/connector.yaml create mode 100644 packages/data-connect/example-integration/dataconnect/connector/mutations.gql create mode 100644 packages/data-connect/example-integration/dataconnect/connector/queries.gql create mode 100644 packages/data-connect/example-integration/dataconnect/dataconnect.yaml create mode 100644 packages/data-connect/example-integration/dataconnect/schema/schema.gql create mode 100644 packages/data-connect/example-integration/dataconnect/test create mode 100644 packages/data-connect/example-integration/firebase-js-config.json create mode 100644 packages/data-connect/example-integration/firebase.json create mode 100644 packages/data-connect/example-integration/package.json create mode 100644 packages/data-connect/example-integration/test.ts create mode 100755 packages/data-connect/example-integration/testscript.sh create mode 100644 packages/data-connect/example-integration/tsconfig.json create mode 100644 packages/data-connect/example-integration/yarn.lock diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/README.md b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/README.md new file mode 100644 index 00000000000..b3f5971d704 --- /dev/null +++ b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/README.md @@ -0,0 +1,257 @@ +# Table of Contents +- [**Overview**](#generated-typescript-readme) +- [**Accessing the connector**](#accessing-the-connector) + - [*Connecting to the local Emulator*](#connecting-to-the-local-emulator) +- [**Queries**](#queries) + - [*ListMovies*](#listmovies) +- [**Mutations**](#mutations) + - [*CreateMovie*](#createmovie) + +# Generated TypeScript README +This README will guide you through the process of using the generated TypeScript SDK package for the connector `default`. It will also provide examples on how to use your generated SDK to call your Data Connect queries and mutations. + +***NOTE:** This README is generated alongside the generated SDK. If you make changes to this file, they will be overwritten when the SDK is regenerated.* + +You can use this generated SDK by importing from the package `@firebasegen/default-connector` as shown below. Both CommonJS and ESM imports are supported. + +You can also follow the instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#set-client). + +# Accessing the connector +A connector is a collection of Queries and Mutations. One SDK is generated for each connector - this SDK is generated for the connector `default`. + +You can find more information about connectors in the [Data Connect documentation](https://firebase.google.com/docs/data-connect#how-does). + +```javascript +import { getDataConnect } from 'firebase/data-connect'; +import { connectorConfig } from '@firebasegen/default-connector'; + +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#instrument-clients). + +```javascript +import { connectDataConnectEmulator, getDataConnect } from 'firebase/data-connect'; +import { connectorConfig } from '@firebasegen/default-connector'; + +const dataConnect = getDataConnect(connectorConfig); +connectDataConnectEmulator(dataConnect, 'localhost', 9399); +``` + +After it's initialized, you can call your Data Connect [queries](#queries) and [mutations](#mutations) from your generated SDK. + +# Queries + +There are two ways to execute a Data Connect Query using the generated Web SDK: +- Using a Query Reference function, which returns a `QueryRef` + - The `QueryRef` can be used as an argument to `executeQuery()`, which will execute the Query and return a `QueryPromise` +- Using an action shortcut function, which returns a `QueryPromise` + - Calling the action shortcut function will execute the Query and return a `QueryPromise` + +The following is true for both the action shortcut function and the `QueryRef` function: +- The `QueryPromise` returned will resolve to the result of the Query once it has finished executing +- If the Query accepts arguments, both the action shortcut function and the `QueryRef` function accept a single argument: an object that contains all the required variables (and the optional variables) for the Query +- Both functions can be called with or without passing in a `DataConnect` instance as an argument. If no `DataConnect` argument is passed in, then the generated SDK will call `getDataConnect(connectorConfig)` behind the scenes for you. + +Below are examples of how to use the `default` connector's generated functions to execute each query. You can also follow the examples from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#using-queries). + +## ListMovies +You can execute the `ListMovies` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +listMovies(): QueryPromise; + +listMoviesRef(): QueryRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. +```javascript +listMovies(dc: DataConnect): QueryPromise; + +listMoviesRef(dc: DataConnect): QueryRef; +``` + +### Variables +The `ListMovies` query has no variables. +### Return Type +Recall that executing the `ListMovies` query returns a `QueryPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `ListMoviesData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface ListMoviesData { + movies: ({ + id: UUIDString; + title: string; + imageUrl: string; + genre?: string | null; + } & Movie_Key)[]; +} +``` +### Using `ListMovies`'s action shortcut function + +```javascript +import { getDataConnect } from 'firebase/data-connect'; +import { connectorConfig, listMovies } from '@firebasegen/default-connector'; + + +// Call the `listMovies()` function to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await listMovies(); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const dataConnect = getDataConnect(connectorConfig); +const { data } = await listMovies(dataConnect); + +console.log(data.movies); + +// Or, you can use the `Promise` API. +listMovies().then((response) => { + const data = response.data; + console.log(data.movies); +}); +``` + +### Using `ListMovies`'s `QueryRef` function + +```javascript +import { getDataConnect, executeQuery } from 'firebase/data-connect'; +import { connectorConfig, listMoviesRef } from '@firebasegen/default-connector'; + + +// Call the `listMoviesRef()` function to get a reference to the query. +const ref = listMoviesRef(); + +// You can also pass in a `DataConnect` instance to the `QueryRef` function. +const dataConnect = getDataConnect(connectorConfig); +const ref = listMoviesRef(dataConnect); + +// Call `executeQuery()` on the reference to execute the query. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeQuery(ref); + +console.log(data.movies); + +// Or, you can use the `Promise` API. +executeQuery(ref).then((response) => { + const data = response.data; + console.log(data.movies); +}); +``` + +# Mutations + +There are two ways to execute a Data Connect Mutation using the generated Web SDK: +- Using a Mutation Reference function, which returns a `MutationRef` + - The `MutationRef` can be used as an argument to `executeMutation()`, which will execute the Mutation and return a `MutationPromise` +- Using an action shortcut function, which returns a `MutationPromise` + - Calling the action shortcut function will execute the Mutation and return a `MutationPromise` + +The following is true for both the action shortcut function and the `MutationRef` function: +- The `MutationPromise` returned will resolve to the result of the Mutation once it has finished executing +- If the Mutation accepts arguments, both the action shortcut function and the `MutationRef` function accept a single argument: an object that contains all the required variables (and the optional variables) for the Mutation +- Both functions can be called with or without passing in a `DataConnect` instance as an argument. If no `DataConnect` argument is passed in, then the generated SDK will call `getDataConnect(connectorConfig)` behind the scenes for you. + +Below are examples of how to use the `default` connector's generated functions to execute each mutation. You can also follow the examples from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#using-mutations). + +## CreateMovie +You can execute the `CreateMovie` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): +```javascript +createMovie(vars: CreateMovieVariables): MutationPromise; + +createMovieRef(vars: CreateMovieVariables): MutationRef; +``` +You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. +```javascript +createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; + +createMovieRef(dc: DataConnect, vars: CreateMovieVariables): MutationRef; +``` + +### Variables +The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: + +```javascript +export interface CreateMovieVariables { + title: string; + genre: string; + imageUrl: string; +} +``` +### Return Type +Recall that executing the `CreateMovie` mutation returns a `MutationPromise` that resolves to an object with a `data` property. + +The `data` property is an object of type `CreateMovieData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: +```javascript +export interface CreateMovieData { + movie_insert: Movie_Key; +} +``` +### Using `CreateMovie`'s action shortcut function + +```javascript +import { getDataConnect } from 'firebase/data-connect'; +import { connectorConfig, createMovie, CreateMovieVariables } from '@firebasegen/default-connector'; + +// The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: +const createMovieVars: CreateMovieVariables = { + title: ..., + genre: ..., + imageUrl: ..., +}; + +// Call the `createMovie()` function to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await createMovie(createMovieVars); +// Variables can be defined inline as well. +const { data } = await createMovie({ title: ..., genre: ..., imageUrl: ..., }); + +// You can also pass in a `DataConnect` instance to the action shortcut function. +const dataConnect = getDataConnect(connectorConfig); +const { data } = await createMovie(dataConnect, createMovieVars); + +console.log(data.movie_insert); + +// Or, you can use the `Promise` API. +createMovie(createMovieVars).then((response) => { + const data = response.data; + console.log(data.movie_insert); +}); +``` + +### Using `CreateMovie`'s `MutationRef` function + +```javascript +import { getDataConnect, executeMutation } from 'firebase/data-connect'; +import { connectorConfig, createMovieRef, CreateMovieVariables } from '@firebasegen/default-connector'; + +// The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: +const createMovieVars: CreateMovieVariables = { + title: ..., + genre: ..., + imageUrl: ..., +}; + +// Call the `createMovieRef()` function to get a reference to the mutation. +const ref = createMovieRef(createMovieVars); +// Variables can be defined inline as well. +const ref = createMovieRef({ title: ..., genre: ..., imageUrl: ..., }); + +// You can also pass in a `DataConnect` instance to the `MutationRef` function. +const dataConnect = getDataConnect(connectorConfig); +const ref = createMovieRef(dataConnect, createMovieVars); + +// Call `executeMutation()` on the reference to execute the mutation. +// You can use the `await` keyword to wait for the promise to resolve. +const { data } = await executeMutation(ref); + +console.log(data.movie_insert); + +// Or, you can use the `Promise` API. +executeMutation(ref).then((response) => { + const data = response.data; + console.log(data.movie_insert); +}); +``` + diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js new file mode 100644 index 00000000000..28675a48069 --- /dev/null +++ b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js @@ -0,0 +1,28 @@ +import { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } from 'firebase/data-connect'; + +export const connectorConfig = { + connector: 'default', + service: 'fdc-test', + location: 'us-central1' +}; + +export function createMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'CreateMovie', inputVars); +} + +export function createMovie(dcOrVars, vars) { + return executeMutation(createMovieRef(dcOrVars, vars)); +} + +export function listMoviesRef(dc) { + const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'ListMovies'); +} + +export function listMovies(dc) { + return executeQuery(listMoviesRef(dc)); +} + diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/package.json b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/package.json new file mode 100644 index 00000000000..7c34deb5837 --- /dev/null +++ b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/package.json @@ -0,0 +1 @@ +{"type":"module"} \ No newline at end of file diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js new file mode 100644 index 00000000000..7f8250f2599 --- /dev/null +++ b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js @@ -0,0 +1,28 @@ +const { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } = require('firebase/data-connect'); + +const connectorConfig = { + connector: 'default', + service: 'fdc-test', + location: 'us-central1' +}; +exports.connectorConfig = connectorConfig; + +exports.createMovieRef = function createMovieRef(dcOrVars, vars) { + const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + dcInstance._useGeneratedSdk(); + return mutationRef(dcInstance, 'CreateMovie', inputVars); +} + +exports.createMovie = function createMovie(dcOrVars, vars) { + return executeMutation(createMovieRef(dcOrVars, vars)); +}; + +exports.listMoviesRef = function listMoviesRef(dc) { + const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + dcInstance._useGeneratedSdk(); + return queryRef(dcInstance, 'ListMovies'); +} + +exports.listMovies = function listMovies(dc) { + return executeQuery(listMoviesRef(dc)); +}; diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts new file mode 100644 index 00000000000..5d821c79cc9 --- /dev/null +++ b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts @@ -0,0 +1,50 @@ +import { ConnectorConfig, DataConnect, QueryRef, QueryPromise, MutationRef, MutationPromise } from 'firebase/data-connect'; + +export const connectorConfig: ConnectorConfig; + +export type TimestampString = string; +export type UUIDString = string; +export type Int64String = string; +export type DateString = string; + + +export interface CreateMovieData { + movie_insert: Movie_Key; +} + +export interface CreateMovieVariables { + title: string; + genre: string; + imageUrl: string; +} + +export interface ListMoviesData { + movies: ({ + id: UUIDString; + title: string; + imageUrl: string; + genre?: string | null; + } & Movie_Key)[]; +} + +export interface Movie_Key { + id: UUIDString; + __typename?: 'Movie_Key'; +} + +/* Allow users to create refs without passing in DataConnect */ +export function createMovieRef(vars: CreateMovieVariables): MutationRef; +/* Allow users to pass in custom DataConnect instances */ +export function createMovieRef(dc: DataConnect, vars: CreateMovieVariables): MutationRef; + +export function createMovie(vars: CreateMovieVariables): MutationPromise; +export function createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; + +/* Allow users to create refs without passing in DataConnect */ +export function listMoviesRef(): QueryRef; +/* Allow users to pass in custom DataConnect instances */ +export function listMoviesRef(dc: DataConnect): QueryRef; + +export function listMovies(): QueryPromise; +export function listMovies(dc: DataConnect): QueryPromise; + diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/package.json b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/package.json new file mode 100644 index 00000000000..d0c9852ce3e --- /dev/null +++ b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/package.json @@ -0,0 +1,25 @@ +{ + "name": "@firebasegen/default-connector", + "version": "1.0.0", + "author": "Firebase (https://firebase.google.com/)", + "description": "Generated SDK For default", + "license": "Apache-2.0", + "engines": { + "node": " >=18.0" + }, + "typings": "index.d.ts", + "module": "esm/index.esm.js", + "main": "index.cjs.js", + "browser": "esm/index.esm.js", + "exports": { + ".": { + "types": "./index.d.ts", + "require": "./index.cjs.js", + "default": "./esm/index.esm.js" + }, + "./package.json": "./package.json" + }, + "peerDependencies": { + "firebase": "^10.14.0 || ^11.3.0" + } +} \ No newline at end of file diff --git a/packages/data-connect/example-integration/dataconnect/connector/connector.yaml b/packages/data-connect/example-integration/dataconnect/connector/connector.yaml new file mode 100644 index 00000000000..b698515fe9f --- /dev/null +++ b/packages/data-connect/example-integration/dataconnect/connector/connector.yaml @@ -0,0 +1,6 @@ +connectorId: default +generate: + javascriptSdk: + outputDir: ../../dataconnect-generated/js/default-connector + package: "@firebasegen/default-connector" +# packageJsonDir: ../.. diff --git a/packages/data-connect/example-integration/dataconnect/connector/mutations.gql b/packages/data-connect/example-integration/dataconnect/connector/mutations.gql new file mode 100644 index 00000000000..2379afeb89c --- /dev/null +++ b/packages/data-connect/example-integration/dataconnect/connector/mutations.gql @@ -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) { + 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 }) +# } diff --git a/packages/data-connect/example-integration/dataconnect/connector/queries.gql b/packages/data-connect/example-integration/dataconnect/connector/queries.gql new file mode 100644 index 00000000000..cb1a6f630bc --- /dev/null +++ b/packages/data-connect/example-integration/dataconnect/connector/queries.gql @@ -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) { + 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 +# # _on_ makes it easy to grab info from another table +# # Here, we use it to grab all the reviews written by the user. +# reviews: reviews_on_user { +# rating +# reviewDate +# reviewText +# movie { +# id +# title +# } +# } +# } +# } + +# # Get movie by id +# query GetMovieById($id: UUID!) @auth(level: PUBLIC) { +# 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) { +# movies( +# where: { +# _and: [{ genre: { eq: $genre } }, { title: { contains: $titleInput } }] +# } +# ) { +# id +# title +# genre +# imageUrl +# } +# } diff --git a/packages/data-connect/example-integration/dataconnect/dataconnect.yaml b/packages/data-connect/example-integration/dataconnect/dataconnect.yaml new file mode 100644 index 00000000000..623fad3e209 --- /dev/null +++ b/packages/data-connect/example-integration/dataconnect/dataconnect.yaml @@ -0,0 +1,12 @@ +specVersion: "v1beta" +serviceId: "fdc-test" +location: "us-central1" +schema: + source: "./schema" + datasource: + postgresql: + database: "fdcdb" + cloudSql: + instanceId: "fdc-test-fdc" + # schemaValidation: "COMPATIBLE" +connectorDirs: ["./connector"] diff --git a/packages/data-connect/example-integration/dataconnect/schema/schema.gql b/packages/data-connect/example-integration/dataconnect/schema/schema.gql new file mode 100644 index 00000000000..f114d9a678a --- /dev/null +++ b/packages/data-connect/example-integration/dataconnect/schema/schema.gql @@ -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") +# } diff --git a/packages/data-connect/example-integration/dataconnect/test b/packages/data-connect/example-integration/dataconnect/test new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/data-connect/example-integration/firebase-js-config.json b/packages/data-connect/example-integration/firebase-js-config.json new file mode 100644 index 00000000000..0e0dcd235c4 --- /dev/null +++ b/packages/data-connect/example-integration/firebase-js-config.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/packages/data-connect/example-integration/firebase.json b/packages/data-connect/example-integration/firebase.json new file mode 100644 index 00000000000..6c9ad90b440 --- /dev/null +++ b/packages/data-connect/example-integration/firebase.json @@ -0,0 +1,10 @@ +{ + "emulators": { + "dataconnect": { + "dataDir": "dataconnect/.dataconnect/pgliteData" + } + }, + "dataconnect": { + "source": "dataconnect" + } +} diff --git a/packages/data-connect/example-integration/package.json b/packages/data-connect/example-integration/package.json new file mode 100644 index 00000000000..c530ffe0952 --- /dev/null +++ b/packages/data-connect/example-integration/package.json @@ -0,0 +1,22 @@ +{ + "name": "fdc-test", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@types/node": "^22.13.14", + "ts-node": "^10.9.2", + "tslib": "^2.8.1", + "typescript": "^5.8.2" + }, + "dependencies": { + "firebase": "11.5.0" + } +} diff --git a/packages/data-connect/example-integration/test.ts b/packages/data-connect/example-integration/test.ts new file mode 100644 index 00000000000..86030405c15 --- /dev/null +++ b/packages/data-connect/example-integration/test.ts @@ -0,0 +1,7 @@ +import { listMovies } from './dataconnect-generated/js/default-connector'; +import * as json from './firebase-js-config.json'; +import { initializeApp } from 'firebase/app'; + +initializeApp(json); +listMovies(); + diff --git a/packages/data-connect/example-integration/testscript.sh b/packages/data-connect/example-integration/testscript.sh new file mode 100755 index 00000000000..6a56cb4d536 --- /dev/null +++ b/packages/data-connect/example-integration/testscript.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +statusResult=$(git status --porcelain | wc -l) +if [[ statusResult -eq "0" ]] +then + echo 'no changes found' +else + echo 'The workspace is modified:' + echo "$statusResult" +fi + diff --git a/packages/data-connect/example-integration/tsconfig.json b/packages/data-connect/example-integration/tsconfig.json new file mode 100644 index 00000000000..e3c427a3163 --- /dev/null +++ b/packages/data-connect/example-integration/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ES5", + "module": "CommonJS", + "resolveJsonModule": true, + "sourceMap": true, + "noEmit": true, + "skipLibCheck": false + } + } diff --git a/packages/data-connect/example-integration/yarn.lock b/packages/data-connect/example-integration/yarn.lock new file mode 100644 index 00000000000..cb23e2383e1 --- /dev/null +++ b/packages/data-connect/example-integration/yarn.lock @@ -0,0 +1,802 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@firebase/analytics-compat@0.2.18": + version "0.2.18" + resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.2.18.tgz#5ea9bdea188d4c91938f539af4c4414813ddc5c9" + integrity sha512-Hw9mzsSMZaQu6wrTbi3kYYwGw9nBqOHr47pVLxfr5v8CalsdrG5gfs9XUlPOZjHRVISp3oQrh1j7d3E+ulHPjQ== + dependencies: + "@firebase/analytics" "0.10.12" + "@firebase/analytics-types" "0.8.3" + "@firebase/component" "0.6.13" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/analytics-types@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.8.3.tgz#d08cd39a6209693ca2039ba7a81570dfa6c1518f" + integrity sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg== + +"@firebase/analytics@0.10.12": + version "0.10.12" + resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.10.12.tgz#b49b9351b8cb19da007320a52932b953fff90d71" + integrity sha512-iDCGnw6qdFqwI5ywkgece99WADJNoymu+nLIQI4fZM/vCZ3bEo4wlpEetW71s1HqGpI0hQStiPhqVjFxDb2yyw== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/installations" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/app-check-compat@0.3.20": + version "0.3.20" + resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.3.20.tgz#0dfce42699402f3b621be98857a8109b9397a37b" + integrity sha512-/twgmlnNAaZ/wbz3kcQrL/26b+X+zUX+lBmu5LwwEcWcpnb+mrVEAKhD7/ttm52dxYiSWtLDeuXy3FXBhqBC5A== + dependencies: + "@firebase/app-check" "0.8.13" + "@firebase/app-check-types" "0.5.3" + "@firebase/component" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/app-check-interop-types@0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz#ed9c4a4f48d1395ef378f007476db3940aa5351a" + integrity sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A== + +"@firebase/app-check-types@0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@firebase/app-check-types/-/app-check-types-0.5.3.tgz#38ba954acf4bffe451581a32fffa20337f11d8e5" + integrity sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng== + +"@firebase/app-check@0.8.13": + version "0.8.13" + resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.8.13.tgz#20b212d0ea5b79c9492f434abc276d4f28b19371" + integrity sha512-ONsgml8/dplUOAP42JQO6hhiWDEwR9+RUTLenxAN9S8N6gel/sDQ9Ci721Py1oASMGdDU8v9R7xAZxzvOX5lPg== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/app-compat@0.2.52": + version "0.2.52" + resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.52.tgz#71ac4334c2dc841be3f101ab1f7d00412568a885" + integrity sha512-0p/l1KiwhwwYTcPWoleFQHftOnYzeXvyVf3WNZyKFBAoQMpCVW6bVm/uO1bXF91AwU1JN0og888Y6Sc8avqZ+A== + dependencies: + "@firebase/app" "0.11.3" + "@firebase/component" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/app-types@0.9.3": + version "0.9.3" + resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.9.3.tgz#8408219eae9b1fb74f86c24e7150a148460414ad" + integrity sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw== + +"@firebase/app@0.11.3": + version "0.11.3" + resolved "https://registry.npmjs.org/@firebase/app/-/app-0.11.3.tgz#80abcb65a1dce743d081022d2934fe69e60c1d41" + integrity sha512-QlTZl/RcqPSonYxB87n8KgAUW2L6ZZz0W4D91PVmQ1tJPsKsKPrWAFHL0ii2cQW6FxTxfNjbZ7kucuIcKXk3tw== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/auth-compat@0.5.19": + version "0.5.19" + resolved "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.19.tgz#6f393e85496754bfc4f31758bc0718a88f9c2f30" + integrity sha512-v898POphOIBJliKF76SiGOXh4EdhO5fM6S9a2ZKf/8wHdBea/qwxwZoVVya4DW6Mi7vWyp1lIzHbFgwRz8G9TA== + dependencies: + "@firebase/auth" "1.9.1" + "@firebase/auth-types" "0.13.0" + "@firebase/component" "0.6.13" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/auth-interop-types@0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz#176a08686b0685596ff03d7879b7e4115af53de0" + integrity sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA== + +"@firebase/auth-types@0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.13.0.tgz#ae6e0015e3bd4bfe18edd0942b48a0a118a098d9" + integrity sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg== + +"@firebase/auth@1.9.1": + version "1.9.1" + resolved "https://registry.npmjs.org/@firebase/auth/-/auth-1.9.1.tgz#5fca654e003a7fa0b3bbb247782633c3aab67ce4" + integrity sha512-9KKo5SNVkyJzftsW+daS+PGDbeJ+MFJWXQFHDqqPPH3acWHtiNnGHH5HGpIJErEELrsm9xMPie5zfZ0XpGU8+w== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/component@0.6.13": + version "0.6.13" + resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.6.13.tgz#6513379f1c09264133969d87282ce0d5bbbb2cd9" + integrity sha512-I/Eg1NpAtZ8AAfq8mpdfXnuUpcLxIDdCDtTzWSh+FXnp/9eCKJ3SNbOCKrUCyhLzNa2SiPJYruei0sxVjaOTeg== + dependencies: + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/data-connect@0.3.2": + version "0.3.2" + resolved "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.3.2.tgz#8a74af2e111fe1a36d7bf37c55a7c2469e8a051f" + integrity sha512-PYG55JRTmvYrUuXXmYBsZexwKVP9aR3mIRRHxB9V2bQeRDZky6JtRZnH3GLhf4ZsxZy5Ewd8ul/jTOYR4gpD9w== + dependencies: + "@firebase/auth-interop-types" "0.2.4" + "@firebase/component" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/database-compat@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-2.0.5.tgz#110f612901995f9800f2435f58686e0c6f3d2544" + integrity sha512-CNf1UbvWh6qIaSf4sn6sx2DTDz/em/D7QxULH1LTxxDQHr9+CeYGvlAqrKnk4ZH0P0eIHyQFQU7RwkUJI0B9gQ== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/database" "1.0.14" + "@firebase/database-types" "1.0.10" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/database-types@1.0.10": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-1.0.10.tgz#14cfed45bb06394cf1641e19265cbf90e4f6fb51" + integrity sha512-mH6RC1E9/Pv8jf1/p+M8YFTX+iu+iHDN89hecvyO7wHrI4R1V0TXjxOHvX3nLJN1sfh0CWG6CHZ0VlrSmK/cwg== + dependencies: + "@firebase/app-types" "0.9.3" + "@firebase/util" "1.11.0" + +"@firebase/database@1.0.14": + version "1.0.14" + resolved "https://registry.yarnpkg.com/@firebase/database/-/database-1.0.14.tgz#1d579b345c0f926eaddb7703051999489300c3bd" + integrity sha512-9nxYtkHAG02/Nh2Ssms1T4BbWPPjiwohCvkHDUl4hNxnki1kPgsLo5xe9kXNzbacOStmVys+RUXvwzynQSKmUQ== + dependencies: + "@firebase/app-check-interop-types" "0.3.3" + "@firebase/auth-interop-types" "0.2.4" + "@firebase/component" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + faye-websocket "0.11.4" + tslib "^2.1.0" + +"@firebase/firestore-compat@0.3.45": + version "0.3.45" + resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.3.45.tgz#93061f7d3644cd511749c9268d146e8c8c49a5de" + integrity sha512-uRvi7AYPmsDl7UZwPyV7jgDGYusEZ2+U2g7MndbQHKIA8fNHpYC6QrzMs58+/IjX+kF/lkUn67Vrr0AkVjlY+Q== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/firestore" "4.7.10" + "@firebase/firestore-types" "3.0.3" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/firestore-types@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-3.0.3.tgz#7d0c3dd8850c0193d8f5ee0cc8f11961407742c1" + integrity sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q== + +"@firebase/firestore@4.7.10": + version "4.7.10" + resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-4.7.10.tgz#6fe0cd31fcd7f4a8e13f9585f53e9300cf3114c0" + integrity sha512-6nKsyo2U+jYSCcSE5sjMdDNA23DMUvYPUvsYGg09CNvcTO8GGKsPs7SpOhspsB91mbacq+u627CDAx3FUhPSSQ== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + "@firebase/webchannel-wrapper" "1.0.3" + "@grpc/grpc-js" "~1.9.0" + "@grpc/proto-loader" "^0.7.8" + tslib "^2.1.0" + +"@firebase/functions-compat@0.3.20": + version "0.3.20" + resolved "https://registry.yarnpkg.com/@firebase/functions-compat/-/functions-compat-0.3.20.tgz#addf89242be8b4d63feacb15ef27785e16c5e220" + integrity sha512-iIudmYDAML6n3c7uXO2YTlzra2/J6lnMzmJTXNthvrKVMgNMaseNoQP1wKfchK84hMuSF8EkM4AvufwbJ+Juew== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/functions" "0.12.3" + "@firebase/functions-types" "0.6.3" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/functions-types@0.6.3": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.6.3.tgz#f5faf770248b13f45d256f614230da6a11bfb654" + integrity sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg== + +"@firebase/functions@0.12.3": + version "0.12.3" + resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.12.3.tgz#b3e395aed1641d0d7169a22698c684a2745e02dd" + integrity sha512-Wv7JZMUkKLb1goOWRtsu3t7m97uK6XQvjQLPvn8rncY91+VgdU72crqnaYCDI/ophNuBEmuK8mn0/pAnjUeA6A== + dependencies: + "@firebase/app-check-interop-types" "0.3.3" + "@firebase/auth-interop-types" "0.2.4" + "@firebase/component" "0.6.13" + "@firebase/messaging-interop-types" "0.2.3" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/installations-compat@0.2.13": + version "0.2.13" + resolved "https://registry.yarnpkg.com/@firebase/installations-compat/-/installations-compat-0.2.13.tgz#0db0867ed58b782f7e2d142d9289a9eef1da24d5" + integrity sha512-f/o6MqCI7LD/ulY9gvgkv6w5k6diaReD8BFHd/y/fEdpsXmFWYS/g28GXCB72bRVBOgPpkOUNl+VsMvDwlRKmw== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/installations" "0.6.13" + "@firebase/installations-types" "0.5.3" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/installations-types@0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.5.3.tgz#cac8a14dd49f09174da9df8ae453f9b359c3ef2f" + integrity sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA== + +"@firebase/installations@0.6.13": + version "0.6.13" + resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.6.13.tgz#a2a00aebb5dfb74fae08600ea98cd2681211dd3c" + integrity sha512-6ZpkUiaygPFwgVneYxuuOuHnSPnTA4KefLEaw/sKk/rNYgC7X6twaGfYb0sYLpbi9xV4i5jXsqZ3WO+yaguNgg== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/util" "1.11.0" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/logger@0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.4.4.tgz#29e8379d20fd1149349a195ee6deee4573a86f48" + integrity sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g== + dependencies: + tslib "^2.1.0" + +"@firebase/messaging-compat@0.2.17": + version "0.2.17" + resolved "https://registry.yarnpkg.com/@firebase/messaging-compat/-/messaging-compat-0.2.17.tgz#fc223495319fe3784347dea77094b6e03548647d" + integrity sha512-5Q+9IG7FuedusdWHVQRjpA3OVD9KUWp/IPegcv0s5qSqRLBjib7FlAeWxN+VL0Ew43tuPJBY2HKhEecuizmO1Q== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/messaging" "0.12.17" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/messaging-interop-types@0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz#e647c9cd1beecfe6a6e82018a6eec37555e4da3e" + integrity sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q== + +"@firebase/messaging@0.12.17": + version "0.12.17" + resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.12.17.tgz#41eaeee70a89136715a4f7cb2b1a602423fc44ec" + integrity sha512-W3CnGhTm6Nx8XGb6E5/+jZTuxX/EK8Vur4QXvO1DwZta/t0xqWMRgO9vNsZFMYBqFV4o3j4F9qK/iddGYwWS6g== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/installations" "0.6.13" + "@firebase/messaging-interop-types" "0.2.3" + "@firebase/util" "1.11.0" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/performance-compat@0.2.15": + version "0.2.15" + resolved "https://registry.yarnpkg.com/@firebase/performance-compat/-/performance-compat-0.2.15.tgz#4e5034add63917cb6357938126e9e6562d0e7208" + integrity sha512-wUxsw7hGBEMN6XfvYQqwPIQp5LcJXawWM5tmYp6L7ClCoTQuEiCKHWWVurJgN8Q1YHzoHVgjNfPQAOVu29iMVg== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/performance" "0.7.2" + "@firebase/performance-types" "0.2.3" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/performance-types@0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.2.3.tgz#5ce64e90fa20ab5561f8b62a305010cf9fab86fb" + integrity sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ== + +"@firebase/performance@0.7.2": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.7.2.tgz#e30ee3e3c120c53f48bde7bdd915687f1e3b27e1" + integrity sha512-DXLLp0R0jdxH/yTmv+WTkOzsLl8YYecXh4lGZE0dzqC0IV8k+AxpLSSWvOTCkAETze8yEU/iF+PtgYVlGjfMMQ== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/installations" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + web-vitals "^4.2.4" + +"@firebase/remote-config-compat@0.2.13": + version "0.2.13" + resolved "https://registry.yarnpkg.com/@firebase/remote-config-compat/-/remote-config-compat-0.2.13.tgz#4a35c2c6bb582d96aecc45da18f5094359cb5361" + integrity sha512-UmHoO7TxAEJPIZf8e1Hy6CeFGMeyjqSCpgoBkQZYXFI2JHhzxIyDpr8jVKJJN1dmAePKZ5EX7dC13CmcdTOl7Q== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/remote-config" "0.6.0" + "@firebase/remote-config-types" "0.4.0" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/remote-config-types@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz#91b9a836d5ca30ced68c1516163b281fbb544537" + integrity sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg== + +"@firebase/remote-config@0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.6.0.tgz#24a6966a4d092260983ba8597cc039f5795cd35f" + integrity sha512-Yrk4l5+6FJLPHC6irNHMzgTtJ3NfHXlAXVChCBdNFtgmzyGmufNs/sr8oA0auEfIJ5VpXCaThRh3P4OdQxiAlQ== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/installations" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/storage-compat@0.3.17": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@firebase/storage-compat/-/storage-compat-0.3.17.tgz#67f6bbc498971e6e404e0ea660fa5df81c5ba5ea" + integrity sha512-CBlODWEZ5b6MJWVh21VZioxwxNwVfPA9CAdsk+ZgVocJQQbE2oDW1XJoRcgthRY1HOitgbn4cVrM+NlQtuUYhw== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/storage" "0.13.7" + "@firebase/storage-types" "0.8.3" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/storage-types@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.8.3.tgz#2531ef593a3452fc12c59117195d6485c6632d3d" + integrity sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg== + +"@firebase/storage@0.13.7": + version "0.13.7" + resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.13.7.tgz#809fc23685ad9ba8fdfb3bc758e3353867c9e796" + integrity sha512-FkRyc24rK+Y6EaQ1tYFm3TevBnnfSNA0VyTfew2hrYyL/aYfatBg7HOgktUdB4kWMHNA9VoTotzZTGoLuK92wg== + dependencies: + "@firebase/component" "0.6.13" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/util@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.11.0.tgz#e74ee2dc260ec4f9e75fe5d52bc4b0254d9872a9" + integrity sha512-PzSrhIr++KI6y4P6C/IdgBNMkEx0Ex6554/cYd0Hm+ovyFSJtJXqb/3OSIdnBoa2cpwZT1/GW56EmRc5qEc5fQ== + dependencies: + tslib "^2.1.0" + +"@firebase/vertexai@1.2.0": + version "1.2.0" + resolved "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.2.0.tgz#8f8a4ae75284c3067c0a06c7d0bef922571e6dd7" + integrity sha512-WUYIzFpOipjFXT2i0hT26wivJoIximizQptVs3KAxFAqbVlO8sjKPsMkgz0bh+tdKlqP4SUDda71fMUZXUKHgA== + dependencies: + "@firebase/app-check-interop-types" "0.3.3" + "@firebase/component" "0.6.13" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.11.0" + tslib "^2.1.0" + +"@firebase/webchannel-wrapper@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz#a73bab8eb491d7b8b7be2f0e6c310647835afe83" + integrity sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ== + +"@grpc/grpc-js@~1.9.0": + version "1.9.15" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.15.tgz#433d7ac19b1754af690ea650ab72190bd700739b" + integrity sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ== + dependencies: + "@grpc/proto-loader" "^0.7.8" + "@types/node" ">=12.12.47" + +"@grpc/proto-loader@^0.7.8": + version "0.7.13" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.13.tgz#f6a44b2b7c9f7b609f5748c6eac2d420e37670cf" + integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw== + dependencies: + lodash.camelcase "^4.3.0" + long "^5.0.0" + protobufjs "^7.2.5" + yargs "^17.7.2" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@^22.13.14": + version "22.14.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.14.0.tgz#d3bfa3936fef0dbacd79ea3eb17d521c628bb47e" + integrity sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA== + dependencies: + undici-types "~6.21.0" + +acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.11.0, acorn@^8.4.1: + version "8.14.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" + integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +faye-websocket@0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +firebase@11.5.0: + version "11.5.0" + resolved "https://registry.npmjs.org/firebase/-/firebase-11.5.0.tgz#9a358ed8c7e805de8df64061840b2593ae706165" + integrity sha512-ZTpO/zD5nYqY02bGpXCg1dRNLggTXPQZdLQeSeur3jYH270p1QkAZZJsm/lrKZ2W4ZjBlafTxxs4OwN38Vyocw== + dependencies: + "@firebase/analytics" "0.10.12" + "@firebase/analytics-compat" "0.2.18" + "@firebase/app" "0.11.3" + "@firebase/app-check" "0.8.13" + "@firebase/app-check-compat" "0.3.20" + "@firebase/app-compat" "0.2.52" + "@firebase/app-types" "0.9.3" + "@firebase/auth" "1.9.1" + "@firebase/auth-compat" "0.5.19" + "@firebase/data-connect" "0.3.2" + "@firebase/database" "1.0.14" + "@firebase/database-compat" "2.0.5" + "@firebase/firestore" "4.7.10" + "@firebase/firestore-compat" "0.3.45" + "@firebase/functions" "0.12.3" + "@firebase/functions-compat" "0.3.20" + "@firebase/installations" "0.6.13" + "@firebase/installations-compat" "0.2.13" + "@firebase/messaging" "0.12.17" + "@firebase/messaging-compat" "0.2.17" + "@firebase/performance" "0.7.2" + "@firebase/performance-compat" "0.2.15" + "@firebase/remote-config" "0.6.0" + "@firebase/remote-config-compat" "0.2.13" + "@firebase/storage" "0.13.7" + "@firebase/storage-compat" "0.3.17" + "@firebase/util" "1.11.0" + "@firebase/vertexai" "1.2.0" + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +http-parser-js@>=0.5.1: + version "0.5.9" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.9.tgz#b817b3ca0edea6236225000d795378707c169cec" + integrity sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw== + +idb@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" + integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +long@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/long/-/long-5.3.1.tgz#9d4222d3213f38a5ec809674834e0f0ab21abe96" + integrity sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng== + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +protobufjs@^7.2.5: + version "7.4.0" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.4.0.tgz#7efe324ce9b3b61c82aae5de810d287bc08a248a" + integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +safe-buffer@>=5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@^2.1.0, tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +typescript@^5.8.2: + version "5.8.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4" + integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +web-vitals@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7" + integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw== + +websocket-driver@>=0.5.1: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From 37d0f189795071ceba6de013054a25a863033a3b Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 11 Apr 2025 14:34:15 -0700 Subject: [PATCH 02/63] Fixed formatting --- .../js/default-connector/esm/index.esm.js | 35 ++++++++++-- .../js/default-connector/index.cjs.js | 38 +++++++++++-- .../js/default-connector/index.d.ts | 54 +++++++++++++++---- .../data-connect/example-integration/test.ts | 18 ++++++- 4 files changed, 126 insertions(+), 19 deletions(-) diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js index 28675a48069..e88d2d56d35 100644 --- a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js +++ b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js @@ -1,4 +1,27 @@ -import { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } from 'firebase/data-connect'; +/** + * @license + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + queryRef, + executeQuery, + mutationRef, + executeMutation, + validateArgs +} from 'firebase/data-connect'; export const connectorConfig = { connector: 'default', @@ -7,7 +30,12 @@ export const connectorConfig = { }; export function createMovieRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + const { dc: dcInstance, vars: inputVars } = validateArgs( + connectorConfig, + dcOrVars, + vars, + true + ); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'CreateMovie', inputVars); } @@ -17,7 +45,7 @@ export function createMovie(dcOrVars, vars) { } export function listMoviesRef(dc) { - const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + const { dc: dcInstance } = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'ListMovies'); } @@ -25,4 +53,3 @@ export function listMoviesRef(dc) { export function listMovies(dc) { return executeQuery(listMoviesRef(dc)); } - diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js index 7f8250f2599..814406ff090 100644 --- a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js +++ b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js @@ -1,4 +1,27 @@ -const { queryRef, executeQuery, mutationRef, executeMutation, validateArgs } = require('firebase/data-connect'); +/** + * @license + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const { + queryRef, + executeQuery, + mutationRef, + executeMutation, + validateArgs +} = require('firebase/data-connect'); const connectorConfig = { connector: 'default', @@ -8,20 +31,25 @@ const connectorConfig = { exports.connectorConfig = connectorConfig; exports.createMovieRef = function createMovieRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars} = validateArgs(connectorConfig, dcOrVars, vars, true); + const { dc: dcInstance, vars: inputVars } = validateArgs( + connectorConfig, + dcOrVars, + vars, + true + ); dcInstance._useGeneratedSdk(); return mutationRef(dcInstance, 'CreateMovie', inputVars); -} +}; exports.createMovie = function createMovie(dcOrVars, vars) { return executeMutation(createMovieRef(dcOrVars, vars)); }; exports.listMoviesRef = function listMoviesRef(dc) { - const { dc: dcInstance} = validateArgs(connectorConfig, dc, undefined); + const { dc: dcInstance } = validateArgs(connectorConfig, dc, undefined); dcInstance._useGeneratedSdk(); return queryRef(dcInstance, 'ListMovies'); -} +}; exports.listMovies = function listMovies(dc) { return executeQuery(listMoviesRef(dc)); diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts index 5d821c79cc9..474fefd0f4b 100644 --- a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts +++ b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts @@ -1,4 +1,28 @@ -import { ConnectorConfig, DataConnect, QueryRef, QueryPromise, MutationRef, MutationPromise } from 'firebase/data-connect'; +/** + * @license + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ConnectorConfig, + DataConnect, + QueryRef, + QueryPromise, + MutationRef, + MutationPromise +} from 'firebase/data-connect'; export const connectorConfig: ConnectorConfig; @@ -7,7 +31,6 @@ export type UUIDString = string; export type Int64String = string; export type DateString = string; - export interface CreateMovieData { movie_insert: Movie_Key; } @@ -33,18 +56,31 @@ export interface Movie_Key { } /* Allow users to create refs without passing in DataConnect */ -export function createMovieRef(vars: CreateMovieVariables): MutationRef; +export function createMovieRef( + vars: CreateMovieVariables +): MutationRef; /* Allow users to pass in custom DataConnect instances */ -export function createMovieRef(dc: DataConnect, vars: CreateMovieVariables): MutationRef; +export function createMovieRef( + dc: DataConnect, + vars: CreateMovieVariables +): MutationRef; -export function createMovie(vars: CreateMovieVariables): MutationPromise; -export function createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; +export function createMovie( + vars: CreateMovieVariables +): MutationPromise; +export function createMovie( + dc: DataConnect, + vars: CreateMovieVariables +): MutationPromise; /* Allow users to create refs without passing in DataConnect */ export function listMoviesRef(): QueryRef; /* Allow users to pass in custom DataConnect instances */ -export function listMoviesRef(dc: DataConnect): QueryRef; +export function listMoviesRef( + dc: DataConnect +): QueryRef; export function listMovies(): QueryPromise; -export function listMovies(dc: DataConnect): QueryPromise; - +export function listMovies( + dc: DataConnect +): QueryPromise; diff --git a/packages/data-connect/example-integration/test.ts b/packages/data-connect/example-integration/test.ts index 86030405c15..cc177b8e47c 100644 --- a/packages/data-connect/example-integration/test.ts +++ b/packages/data-connect/example-integration/test.ts @@ -1,7 +1,23 @@ +/** + * @license + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { listMovies } from './dataconnect-generated/js/default-connector'; import * as json from './firebase-js-config.json'; import { initializeApp } from 'firebase/app'; initializeApp(json); listMovies(); - From a4d7813ef59e2514c9f0c5802c76ceb5ac94bab0 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 11 Apr 2025 14:42:56 -0700 Subject: [PATCH 03/63] Fix linting --- packages/data-connect/.eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/data-connect/.eslintrc.js b/packages/data-connect/.eslintrc.js index faef63a0395..a6d8d8c7c84 100644 --- a/packages/data-connect/.eslintrc.js +++ b/packages/data-connect/.eslintrc.js @@ -24,7 +24,7 @@ module.exports = { tsconfigRootDir: __dirname }, plugins: ['import'], - ignorePatterns: ['compat/*'], + ignorePatterns: ['compat/*', 'example-integration/*'], rules: { 'no-console': ['error', { allow: ['warn', 'error'] }], '@typescript-eslint/no-unused-vars': [ From 170b15a624b151880c7c5e37b5fb006a55325da0 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 11 Apr 2025 14:47:03 -0700 Subject: [PATCH 04/63] Excluded example integration from tsconfig --- packages/data-connect/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/data-connect/tsconfig.json b/packages/data-connect/tsconfig.json index 58561f50f5d..ba35aaa2516 100644 --- a/packages/data-connect/tsconfig.json +++ b/packages/data-connect/tsconfig.json @@ -4,5 +4,5 @@ "outDir": "dist", "strict": false }, - "exclude": ["dist/**/*", "test/**/*"] + "exclude": ["dist/**/*", "test/**/*", "example-integration/**/*"] } From ec405ae24325adecb340785c34e81f5c65001bd7 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 11 Apr 2025 14:57:06 -0700 Subject: [PATCH 05/63] Fixed example-integration package.json --- packages/data-connect/example-integration/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/data-connect/example-integration/package.json b/packages/data-connect/example-integration/package.json index c530ffe0952..4cfd55079dc 100644 --- a/packages/data-connect/example-integration/package.json +++ b/packages/data-connect/example-integration/package.json @@ -2,7 +2,6 @@ "name": "fdc-test", "version": "1.0.0", "description": "", - "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "tsc" From 248f6547ea990ed52ac8702622e310dc9f98495e Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 23 Apr 2025 10:43:38 -0700 Subject: [PATCH 06/63] Added ssl check for firestore --- packages/firestore/src/lite-api/database.ts | 7 ++++++- packages/firestore/test/unit/api/database.test.ts | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/firestore/src/lite-api/database.ts b/packages/firestore/src/lite-api/database.ts index 9a68e2a86d6..5c344fb72c6 100644 --- a/packages/firestore/src/lite-api/database.ts +++ b/packages/firestore/src/lite-api/database.ts @@ -325,6 +325,11 @@ export function connectFirestoreEmulator( } = {} ): void { firestore = cast(firestore, Firestore); + let ssl = false; + if (/^https:\/\//.test(host)) { + ssl = true; + host = host.substring(8); + } const settings = firestore._getSettings(); const existingConfig = { ...settings, @@ -340,7 +345,7 @@ export function connectFirestoreEmulator( const newConfig = { ...settings, host: newHostSetting, - ssl: false, + ssl, emulatorOptions: options }; // No-op if the new configuration matches the current configuration. This supports SSR diff --git a/packages/firestore/test/unit/api/database.test.ts b/packages/firestore/test/unit/api/database.test.ts index 1cc1df51063..8d05c039e0e 100644 --- a/packages/firestore/test/unit/api/database.test.ts +++ b/packages/firestore/test/unit/api/database.test.ts @@ -564,6 +564,17 @@ describe('Settings', () => { expect(db._getEmulatorOptions()).to.equal(emulatorOptions); }); + it('sets ssl to true if prefixed with https://', () => { + // Use a new instance of Firestore in order to configure settings. + const db = newTestFirestore(); + const emulatorOptions = { mockUserToken: 'test' }; + connectFirestoreEmulator(db, 'https://127.0.0.1', 9000, emulatorOptions); + + expect(db._getSettings().host).to.exist.and.to.equal('127.0.0.1:9000'); + expect(db._getSettings().ssl).to.exist.and.to.be.true; + expect(db._getEmulatorOptions()).to.equal(emulatorOptions); + }); + it('prefers host from useEmulator to host from settings', () => { // Use a new instance of Firestore in order to configure settings. const db = newTestFirestore(); From 14ef1bcc5c43d3cefa07e7f686043f3fbcf550e2 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 23 Apr 2025 11:07:56 -0700 Subject: [PATCH 07/63] Added ssl checks for RTDB --- packages/database-compat/test/database.test.ts | 16 ++++++++++++++++ packages/database/src/api/Database.ts | 15 +++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/database-compat/test/database.test.ts b/packages/database-compat/test/database.test.ts index fa21058591f..95b3b0a9b87 100644 --- a/packages/database-compat/test/database.test.ts +++ b/packages/database-compat/test/database.test.ts @@ -292,6 +292,22 @@ describe('Database Tests', () => { expect((db as any)._delegate._repo.repoInfo_.isUsingEmulator).to.be.false; }); + it('uses ssl when useEmulator is called with https is specified', () => { + const db = firebase.database(); + db.useEmulator('https://localhost', 80); + expect((db as any)._delegate._repo.repoInfo_.isUsingEmulator).to.be.true; + expect((db as any)._delegate._repo.repoInfo_.host).to.equal('localhost:80'); + expect((db as any)._delegate._repo.repoInfo_.secure).to.be.true; + }); + + it('uses ssl when useEmulator is called with wss is specified', () => { + const db = firebase.database(); + db.useEmulator('wss://localhost', 80); + expect((db as any)._delegate._repo.repoInfo_.isUsingEmulator).to.be.true; + expect((db as any)._delegate._repo.repoInfo_.host).to.equal('localhost:80'); + expect((db as any)._delegate._repo.repoInfo_.secure).to.be.true; + }); + it('cannot call useEmulator after use', () => { const db = (firebase as any).database(); diff --git a/packages/database/src/api/Database.ts b/packages/database/src/api/Database.ts index 32fd4674a44..60c6148f77e 100644 --- a/packages/database/src/api/Database.ts +++ b/packages/database/src/api/Database.ts @@ -89,9 +89,19 @@ function repoManagerApplyEmulatorSettings( emulatorOptions: RepoInfoEmulatorOptions, tokenProvider?: AuthTokenProvider ): void { + let ssl = false; + let finalHost = hostAndPort; + if (/^https:\/\//.test(finalHost)) { + ssl = true; + finalHost = finalHost.substring(8); + } + if (/^wss:\/\//.test(finalHost)) { + ssl = true; + finalHost = finalHost.substring(6); + } repo.repoInfo_ = new RepoInfo( - hostAndPort, - /* secure= */ false, + finalHost, + /* secure= */ ssl, repo.repoInfo_.namespace, repo.repoInfo_.webSocketOnly, repo.repoInfo_.nodeAdmin, @@ -352,6 +362,7 @@ export function connectDatabaseEmulator( ): void { db = getModularInstance(db); db._checkNotDeleted('useEmulator'); + const hostAndPort = `${host}:${port}`; const repo = db._repoInternal; if (db._instanceStarted) { From df4a1158c4e5f7bf375c23798b7652c37a3806a2 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 23 Apr 2025 11:11:37 -0700 Subject: [PATCH 08/63] Removed unnecessary files --- .../js/default-connector/README.md | 257 ------ .../js/default-connector/esm/index.esm.js | 55 -- .../js/default-connector/esm/package.json | 1 - .../js/default-connector/index.cjs.js | 56 -- .../js/default-connector/index.d.ts | 86 -- .../js/default-connector/package.json | 25 - .../dataconnect/connector/connector.yaml | 6 - .../dataconnect/connector/mutations.gql | 33 - .../dataconnect/connector/queries.gql | 78 -- .../dataconnect/dataconnect.yaml | 12 - .../dataconnect/schema/schema.gql | 52 -- .../example-integration/dataconnect/test | 0 .../firebase-js-config.json | 3 - .../example-integration/firebase.json | 10 - .../example-integration/package.json | 21 - .../data-connect/example-integration/test.ts | 23 - .../example-integration/testscript.sh | 11 - .../example-integration/tsconfig.json | 10 - .../example-integration/yarn.lock | 802 ------------------ 19 files changed, 1541 deletions(-) delete mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/README.md delete mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js delete mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/package.json delete mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js delete mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts delete mode 100644 packages/data-connect/example-integration/dataconnect-generated/js/default-connector/package.json delete mode 100644 packages/data-connect/example-integration/dataconnect/connector/connector.yaml delete mode 100644 packages/data-connect/example-integration/dataconnect/connector/mutations.gql delete mode 100644 packages/data-connect/example-integration/dataconnect/connector/queries.gql delete mode 100644 packages/data-connect/example-integration/dataconnect/dataconnect.yaml delete mode 100644 packages/data-connect/example-integration/dataconnect/schema/schema.gql delete mode 100644 packages/data-connect/example-integration/dataconnect/test delete mode 100644 packages/data-connect/example-integration/firebase-js-config.json delete mode 100644 packages/data-connect/example-integration/firebase.json delete mode 100644 packages/data-connect/example-integration/package.json delete mode 100644 packages/data-connect/example-integration/test.ts delete mode 100755 packages/data-connect/example-integration/testscript.sh delete mode 100644 packages/data-connect/example-integration/tsconfig.json delete mode 100644 packages/data-connect/example-integration/yarn.lock diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/README.md b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/README.md deleted file mode 100644 index b3f5971d704..00000000000 --- a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/README.md +++ /dev/null @@ -1,257 +0,0 @@ -# Table of Contents -- [**Overview**](#generated-typescript-readme) -- [**Accessing the connector**](#accessing-the-connector) - - [*Connecting to the local Emulator*](#connecting-to-the-local-emulator) -- [**Queries**](#queries) - - [*ListMovies*](#listmovies) -- [**Mutations**](#mutations) - - [*CreateMovie*](#createmovie) - -# Generated TypeScript README -This README will guide you through the process of using the generated TypeScript SDK package for the connector `default`. It will also provide examples on how to use your generated SDK to call your Data Connect queries and mutations. - -***NOTE:** This README is generated alongside the generated SDK. If you make changes to this file, they will be overwritten when the SDK is regenerated.* - -You can use this generated SDK by importing from the package `@firebasegen/default-connector` as shown below. Both CommonJS and ESM imports are supported. - -You can also follow the instructions from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#set-client). - -# Accessing the connector -A connector is a collection of Queries and Mutations. One SDK is generated for each connector - this SDK is generated for the connector `default`. - -You can find more information about connectors in the [Data Connect documentation](https://firebase.google.com/docs/data-connect#how-does). - -```javascript -import { getDataConnect } from 'firebase/data-connect'; -import { connectorConfig } from '@firebasegen/default-connector'; - -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#instrument-clients). - -```javascript -import { connectDataConnectEmulator, getDataConnect } from 'firebase/data-connect'; -import { connectorConfig } from '@firebasegen/default-connector'; - -const dataConnect = getDataConnect(connectorConfig); -connectDataConnectEmulator(dataConnect, 'localhost', 9399); -``` - -After it's initialized, you can call your Data Connect [queries](#queries) and [mutations](#mutations) from your generated SDK. - -# Queries - -There are two ways to execute a Data Connect Query using the generated Web SDK: -- Using a Query Reference function, which returns a `QueryRef` - - The `QueryRef` can be used as an argument to `executeQuery()`, which will execute the Query and return a `QueryPromise` -- Using an action shortcut function, which returns a `QueryPromise` - - Calling the action shortcut function will execute the Query and return a `QueryPromise` - -The following is true for both the action shortcut function and the `QueryRef` function: -- The `QueryPromise` returned will resolve to the result of the Query once it has finished executing -- If the Query accepts arguments, both the action shortcut function and the `QueryRef` function accept a single argument: an object that contains all the required variables (and the optional variables) for the Query -- Both functions can be called with or without passing in a `DataConnect` instance as an argument. If no `DataConnect` argument is passed in, then the generated SDK will call `getDataConnect(connectorConfig)` behind the scenes for you. - -Below are examples of how to use the `default` connector's generated functions to execute each query. You can also follow the examples from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#using-queries). - -## ListMovies -You can execute the `ListMovies` query using the following action shortcut function, or by calling `executeQuery()` after calling the following `QueryRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): -```javascript -listMovies(): QueryPromise; - -listMoviesRef(): QueryRef; -``` -You can also pass in a `DataConnect` instance to the action shortcut function or `QueryRef` function. -```javascript -listMovies(dc: DataConnect): QueryPromise; - -listMoviesRef(dc: DataConnect): QueryRef; -``` - -### Variables -The `ListMovies` query has no variables. -### Return Type -Recall that executing the `ListMovies` query returns a `QueryPromise` that resolves to an object with a `data` property. - -The `data` property is an object of type `ListMoviesData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: -```javascript -export interface ListMoviesData { - movies: ({ - id: UUIDString; - title: string; - imageUrl: string; - genre?: string | null; - } & Movie_Key)[]; -} -``` -### Using `ListMovies`'s action shortcut function - -```javascript -import { getDataConnect } from 'firebase/data-connect'; -import { connectorConfig, listMovies } from '@firebasegen/default-connector'; - - -// Call the `listMovies()` function to execute the query. -// You can use the `await` keyword to wait for the promise to resolve. -const { data } = await listMovies(); - -// You can also pass in a `DataConnect` instance to the action shortcut function. -const dataConnect = getDataConnect(connectorConfig); -const { data } = await listMovies(dataConnect); - -console.log(data.movies); - -// Or, you can use the `Promise` API. -listMovies().then((response) => { - const data = response.data; - console.log(data.movies); -}); -``` - -### Using `ListMovies`'s `QueryRef` function - -```javascript -import { getDataConnect, executeQuery } from 'firebase/data-connect'; -import { connectorConfig, listMoviesRef } from '@firebasegen/default-connector'; - - -// Call the `listMoviesRef()` function to get a reference to the query. -const ref = listMoviesRef(); - -// You can also pass in a `DataConnect` instance to the `QueryRef` function. -const dataConnect = getDataConnect(connectorConfig); -const ref = listMoviesRef(dataConnect); - -// Call `executeQuery()` on the reference to execute the query. -// You can use the `await` keyword to wait for the promise to resolve. -const { data } = await executeQuery(ref); - -console.log(data.movies); - -// Or, you can use the `Promise` API. -executeQuery(ref).then((response) => { - const data = response.data; - console.log(data.movies); -}); -``` - -# Mutations - -There are two ways to execute a Data Connect Mutation using the generated Web SDK: -- Using a Mutation Reference function, which returns a `MutationRef` - - The `MutationRef` can be used as an argument to `executeMutation()`, which will execute the Mutation and return a `MutationPromise` -- Using an action shortcut function, which returns a `MutationPromise` - - Calling the action shortcut function will execute the Mutation and return a `MutationPromise` - -The following is true for both the action shortcut function and the `MutationRef` function: -- The `MutationPromise` returned will resolve to the result of the Mutation once it has finished executing -- If the Mutation accepts arguments, both the action shortcut function and the `MutationRef` function accept a single argument: an object that contains all the required variables (and the optional variables) for the Mutation -- Both functions can be called with or without passing in a `DataConnect` instance as an argument. If no `DataConnect` argument is passed in, then the generated SDK will call `getDataConnect(connectorConfig)` behind the scenes for you. - -Below are examples of how to use the `default` connector's generated functions to execute each mutation. You can also follow the examples from the [Data Connect documentation](https://firebase.google.com/docs/data-connect/web-sdk#using-mutations). - -## CreateMovie -You can execute the `CreateMovie` mutation using the following action shortcut function, or by calling `executeMutation()` after calling the following `MutationRef` function, both of which are defined in [default-connector/index.d.ts](./index.d.ts): -```javascript -createMovie(vars: CreateMovieVariables): MutationPromise; - -createMovieRef(vars: CreateMovieVariables): MutationRef; -``` -You can also pass in a `DataConnect` instance to the action shortcut function or `MutationRef` function. -```javascript -createMovie(dc: DataConnect, vars: CreateMovieVariables): MutationPromise; - -createMovieRef(dc: DataConnect, vars: CreateMovieVariables): MutationRef; -``` - -### Variables -The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: - -```javascript -export interface CreateMovieVariables { - title: string; - genre: string; - imageUrl: string; -} -``` -### Return Type -Recall that executing the `CreateMovie` mutation returns a `MutationPromise` that resolves to an object with a `data` property. - -The `data` property is an object of type `CreateMovieData`, which is defined in [default-connector/index.d.ts](./index.d.ts). It has the following fields: -```javascript -export interface CreateMovieData { - movie_insert: Movie_Key; -} -``` -### Using `CreateMovie`'s action shortcut function - -```javascript -import { getDataConnect } from 'firebase/data-connect'; -import { connectorConfig, createMovie, CreateMovieVariables } from '@firebasegen/default-connector'; - -// The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: -const createMovieVars: CreateMovieVariables = { - title: ..., - genre: ..., - imageUrl: ..., -}; - -// Call the `createMovie()` function to execute the mutation. -// You can use the `await` keyword to wait for the promise to resolve. -const { data } = await createMovie(createMovieVars); -// Variables can be defined inline as well. -const { data } = await createMovie({ title: ..., genre: ..., imageUrl: ..., }); - -// You can also pass in a `DataConnect` instance to the action shortcut function. -const dataConnect = getDataConnect(connectorConfig); -const { data } = await createMovie(dataConnect, createMovieVars); - -console.log(data.movie_insert); - -// Or, you can use the `Promise` API. -createMovie(createMovieVars).then((response) => { - const data = response.data; - console.log(data.movie_insert); -}); -``` - -### Using `CreateMovie`'s `MutationRef` function - -```javascript -import { getDataConnect, executeMutation } from 'firebase/data-connect'; -import { connectorConfig, createMovieRef, CreateMovieVariables } from '@firebasegen/default-connector'; - -// The `CreateMovie` mutation requires an argument of type `CreateMovieVariables`: -const createMovieVars: CreateMovieVariables = { - title: ..., - genre: ..., - imageUrl: ..., -}; - -// Call the `createMovieRef()` function to get a reference to the mutation. -const ref = createMovieRef(createMovieVars); -// Variables can be defined inline as well. -const ref = createMovieRef({ title: ..., genre: ..., imageUrl: ..., }); - -// You can also pass in a `DataConnect` instance to the `MutationRef` function. -const dataConnect = getDataConnect(connectorConfig); -const ref = createMovieRef(dataConnect, createMovieVars); - -// Call `executeMutation()` on the reference to execute the mutation. -// You can use the `await` keyword to wait for the promise to resolve. -const { data } = await executeMutation(ref); - -console.log(data.movie_insert); - -// Or, you can use the `Promise` API. -executeMutation(ref).then((response) => { - const data = response.data; - console.log(data.movie_insert); -}); -``` - diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js deleted file mode 100644 index e88d2d56d35..00000000000 --- a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/index.esm.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @license - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - queryRef, - executeQuery, - mutationRef, - executeMutation, - validateArgs -} from 'firebase/data-connect'; - -export const connectorConfig = { - connector: 'default', - service: 'fdc-test', - location: 'us-central1' -}; - -export function createMovieRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars } = validateArgs( - connectorConfig, - dcOrVars, - vars, - true - ); - dcInstance._useGeneratedSdk(); - return mutationRef(dcInstance, 'CreateMovie', inputVars); -} - -export function createMovie(dcOrVars, vars) { - return executeMutation(createMovieRef(dcOrVars, vars)); -} - -export function listMoviesRef(dc) { - const { dc: dcInstance } = validateArgs(connectorConfig, dc, undefined); - dcInstance._useGeneratedSdk(); - return queryRef(dcInstance, 'ListMovies'); -} - -export function listMovies(dc) { - return executeQuery(listMoviesRef(dc)); -} diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/package.json b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/package.json deleted file mode 100644 index 7c34deb5837..00000000000 --- a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/esm/package.json +++ /dev/null @@ -1 +0,0 @@ -{"type":"module"} \ No newline at end of file diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js deleted file mode 100644 index 814406ff090..00000000000 --- a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.cjs.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @license - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const { - queryRef, - executeQuery, - mutationRef, - executeMutation, - validateArgs -} = require('firebase/data-connect'); - -const connectorConfig = { - connector: 'default', - service: 'fdc-test', - location: 'us-central1' -}; -exports.connectorConfig = connectorConfig; - -exports.createMovieRef = function createMovieRef(dcOrVars, vars) { - const { dc: dcInstance, vars: inputVars } = validateArgs( - connectorConfig, - dcOrVars, - vars, - true - ); - dcInstance._useGeneratedSdk(); - return mutationRef(dcInstance, 'CreateMovie', inputVars); -}; - -exports.createMovie = function createMovie(dcOrVars, vars) { - return executeMutation(createMovieRef(dcOrVars, vars)); -}; - -exports.listMoviesRef = function listMoviesRef(dc) { - const { dc: dcInstance } = validateArgs(connectorConfig, dc, undefined); - dcInstance._useGeneratedSdk(); - return queryRef(dcInstance, 'ListMovies'); -}; - -exports.listMovies = function listMovies(dc) { - return executeQuery(listMoviesRef(dc)); -}; diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts deleted file mode 100644 index 474fefd0f4b..00000000000 --- a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/index.d.ts +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @license - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - ConnectorConfig, - DataConnect, - QueryRef, - QueryPromise, - MutationRef, - MutationPromise -} from 'firebase/data-connect'; - -export const connectorConfig: ConnectorConfig; - -export type TimestampString = string; -export type UUIDString = string; -export type Int64String = string; -export type DateString = string; - -export interface CreateMovieData { - movie_insert: Movie_Key; -} - -export interface CreateMovieVariables { - title: string; - genre: string; - imageUrl: string; -} - -export interface ListMoviesData { - movies: ({ - id: UUIDString; - title: string; - imageUrl: string; - genre?: string | null; - } & Movie_Key)[]; -} - -export interface Movie_Key { - id: UUIDString; - __typename?: 'Movie_Key'; -} - -/* Allow users to create refs without passing in DataConnect */ -export function createMovieRef( - vars: CreateMovieVariables -): MutationRef; -/* Allow users to pass in custom DataConnect instances */ -export function createMovieRef( - dc: DataConnect, - vars: CreateMovieVariables -): MutationRef; - -export function createMovie( - vars: CreateMovieVariables -): MutationPromise; -export function createMovie( - dc: DataConnect, - vars: CreateMovieVariables -): MutationPromise; - -/* Allow users to create refs without passing in DataConnect */ -export function listMoviesRef(): QueryRef; -/* Allow users to pass in custom DataConnect instances */ -export function listMoviesRef( - dc: DataConnect -): QueryRef; - -export function listMovies(): QueryPromise; -export function listMovies( - dc: DataConnect -): QueryPromise; diff --git a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/package.json b/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/package.json deleted file mode 100644 index d0c9852ce3e..00000000000 --- a/packages/data-connect/example-integration/dataconnect-generated/js/default-connector/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@firebasegen/default-connector", - "version": "1.0.0", - "author": "Firebase (https://firebase.google.com/)", - "description": "Generated SDK For default", - "license": "Apache-2.0", - "engines": { - "node": " >=18.0" - }, - "typings": "index.d.ts", - "module": "esm/index.esm.js", - "main": "index.cjs.js", - "browser": "esm/index.esm.js", - "exports": { - ".": { - "types": "./index.d.ts", - "require": "./index.cjs.js", - "default": "./esm/index.esm.js" - }, - "./package.json": "./package.json" - }, - "peerDependencies": { - "firebase": "^10.14.0 || ^11.3.0" - } -} \ No newline at end of file diff --git a/packages/data-connect/example-integration/dataconnect/connector/connector.yaml b/packages/data-connect/example-integration/dataconnect/connector/connector.yaml deleted file mode 100644 index b698515fe9f..00000000000 --- a/packages/data-connect/example-integration/dataconnect/connector/connector.yaml +++ /dev/null @@ -1,6 +0,0 @@ -connectorId: default -generate: - javascriptSdk: - outputDir: ../../dataconnect-generated/js/default-connector - package: "@firebasegen/default-connector" -# packageJsonDir: ../.. diff --git a/packages/data-connect/example-integration/dataconnect/connector/mutations.gql b/packages/data-connect/example-integration/dataconnect/connector/mutations.gql deleted file mode 100644 index 2379afeb89c..00000000000 --- a/packages/data-connect/example-integration/dataconnect/connector/mutations.gql +++ /dev/null @@ -1,33 +0,0 @@ -# # Example mutations for a simple movie app - -# # Create a movie based on user input -mutation CreateMovie($title: String!, $genre: String!, $imageUrl: String!) -@auth(level: USER_EMAIL_VERIFIED) { - 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 }) -# } diff --git a/packages/data-connect/example-integration/dataconnect/connector/queries.gql b/packages/data-connect/example-integration/dataconnect/connector/queries.gql deleted file mode 100644 index cb1a6f630bc..00000000000 --- a/packages/data-connect/example-integration/dataconnect/connector/queries.gql +++ /dev/null @@ -1,78 +0,0 @@ -# # Example queries for a simple movie app. - -# # @auth() directives control who can call each operation. -# # Anyone should be able to list all movies, so the auth level is set to PUBLIC -query ListMovies @auth(level: PUBLIC) { - movies { - id - title - imageUrl - genre - } -} - -# # 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 -# # _on_ makes it easy to grab info from another table -# # Here, we use it to grab all the reviews written by the user. -# reviews: reviews_on_user { -# rating -# reviewDate -# reviewText -# movie { -# id -# title -# } -# } -# } -# } - -# # Get movie by id -# query GetMovieById($id: UUID!) @auth(level: PUBLIC) { -# 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) { -# movies( -# where: { -# _and: [{ genre: { eq: $genre } }, { title: { contains: $titleInput } }] -# } -# ) { -# id -# title -# genre -# imageUrl -# } -# } diff --git a/packages/data-connect/example-integration/dataconnect/dataconnect.yaml b/packages/data-connect/example-integration/dataconnect/dataconnect.yaml deleted file mode 100644 index 623fad3e209..00000000000 --- a/packages/data-connect/example-integration/dataconnect/dataconnect.yaml +++ /dev/null @@ -1,12 +0,0 @@ -specVersion: "v1beta" -serviceId: "fdc-test" -location: "us-central1" -schema: - source: "./schema" - datasource: - postgresql: - database: "fdcdb" - cloudSql: - instanceId: "fdc-test-fdc" - # schemaValidation: "COMPATIBLE" -connectorDirs: ["./connector"] diff --git a/packages/data-connect/example-integration/dataconnect/schema/schema.gql b/packages/data-connect/example-integration/dataconnect/schema/schema.gql deleted file mode 100644 index f114d9a678a..00000000000 --- a/packages/data-connect/example-integration/dataconnect/schema/schema.gql +++ /dev/null @@ -1,52 +0,0 @@ -# # 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") -# } diff --git a/packages/data-connect/example-integration/dataconnect/test b/packages/data-connect/example-integration/dataconnect/test deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/data-connect/example-integration/firebase-js-config.json b/packages/data-connect/example-integration/firebase-js-config.json deleted file mode 100644 index 0e0dcd235c4..00000000000 --- a/packages/data-connect/example-integration/firebase-js-config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} \ No newline at end of file diff --git a/packages/data-connect/example-integration/firebase.json b/packages/data-connect/example-integration/firebase.json deleted file mode 100644 index 6c9ad90b440..00000000000 --- a/packages/data-connect/example-integration/firebase.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "emulators": { - "dataconnect": { - "dataDir": "dataconnect/.dataconnect/pgliteData" - } - }, - "dataconnect": { - "source": "dataconnect" - } -} diff --git a/packages/data-connect/example-integration/package.json b/packages/data-connect/example-integration/package.json deleted file mode 100644 index 4cfd55079dc..00000000000 --- a/packages/data-connect/example-integration/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "fdc-test", - "version": "1.0.0", - "description": "", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "build": "tsc" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "@types/node": "^22.13.14", - "ts-node": "^10.9.2", - "tslib": "^2.8.1", - "typescript": "^5.8.2" - }, - "dependencies": { - "firebase": "11.5.0" - } -} diff --git a/packages/data-connect/example-integration/test.ts b/packages/data-connect/example-integration/test.ts deleted file mode 100644 index cc177b8e47c..00000000000 --- a/packages/data-connect/example-integration/test.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @license - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { listMovies } from './dataconnect-generated/js/default-connector'; -import * as json from './firebase-js-config.json'; -import { initializeApp } from 'firebase/app'; - -initializeApp(json); -listMovies(); diff --git a/packages/data-connect/example-integration/testscript.sh b/packages/data-connect/example-integration/testscript.sh deleted file mode 100755 index 6a56cb4d536..00000000000 --- a/packages/data-connect/example-integration/testscript.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -statusResult=$(git status --porcelain | wc -l) -if [[ statusResult -eq "0" ]] -then - echo 'no changes found' -else - echo 'The workspace is modified:' - echo "$statusResult" -fi - diff --git a/packages/data-connect/example-integration/tsconfig.json b/packages/data-connect/example-integration/tsconfig.json deleted file mode 100644 index e3c427a3163..00000000000 --- a/packages/data-connect/example-integration/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "target": "ES5", - "module": "CommonJS", - "resolveJsonModule": true, - "sourceMap": true, - "noEmit": true, - "skipLibCheck": false - } - } diff --git a/packages/data-connect/example-integration/yarn.lock b/packages/data-connect/example-integration/yarn.lock deleted file mode 100644 index cb23e2383e1..00000000000 --- a/packages/data-connect/example-integration/yarn.lock +++ /dev/null @@ -1,802 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@firebase/analytics-compat@0.2.18": - version "0.2.18" - resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.2.18.tgz#5ea9bdea188d4c91938f539af4c4414813ddc5c9" - integrity sha512-Hw9mzsSMZaQu6wrTbi3kYYwGw9nBqOHr47pVLxfr5v8CalsdrG5gfs9XUlPOZjHRVISp3oQrh1j7d3E+ulHPjQ== - dependencies: - "@firebase/analytics" "0.10.12" - "@firebase/analytics-types" "0.8.3" - "@firebase/component" "0.6.13" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/analytics-types@0.8.3": - version "0.8.3" - resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.8.3.tgz#d08cd39a6209693ca2039ba7a81570dfa6c1518f" - integrity sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg== - -"@firebase/analytics@0.10.12": - version "0.10.12" - resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.10.12.tgz#b49b9351b8cb19da007320a52932b953fff90d71" - integrity sha512-iDCGnw6qdFqwI5ywkgece99WADJNoymu+nLIQI4fZM/vCZ3bEo4wlpEetW71s1HqGpI0hQStiPhqVjFxDb2yyw== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/installations" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/app-check-compat@0.3.20": - version "0.3.20" - resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.3.20.tgz#0dfce42699402f3b621be98857a8109b9397a37b" - integrity sha512-/twgmlnNAaZ/wbz3kcQrL/26b+X+zUX+lBmu5LwwEcWcpnb+mrVEAKhD7/ttm52dxYiSWtLDeuXy3FXBhqBC5A== - dependencies: - "@firebase/app-check" "0.8.13" - "@firebase/app-check-types" "0.5.3" - "@firebase/component" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/app-check-interop-types@0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz#ed9c4a4f48d1395ef378f007476db3940aa5351a" - integrity sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A== - -"@firebase/app-check-types@0.5.3": - version "0.5.3" - resolved "https://registry.yarnpkg.com/@firebase/app-check-types/-/app-check-types-0.5.3.tgz#38ba954acf4bffe451581a32fffa20337f11d8e5" - integrity sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng== - -"@firebase/app-check@0.8.13": - version "0.8.13" - resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.8.13.tgz#20b212d0ea5b79c9492f434abc276d4f28b19371" - integrity sha512-ONsgml8/dplUOAP42JQO6hhiWDEwR9+RUTLenxAN9S8N6gel/sDQ9Ci721Py1oASMGdDU8v9R7xAZxzvOX5lPg== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/app-compat@0.2.52": - version "0.2.52" - resolved "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.52.tgz#71ac4334c2dc841be3f101ab1f7d00412568a885" - integrity sha512-0p/l1KiwhwwYTcPWoleFQHftOnYzeXvyVf3WNZyKFBAoQMpCVW6bVm/uO1bXF91AwU1JN0og888Y6Sc8avqZ+A== - dependencies: - "@firebase/app" "0.11.3" - "@firebase/component" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/app-types@0.9.3": - version "0.9.3" - resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.9.3.tgz#8408219eae9b1fb74f86c24e7150a148460414ad" - integrity sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw== - -"@firebase/app@0.11.3": - version "0.11.3" - resolved "https://registry.npmjs.org/@firebase/app/-/app-0.11.3.tgz#80abcb65a1dce743d081022d2934fe69e60c1d41" - integrity sha512-QlTZl/RcqPSonYxB87n8KgAUW2L6ZZz0W4D91PVmQ1tJPsKsKPrWAFHL0ii2cQW6FxTxfNjbZ7kucuIcKXk3tw== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - idb "7.1.1" - tslib "^2.1.0" - -"@firebase/auth-compat@0.5.19": - version "0.5.19" - resolved "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.19.tgz#6f393e85496754bfc4f31758bc0718a88f9c2f30" - integrity sha512-v898POphOIBJliKF76SiGOXh4EdhO5fM6S9a2ZKf/8wHdBea/qwxwZoVVya4DW6Mi7vWyp1lIzHbFgwRz8G9TA== - dependencies: - "@firebase/auth" "1.9.1" - "@firebase/auth-types" "0.13.0" - "@firebase/component" "0.6.13" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/auth-interop-types@0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz#176a08686b0685596ff03d7879b7e4115af53de0" - integrity sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA== - -"@firebase/auth-types@0.13.0": - version "0.13.0" - resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.13.0.tgz#ae6e0015e3bd4bfe18edd0942b48a0a118a098d9" - integrity sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg== - -"@firebase/auth@1.9.1": - version "1.9.1" - resolved "https://registry.npmjs.org/@firebase/auth/-/auth-1.9.1.tgz#5fca654e003a7fa0b3bbb247782633c3aab67ce4" - integrity sha512-9KKo5SNVkyJzftsW+daS+PGDbeJ+MFJWXQFHDqqPPH3acWHtiNnGHH5HGpIJErEELrsm9xMPie5zfZ0XpGU8+w== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/component@0.6.13": - version "0.6.13" - resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.6.13.tgz#6513379f1c09264133969d87282ce0d5bbbb2cd9" - integrity sha512-I/Eg1NpAtZ8AAfq8mpdfXnuUpcLxIDdCDtTzWSh+FXnp/9eCKJ3SNbOCKrUCyhLzNa2SiPJYruei0sxVjaOTeg== - dependencies: - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/data-connect@0.3.2": - version "0.3.2" - resolved "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.3.2.tgz#8a74af2e111fe1a36d7bf37c55a7c2469e8a051f" - integrity sha512-PYG55JRTmvYrUuXXmYBsZexwKVP9aR3mIRRHxB9V2bQeRDZky6JtRZnH3GLhf4ZsxZy5Ewd8ul/jTOYR4gpD9w== - dependencies: - "@firebase/auth-interop-types" "0.2.4" - "@firebase/component" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/database-compat@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-2.0.5.tgz#110f612901995f9800f2435f58686e0c6f3d2544" - integrity sha512-CNf1UbvWh6qIaSf4sn6sx2DTDz/em/D7QxULH1LTxxDQHr9+CeYGvlAqrKnk4ZH0P0eIHyQFQU7RwkUJI0B9gQ== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/database" "1.0.14" - "@firebase/database-types" "1.0.10" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/database-types@1.0.10": - version "1.0.10" - resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-1.0.10.tgz#14cfed45bb06394cf1641e19265cbf90e4f6fb51" - integrity sha512-mH6RC1E9/Pv8jf1/p+M8YFTX+iu+iHDN89hecvyO7wHrI4R1V0TXjxOHvX3nLJN1sfh0CWG6CHZ0VlrSmK/cwg== - dependencies: - "@firebase/app-types" "0.9.3" - "@firebase/util" "1.11.0" - -"@firebase/database@1.0.14": - version "1.0.14" - resolved "https://registry.yarnpkg.com/@firebase/database/-/database-1.0.14.tgz#1d579b345c0f926eaddb7703051999489300c3bd" - integrity sha512-9nxYtkHAG02/Nh2Ssms1T4BbWPPjiwohCvkHDUl4hNxnki1kPgsLo5xe9kXNzbacOStmVys+RUXvwzynQSKmUQ== - dependencies: - "@firebase/app-check-interop-types" "0.3.3" - "@firebase/auth-interop-types" "0.2.4" - "@firebase/component" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - faye-websocket "0.11.4" - tslib "^2.1.0" - -"@firebase/firestore-compat@0.3.45": - version "0.3.45" - resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.3.45.tgz#93061f7d3644cd511749c9268d146e8c8c49a5de" - integrity sha512-uRvi7AYPmsDl7UZwPyV7jgDGYusEZ2+U2g7MndbQHKIA8fNHpYC6QrzMs58+/IjX+kF/lkUn67Vrr0AkVjlY+Q== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/firestore" "4.7.10" - "@firebase/firestore-types" "3.0.3" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/firestore-types@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-3.0.3.tgz#7d0c3dd8850c0193d8f5ee0cc8f11961407742c1" - integrity sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q== - -"@firebase/firestore@4.7.10": - version "4.7.10" - resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-4.7.10.tgz#6fe0cd31fcd7f4a8e13f9585f53e9300cf3114c0" - integrity sha512-6nKsyo2U+jYSCcSE5sjMdDNA23DMUvYPUvsYGg09CNvcTO8GGKsPs7SpOhspsB91mbacq+u627CDAx3FUhPSSQ== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - "@firebase/webchannel-wrapper" "1.0.3" - "@grpc/grpc-js" "~1.9.0" - "@grpc/proto-loader" "^0.7.8" - tslib "^2.1.0" - -"@firebase/functions-compat@0.3.20": - version "0.3.20" - resolved "https://registry.yarnpkg.com/@firebase/functions-compat/-/functions-compat-0.3.20.tgz#addf89242be8b4d63feacb15ef27785e16c5e220" - integrity sha512-iIudmYDAML6n3c7uXO2YTlzra2/J6lnMzmJTXNthvrKVMgNMaseNoQP1wKfchK84hMuSF8EkM4AvufwbJ+Juew== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/functions" "0.12.3" - "@firebase/functions-types" "0.6.3" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/functions-types@0.6.3": - version "0.6.3" - resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.6.3.tgz#f5faf770248b13f45d256f614230da6a11bfb654" - integrity sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg== - -"@firebase/functions@0.12.3": - version "0.12.3" - resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.12.3.tgz#b3e395aed1641d0d7169a22698c684a2745e02dd" - integrity sha512-Wv7JZMUkKLb1goOWRtsu3t7m97uK6XQvjQLPvn8rncY91+VgdU72crqnaYCDI/ophNuBEmuK8mn0/pAnjUeA6A== - dependencies: - "@firebase/app-check-interop-types" "0.3.3" - "@firebase/auth-interop-types" "0.2.4" - "@firebase/component" "0.6.13" - "@firebase/messaging-interop-types" "0.2.3" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/installations-compat@0.2.13": - version "0.2.13" - resolved "https://registry.yarnpkg.com/@firebase/installations-compat/-/installations-compat-0.2.13.tgz#0db0867ed58b782f7e2d142d9289a9eef1da24d5" - integrity sha512-f/o6MqCI7LD/ulY9gvgkv6w5k6diaReD8BFHd/y/fEdpsXmFWYS/g28GXCB72bRVBOgPpkOUNl+VsMvDwlRKmw== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/installations" "0.6.13" - "@firebase/installations-types" "0.5.3" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/installations-types@0.5.3": - version "0.5.3" - resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.5.3.tgz#cac8a14dd49f09174da9df8ae453f9b359c3ef2f" - integrity sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA== - -"@firebase/installations@0.6.13": - version "0.6.13" - resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.6.13.tgz#a2a00aebb5dfb74fae08600ea98cd2681211dd3c" - integrity sha512-6ZpkUiaygPFwgVneYxuuOuHnSPnTA4KefLEaw/sKk/rNYgC7X6twaGfYb0sYLpbi9xV4i5jXsqZ3WO+yaguNgg== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/util" "1.11.0" - idb "7.1.1" - tslib "^2.1.0" - -"@firebase/logger@0.4.4": - version "0.4.4" - resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.4.4.tgz#29e8379d20fd1149349a195ee6deee4573a86f48" - integrity sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g== - dependencies: - tslib "^2.1.0" - -"@firebase/messaging-compat@0.2.17": - version "0.2.17" - resolved "https://registry.yarnpkg.com/@firebase/messaging-compat/-/messaging-compat-0.2.17.tgz#fc223495319fe3784347dea77094b6e03548647d" - integrity sha512-5Q+9IG7FuedusdWHVQRjpA3OVD9KUWp/IPegcv0s5qSqRLBjib7FlAeWxN+VL0Ew43tuPJBY2HKhEecuizmO1Q== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/messaging" "0.12.17" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/messaging-interop-types@0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz#e647c9cd1beecfe6a6e82018a6eec37555e4da3e" - integrity sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q== - -"@firebase/messaging@0.12.17": - version "0.12.17" - resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.12.17.tgz#41eaeee70a89136715a4f7cb2b1a602423fc44ec" - integrity sha512-W3CnGhTm6Nx8XGb6E5/+jZTuxX/EK8Vur4QXvO1DwZta/t0xqWMRgO9vNsZFMYBqFV4o3j4F9qK/iddGYwWS6g== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/installations" "0.6.13" - "@firebase/messaging-interop-types" "0.2.3" - "@firebase/util" "1.11.0" - idb "7.1.1" - tslib "^2.1.0" - -"@firebase/performance-compat@0.2.15": - version "0.2.15" - resolved "https://registry.yarnpkg.com/@firebase/performance-compat/-/performance-compat-0.2.15.tgz#4e5034add63917cb6357938126e9e6562d0e7208" - integrity sha512-wUxsw7hGBEMN6XfvYQqwPIQp5LcJXawWM5tmYp6L7ClCoTQuEiCKHWWVurJgN8Q1YHzoHVgjNfPQAOVu29iMVg== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/performance" "0.7.2" - "@firebase/performance-types" "0.2.3" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/performance-types@0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.2.3.tgz#5ce64e90fa20ab5561f8b62a305010cf9fab86fb" - integrity sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ== - -"@firebase/performance@0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.7.2.tgz#e30ee3e3c120c53f48bde7bdd915687f1e3b27e1" - integrity sha512-DXLLp0R0jdxH/yTmv+WTkOzsLl8YYecXh4lGZE0dzqC0IV8k+AxpLSSWvOTCkAETze8yEU/iF+PtgYVlGjfMMQ== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/installations" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - web-vitals "^4.2.4" - -"@firebase/remote-config-compat@0.2.13": - version "0.2.13" - resolved "https://registry.yarnpkg.com/@firebase/remote-config-compat/-/remote-config-compat-0.2.13.tgz#4a35c2c6bb582d96aecc45da18f5094359cb5361" - integrity sha512-UmHoO7TxAEJPIZf8e1Hy6CeFGMeyjqSCpgoBkQZYXFI2JHhzxIyDpr8jVKJJN1dmAePKZ5EX7dC13CmcdTOl7Q== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/remote-config" "0.6.0" - "@firebase/remote-config-types" "0.4.0" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/remote-config-types@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz#91b9a836d5ca30ced68c1516163b281fbb544537" - integrity sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg== - -"@firebase/remote-config@0.6.0": - version "0.6.0" - resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.6.0.tgz#24a6966a4d092260983ba8597cc039f5795cd35f" - integrity sha512-Yrk4l5+6FJLPHC6irNHMzgTtJ3NfHXlAXVChCBdNFtgmzyGmufNs/sr8oA0auEfIJ5VpXCaThRh3P4OdQxiAlQ== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/installations" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/storage-compat@0.3.17": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@firebase/storage-compat/-/storage-compat-0.3.17.tgz#67f6bbc498971e6e404e0ea660fa5df81c5ba5ea" - integrity sha512-CBlODWEZ5b6MJWVh21VZioxwxNwVfPA9CAdsk+ZgVocJQQbE2oDW1XJoRcgthRY1HOitgbn4cVrM+NlQtuUYhw== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/storage" "0.13.7" - "@firebase/storage-types" "0.8.3" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/storage-types@0.8.3": - version "0.8.3" - resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.8.3.tgz#2531ef593a3452fc12c59117195d6485c6632d3d" - integrity sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg== - -"@firebase/storage@0.13.7": - version "0.13.7" - resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.13.7.tgz#809fc23685ad9ba8fdfb3bc758e3353867c9e796" - integrity sha512-FkRyc24rK+Y6EaQ1tYFm3TevBnnfSNA0VyTfew2hrYyL/aYfatBg7HOgktUdB4kWMHNA9VoTotzZTGoLuK92wg== - dependencies: - "@firebase/component" "0.6.13" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/util@1.11.0": - version "1.11.0" - resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.11.0.tgz#e74ee2dc260ec4f9e75fe5d52bc4b0254d9872a9" - integrity sha512-PzSrhIr++KI6y4P6C/IdgBNMkEx0Ex6554/cYd0Hm+ovyFSJtJXqb/3OSIdnBoa2cpwZT1/GW56EmRc5qEc5fQ== - dependencies: - tslib "^2.1.0" - -"@firebase/vertexai@1.2.0": - version "1.2.0" - resolved "https://registry.npmjs.org/@firebase/vertexai/-/vertexai-1.2.0.tgz#8f8a4ae75284c3067c0a06c7d0bef922571e6dd7" - integrity sha512-WUYIzFpOipjFXT2i0hT26wivJoIximizQptVs3KAxFAqbVlO8sjKPsMkgz0bh+tdKlqP4SUDda71fMUZXUKHgA== - dependencies: - "@firebase/app-check-interop-types" "0.3.3" - "@firebase/component" "0.6.13" - "@firebase/logger" "0.4.4" - "@firebase/util" "1.11.0" - tslib "^2.1.0" - -"@firebase/webchannel-wrapper@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz#a73bab8eb491d7b8b7be2f0e6c310647835afe83" - integrity sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ== - -"@grpc/grpc-js@~1.9.0": - version "1.9.15" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.15.tgz#433d7ac19b1754af690ea650ab72190bd700739b" - integrity sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ== - dependencies: - "@grpc/proto-loader" "^0.7.8" - "@types/node" ">=12.12.47" - -"@grpc/proto-loader@^0.7.8": - version "0.7.13" - resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.13.tgz#f6a44b2b7c9f7b609f5748c6eac2d420e37670cf" - integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw== - dependencies: - lodash.camelcase "^4.3.0" - long "^5.0.0" - protobufjs "^7.2.5" - yargs "^17.7.2" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" - integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" - integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== - -"@protobufjs/base64@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" - integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== - -"@protobufjs/codegen@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" - integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== - -"@protobufjs/eventemitter@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" - integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== - -"@protobufjs/fetch@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" - integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== - dependencies: - "@protobufjs/aspromise" "^1.1.1" - "@protobufjs/inquire" "^1.1.0" - -"@protobufjs/float@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" - integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== - -"@protobufjs/inquire@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" - integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== - -"@protobufjs/path@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" - integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== - -"@protobufjs/pool@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" - integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== - -"@protobufjs/utf8@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" - integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== - -"@tsconfig/node10@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" - integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" - integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== - -"@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@^22.13.14": - version "22.14.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.14.0.tgz#d3bfa3936fef0dbacd79ea3eb17d521c628bb47e" - integrity sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA== - dependencies: - undici-types "~6.21.0" - -acorn-walk@^8.1.1: - version "8.3.4" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" - integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== - dependencies: - acorn "^8.11.0" - -acorn@^8.11.0, acorn@^8.4.1: - version "8.14.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" - integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -escalade@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" - integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== - -faye-websocket@0.11.4: - version "0.11.4" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" - integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== - dependencies: - websocket-driver ">=0.5.1" - -firebase@11.5.0: - version "11.5.0" - resolved "https://registry.npmjs.org/firebase/-/firebase-11.5.0.tgz#9a358ed8c7e805de8df64061840b2593ae706165" - integrity sha512-ZTpO/zD5nYqY02bGpXCg1dRNLggTXPQZdLQeSeur3jYH270p1QkAZZJsm/lrKZ2W4ZjBlafTxxs4OwN38Vyocw== - dependencies: - "@firebase/analytics" "0.10.12" - "@firebase/analytics-compat" "0.2.18" - "@firebase/app" "0.11.3" - "@firebase/app-check" "0.8.13" - "@firebase/app-check-compat" "0.3.20" - "@firebase/app-compat" "0.2.52" - "@firebase/app-types" "0.9.3" - "@firebase/auth" "1.9.1" - "@firebase/auth-compat" "0.5.19" - "@firebase/data-connect" "0.3.2" - "@firebase/database" "1.0.14" - "@firebase/database-compat" "2.0.5" - "@firebase/firestore" "4.7.10" - "@firebase/firestore-compat" "0.3.45" - "@firebase/functions" "0.12.3" - "@firebase/functions-compat" "0.3.20" - "@firebase/installations" "0.6.13" - "@firebase/installations-compat" "0.2.13" - "@firebase/messaging" "0.12.17" - "@firebase/messaging-compat" "0.2.17" - "@firebase/performance" "0.7.2" - "@firebase/performance-compat" "0.2.15" - "@firebase/remote-config" "0.6.0" - "@firebase/remote-config-compat" "0.2.13" - "@firebase/storage" "0.13.7" - "@firebase/storage-compat" "0.3.17" - "@firebase/util" "1.11.0" - "@firebase/vertexai" "1.2.0" - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -http-parser-js@>=0.5.1: - version "0.5.9" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.9.tgz#b817b3ca0edea6236225000d795378707c169cec" - integrity sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw== - -idb@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" - integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== - -long@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/long/-/long-5.3.1.tgz#9d4222d3213f38a5ec809674834e0f0ab21abe96" - integrity sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng== - -make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -protobufjs@^7.2.5: - version "7.4.0" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.4.0.tgz#7efe324ce9b3b61c82aae5de810d287bc08a248a" - integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw== - dependencies: - "@protobufjs/aspromise" "^1.1.2" - "@protobufjs/base64" "^1.1.2" - "@protobufjs/codegen" "^2.0.4" - "@protobufjs/eventemitter" "^1.1.0" - "@protobufjs/fetch" "^1.1.0" - "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.0" - "@protobufjs/path" "^1.1.2" - "@protobufjs/pool" "^1.1.0" - "@protobufjs/utf8" "^1.1.0" - "@types/node" ">=13.7.0" - long "^5.0.0" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -safe-buffer@>=5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -ts-node@^10.9.2: - version "10.9.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" - integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tslib@^2.1.0, tslib@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - -typescript@^5.8.2: - version "5.8.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4" - integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ== - -undici-types@~6.21.0: - version "6.21.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" - integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -web-vitals@^4.2.4: - version "4.2.4" - resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7" - integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw== - -websocket-driver@>=0.5.1: - version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== - dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.7.2: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From f867d3b2a8363896c098d27e4229e36f9175a2c7 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 23 Apr 2025 11:12:13 -0700 Subject: [PATCH 09/63] Removed unnecessary data connect changes --- packages/data-connect/.eslintrc.js | 2 +- packages/data-connect/tsconfig.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/data-connect/.eslintrc.js b/packages/data-connect/.eslintrc.js index a6d8d8c7c84..faef63a0395 100644 --- a/packages/data-connect/.eslintrc.js +++ b/packages/data-connect/.eslintrc.js @@ -24,7 +24,7 @@ module.exports = { tsconfigRootDir: __dirname }, plugins: ['import'], - ignorePatterns: ['compat/*', 'example-integration/*'], + ignorePatterns: ['compat/*'], rules: { 'no-console': ['error', { allow: ['warn', 'error'] }], '@typescript-eslint/no-unused-vars': [ diff --git a/packages/data-connect/tsconfig.json b/packages/data-connect/tsconfig.json index ba35aaa2516..58561f50f5d 100644 --- a/packages/data-connect/tsconfig.json +++ b/packages/data-connect/tsconfig.json @@ -4,5 +4,5 @@ "outDir": "dist", "strict": false }, - "exclude": ["dist/**/*", "test/**/*", "example-integration/**/*"] + "exclude": ["dist/**/*", "test/**/*"] } From 4f23f3343146f15ea27fcba85ba9e22e1e96117c Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 23 Apr 2025 11:15:53 -0700 Subject: [PATCH 10/63] Create gentle-laws-kneel.md --- .changeset/gentle-laws-kneel.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/gentle-laws-kneel.md diff --git a/.changeset/gentle-laws-kneel.md b/.changeset/gentle-laws-kneel.md new file mode 100644 index 00000000000..46dc7d25ecf --- /dev/null +++ b/.changeset/gentle-laws-kneel.md @@ -0,0 +1,7 @@ +--- +"@firebase/database-compat": patch +"@firebase/database": patch +"@firebase/firestore": patch +--- + +Add SSL checks to `connectDatabaseEmulator` and `connectFirestoreEmulator` From e755d8c486e922ef0eff9014924f8b6f1429a1e8 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 13:49:33 -0700 Subject: [PATCH 11/63] Addressed feedback --- common/api-review/firestore-lite.api.md | 1 + common/api-review/firestore.api.md | 1 + config/.eslintrc.js | 16 ++++++++-------- packages/database/src/api/Database.ts | 15 +++------------ packages/database/src/core/RepoInfo.ts | 1 + packages/firestore/src/lite-api/database.ts | 7 ++----- .../firestore/test/unit/api/database.test.ts | 6 +++--- 7 files changed, 19 insertions(+), 28 deletions(-) diff --git a/common/api-review/firestore-lite.api.md b/common/api-review/firestore-lite.api.md index 4a9ef4c0171..1c05aac46b7 100644 --- a/common/api-review/firestore-lite.api.md +++ b/common/api-review/firestore-lite.api.md @@ -103,6 +103,7 @@ export class CollectionReference { expect(db._getEmulatorOptions()).to.equal(emulatorOptions); }); - it('sets ssl to true if prefixed with https://', () => { + it('sets ssl to true if set in options', () => { // Use a new instance of Firestore in order to configure settings. const db = newTestFirestore(); - const emulatorOptions = { mockUserToken: 'test' }; - connectFirestoreEmulator(db, 'https://127.0.0.1', 9000, emulatorOptions); + const emulatorOptions = { mockUserToken: 'test', ssl: true }; + connectFirestoreEmulator(db, '127.0.0.1', 9000, emulatorOptions); expect(db._getSettings().host).to.exist.and.to.equal('127.0.0.1:9000'); expect(db._getSettings().ssl).to.exist.and.to.be.true; From ceed5ab037082e794c001c1a8442869b47871ddd Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 13:53:29 -0700 Subject: [PATCH 12/63] Addressed linting issue --- packages/firestore/src/lite-api/database.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firestore/src/lite-api/database.ts b/packages/firestore/src/lite-api/database.ts index 994aab8e86c..aa9b89162a1 100644 --- a/packages/firestore/src/lite-api/database.ts +++ b/packages/firestore/src/lite-api/database.ts @@ -326,7 +326,7 @@ export function connectFirestoreEmulator( } = {} ): void { firestore = cast(firestore, Firestore); - let ssl = options.ssl ?? false; + const ssl = options.ssl ?? false; const settings = firestore._getSettings(); const existingConfig = { ...settings, From 44e2d8be815b5b8e06e2682c8a1246d9eb4b0d1a Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 14:05:30 -0700 Subject: [PATCH 13/63] Added functions change --- packages/functions/src/service.test.ts | 8 ++++++++ packages/functions/src/service.ts | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/functions/src/service.test.ts b/packages/functions/src/service.test.ts index bb29f9025fe..d9300cc1dd3 100644 --- a/packages/functions/src/service.test.ts +++ b/packages/functions/src/service.test.ts @@ -47,6 +47,14 @@ describe('Firebase Functions > Service', () => { 'http://localhost:5005/my-project/us-central1/foo' ); }); + it('can use emulator with SSL', () => { + service = createTestService(app); + connectFunctionsEmulator(service, 'localhost', 5005, true); + assert.equal( + service._url('foo'), + 'https://localhost:5005/my-project/us-central1/foo' + ); + }); it('correctly sets region', () => { service = createTestService(app, 'my-region'); diff --git a/packages/functions/src/service.ts b/packages/functions/src/service.ts index 34cb732bf71..b782e3428f2 100644 --- a/packages/functions/src/service.ts +++ b/packages/functions/src/service.ts @@ -172,9 +172,10 @@ export class FunctionsService implements _FirebaseService { export function connectFunctionsEmulator( functionsInstance: FunctionsService, host: string, - port: number + port: number, + ssl?: boolean ): void { - functionsInstance.emulatorOrigin = `http://${host}:${port}`; + functionsInstance.emulatorOrigin = `http${ssl ? 's' : ''}://${host}:${port}`; } /** From a1b85e249a362864261f218bb62b627a322be3a5 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 14:09:09 -0700 Subject: [PATCH 14/63] Removed linting rules --- config/.eslintrc.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/config/.eslintrc.js b/config/.eslintrc.js index 589dbf4cccd..57243a3e2a4 100644 --- a/config/.eslintrc.js +++ b/config/.eslintrc.js @@ -98,18 +98,18 @@ module.exports = { 'object': 'it', 'property': 'skip' }, - // { - // 'object': 'it', - // 'property': 'only' - // }, + { + 'object': 'it', + 'property': 'only' + }, { 'object': 'describe', 'property': 'skip' }, - // { - // 'object': 'describe', - // 'property': 'only' - // }, + { + 'object': 'describe', + 'property': 'only' + }, { 'object': 'xit' } From d67b2844dd4db783cec8e3b003596d0c9986a5db Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 14:21:04 -0700 Subject: [PATCH 15/63] Updated useEmulator --- .changeset/gentle-laws-kneel.md | 2 ++ common/api-review/database.api.md | 1 + packages/database-compat/src/api/Database.ts | 1 + packages/database-compat/test/database.test.ts | 12 ++---------- packages/database-types/index.d.ts | 2 ++ 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.changeset/gentle-laws-kneel.md b/.changeset/gentle-laws-kneel.md index 46dc7d25ecf..6fb16d77d4c 100644 --- a/.changeset/gentle-laws-kneel.md +++ b/.changeset/gentle-laws-kneel.md @@ -1,7 +1,9 @@ --- "@firebase/database-compat": patch +"@firebase/database-types": patch "@firebase/database": patch "@firebase/firestore": patch +"@firebase/functions": patch --- Add SSL checks to `connectDatabaseEmulator` and `connectFirestoreEmulator` diff --git a/common/api-review/database.api.md b/common/api-review/database.api.md index 0b7b36869d6..edec4d6d709 100644 --- a/common/api-review/database.api.md +++ b/common/api-review/database.api.md @@ -13,6 +13,7 @@ export function child(parent: DatabaseReference, path: string): DatabaseReferenc // @public export function connectDatabaseEmulator(db: Database, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; + ssl?: boolean; }): void; // @public diff --git a/packages/database-compat/src/api/Database.ts b/packages/database-compat/src/api/Database.ts index 48682dc8b5c..2b34cfe7228 100644 --- a/packages/database-compat/src/api/Database.ts +++ b/packages/database-compat/src/api/Database.ts @@ -72,6 +72,7 @@ export class Database implements FirebaseService, Compat { port: number, options: { mockUserToken?: EmulatorMockTokenOptions; + ssl?: boolean; } = {} ): void { connectDatabaseEmulator(this._delegate, host, port, options); diff --git a/packages/database-compat/test/database.test.ts b/packages/database-compat/test/database.test.ts index 95b3b0a9b87..8d95b03efd3 100644 --- a/packages/database-compat/test/database.test.ts +++ b/packages/database-compat/test/database.test.ts @@ -292,17 +292,9 @@ describe('Database Tests', () => { expect((db as any)._delegate._repo.repoInfo_.isUsingEmulator).to.be.false; }); - it('uses ssl when useEmulator is called with https is specified', () => { + it('uses ssl when useEmulator is called with ssl specified', () => { const db = firebase.database(); - db.useEmulator('https://localhost', 80); - expect((db as any)._delegate._repo.repoInfo_.isUsingEmulator).to.be.true; - expect((db as any)._delegate._repo.repoInfo_.host).to.equal('localhost:80'); - expect((db as any)._delegate._repo.repoInfo_.secure).to.be.true; - }); - - it('uses ssl when useEmulator is called with wss is specified', () => { - const db = firebase.database(); - db.useEmulator('wss://localhost', 80); + db.useEmulator('localhost', 80, { ssl: true }); expect((db as any)._delegate._repo.repoInfo_.isUsingEmulator).to.be.true; expect((db as any)._delegate._repo.repoInfo_.host).to.equal('localhost:80'); expect((db as any)._delegate._repo.repoInfo_.secure).to.be.true; diff --git a/packages/database-types/index.d.ts b/packages/database-types/index.d.ts index 43557ebe1ac..a7a276a2abe 100644 --- a/packages/database-types/index.d.ts +++ b/packages/database-types/index.d.ts @@ -47,6 +47,7 @@ export interface Database { port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; + ssl?: boolean; } ): void; goOffline(): void; @@ -63,6 +64,7 @@ export class FirebaseDatabase implements Database { port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; + ssl?: boolean; } ): void; goOffline(): void; From a8b208b7c34eda5bfef21ef4471fc1239e99afa6 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 14:33:28 -0700 Subject: [PATCH 16/63] Updated functions signatures --- common/api-review/functions.api.md | 2 +- packages/functions/src/api.ts | 6 ++++-- packages/storage/src/service.ts | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/common/api-review/functions.api.md b/common/api-review/functions.api.md index 883bde3bc0d..53bcf8539f6 100644 --- a/common/api-review/functions.api.md +++ b/common/api-review/functions.api.md @@ -8,7 +8,7 @@ import { FirebaseApp } from '@firebase/app'; import { FirebaseError } from '@firebase/util'; // @public -export function connectFunctionsEmulator(functionsInstance: Functions, host: string, port: number): void; +export function connectFunctionsEmulator(functionsInstance: Functions, host: string, port: number, ssl?: boolean): void; // @public export interface Functions { diff --git a/packages/functions/src/api.ts b/packages/functions/src/api.ts index 7f92cba8343..e4deac11623 100644 --- a/packages/functions/src/api.ts +++ b/packages/functions/src/api.ts @@ -74,12 +74,14 @@ export function getFunctions( export function connectFunctionsEmulator( functionsInstance: Functions, host: string, - port: number + port: number, + ssl?: boolean ): void { _connectFunctionsEmulator( getModularInstance(functionsInstance as FunctionsService), host, - port + port, + ssl ); } diff --git a/packages/storage/src/service.ts b/packages/storage/src/service.ts index 422e3e1a188..219041f30a9 100644 --- a/packages/storage/src/service.ts +++ b/packages/storage/src/service.ts @@ -138,10 +138,11 @@ export function connectStorageEmulator( port: number, options: { mockUserToken?: EmulatorMockTokenOptions | string; + ssl?: boolean; } = {} ): void { storage.host = `${host}:${port}`; - storage._protocol = 'http'; + storage._protocol = options.ssl ? 'http' : 'https'; const { mockUserToken } = options; if (mockUserToken) { storage._overrideAuthToken = From 205f9caac02ebb44627031b3f02c822f635b5e50 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 14:35:48 -0700 Subject: [PATCH 17/63] Updated docsite changes --- docs-devsite/database.md | 7 ++++--- docs-devsite/firestore_.md | 7 ++++--- docs-devsite/firestore_lite.md | 7 ++++--- docs-devsite/functions.md | 7 ++++--- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/docs-devsite/database.md b/docs-devsite/database.md index e6c6c4af8c6..7f8d3a7bf2f 100644 --- a/docs-devsite/database.md +++ b/docs-devsite/database.md @@ -19,7 +19,7 @@ Firebase Realtime Database | function(app, ...) | | [getDatabase(app, url)](./database.md#getdatabase_d9cea01) | Returns the instance of the Realtime Database SDK that is associated with the provided [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface). Initializes a new instance with default settings if no instance exists or if the existing instance uses a custom database URL. | | function(db, ...) | -| [connectDatabaseEmulator(db, host, port, options)](./database.md#connectdatabaseemulator_27b9e93) | Modify the provided instance to communicate with the Realtime Database emulator.

Note: This method must be called before performing any other operation. | +| [connectDatabaseEmulator(db, host, port, options)](./database.md#connectdatabaseemulator_20a9664) | Modify the provided instance to communicate with the Realtime Database emulator.

Note: This method must be called before performing any other operation. | | [goOffline(db)](./database.md#gooffline_732b338) | Disconnects from the server (all Database operations will be completed offline).The client automatically maintains a persistent connection to the Database server, which will remain active indefinitely and reconnect when disconnected. However, the goOffline() and goOnline() methods may be used to control the client connection in cases where a persistent connection is undesirable.While offline, the client will no longer receive data updates from the Database. However, all Database operations performed locally will continue to immediately fire events, allowing your application to continue behaving normally. Additionally, each operation performed locally will automatically be queued and retried upon reconnection to the Database server.To reconnect to the Database and begin receiving remote events, see goOnline(). | | [goOnline(db)](./database.md#goonline_732b338) | Reconnects to the server and synchronizes the offline Database state with the server state.This method should be used after disabling the active connection with goOffline(). Once reconnected, the client will transmit the proper data and fire the appropriate events so that your client "catches up" automatically. | | [ref(db, path)](./database.md#ref_5f88fa2) | Returns a Reference representing the location in the Database corresponding to the provided path. If no path is provided, the Reference will point to the root of the Database. | @@ -135,7 +135,7 @@ The `Database` instance of the provided app. ## function(db, ...) -### connectDatabaseEmulator(db, host, port, options) {:#connectdatabaseemulator_27b9e93} +### connectDatabaseEmulator(db, host, port, options) {:#connectdatabaseemulator_20a9664} Modify the provided instance to communicate with the Realtime Database emulator. @@ -146,6 +146,7 @@ Modify the provided instance to communicate with the Realtime Database emulator. ```typescript export declare function connectDatabaseEmulator(db: Database, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; + ssl?: boolean; }): void; ``` @@ -156,7 +157,7 @@ export declare function connectDatabaseEmulator(db: Database, host: string, port | db | [Database](./database.database.md#database_class) | The instance to modify. | | host | string | The emulator host (ex: localhost) | | port | number | The emulator port (ex: 8080) | -| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; } | | +| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; ssl?: boolean; } | | Returns: diff --git a/docs-devsite/firestore_.md b/docs-devsite/firestore_.md index 91d21e32708..70cc5221043 100644 --- a/docs-devsite/firestore_.md +++ b/docs-devsite/firestore_.md @@ -23,7 +23,7 @@ https://github.com/firebase/firebase-js-sdk | [clearIndexedDbPersistence(firestore)](./firestore_.md#clearindexeddbpersistence_231a8e0) | Clears the persistent storage. This includes pending writes and cached documents.Must be called while the [Firestore](./firestore_.firestore.md#firestore_class) instance is not started (after the app is terminated or when the app is first initialized). On startup, this function must be called before other functions (other than [initializeFirestore()](./firestore_.md#initializefirestore_fc7d200) or [getFirestore()](./firestore_.md#getfirestore))). If the [Firestore](./firestore_.firestore.md#firestore_class) instance is still running, the promise will be rejected with the error code of failed-precondition.Note: clearIndexedDbPersistence() is primarily intended to help write reliable tests that use Cloud Firestore. It uses an efficient mechanism for dropping existing data but does not attempt to securely overwrite or otherwise make cached data unrecoverable. For applications that are sensitive to the disclosure of cached data in between user sessions, we strongly recommend not enabling persistence at all. | | [collection(firestore, path, pathSegments)](./firestore_.md#collection_1eb4c23) | Gets a CollectionReference instance that refers to the collection at the specified absolute path. | | [collectionGroup(firestore, collectionId)](./firestore_.md#collectiongroup_1838fc3) | Creates and returns a new Query instance that includes all documents in the database that are contained in a collection or subcollection with the given collectionId. | -| [connectFirestoreEmulator(firestore, host, port, options)](./firestore_.md#connectfirestoreemulator_7c247cd) | Modify this instance to communicate with the Cloud Firestore emulator.Note: This must be called before this instance has been used to do any operations. | +| [connectFirestoreEmulator(firestore, host, port, options)](./firestore_.md#connectfirestoreemulator_6c8868a) | Modify this instance to communicate with the Cloud Firestore emulator.Note: This must be called before this instance has been used to do any operations. | | [disableNetwork(firestore)](./firestore_.md#disablenetwork_231a8e0) | Disables network usage for this instance. It can be re-enabled via [enableNetwork()](./firestore_.md#enablenetwork_231a8e0). While the network is disabled, any snapshot listeners, getDoc() or getDocs() calls will return results from cache, and any write operations will be queued until the network is restored. | | [doc(firestore, path, pathSegments)](./firestore_.md#doc_1eb4c23) | Gets a DocumentReference instance that refers to the document at the specified absolute path. | | [enableIndexedDbPersistence(firestore, persistenceSettings)](./firestore_.md#enableindexeddbpersistence_224174f) | Attempts to enable persistent storage, if possible.On failure, enableIndexedDbPersistence() will reject the promise or throw an exception. There are several reasons why this can fail, which can be identified by the code on the error.\* failed-precondition: The app is already open in another browser tab. \* unimplemented: The browser is incompatible with the offline persistence implementation.Note that even after a failure, the [Firestore](./firestore_.firestore.md#firestore_class) instance will remain usable, however offline persistence will be disabled.Note: enableIndexedDbPersistence() must be called before any other functions (other than [initializeFirestore()](./firestore_.md#initializefirestore_fc7d200), [getFirestore()](./firestore_.md#getfirestore) or [clearIndexedDbPersistence()](./firestore_.md#clearindexeddbpersistence_231a8e0).Persistence cannot be used in a Node.js environment. | @@ -377,7 +377,7 @@ export declare function collectionGroup(firestore: Firestore, collectionId: stri The created `Query`. -### connectFirestoreEmulator(firestore, host, port, options) {:#connectfirestoreemulator_7c247cd} +### connectFirestoreEmulator(firestore, host, port, options) {:#connectfirestoreemulator_6c8868a} Modify this instance to communicate with the Cloud Firestore emulator. @@ -388,6 +388,7 @@ Note: This must be called before this instance has been used to do any operation ```typescript export declare function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; + ssl?: boolean; }): void; ``` @@ -398,7 +399,7 @@ export declare function connectFirestoreEmulator(firestore: Firestore, host: str | firestore | [Firestore](./firestore_.firestore.md#firestore_class) | The Firestore instance to configure to connect to the emulator. | | host | string | the emulator host (ex: localhost). | | port | number | the emulator port (ex: 9000). | -| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; } | | +| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; ssl?: boolean; } | | Returns: diff --git a/docs-devsite/firestore_lite.md b/docs-devsite/firestore_lite.md index 20fafd66c59..fe18f38bf47 100644 --- a/docs-devsite/firestore_lite.md +++ b/docs-devsite/firestore_lite.md @@ -23,7 +23,7 @@ https://github.com/firebase/firebase-js-sdk | function(firestore, ...) | | [collection(firestore, path, pathSegments)](./firestore_lite.md#collection_1eb4c23) | Gets a CollectionReference instance that refers to the collection at the specified absolute path. | | [collectionGroup(firestore, collectionId)](./firestore_lite.md#collectiongroup_1838fc3) | Creates and returns a new Query instance that includes all documents in the database that are contained in a collection or subcollection with the given collectionId. | -| [connectFirestoreEmulator(firestore, host, port, options)](./firestore_lite.md#connectfirestoreemulator_7c247cd) | Modify this instance to communicate with the Cloud Firestore emulator.Note: This must be called before this instance has been used to do any operations. | +| [connectFirestoreEmulator(firestore, host, port, options)](./firestore_lite.md#connectfirestoreemulator_6c8868a) | Modify this instance to communicate with the Cloud Firestore emulator.Note: This must be called before this instance has been used to do any operations. | | [doc(firestore, path, pathSegments)](./firestore_lite.md#doc_1eb4c23) | Gets a DocumentReference instance that refers to the document at the specified absolute path. | | [runTransaction(firestore, updateFunction, options)](./firestore_lite.md#runtransaction_6f03ec4) | Executes the given updateFunction and then attempts to commit the changes applied within the transaction. If any document read within the transaction has changed, Cloud Firestore retries the updateFunction. If it fails to commit after 5 attempts, the transaction fails.The maximum number of writes allowed in a single transaction is 500. | | [terminate(firestore)](./firestore_lite.md#terminate_231a8e0) | Terminates the provided Firestore instance.After calling terminate() only the clearIndexedDbPersistence() functions may be used. Any other function will throw a FirestoreError. Termination does not cancel any pending writes, and any promises that are awaiting a response from the server will not be resolved.To restart after termination, create a new instance of Firestore with [getFirestore()](./firestore_.md#getfirestore).Note: Under normal circumstances, calling terminate() is not required. This function is useful only when you want to force this instance to release all of its resources or in combination with [clearIndexedDbPersistence()](./firestore_.md#clearindexeddbpersistence_231a8e0) to ensure that all local state is destroyed between test runs. | @@ -308,7 +308,7 @@ export declare function collectionGroup(firestore: Firestore, collectionId: stri The created `Query`. -### connectFirestoreEmulator(firestore, host, port, options) {:#connectfirestoreemulator_7c247cd} +### connectFirestoreEmulator(firestore, host, port, options) {:#connectfirestoreemulator_6c8868a} Modify this instance to communicate with the Cloud Firestore emulator. @@ -319,6 +319,7 @@ Note: This must be called before this instance has been used to do any operation ```typescript export declare function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; + ssl?: boolean; }): void; ``` @@ -329,7 +330,7 @@ export declare function connectFirestoreEmulator(firestore: Firestore, host: str | firestore | [Firestore](./firestore_lite.firestore.md#firestore_class) | The Firestore instance to configure to connect to the emulator. | | host | string | the emulator host (ex: localhost). | | port | number | the emulator port (ex: 9000). | -| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; } | | +| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; ssl?: boolean; } | | Returns: diff --git a/docs-devsite/functions.md b/docs-devsite/functions.md index 7e2eefa1569..b44bd5ec3cb 100644 --- a/docs-devsite/functions.md +++ b/docs-devsite/functions.md @@ -19,7 +19,7 @@ Cloud Functions for Firebase | function(app, ...) | | [getFunctions(app, regionOrCustomDomain)](./functions.md#getfunctions_60f2095) | Returns a [Functions](./functions.functions.md#functions_interface) instance for the given app. | | function(functionsInstance, ...) | -| [connectFunctionsEmulator(functionsInstance, host, port)](./functions.md#connectfunctionsemulator_505c08d) | Modify this instance to communicate with the Cloud Functions emulator.Note: this must be called before this instance has been used to do any operations. | +| [connectFunctionsEmulator(functionsInstance, host, port, ssl)](./functions.md#connectfunctionsemulator_a989598) | Modify this instance to communicate with the Cloud Functions emulator.Note: this must be called before this instance has been used to do any operations. | | [httpsCallable(functionsInstance, name, options)](./functions.md#httpscallable_1dd297c) | Returns a reference to the callable HTTPS trigger with the given name. | | [httpsCallableFromURL(functionsInstance, url, options)](./functions.md#httpscallablefromurl_7af6987) | Returns a reference to the callable HTTPS trigger with the specified url. | @@ -72,7 +72,7 @@ export declare function getFunctions(app?: FirebaseApp, regionOrCustomDomain?: s ## function(functionsInstance, ...) -### connectFunctionsEmulator(functionsInstance, host, port) {:#connectfunctionsemulator_505c08d} +### connectFunctionsEmulator(functionsInstance, host, port, ssl) {:#connectfunctionsemulator_a989598} Modify this instance to communicate with the Cloud Functions emulator. @@ -81,7 +81,7 @@ Note: this must be called before this instance has been used to do any operation Signature: ```typescript -export declare function connectFunctionsEmulator(functionsInstance: Functions, host: string, port: number): void; +export declare function connectFunctionsEmulator(functionsInstance: Functions, host: string, port: number, ssl?: boolean): void; ``` #### Parameters @@ -91,6 +91,7 @@ export declare function connectFunctionsEmulator(functionsInstance: Functions, h | functionsInstance | [Functions](./functions.functions.md#functions_interface) | | | host | string | The emulator host (ex: localhost) | | port | number | The emulator port (ex: 5001) | +| ssl | boolean | | Returns: From 4bc94333ed3b8c68ac81b8af0ee919528e363ebb Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 14:41:45 -0700 Subject: [PATCH 18/63] Added tests --- .changeset/gentle-laws-kneel.md | 1 + packages/storage/src/api.ts | 1 + packages/storage/src/service.ts | 2 +- packages/storage/test/unit/service.test.ts | 21 +++++++++++++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.changeset/gentle-laws-kneel.md b/.changeset/gentle-laws-kneel.md index 6fb16d77d4c..b90115f77c5 100644 --- a/.changeset/gentle-laws-kneel.md +++ b/.changeset/gentle-laws-kneel.md @@ -4,6 +4,7 @@ "@firebase/database": patch "@firebase/firestore": patch "@firebase/functions": patch +"@firebase/storage": patch --- Add SSL checks to `connectDatabaseEmulator` and `connectFirestoreEmulator` diff --git a/packages/storage/src/api.ts b/packages/storage/src/api.ts index 84c77ea0c8c..c7393847f53 100644 --- a/packages/storage/src/api.ts +++ b/packages/storage/src/api.ts @@ -359,6 +359,7 @@ export function connectStorageEmulator( port: number, options: { mockUserToken?: EmulatorMockTokenOptions | string; + ssl?: boolean; } = {} ): void { connectEmulatorInternal(storage as FirebaseStorageImpl, host, port, options); diff --git a/packages/storage/src/service.ts b/packages/storage/src/service.ts index 219041f30a9..ce4513bb5d9 100644 --- a/packages/storage/src/service.ts +++ b/packages/storage/src/service.ts @@ -142,7 +142,7 @@ export function connectStorageEmulator( } = {} ): void { storage.host = `${host}:${port}`; - storage._protocol = options.ssl ? 'http' : 'https'; + storage._protocol = options.ssl ? 'https' : 'http'; const { mockUserToken } = options; if (mockUserToken) { storage._overrideAuthToken = diff --git a/packages/storage/test/unit/service.test.ts b/packages/storage/test/unit/service.test.ts index be42bb8dd6e..b4d0b0b38af 100644 --- a/packages/storage/test/unit/service.test.ts +++ b/packages/storage/test/unit/service.test.ts @@ -248,6 +248,27 @@ GOOG4-RSA-SHA256` expect(service._protocol).to.equal('http'); void getDownloadURL(ref(service, 'test.png')); }); + it('sets emulator host correctly with ssl', done => { + function newSend(connection: TestingConnection, url: string): void { + // Expect emulator host to be in url of storage operations requests, + // in this case getDownloadURL. + expect(url).to.match(/^https:\/\/test\.host\.org:1234.+/); + connection.abort(); + injectTestConnection(null); + done(); + } + + injectTestConnection(() => newTestConnection(newSend)); + const service = new FirebaseStorageImpl( + testShared.fakeApp, + testShared.fakeAuthProvider, + testShared.fakeAppCheckTokenProvider + ); + connectStorageEmulator(service, 'test.host.org', 1234, { ssl: true }); + expect(service.host).to.equal('test.host.org:1234'); + expect(service._protocol).to.equal('https'); + void getDownloadURL(ref(service, 'test.png')); + }); it('sets mock user token string if specified', done => { const mockUserToken = 'my-mock-user-token'; function newSend( From a32ea8b63e2a0adb429c45c760b87ef1be91e7ca Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 14:46:49 -0700 Subject: [PATCH 19/63] Updated docsite --- common/api-review/storage.api.md | 1 + docs-devsite/storage.md | 7 ++++--- packages/storage-compat/src/service.ts | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/common/api-review/storage.api.md b/common/api-review/storage.api.md index 4964aa40af7..1135484cd1c 100644 --- a/common/api-review/storage.api.md +++ b/common/api-review/storage.api.md @@ -19,6 +19,7 @@ import { Unsubscribe } from '@firebase/util'; // @public export function connectStorageEmulator(storage: FirebaseStorage, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; + ssl?: boolean; }): void; // Warning: (ae-forgotten-export) The symbol "StringData" needs to be exported by the entry point index.d.ts diff --git a/docs-devsite/storage.md b/docs-devsite/storage.md index da72929ebc9..3cfaa98407e 100644 --- a/docs-devsite/storage.md +++ b/docs-devsite/storage.md @@ -19,7 +19,7 @@ Cloud Storage for Firebase | function(app, ...) | | [getStorage(app, bucketUrl)](./storage.md#getstorage_25f3a57) | Gets a [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) instance for the given Firebase app. | | function(storage, ...) | -| [connectStorageEmulator(storage, host, port, options)](./storage.md#connectstorageemulator_e9039de) | Modify this [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) instance to communicate with the Cloud Storage emulator. | +| [connectStorageEmulator(storage, host, port, options)](./storage.md#connectstorageemulator_ac343b7) | Modify this [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) instance to communicate with the Cloud Storage emulator. | | [ref(storage, url)](./storage.md#ref_5672fc1) | Returns a [StorageReference](./storage.storagereference.md#storagereference_interface) for the given url. | | function(ref, ...) | | [deleteObject(ref)](./storage.md#deleteobject_30df0b2) | Deletes the object at this location. | @@ -106,7 +106,7 @@ A [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) inst ## function(storage, ...) -### connectStorageEmulator(storage, host, port, options) {:#connectstorageemulator_e9039de} +### connectStorageEmulator(storage, host, port, options) {:#connectstorageemulator_ac343b7} Modify this [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) instance to communicate with the Cloud Storage emulator. @@ -115,6 +115,7 @@ Modify this [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_inter ```typescript export declare function connectStorageEmulator(storage: FirebaseStorage, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; + ssl?: boolean; }): void; ``` @@ -125,7 +126,7 @@ export declare function connectStorageEmulator(storage: FirebaseStorage, host: s | storage | [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) | The [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) instance | | host | string | The emulator host (ex: localhost) | | port | number | The emulator port (ex: 5001) | -| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; } | Emulator options. options.mockUserToken is the mock auth token to use for unit testing Security Rules. | +| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; ssl?: boolean; } | Emulator options. options.mockUserToken is the mock auth token to use for unit testing Security Rules. | Returns: diff --git a/packages/storage-compat/src/service.ts b/packages/storage-compat/src/service.ts index b719802b74a..c8deab281e2 100644 --- a/packages/storage-compat/src/service.ts +++ b/packages/storage-compat/src/service.ts @@ -92,6 +92,7 @@ export class StorageServiceCompat port: number, options: { mockUserToken?: EmulatorMockTokenOptions | string; + ssl?: boolean } = {} ): void { connectStorageEmulator(this._delegate, host, port, options); From 07f44b6cd968922e8d3ce05b23b8b47fb6baf440 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 14:49:01 -0700 Subject: [PATCH 20/63] Fixed formatting --- packages/storage-compat/src/service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/storage-compat/src/service.ts b/packages/storage-compat/src/service.ts index c8deab281e2..034ce35e823 100644 --- a/packages/storage-compat/src/service.ts +++ b/packages/storage-compat/src/service.ts @@ -92,7 +92,7 @@ export class StorageServiceCompat port: number, options: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean + ssl?: boolean; } = {} ): void { connectStorageEmulator(this._delegate, host, port, options); From d305dec092a3c309b9298fd58b7d86088a874201 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 17:05:29 -0700 Subject: [PATCH 21/63] Only checked if user is on cloudworkstation for ssl --- common/api-review/firestore-lite.api.md | 1 - common/api-review/firestore.api.md | 1 - common/api-review/functions.api.md | 2 +- common/api-review/storage.api.md | 1 - common/api-review/util.api.md | 5 +++++ packages/database-compat/src/api/Database.ts | 1 - packages/database-types/index.d.ts | 2 -- packages/database/src/api/Database.ts | 9 ++++++--- packages/database/src/core/RepoInfo.ts | 1 - packages/firestore/externs.json | 1 + packages/firestore/src/lite-api/database.ts | 8 ++++---- packages/firestore/test/unit/api/database.test.ts | 11 +++++++---- packages/functions/src/api.ts | 4 +--- packages/functions/src/service.test.ts | 5 +++-- packages/functions/src/service.ts | 9 ++++++--- packages/storage/src/api.ts | 1 - packages/storage/src/service.ts | 10 +++++++--- packages/storage/test/unit/service.test.ts | 5 +++-- packages/util/index.node.ts | 1 + packages/util/index.ts | 1 + packages/util/src/url.ts | 6 ++++++ 21 files changed, 52 insertions(+), 33 deletions(-) create mode 100644 packages/util/src/url.ts diff --git a/common/api-review/firestore-lite.api.md b/common/api-review/firestore-lite.api.md index 1c05aac46b7..4a9ef4c0171 100644 --- a/common/api-review/firestore-lite.api.md +++ b/common/api-review/firestore-lite.api.md @@ -103,7 +103,6 @@ export class CollectionReference { port: number, options: { mockUserToken?: EmulatorMockTokenOptions; - ssl?: boolean; } = {} ): void { connectDatabaseEmulator(this._delegate, host, port, options); diff --git a/packages/database-types/index.d.ts b/packages/database-types/index.d.ts index a7a276a2abe..43557ebe1ac 100644 --- a/packages/database-types/index.d.ts +++ b/packages/database-types/index.d.ts @@ -47,7 +47,6 @@ export interface Database { port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; } ): void; goOffline(): void; @@ -64,7 +63,6 @@ export class FirebaseDatabase implements Database { port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; } ): void; goOffline(): void; diff --git a/packages/database/src/api/Database.ts b/packages/database/src/api/Database.ts index 27d0f8180a5..44931e2ea83 100644 --- a/packages/database/src/api/Database.ts +++ b/packages/database/src/api/Database.ts @@ -29,7 +29,8 @@ import { createMockUserToken, deepEqual, EmulatorMockTokenOptions, - getDefaultEmulatorHostnameAndPort + getDefaultEmulatorHostnameAndPort, + isCloudWorkstation } from '@firebase/util'; import { AppCheckTokenProvider } from '../core/AppCheckTokenProvider'; @@ -89,9 +90,12 @@ function repoManagerApplyEmulatorSettings( emulatorOptions: RepoInfoEmulatorOptions, tokenProvider?: AuthTokenProvider ): void { + const portIndex = hostAndPort.lastIndexOf(':'); + const host = hostAndPort.substring(portIndex); + const useSsl = isCloudWorkstation(host); repo.repoInfo_ = new RepoInfo( hostAndPort, - /* secure= */ emulatorOptions?.ssl ?? false, + /* secure= */ useSsl, repo.repoInfo_.namespace, repo.repoInfo_.webSocketOnly, repo.repoInfo_.nodeAdmin, @@ -348,7 +352,6 @@ export function connectDatabaseEmulator( port: number, options: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; } = {} ): void { db = getModularInstance(db); diff --git a/packages/database/src/core/RepoInfo.ts b/packages/database/src/core/RepoInfo.ts index 0eb53c3e552..1f8934c71d2 100644 --- a/packages/database/src/core/RepoInfo.ts +++ b/packages/database/src/core/RepoInfo.ts @@ -24,7 +24,6 @@ import { each } from './util/util'; export interface RepoInfoEmulatorOptions { mockUserToken?: string | EmulatorMockTokenOptions; - ssl?: boolean; } /** diff --git a/packages/firestore/externs.json b/packages/firestore/externs.json index 03d19ee8e83..d730cfeac0a 100644 --- a/packages/firestore/externs.json +++ b/packages/firestore/externs.json @@ -33,6 +33,7 @@ "packages/util/dist/src/compat.d.ts", "packages/util/dist/src/global.d.ts", "packages/util/dist/src/obj.d.ts", + "packages/util/dist/src/url.d.ts", "packages/firestore/src/protos/firestore_bundle_proto.ts", "packages/firestore/src/protos/firestore_proto_api.ts", "packages/firestore/src/util/error.ts", diff --git a/packages/firestore/src/lite-api/database.ts b/packages/firestore/src/lite-api/database.ts index aa9b89162a1..294206e54c2 100644 --- a/packages/firestore/src/lite-api/database.ts +++ b/packages/firestore/src/lite-api/database.ts @@ -26,7 +26,8 @@ import { createMockUserToken, deepEqual, EmulatorMockTokenOptions, - getDefaultEmulatorHostnameAndPort + getDefaultEmulatorHostnameAndPort, + isCloudWorkstation } from '@firebase/util'; import { @@ -322,11 +323,10 @@ export function connectFirestoreEmulator( port: number, options: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; } = {} ): void { firestore = cast(firestore, Firestore); - const ssl = options.ssl ?? false; + const useSsl = isCloudWorkstation(host); const settings = firestore._getSettings(); const existingConfig = { ...settings, @@ -342,7 +342,7 @@ export function connectFirestoreEmulator( const newConfig = { ...settings, host: newHostSetting, - ssl, + ssl: useSsl, emulatorOptions: options }; // No-op if the new configuration matches the current configuration. This supports SSR diff --git a/packages/firestore/test/unit/api/database.test.ts b/packages/firestore/test/unit/api/database.test.ts index 468f5922796..7b0fee09a7f 100644 --- a/packages/firestore/test/unit/api/database.test.ts +++ b/packages/firestore/test/unit/api/database.test.ts @@ -564,13 +564,16 @@ describe('Settings', () => { expect(db._getEmulatorOptions()).to.equal(emulatorOptions); }); - it('sets ssl to true if set in options', () => { + it('sets ssl to true if cloud workstation host', () => { // Use a new instance of Firestore in order to configure settings. const db = newTestFirestore(); - const emulatorOptions = { mockUserToken: 'test', ssl: true }; - connectFirestoreEmulator(db, '127.0.0.1', 9000, emulatorOptions); + const emulatorOptions = { mockUserToken: 'test' }; + const workstationHost = 'abc.workstations.dev'; + connectFirestoreEmulator(db, workstationHost, 9000, emulatorOptions); - expect(db._getSettings().host).to.exist.and.to.equal('127.0.0.1:9000'); + expect(db._getSettings().host).to.exist.and.to.equal( + `${workstationHost}:9000` + ); expect(db._getSettings().ssl).to.exist.and.to.be.true; expect(db._getEmulatorOptions()).to.equal(emulatorOptions); }); diff --git a/packages/functions/src/api.ts b/packages/functions/src/api.ts index e4deac11623..e15d5ffef70 100644 --- a/packages/functions/src/api.ts +++ b/packages/functions/src/api.ts @@ -75,13 +75,11 @@ export function connectFunctionsEmulator( functionsInstance: Functions, host: string, port: number, - ssl?: boolean ): void { _connectFunctionsEmulator( getModularInstance(functionsInstance as FunctionsService), host, - port, - ssl + port ); } diff --git a/packages/functions/src/service.test.ts b/packages/functions/src/service.test.ts index d9300cc1dd3..8119fda39d5 100644 --- a/packages/functions/src/service.test.ts +++ b/packages/functions/src/service.test.ts @@ -49,10 +49,11 @@ describe('Firebase Functions > Service', () => { }); it('can use emulator with SSL', () => { service = createTestService(app); - connectFunctionsEmulator(service, 'localhost', 5005, true); + const workstationHost = 'abc.cloudworkstations.dev'; + connectFunctionsEmulator(service, workstationHost, 5005); assert.equal( service._url('foo'), - 'https://localhost:5005/my-project/us-central1/foo' + `https://${workstationHost}:5005/my-project/us-central1/foo` ); }); diff --git a/packages/functions/src/service.ts b/packages/functions/src/service.ts index b782e3428f2..dce52e1f19d 100644 --- a/packages/functions/src/service.ts +++ b/packages/functions/src/service.ts @@ -30,6 +30,7 @@ import { Provider } from '@firebase/component'; import { FirebaseAuthInternalName } from '@firebase/auth-interop-types'; import { MessagingInternalComponentName } from '@firebase/messaging-interop-types'; import { AppCheckInternalComponentName } from '@firebase/app-check-interop-types'; +import { isCloudWorkstation } from '@firebase/util'; export const DEFAULT_REGION = 'us-central1'; @@ -172,10 +173,12 @@ export class FunctionsService implements _FirebaseService { export function connectFunctionsEmulator( functionsInstance: FunctionsService, host: string, - port: number, - ssl?: boolean + port: number ): void { - functionsInstance.emulatorOrigin = `http${ssl ? 's' : ''}://${host}:${port}`; + const useSsl = isCloudWorkstation(host); + functionsInstance.emulatorOrigin = `http${ + useSsl ? 's' : '' + }://${host}:${port}`; } /** diff --git a/packages/storage/src/api.ts b/packages/storage/src/api.ts index c7393847f53..84c77ea0c8c 100644 --- a/packages/storage/src/api.ts +++ b/packages/storage/src/api.ts @@ -359,7 +359,6 @@ export function connectStorageEmulator( port: number, options: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; } = {} ): void { connectEmulatorInternal(storage as FirebaseStorageImpl, host, port, options); diff --git a/packages/storage/src/service.ts b/packages/storage/src/service.ts index ce4513bb5d9..8a942aac62a 100644 --- a/packages/storage/src/service.ts +++ b/packages/storage/src/service.ts @@ -42,7 +42,11 @@ import { } from './implementation/error'; import { validateNumber } from './implementation/type'; import { FirebaseStorage } from './public-types'; -import { createMockUserToken, EmulatorMockTokenOptions } from '@firebase/util'; +import { + createMockUserToken, + EmulatorMockTokenOptions, + isCloudWorkstation +} from '@firebase/util'; import { Connection, ConnectionType } from './implementation/connection'; export function isUrl(path?: string): boolean { @@ -138,11 +142,11 @@ export function connectStorageEmulator( port: number, options: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; } = {} ): void { storage.host = `${host}:${port}`; - storage._protocol = options.ssl ? 'https' : 'http'; + const useSsl = isCloudWorkstation(host); + storage._protocol = useSsl ? 'https' : 'http'; const { mockUserToken } = options; if (mockUserToken) { storage._overrideAuthToken = diff --git a/packages/storage/test/unit/service.test.ts b/packages/storage/test/unit/service.test.ts index b4d0b0b38af..9984482177d 100644 --- a/packages/storage/test/unit/service.test.ts +++ b/packages/storage/test/unit/service.test.ts @@ -264,8 +264,9 @@ GOOG4-RSA-SHA256` testShared.fakeAuthProvider, testShared.fakeAppCheckTokenProvider ); - connectStorageEmulator(service, 'test.host.org', 1234, { ssl: true }); - expect(service.host).to.equal('test.host.org:1234'); + const workstationHost = 'test.cloudworkations.dev'; + connectStorageEmulator(service, workstationHost, 1234); + expect(service.host).to.equal(`${workstationHost}:1234`); expect(service._protocol).to.equal('https'); void getDownloadURL(ref(service, 'test.png')); }); diff --git a/packages/util/index.node.ts b/packages/util/index.node.ts index d839460713c..12fcf8a6de5 100644 --- a/packages/util/index.node.ts +++ b/packages/util/index.node.ts @@ -42,3 +42,4 @@ export * from './src/exponential_backoff'; export * from './src/formatters'; export * from './src/compat'; export * from './src/global'; +export * from './src/url'; diff --git a/packages/util/index.ts b/packages/util/index.ts index 51c27c31099..1829c32a420 100644 --- a/packages/util/index.ts +++ b/packages/util/index.ts @@ -37,3 +37,4 @@ export * from './src/exponential_backoff'; export * from './src/formatters'; export * from './src/compat'; export * from './src/global'; +export * from './src/url'; diff --git a/packages/util/src/url.ts b/packages/util/src/url.ts new file mode 100644 index 00000000000..5b1e724eaa6 --- /dev/null +++ b/packages/util/src/url.ts @@ -0,0 +1,6 @@ +/** + * Checks whether host is a cloud workstation or not. + */ +export function isCloudWorkstation(host: string) { + return host.endsWith('.cloudworkstations.dev'); +} \ No newline at end of file From fc6469a38220e245cffd5e9053b48f71c8c1f41f Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 17:07:20 -0700 Subject: [PATCH 22/63] Removed ssl from storage compat --- packages/functions/src/api.ts | 2 +- packages/storage-compat/src/service.ts | 1 - packages/util/src/url.ts | 21 +++++++++++++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/functions/src/api.ts b/packages/functions/src/api.ts index e15d5ffef70..7f92cba8343 100644 --- a/packages/functions/src/api.ts +++ b/packages/functions/src/api.ts @@ -74,7 +74,7 @@ export function getFunctions( export function connectFunctionsEmulator( functionsInstance: Functions, host: string, - port: number, + port: number ): void { _connectFunctionsEmulator( getModularInstance(functionsInstance as FunctionsService), diff --git a/packages/storage-compat/src/service.ts b/packages/storage-compat/src/service.ts index 034ce35e823..b719802b74a 100644 --- a/packages/storage-compat/src/service.ts +++ b/packages/storage-compat/src/service.ts @@ -92,7 +92,6 @@ export class StorageServiceCompat port: number, options: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; } = {} ): void { connectStorageEmulator(this._delegate, host, port, options); diff --git a/packages/util/src/url.ts b/packages/util/src/url.ts index 5b1e724eaa6..95606841fd2 100644 --- a/packages/util/src/url.ts +++ b/packages/util/src/url.ts @@ -1,6 +1,23 @@ +/** + * @license + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /** * Checks whether host is a cloud workstation or not. */ export function isCloudWorkstation(host: string) { - return host.endsWith('.cloudworkstations.dev'); -} \ No newline at end of file + return host.endsWith('.cloudworkstations.dev'); +} From 0a0cb7a439c976860614284b8877ddc8e95cd35e Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 17:09:31 -0700 Subject: [PATCH 23/63] Revert devsite changes --- common/api-review/database.api.md | 1 - docs-devsite/database.md | 7 +++---- docs-devsite/firestore_.md | 7 +++---- docs-devsite/firestore_lite.md | 7 +++---- docs-devsite/functions.md | 7 +++---- docs-devsite/storage.md | 7 +++---- 6 files changed, 15 insertions(+), 21 deletions(-) diff --git a/common/api-review/database.api.md b/common/api-review/database.api.md index edec4d6d709..0b7b36869d6 100644 --- a/common/api-review/database.api.md +++ b/common/api-review/database.api.md @@ -13,7 +13,6 @@ export function child(parent: DatabaseReference, path: string): DatabaseReferenc // @public export function connectDatabaseEmulator(db: Database, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; }): void; // @public diff --git a/docs-devsite/database.md b/docs-devsite/database.md index 7f8d3a7bf2f..e6c6c4af8c6 100644 --- a/docs-devsite/database.md +++ b/docs-devsite/database.md @@ -19,7 +19,7 @@ Firebase Realtime Database | function(app, ...) | | [getDatabase(app, url)](./database.md#getdatabase_d9cea01) | Returns the instance of the Realtime Database SDK that is associated with the provided [FirebaseApp](./app.firebaseapp.md#firebaseapp_interface). Initializes a new instance with default settings if no instance exists or if the existing instance uses a custom database URL. | | function(db, ...) | -| [connectDatabaseEmulator(db, host, port, options)](./database.md#connectdatabaseemulator_20a9664) | Modify the provided instance to communicate with the Realtime Database emulator.

Note: This method must be called before performing any other operation. | +| [connectDatabaseEmulator(db, host, port, options)](./database.md#connectdatabaseemulator_27b9e93) | Modify the provided instance to communicate with the Realtime Database emulator.

Note: This method must be called before performing any other operation. | | [goOffline(db)](./database.md#gooffline_732b338) | Disconnects from the server (all Database operations will be completed offline).The client automatically maintains a persistent connection to the Database server, which will remain active indefinitely and reconnect when disconnected. However, the goOffline() and goOnline() methods may be used to control the client connection in cases where a persistent connection is undesirable.While offline, the client will no longer receive data updates from the Database. However, all Database operations performed locally will continue to immediately fire events, allowing your application to continue behaving normally. Additionally, each operation performed locally will automatically be queued and retried upon reconnection to the Database server.To reconnect to the Database and begin receiving remote events, see goOnline(). | | [goOnline(db)](./database.md#goonline_732b338) | Reconnects to the server and synchronizes the offline Database state with the server state.This method should be used after disabling the active connection with goOffline(). Once reconnected, the client will transmit the proper data and fire the appropriate events so that your client "catches up" automatically. | | [ref(db, path)](./database.md#ref_5f88fa2) | Returns a Reference representing the location in the Database corresponding to the provided path. If no path is provided, the Reference will point to the root of the Database. | @@ -135,7 +135,7 @@ The `Database` instance of the provided app. ## function(db, ...) -### connectDatabaseEmulator(db, host, port, options) {:#connectdatabaseemulator_20a9664} +### connectDatabaseEmulator(db, host, port, options) {:#connectdatabaseemulator_27b9e93} Modify the provided instance to communicate with the Realtime Database emulator. @@ -146,7 +146,6 @@ Modify the provided instance to communicate with the Realtime Database emulator. ```typescript export declare function connectDatabaseEmulator(db: Database, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; }): void; ``` @@ -157,7 +156,7 @@ export declare function connectDatabaseEmulator(db: Database, host: string, port | db | [Database](./database.database.md#database_class) | The instance to modify. | | host | string | The emulator host (ex: localhost) | | port | number | The emulator port (ex: 8080) | -| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; ssl?: boolean; } | | +| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; } | | Returns: diff --git a/docs-devsite/firestore_.md b/docs-devsite/firestore_.md index 70cc5221043..91d21e32708 100644 --- a/docs-devsite/firestore_.md +++ b/docs-devsite/firestore_.md @@ -23,7 +23,7 @@ https://github.com/firebase/firebase-js-sdk | [clearIndexedDbPersistence(firestore)](./firestore_.md#clearindexeddbpersistence_231a8e0) | Clears the persistent storage. This includes pending writes and cached documents.Must be called while the [Firestore](./firestore_.firestore.md#firestore_class) instance is not started (after the app is terminated or when the app is first initialized). On startup, this function must be called before other functions (other than [initializeFirestore()](./firestore_.md#initializefirestore_fc7d200) or [getFirestore()](./firestore_.md#getfirestore))). If the [Firestore](./firestore_.firestore.md#firestore_class) instance is still running, the promise will be rejected with the error code of failed-precondition.Note: clearIndexedDbPersistence() is primarily intended to help write reliable tests that use Cloud Firestore. It uses an efficient mechanism for dropping existing data but does not attempt to securely overwrite or otherwise make cached data unrecoverable. For applications that are sensitive to the disclosure of cached data in between user sessions, we strongly recommend not enabling persistence at all. | | [collection(firestore, path, pathSegments)](./firestore_.md#collection_1eb4c23) | Gets a CollectionReference instance that refers to the collection at the specified absolute path. | | [collectionGroup(firestore, collectionId)](./firestore_.md#collectiongroup_1838fc3) | Creates and returns a new Query instance that includes all documents in the database that are contained in a collection or subcollection with the given collectionId. | -| [connectFirestoreEmulator(firestore, host, port, options)](./firestore_.md#connectfirestoreemulator_6c8868a) | Modify this instance to communicate with the Cloud Firestore emulator.Note: This must be called before this instance has been used to do any operations. | +| [connectFirestoreEmulator(firestore, host, port, options)](./firestore_.md#connectfirestoreemulator_7c247cd) | Modify this instance to communicate with the Cloud Firestore emulator.Note: This must be called before this instance has been used to do any operations. | | [disableNetwork(firestore)](./firestore_.md#disablenetwork_231a8e0) | Disables network usage for this instance. It can be re-enabled via [enableNetwork()](./firestore_.md#enablenetwork_231a8e0). While the network is disabled, any snapshot listeners, getDoc() or getDocs() calls will return results from cache, and any write operations will be queued until the network is restored. | | [doc(firestore, path, pathSegments)](./firestore_.md#doc_1eb4c23) | Gets a DocumentReference instance that refers to the document at the specified absolute path. | | [enableIndexedDbPersistence(firestore, persistenceSettings)](./firestore_.md#enableindexeddbpersistence_224174f) | Attempts to enable persistent storage, if possible.On failure, enableIndexedDbPersistence() will reject the promise or throw an exception. There are several reasons why this can fail, which can be identified by the code on the error.\* failed-precondition: The app is already open in another browser tab. \* unimplemented: The browser is incompatible with the offline persistence implementation.Note that even after a failure, the [Firestore](./firestore_.firestore.md#firestore_class) instance will remain usable, however offline persistence will be disabled.Note: enableIndexedDbPersistence() must be called before any other functions (other than [initializeFirestore()](./firestore_.md#initializefirestore_fc7d200), [getFirestore()](./firestore_.md#getfirestore) or [clearIndexedDbPersistence()](./firestore_.md#clearindexeddbpersistence_231a8e0).Persistence cannot be used in a Node.js environment. | @@ -377,7 +377,7 @@ export declare function collectionGroup(firestore: Firestore, collectionId: stri The created `Query`. -### connectFirestoreEmulator(firestore, host, port, options) {:#connectfirestoreemulator_6c8868a} +### connectFirestoreEmulator(firestore, host, port, options) {:#connectfirestoreemulator_7c247cd} Modify this instance to communicate with the Cloud Firestore emulator. @@ -388,7 +388,6 @@ Note: This must be called before this instance has been used to do any operation ```typescript export declare function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; }): void; ``` @@ -399,7 +398,7 @@ export declare function connectFirestoreEmulator(firestore: Firestore, host: str | firestore | [Firestore](./firestore_.firestore.md#firestore_class) | The Firestore instance to configure to connect to the emulator. | | host | string | the emulator host (ex: localhost). | | port | number | the emulator port (ex: 9000). | -| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; ssl?: boolean; } | | +| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; } | | Returns: diff --git a/docs-devsite/firestore_lite.md b/docs-devsite/firestore_lite.md index fe18f38bf47..20fafd66c59 100644 --- a/docs-devsite/firestore_lite.md +++ b/docs-devsite/firestore_lite.md @@ -23,7 +23,7 @@ https://github.com/firebase/firebase-js-sdk | function(firestore, ...) | | [collection(firestore, path, pathSegments)](./firestore_lite.md#collection_1eb4c23) | Gets a CollectionReference instance that refers to the collection at the specified absolute path. | | [collectionGroup(firestore, collectionId)](./firestore_lite.md#collectiongroup_1838fc3) | Creates and returns a new Query instance that includes all documents in the database that are contained in a collection or subcollection with the given collectionId. | -| [connectFirestoreEmulator(firestore, host, port, options)](./firestore_lite.md#connectfirestoreemulator_6c8868a) | Modify this instance to communicate with the Cloud Firestore emulator.Note: This must be called before this instance has been used to do any operations. | +| [connectFirestoreEmulator(firestore, host, port, options)](./firestore_lite.md#connectfirestoreemulator_7c247cd) | Modify this instance to communicate with the Cloud Firestore emulator.Note: This must be called before this instance has been used to do any operations. | | [doc(firestore, path, pathSegments)](./firestore_lite.md#doc_1eb4c23) | Gets a DocumentReference instance that refers to the document at the specified absolute path. | | [runTransaction(firestore, updateFunction, options)](./firestore_lite.md#runtransaction_6f03ec4) | Executes the given updateFunction and then attempts to commit the changes applied within the transaction. If any document read within the transaction has changed, Cloud Firestore retries the updateFunction. If it fails to commit after 5 attempts, the transaction fails.The maximum number of writes allowed in a single transaction is 500. | | [terminate(firestore)](./firestore_lite.md#terminate_231a8e0) | Terminates the provided Firestore instance.After calling terminate() only the clearIndexedDbPersistence() functions may be used. Any other function will throw a FirestoreError. Termination does not cancel any pending writes, and any promises that are awaiting a response from the server will not be resolved.To restart after termination, create a new instance of Firestore with [getFirestore()](./firestore_.md#getfirestore).Note: Under normal circumstances, calling terminate() is not required. This function is useful only when you want to force this instance to release all of its resources or in combination with [clearIndexedDbPersistence()](./firestore_.md#clearindexeddbpersistence_231a8e0) to ensure that all local state is destroyed between test runs. | @@ -308,7 +308,7 @@ export declare function collectionGroup(firestore: Firestore, collectionId: stri The created `Query`. -### connectFirestoreEmulator(firestore, host, port, options) {:#connectfirestoreemulator_6c8868a} +### connectFirestoreEmulator(firestore, host, port, options) {:#connectfirestoreemulator_7c247cd} Modify this instance to communicate with the Cloud Firestore emulator. @@ -319,7 +319,6 @@ Note: This must be called before this instance has been used to do any operation ```typescript export declare function connectFirestoreEmulator(firestore: Firestore, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; }): void; ``` @@ -330,7 +329,7 @@ export declare function connectFirestoreEmulator(firestore: Firestore, host: str | firestore | [Firestore](./firestore_lite.firestore.md#firestore_class) | The Firestore instance to configure to connect to the emulator. | | host | string | the emulator host (ex: localhost). | | port | number | the emulator port (ex: 9000). | -| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; ssl?: boolean; } | | +| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; } | | Returns: diff --git a/docs-devsite/functions.md b/docs-devsite/functions.md index b44bd5ec3cb..7e2eefa1569 100644 --- a/docs-devsite/functions.md +++ b/docs-devsite/functions.md @@ -19,7 +19,7 @@ Cloud Functions for Firebase | function(app, ...) | | [getFunctions(app, regionOrCustomDomain)](./functions.md#getfunctions_60f2095) | Returns a [Functions](./functions.functions.md#functions_interface) instance for the given app. | | function(functionsInstance, ...) | -| [connectFunctionsEmulator(functionsInstance, host, port, ssl)](./functions.md#connectfunctionsemulator_a989598) | Modify this instance to communicate with the Cloud Functions emulator.Note: this must be called before this instance has been used to do any operations. | +| [connectFunctionsEmulator(functionsInstance, host, port)](./functions.md#connectfunctionsemulator_505c08d) | Modify this instance to communicate with the Cloud Functions emulator.Note: this must be called before this instance has been used to do any operations. | | [httpsCallable(functionsInstance, name, options)](./functions.md#httpscallable_1dd297c) | Returns a reference to the callable HTTPS trigger with the given name. | | [httpsCallableFromURL(functionsInstance, url, options)](./functions.md#httpscallablefromurl_7af6987) | Returns a reference to the callable HTTPS trigger with the specified url. | @@ -72,7 +72,7 @@ export declare function getFunctions(app?: FirebaseApp, regionOrCustomDomain?: s ## function(functionsInstance, ...) -### connectFunctionsEmulator(functionsInstance, host, port, ssl) {:#connectfunctionsemulator_a989598} +### connectFunctionsEmulator(functionsInstance, host, port) {:#connectfunctionsemulator_505c08d} Modify this instance to communicate with the Cloud Functions emulator. @@ -81,7 +81,7 @@ Note: this must be called before this instance has been used to do any operation Signature: ```typescript -export declare function connectFunctionsEmulator(functionsInstance: Functions, host: string, port: number, ssl?: boolean): void; +export declare function connectFunctionsEmulator(functionsInstance: Functions, host: string, port: number): void; ``` #### Parameters @@ -91,7 +91,6 @@ export declare function connectFunctionsEmulator(functionsInstance: Functions, h | functionsInstance | [Functions](./functions.functions.md#functions_interface) | | | host | string | The emulator host (ex: localhost) | | port | number | The emulator port (ex: 5001) | -| ssl | boolean | | Returns: diff --git a/docs-devsite/storage.md b/docs-devsite/storage.md index 3cfaa98407e..da72929ebc9 100644 --- a/docs-devsite/storage.md +++ b/docs-devsite/storage.md @@ -19,7 +19,7 @@ Cloud Storage for Firebase | function(app, ...) | | [getStorage(app, bucketUrl)](./storage.md#getstorage_25f3a57) | Gets a [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) instance for the given Firebase app. | | function(storage, ...) | -| [connectStorageEmulator(storage, host, port, options)](./storage.md#connectstorageemulator_ac343b7) | Modify this [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) instance to communicate with the Cloud Storage emulator. | +| [connectStorageEmulator(storage, host, port, options)](./storage.md#connectstorageemulator_e9039de) | Modify this [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) instance to communicate with the Cloud Storage emulator. | | [ref(storage, url)](./storage.md#ref_5672fc1) | Returns a [StorageReference](./storage.storagereference.md#storagereference_interface) for the given url. | | function(ref, ...) | | [deleteObject(ref)](./storage.md#deleteobject_30df0b2) | Deletes the object at this location. | @@ -106,7 +106,7 @@ A [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) inst ## function(storage, ...) -### connectStorageEmulator(storage, host, port, options) {:#connectstorageemulator_ac343b7} +### connectStorageEmulator(storage, host, port, options) {:#connectstorageemulator_e9039de} Modify this [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) instance to communicate with the Cloud Storage emulator. @@ -115,7 +115,6 @@ Modify this [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_inter ```typescript export declare function connectStorageEmulator(storage: FirebaseStorage, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; - ssl?: boolean; }): void; ``` @@ -126,7 +125,7 @@ export declare function connectStorageEmulator(storage: FirebaseStorage, host: s | storage | [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) | The [FirebaseStorage](./storage.firebasestorage.md#firebasestorage_interface) instance | | host | string | The emulator host (ex: localhost) | | port | number | The emulator port (ex: 5001) | -| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; ssl?: boolean; } | Emulator options. options.mockUserToken is the mock auth token to use for unit testing Security Rules. | +| options | { mockUserToken?: [EmulatorMockTokenOptions](./util.md#emulatormocktokenoptions) \| string; } | Emulator options. options.mockUserToken is the mock auth token to use for unit testing Security Rules. | Returns: From 25f8be99b496185da926d4a93fb1e5fb30c67584 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 17:12:04 -0700 Subject: [PATCH 24/63] Added return type --- packages/util/src/url.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/util/src/url.ts b/packages/util/src/url.ts index 95606841fd2..4e2559ca173 100644 --- a/packages/util/src/url.ts +++ b/packages/util/src/url.ts @@ -18,6 +18,6 @@ /** * Checks whether host is a cloud workstation or not. */ -export function isCloudWorkstation(host: string) { +export function isCloudWorkstation(host: string): boolean { return host.endsWith('.cloudworkstations.dev'); } From 59ab583abcd5aaefcc0a0810979f53d3d4fdee73 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 17:28:12 -0700 Subject: [PATCH 25/63] Fixed tests --- packages/database-compat/test/database.test.ts | 7 +++++-- packages/database/src/api/Database.ts | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/database-compat/test/database.test.ts b/packages/database-compat/test/database.test.ts index 8d95b03efd3..19e02943c9c 100644 --- a/packages/database-compat/test/database.test.ts +++ b/packages/database-compat/test/database.test.ts @@ -294,9 +294,12 @@ describe('Database Tests', () => { it('uses ssl when useEmulator is called with ssl specified', () => { const db = firebase.database(); - db.useEmulator('localhost', 80, { ssl: true }); + const cloudWorkstation = 'abc.cloudworkstations.dev'; + db.useEmulator(cloudWorkstation, 80); expect((db as any)._delegate._repo.repoInfo_.isUsingEmulator).to.be.true; - expect((db as any)._delegate._repo.repoInfo_.host).to.equal('localhost:80'); + expect((db as any)._delegate._repo.repoInfo_.host).to.equal( + `${cloudWorkstation}:80` + ); expect((db as any)._delegate._repo.repoInfo_.secure).to.be.true; }); diff --git a/packages/database/src/api/Database.ts b/packages/database/src/api/Database.ts index 44931e2ea83..f247fc6288c 100644 --- a/packages/database/src/api/Database.ts +++ b/packages/database/src/api/Database.ts @@ -91,7 +91,7 @@ function repoManagerApplyEmulatorSettings( tokenProvider?: AuthTokenProvider ): void { const portIndex = hostAndPort.lastIndexOf(':'); - const host = hostAndPort.substring(portIndex); + const host = hostAndPort.substring(0, portIndex); const useSsl = isCloudWorkstation(host); repo.repoInfo_ = new RepoInfo( hostAndPort, From d473c4552838b837aea80fa2963536dbd8348a78 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 17:29:02 -0700 Subject: [PATCH 26/63] Removed changeset --- .changeset/gentle-laws-kneel.md | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .changeset/gentle-laws-kneel.md diff --git a/.changeset/gentle-laws-kneel.md b/.changeset/gentle-laws-kneel.md deleted file mode 100644 index b90115f77c5..00000000000 --- a/.changeset/gentle-laws-kneel.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -"@firebase/database-compat": patch -"@firebase/database-types": patch -"@firebase/database": patch -"@firebase/firestore": patch -"@firebase/functions": patch -"@firebase/storage": patch ---- - -Add SSL checks to `connectDatabaseEmulator` and `connectFirestoreEmulator` From 43b4d6d7a29daa9468094ea7eb2449f646e9160d Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 17:29:23 -0700 Subject: [PATCH 27/63] Create nice-plants-thank.md --- .changeset/nice-plants-thank.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/nice-plants-thank.md diff --git a/.changeset/nice-plants-thank.md b/.changeset/nice-plants-thank.md new file mode 100644 index 00000000000..05fb520760f --- /dev/null +++ b/.changeset/nice-plants-thank.md @@ -0,0 +1,10 @@ +--- +"@firebase/database-compat": patch +"@firebase/database": patch +"@firebase/firestore": patch +"@firebase/functions": patch +"@firebase/storage": patch +"@firebase/util": patch +--- + +Auto Enable SSL for Firebase Studio From 5538911449f394a1918f867fa9bc2dff2d2c18ca Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 09:48:35 -0700 Subject: [PATCH 28/63] Fixed test --- packages/storage/test/unit/service.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/storage/test/unit/service.test.ts b/packages/storage/test/unit/service.test.ts index 9984482177d..bc443c60a03 100644 --- a/packages/storage/test/unit/service.test.ts +++ b/packages/storage/test/unit/service.test.ts @@ -252,7 +252,7 @@ GOOG4-RSA-SHA256` function newSend(connection: TestingConnection, url: string): void { // Expect emulator host to be in url of storage operations requests, // in this case getDownloadURL. - expect(url).to.match(/^https:\/\/test\.host\.org:1234.+/); + expect(url).to.match(/^https:\/\/test\.cloudworkstations\.dev:1234.+/); connection.abort(); injectTestConnection(null); done(); @@ -264,7 +264,7 @@ GOOG4-RSA-SHA256` testShared.fakeAuthProvider, testShared.fakeAppCheckTokenProvider ); - const workstationHost = 'test.cloudworkations.dev'; + const workstationHost = 'test.cloudworkstations.dev'; connectStorageEmulator(service, workstationHost, 1234); expect(service.host).to.equal(`${workstationHost}:1234`); expect(service._protocol).to.equal('https'); From 0b807f93e3608483bfc41818a7a8437d25ab295c Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 10:12:33 -0700 Subject: [PATCH 29/63] Fixed firestore test --- packages/firestore/test/unit/api/database.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firestore/test/unit/api/database.test.ts b/packages/firestore/test/unit/api/database.test.ts index 7b0fee09a7f..46e4c65f180 100644 --- a/packages/firestore/test/unit/api/database.test.ts +++ b/packages/firestore/test/unit/api/database.test.ts @@ -568,7 +568,7 @@ describe('Settings', () => { // Use a new instance of Firestore in order to configure settings. const db = newTestFirestore(); const emulatorOptions = { mockUserToken: 'test' }; - const workstationHost = 'abc.workstations.dev'; + const workstationHost = 'abc.cloudworkstations.dev'; connectFirestoreEmulator(db, workstationHost, 9000, emulatorOptions); expect(db._getSettings().host).to.exist.and.to.equal( From e6f82632471b4d96f3b58b1708314c51f1bebf38 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 10:17:13 -0700 Subject: [PATCH 30/63] Added public tag to --- common/api-review/util.api.md | 2 -- packages/util/src/url.ts | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/common/api-review/util.api.md b/common/api-review/util.api.md index 25abe9d450b..28cc9a160d4 100644 --- a/common/api-review/util.api.md +++ b/common/api-review/util.api.md @@ -269,8 +269,6 @@ export function isBrowserExtension(): boolean; // @public export function isCloudflareWorker(): boolean; -// Warning: (ae-missing-release-tag) "isCloudWorkstation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function isCloudWorkstation(host: string): boolean; diff --git a/packages/util/src/url.ts b/packages/util/src/url.ts index 4e2559ca173..33cec43bea9 100644 --- a/packages/util/src/url.ts +++ b/packages/util/src/url.ts @@ -17,6 +17,7 @@ /** * Checks whether host is a cloud workstation or not. + * @public */ export function isCloudWorkstation(host: string): boolean { return host.endsWith('.cloudworkstations.dev'); From 8749b8334e5580244831e30c14861de8afe2b7c3 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 11:15:42 -0700 Subject: [PATCH 31/63] Added code to pass on credentials if using a cloud workstation --- packages/app-check/src/client.ts | 4 +++ packages/auth/src/api/index.ts | 12 +++++++- packages/data-connect/src/network/fetch.ts | 13 +++++--- .../platform/browser/webchannel_connection.ts | 1 + .../platform/browser_lite/fetch_connection.ts | 9 ++++-- .../storage/src/platform/node/connection.ts | 30 ++++++++++++------- 6 files changed, 52 insertions(+), 17 deletions(-) diff --git a/packages/app-check/src/client.ts b/packages/app-check/src/client.ts index 1861383174d..e8223675ae3 100644 --- a/packages/app-check/src/client.ts +++ b/packages/app-check/src/client.ts @@ -25,6 +25,7 @@ import { FirebaseApp } from '@firebase/app'; import { ERROR_FACTORY, AppCheckError } from './errors'; import { Provider } from '@firebase/component'; import { AppCheckTokenInternal } from './types'; +import { isCloudWorkstation } from '@firebase/util'; /** * Response JSON returned from AppCheck server endpoint. @@ -62,6 +63,9 @@ export async function exchangeToken( body: JSON.stringify(body), headers }; + if (isCloudWorkstation(url)) { + options.credentials = 'include'; + } let response; try { response = await fetch(url, options); diff --git a/packages/auth/src/api/index.ts b/packages/auth/src/api/index.ts index 769a1b6accc..682a37f2303 100644 --- a/packages/auth/src/api/index.ts +++ b/packages/auth/src/api/index.ts @@ -15,7 +15,12 @@ * limitations under the License. */ -import { FirebaseError, isCloudflareWorker, querystring } from '@firebase/util'; +import { + FirebaseError, + isCloudflareWorker, + isCloudWorkstation, + querystring +} from '@firebase/util'; import { AuthErrorCode, NamedErrorParams } from '../core/errors'; import { @@ -33,6 +38,7 @@ import { IdTokenMfaResponse } from './authentication/mfa'; import { SERVER_ERROR_MAP, ServerError, ServerErrorMap } from './errors'; import { PersistenceType } from '../core/persistence'; import { CookiePersistence } from '../platform_browser/persistence/cookie_storage'; +import { FirebaseAuth } from '@firebase/auth-types'; export const enum HttpMethod { POST = 'POST', @@ -177,6 +183,10 @@ export async function _performApiRequest( fetchArgs.referrerPolicy = 'no-referrer'; } + if (auth.emulatorConfig && isCloudWorkstation(auth.emulatorConfig.host)) { + fetchArgs.credentials = 'include'; + } + return FetchProvider.fetch()( await _getFinalTarget(auth, auth.config.apiHost, path, query), fetchArgs diff --git a/packages/data-connect/src/network/fetch.ts b/packages/data-connect/src/network/fetch.ts index 8353c6b99ab..2488287b611 100644 --- a/packages/data-connect/src/network/fetch.ts +++ b/packages/data-connect/src/network/fetch.ts @@ -25,6 +25,7 @@ import { SDK_VERSION } from '../core/version'; import { logDebug, logError } from '../logger'; import { CallerSdkType, CallerSdkTypeEnum } from './transport'; +import { isCloudWorkstation } from '@firebase/util'; let connectFetch: typeof fetch | null = globalThis.fetch; export function initializeFetch(fetchImpl: typeof fetch): void { @@ -77,14 +78,18 @@ export function dcFetch( headers['X-Firebase-AppCheck'] = appCheckToken; } const bodyStr = JSON.stringify(body); - logDebug(`Making request out to ${url} with body: ${bodyStr}`); - - return connectFetch(url, { + const fetchOptions: RequestInit = { body: bodyStr, method: 'POST', headers, signal - }) + }; + if (isCloudWorkstation(url)) { + fetchOptions.credentials = 'include'; + } + logDebug(`Making request out to ${url} with body: ${bodyStr}`); + + return connectFetch(url, fetchOptions) .catch(err => { throw new DataConnectError( Code.OTHER, diff --git a/packages/firestore/src/platform/browser/webchannel_connection.ts b/packages/firestore/src/platform/browser/webchannel_connection.ts index 5223285c5a4..b5224eac117 100644 --- a/packages/firestore/src/platform/browser/webchannel_connection.ts +++ b/packages/firestore/src/platform/browser/webchannel_connection.ts @@ -46,6 +46,7 @@ import { Code, FirestoreError } from '../../util/error'; import { logDebug, logWarn } from '../../util/log'; import { Rejecter, Resolver } from '../../util/promise'; import { StringMap } from '../../util/types'; +import { isCloudWorkstation } from '@firebase/util'; const LOG_TAG = 'WebChannelConnection'; diff --git a/packages/firestore/src/platform/browser_lite/fetch_connection.ts b/packages/firestore/src/platform/browser_lite/fetch_connection.ts index d11247c8019..f3b2b9dbb21 100644 --- a/packages/firestore/src/platform/browser_lite/fetch_connection.ts +++ b/packages/firestore/src/platform/browser_lite/fetch_connection.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { isCloudWorkstation } from '@firebase/util'; import { Token } from '../../api/credentials'; import { Stream } from '../../remote/connection'; import { RestConnection } from '../../remote/rest_connection'; @@ -44,11 +45,15 @@ export class FetchConnection extends RestConnection { let response: Response; try { - response = await fetch(url, { + const fetchArgs: RequestInit = { method: 'POST', headers, body: requestJson - }); + }; + if (isCloudWorkstation(url)) { + fetchArgs.credentials = 'include'; + } + response = await fetch(url, fetchArgs); } catch (e) { const err = e as { status: number | undefined; statusText: string }; throw new FirestoreError( diff --git a/packages/storage/src/platform/node/connection.ts b/packages/storage/src/platform/node/connection.ts index c90f664c3b2..00371ff2bc5 100644 --- a/packages/storage/src/platform/node/connection.ts +++ b/packages/storage/src/platform/node/connection.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { isCloudWorkstation } from '@firebase/util'; import { Connection, ConnectionType, @@ -57,11 +58,7 @@ abstract class FetchConnection this.sent_ = true; try { - const response = await fetch(url, { - method, - headers: headers || {}, - body: body as NodeJS.ArrayBufferView | string - }); + const response = await newFetch(url, method, headers, body); this.headers_ = response.headers; this.statusCode_ = response.status; this.errorCode_ = ErrorCode.NO_ERROR; @@ -161,11 +158,7 @@ export class FetchStreamConnection extends FetchConnection< this.sent_ = true; try { - const response = await fetch(url, { - method, - headers: headers || {}, - body: body as NodeJS.ArrayBufferView | string - }); + const response = await newFetch(url, method, headers, body); this.headers_ = response.headers; this.statusCode_ = response.status; this.errorCode_ = ErrorCode.NO_ERROR; @@ -186,6 +179,23 @@ export class FetchStreamConnection extends FetchConnection< } } +function newFetch( + url: string, + method: string, + headers?: Record, + body?: NodeJS.ArrayBufferView | Blob | string +) { + const fetchArgs: RequestInit = { + method, + headers: headers || {}, + body: body as NodeJS.ArrayBufferView | string + }; + if (isCloudWorkstation(url)) { + fetchArgs.credentials = 'include'; + } + return fetch(url, fetchArgs); +} + export function newStreamConnection(): Connection> { return new FetchStreamConnection(); } From 5ae4e9ef80c09401c7c4a957c9033646234be630 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Thu, 24 Apr 2025 09:29:35 -0700 Subject: [PATCH 32/63] Addressed comments --- packages/data-connect/src/network/fetch.ts | 6 +++--- packages/data-connect/src/network/transport/rest.ts | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/data-connect/src/network/fetch.ts b/packages/data-connect/src/network/fetch.ts index 2488287b611..cc71844cac1 100644 --- a/packages/data-connect/src/network/fetch.ts +++ b/packages/data-connect/src/network/fetch.ts @@ -59,7 +59,8 @@ export function dcFetch( accessToken: string | null, appCheckToken: string | null, _isUsingGen: boolean, - _callerSdkType: CallerSdkType + _callerSdkType: CallerSdkType, + _isUsingEmulator: boolean ): Promise<{ data: T; errors: Error[] }> { if (!connectFetch) { throw new DataConnectError(Code.OTHER, 'No Fetch Implementation detected!'); @@ -84,10 +85,9 @@ export function dcFetch( headers, signal }; - if (isCloudWorkstation(url)) { + if (isCloudWorkstation(url) && _isUsingEmulator) { fetchOptions.credentials = 'include'; } - logDebug(`Making request out to ${url} with body: ${bodyStr}`); return connectFetch(url, fetchOptions) .catch(err => { diff --git a/packages/data-connect/src/network/transport/rest.ts b/packages/data-connect/src/network/transport/rest.ts index 0663bc026db..f16154dcb2a 100644 --- a/packages/data-connect/src/network/transport/rest.ts +++ b/packages/data-connect/src/network/transport/rest.ts @@ -36,6 +36,7 @@ export class RESTTransport implements DataConnectTransport { private _accessToken: string | null = null; private _appCheckToken: string | null = null; private _lastToken: string | null = null; + private _isUsingEmulator = false; constructor( options: DataConnectOptions, private apiKey?: string | undefined, @@ -93,6 +94,7 @@ export class RESTTransport implements DataConnectTransport { } useEmulator(host: string, port?: number, isSecure?: boolean): void { this._host = host; + this._isUsingEmulator = true; if (typeof port === 'number') { this._port = port; } @@ -182,7 +184,8 @@ export class RESTTransport implements DataConnectTransport { this._accessToken, this._appCheckToken, this._isUsingGen, - this._callerSdkType + this._callerSdkType, + this._isUsingEmulator ) ); return withAuth; @@ -208,7 +211,8 @@ export class RESTTransport implements DataConnectTransport { this._accessToken, this._appCheckToken, this._isUsingGen, - this._callerSdkType + this._callerSdkType, + this._isUsingEmulator ); }); return taskResult; From 9e408acd80c4f9ad4ebcd321d27926dc87ab3676 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 23 Apr 2025 15:42:43 -0700 Subject: [PATCH 33/63] Create nine-pugs-crash.md --- .changeset/nine-pugs-crash.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .changeset/nine-pugs-crash.md diff --git a/.changeset/nine-pugs-crash.md b/.changeset/nine-pugs-crash.md new file mode 100644 index 00000000000..c3542b35d54 --- /dev/null +++ b/.changeset/nine-pugs-crash.md @@ -0,0 +1,12 @@ +--- +"@firebase/app-check": patch +"@firebase/auth": patch +"@firebase/data-connect": patch +"@firebase/database-compat": patch +"@firebase/database": patch +"@firebase/firestore": patch +"@firebase/storage": patch +"@firebase/util": patch +--- + +Fix Auth Redirects on Firebase Studio From 83da6b19f783439473993761a4507ad0795b7209 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Thu, 24 Apr 2025 09:32:50 -0700 Subject: [PATCH 34/63] Removed unused import --- packages/auth/src/api/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/auth/src/api/index.ts b/packages/auth/src/api/index.ts index 682a37f2303..af9b3c63bf1 100644 --- a/packages/auth/src/api/index.ts +++ b/packages/auth/src/api/index.ts @@ -38,7 +38,6 @@ import { IdTokenMfaResponse } from './authentication/mfa'; import { SERVER_ERROR_MAP, ServerError, ServerErrorMap } from './errors'; import { PersistenceType } from '../core/persistence'; import { CookiePersistence } from '../platform_browser/persistence/cookie_storage'; -import { FirebaseAuth } from '@firebase/auth-types'; export const enum HttpMethod { POST = 'POST', From a8df49c4432b6b5354ca862bca7f710b68f79980 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Thu, 24 Apr 2025 15:45:33 -0700 Subject: [PATCH 35/63] include storage changes --- .../storage/src/implementation/connection.ts | 3 ++- packages/storage/src/implementation/request.ts | 17 +++++++++++++---- .../storage/src/platform/browser/connection.ts | 7 ++++++- .../storage/src/platform/node/connection.ts | 18 +++++++++++++----- packages/storage/src/service.ts | 6 ++++-- 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/packages/storage/src/implementation/connection.ts b/packages/storage/src/implementation/connection.ts index 80e29c9cd2f..ec65ace3c00 100644 --- a/packages/storage/src/implementation/connection.ts +++ b/packages/storage/src/implementation/connection.ts @@ -43,7 +43,8 @@ export interface Connection { url: string, method: string, body?: ArrayBufferView | Blob | string | null, - headers?: Headers + headers?: Headers, + isUsingEmulator?: boolean ): Promise; getErrorCode(): ErrorCode; diff --git a/packages/storage/src/implementation/request.ts b/packages/storage/src/implementation/request.ts index fae46d7a5ab..7433cd53955 100644 --- a/packages/storage/src/implementation/request.ts +++ b/packages/storage/src/implementation/request.ts @@ -71,7 +71,8 @@ class NetworkRequest implements Request { private timeout_: number, private progressCallback_: ((p1: number, p2: number) => void) | null, private connectionFactory_: () => Connection, - private retry = true + private retry = true, + private isUsingEmulator = false ) { this.promise_ = new Promise((resolve, reject) => { this.resolve_ = resolve as (value?: O | PromiseLike) => void; @@ -111,7 +112,13 @@ class NetworkRequest implements Request { // connection.send() never rejects, so we don't need to have a error handler or use catch on the returned promise. // eslint-disable-next-line @typescript-eslint/no-floating-promises connection - .send(this.url_, this.method_, this.body_, this.headers_) + .send( + this.url_, + this.method_, + this.body_, + this.headers_, + this.isUsingEmulator + ) .then(() => { if (this.progressCallback_ !== null) { connection.removeUploadProgressListener(progressListener); @@ -261,7 +268,8 @@ export function makeRequest( appCheckToken: string | null, requestFactory: () => Connection, firebaseVersion?: string, - retry = true + retry = true, + isUsingEmulator = false ): Request { const queryPart = makeQueryString(requestInfo.urlParams); const url = requestInfo.url + queryPart; @@ -282,6 +290,7 @@ export function makeRequest( requestInfo.timeout, requestInfo.progressCallback, requestFactory, - retry + retry, + isUsingEmulator ); } diff --git a/packages/storage/src/platform/browser/connection.ts b/packages/storage/src/platform/browser/connection.ts index fdd9b496242..fcbd5db0c2a 100644 --- a/packages/storage/src/platform/browser/connection.ts +++ b/packages/storage/src/platform/browser/connection.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { isCloudWorkstation } from '@firebase/util'; import { Connection, ConnectionType, @@ -63,11 +64,15 @@ abstract class XhrConnection url: string, method: string, body?: ArrayBufferView | Blob | string, - headers?: Headers + headers?: Headers, + isUsingEmulator?: boolean ): Promise { if (this.sent_) { throw internalError('cannot .send() more than once'); } + if (isCloudWorkstation(url) && isUsingEmulator) { + this.xhr_.withCredentials = true; + } this.sent_ = true; this.xhr_.open(method, url, true); if (headers !== undefined) { diff --git a/packages/storage/src/platform/node/connection.ts b/packages/storage/src/platform/node/connection.ts index 00371ff2bc5..e201ce8ffba 100644 --- a/packages/storage/src/platform/node/connection.ts +++ b/packages/storage/src/platform/node/connection.ts @@ -50,7 +50,8 @@ abstract class FetchConnection url: string, method: string, body?: NodeJS.ArrayBufferView | Blob | string, - headers?: Record + headers?: Record, + isUsingEmulator?: boolean ): Promise { if (this.sent_) { throw internalError('cannot .send() more than once'); @@ -58,7 +59,13 @@ abstract class FetchConnection this.sent_ = true; try { - const response = await newFetch(url, method, headers, body); + const response = await newFetch( + url, + method, + headers, + body, + isUsingEmulator + ); this.headers_ = response.headers; this.statusCode_ = response.status; this.errorCode_ = ErrorCode.NO_ERROR; @@ -183,14 +190,15 @@ function newFetch( url: string, method: string, headers?: Record, - body?: NodeJS.ArrayBufferView | Blob | string -) { + body?: NodeJS.ArrayBufferView | Blob | string, + isUsingEmulator?: boolean +): Promise { const fetchArgs: RequestInit = { method, headers: headers || {}, body: body as NodeJS.ArrayBufferView | string }; - if (isCloudWorkstation(url)) { + if (isCloudWorkstation(url) && isUsingEmulator) { fetchArgs.credentials = 'include'; } return fetch(url, fetchArgs); diff --git a/packages/storage/src/service.ts b/packages/storage/src/service.ts index 8a942aac62a..f7b35219849 100644 --- a/packages/storage/src/service.ts +++ b/packages/storage/src/service.ts @@ -192,7 +192,8 @@ export class FirebaseStorageImpl implements FirebaseStorage { * @internal */ readonly _url?: string, - readonly _firebaseVersion?: string + readonly _firebaseVersion?: string, + readonly _isUsingEmulator = false ) { this._maxOperationRetryTime = DEFAULT_MAX_OPERATION_RETRY_TIME; this._maxUploadRetryTime = DEFAULT_MAX_UPLOAD_RETRY_TIME; @@ -325,7 +326,8 @@ export class FirebaseStorageImpl implements FirebaseStorage { appCheckToken, requestFactory, this._firebaseVersion, - retry + retry, + this._isUsingEmulator ); this._requests.add(request); // Request removes itself from set when complete. From 903d3b731baff904142766b245072af3dcd34c8b Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 25 Apr 2025 09:05:35 -0700 Subject: [PATCH 36/63] Removed unnecessary import --- packages/firestore/src/platform/browser/webchannel_connection.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/firestore/src/platform/browser/webchannel_connection.ts b/packages/firestore/src/platform/browser/webchannel_connection.ts index b5224eac117..5223285c5a4 100644 --- a/packages/firestore/src/platform/browser/webchannel_connection.ts +++ b/packages/firestore/src/platform/browser/webchannel_connection.ts @@ -46,7 +46,6 @@ import { Code, FirestoreError } from '../../util/error'; import { logDebug, logWarn } from '../../util/log'; import { Rejecter, Resolver } from '../../util/promise'; import { StringMap } from '../../util/types'; -import { isCloudWorkstation } from '@firebase/util'; const LOG_TAG = 'WebChannelConnection'; From 7291e56b69caa2af31c0ca6927d268e7fc7d3821 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 25 Apr 2025 09:09:52 -0700 Subject: [PATCH 37/63] Fix formatting --- packages/firestore/src/platform/browser_lite/fetch_connection.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/firestore/src/platform/browser_lite/fetch_connection.ts b/packages/firestore/src/platform/browser_lite/fetch_connection.ts index f3b2b9dbb21..690a9435dd5 100644 --- a/packages/firestore/src/platform/browser_lite/fetch_connection.ts +++ b/packages/firestore/src/platform/browser_lite/fetch_connection.ts @@ -16,6 +16,7 @@ */ import { isCloudWorkstation } from '@firebase/util'; + import { Token } from '../../api/credentials'; import { Stream } from '../../remote/connection'; import { RestConnection } from '../../remote/rest_connection'; From 411b72d4ea6488ff7a092f133bd8c87006ab3f19 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 25 Apr 2025 09:17:44 -0700 Subject: [PATCH 38/63] Fixed data connect test --- packages/data-connect/test/unit/fetch.test.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/data-connect/test/unit/fetch.test.ts b/packages/data-connect/test/unit/fetch.test.ts index 6cf2750d50d..11bc8d03818 100644 --- a/packages/data-connect/test/unit/fetch.test.ts +++ b/packages/data-connect/test/unit/fetch.test.ts @@ -57,7 +57,8 @@ describe('fetch', () => { null, null, false, - CallerSdkTypeEnum.Base + CallerSdkTypeEnum.Base, + false ) ).to.eventually.be.rejectedWith(message); }); @@ -81,7 +82,8 @@ describe('fetch', () => { null, null, false, - CallerSdkTypeEnum.Base + CallerSdkTypeEnum.Base, + false ) ).to.eventually.be.rejectedWith(JSON.stringify(json)); }); @@ -112,7 +114,8 @@ describe('fetch', () => { null, null, false, - CallerSdkTypeEnum.Base + CallerSdkTypeEnum.Base, + false ) ).to.eventually.be.rejected.then(error => { expect(error.response.data).to.eq(json.data); @@ -143,7 +146,8 @@ describe('fetch', () => { null, null, false, // _isUsingGen is false - callerSdkType as CallerSdkType + callerSdkType as CallerSdkType, + false ); let expectedHeaderRegex: RegExp; @@ -191,7 +195,8 @@ describe('fetch', () => { null, null, true, // _isUsingGen is true - callerSdkType as CallerSdkType + callerSdkType as CallerSdkType, + false ); let expectedHeaderRegex: RegExp; From 3ce5912634a318c4c139aed80bc591b488d8628e Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 25 Apr 2025 10:57:29 -0700 Subject: [PATCH 39/63] Included extra url in externs --- packages/firestore/externs.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/firestore/externs.json b/packages/firestore/externs.json index d730cfeac0a..c56b078dddf 100644 --- a/packages/firestore/externs.json +++ b/packages/firestore/externs.json @@ -30,6 +30,7 @@ "packages/util/dist/src/defaults.d.ts", "packages/util/dist/src/emulator.d.ts", "packages/util/dist/src/environment.d.ts", + "packages/util/dist/src/url.d.ts", "packages/util/dist/src/compat.d.ts", "packages/util/dist/src/global.d.ts", "packages/util/dist/src/obj.d.ts", From ff41e76394cd09e4d9282b61ec368d6431e08a7c Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 25 Apr 2025 11:29:48 -0700 Subject: [PATCH 40/63] Fixed fdc tests --- packages/data-connect/src/network/fetch.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/data-connect/src/network/fetch.ts b/packages/data-connect/src/network/fetch.ts index cc71844cac1..3e8e2cab476 100644 --- a/packages/data-connect/src/network/fetch.ts +++ b/packages/data-connect/src/network/fetch.ts @@ -15,6 +15,8 @@ * limitations under the License. */ +import { isCloudWorkstation } from '@firebase/util'; + import { Code, DataConnectError, @@ -22,10 +24,9 @@ import { DataConnectOperationFailureResponse } from '../core/error'; import { SDK_VERSION } from '../core/version'; -import { logDebug, logError } from '../logger'; +import { logError } from '../logger'; import { CallerSdkType, CallerSdkTypeEnum } from './transport'; -import { isCloudWorkstation } from '@firebase/util'; let connectFetch: typeof fetch | null = globalThis.fetch; export function initializeFetch(fetchImpl: typeof fetch): void { From c014176f67698eeeacfec0738b24e482756c19ef Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 25 Apr 2025 11:43:41 -0700 Subject: [PATCH 41/63] Passed in emulator information --- packages/firestore/src/core/database_info.ts | 3 ++- packages/firestore/src/lite-api/components.ts | 6 ++++-- .../firestore/src/platform/browser/webchannel_connection.ts | 3 ++- .../firestore/src/platform/browser_lite/fetch_connection.ts | 5 +++-- packages/firestore/src/remote/rest_connection.ts | 5 +++-- .../firestore/test/integration/util/internal_helpers.ts | 3 ++- packages/firestore/test/unit/remote/rest_connection.test.ts | 3 ++- packages/firestore/test/unit/specs/spec_test_runner.ts | 3 ++- 8 files changed, 20 insertions(+), 11 deletions(-) diff --git a/packages/firestore/src/core/database_info.ts b/packages/firestore/src/core/database_info.ts index 0325f8166b6..a057516763f 100644 --- a/packages/firestore/src/core/database_info.ts +++ b/packages/firestore/src/core/database_info.ts @@ -48,7 +48,8 @@ export class DatabaseInfo { readonly forceLongPolling: boolean, readonly autoDetectLongPolling: boolean, readonly longPollingOptions: ExperimentalLongPollingOptions, - readonly useFetchStreams: boolean + readonly useFetchStreams: boolean, + readonly isUsingEmulator: boolean ) {} } diff --git a/packages/firestore/src/lite-api/components.ts b/packages/firestore/src/lite-api/components.ts index 436d2b5d4d8..a51e451dcac 100644 --- a/packages/firestore/src/lite-api/components.ts +++ b/packages/firestore/src/lite-api/components.ts @@ -28,7 +28,7 @@ import { Datastore, newDatastore } from '../remote/datastore'; import { Code, FirestoreError } from '../util/error'; import { logDebug } from '../util/log'; -import { FirestoreSettingsImpl } from './settings'; +import { FirestoreSettingsImpl, PrivateSettings } from './settings'; export const LOG_TAG = 'ComponentProvider'; @@ -110,6 +110,7 @@ export function makeDatabaseInfo( persistenceKey: string, settings: FirestoreSettingsImpl ): DatabaseInfo { + const privateSettings = settings as PrivateSettings; return new DatabaseInfo( databaseId, appId, @@ -119,6 +120,7 @@ export function makeDatabaseInfo( settings.experimentalForceLongPolling, settings.experimentalAutoDetectLongPolling, cloneLongPollingOptions(settings.experimentalLongPollingOptions), - settings.useFetchStreams + settings.useFetchStreams, + privateSettings.emulatorOptions !== undefined ); } diff --git a/packages/firestore/src/platform/browser/webchannel_connection.ts b/packages/firestore/src/platform/browser/webchannel_connection.ts index 5223285c5a4..a2d540b0e85 100644 --- a/packages/firestore/src/platform/browser/webchannel_connection.ts +++ b/packages/firestore/src/platform/browser/webchannel_connection.ts @@ -71,7 +71,8 @@ export class WebChannelConnection extends RestConnection { rpcName: string, url: string, headers: StringMap, - body: Req + body: Req, + _isUsingEmulator: boolean ): Promise { const streamId = generateUniqueDebugId(); return new Promise((resolve: Resolver, reject: Rejecter) => { diff --git a/packages/firestore/src/platform/browser_lite/fetch_connection.ts b/packages/firestore/src/platform/browser_lite/fetch_connection.ts index 690a9435dd5..580c83c99ff 100644 --- a/packages/firestore/src/platform/browser_lite/fetch_connection.ts +++ b/packages/firestore/src/platform/browser_lite/fetch_connection.ts @@ -40,7 +40,8 @@ export class FetchConnection extends RestConnection { rpcName: string, url: string, headers: StringMap, - body: Req + body: Req, + isUsingEmulator: boolean ): Promise { const requestJson = JSON.stringify(body); let response: Response; @@ -51,7 +52,7 @@ export class FetchConnection extends RestConnection { headers, body: requestJson }; - if (isCloudWorkstation(url)) { + if (isCloudWorkstation(url) && isUsingEmulator) { fetchArgs.credentials = 'include'; } response = await fetch(url, fetchArgs); diff --git a/packages/firestore/src/remote/rest_connection.ts b/packages/firestore/src/remote/rest_connection.ts index 470cb332ce2..f80c075a06b 100644 --- a/packages/firestore/src/remote/rest_connection.ts +++ b/packages/firestore/src/remote/rest_connection.ts @@ -98,7 +98,7 @@ export abstract class RestConnection implements Connection { }; this.modifyHeadersForRequest(headers, authToken, appCheckToken); - return this.performRPCRequest(rpcName, url, headers, req).then( + return this.performRPCRequest(rpcName, url, headers, req, this.databaseInfo.isUsingEmulator).then( response => { logDebug(LOG_TAG, `Received RPC '${rpcName}' ${streamId}: `, response); return response; @@ -179,7 +179,8 @@ export abstract class RestConnection implements Connection { rpcName: string, url: string, headers: StringMap, - body: Req + body: Req, + isUsingEmulator: boolean ): Promise; private makeUrl(rpcName: string, path: string): string { diff --git a/packages/firestore/test/integration/util/internal_helpers.ts b/packages/firestore/test/integration/util/internal_helpers.ts index 86ded6af3c1..768b85df816 100644 --- a/packages/firestore/test/integration/util/internal_helpers.ts +++ b/packages/firestore/test/integration/util/internal_helpers.ts @@ -61,7 +61,8 @@ export function getDefaultDatabaseInfo(): DatabaseInfo { cloneLongPollingOptions( DEFAULT_SETTINGS.experimentalLongPollingOptions ?? {} ), - /*use FetchStreams= */ false + /*use FetchStreams= */ false, + /*isUsingEmulator=*/false ); } diff --git a/packages/firestore/test/unit/remote/rest_connection.test.ts b/packages/firestore/test/unit/remote/rest_connection.test.ts index d45a75ce67b..100b8b8368e 100644 --- a/packages/firestore/test/unit/remote/rest_connection.test.ts +++ b/packages/firestore/test/unit/remote/rest_connection.test.ts @@ -67,7 +67,8 @@ describe('RestConnection', () => { /*forceLongPolling=*/ false, /*autoDetectLongPolling=*/ false, /*longPollingOptions=*/ {}, - /*useFetchStreams=*/ false + /*useFetchStreams=*/ false, + /*isUsingEmulator=*/ false ); const connection = new TestRestConnection(testDatabaseInfo); diff --git a/packages/firestore/test/unit/specs/spec_test_runner.ts b/packages/firestore/test/unit/specs/spec_test_runner.ts index ee0af0b8bf8..51d2229b8a1 100644 --- a/packages/firestore/test/unit/specs/spec_test_runner.ts +++ b/packages/firestore/test/unit/specs/spec_test_runner.ts @@ -282,7 +282,8 @@ abstract class TestRunner { /*forceLongPolling=*/ false, /*autoDetectLongPolling=*/ false, /*longPollingOptions=*/ {}, - /*useFetchStreams=*/ false + /*useFetchStreams=*/ false, + /*isUsingEmulator=*/ false ); // TODO(mrschmidt): During client startup in `firestore_client`, we block From a57e5e995d4815c72b1239e8552d604ab8cf1a67 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 25 Apr 2025 11:47:14 -0700 Subject: [PATCH 42/63] Fixed formattign --- packages/firestore/src/remote/rest_connection.ts | 8 +++++++- .../firestore/test/integration/util/internal_helpers.ts | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/firestore/src/remote/rest_connection.ts b/packages/firestore/src/remote/rest_connection.ts index f80c075a06b..60d4af5c1af 100644 --- a/packages/firestore/src/remote/rest_connection.ts +++ b/packages/firestore/src/remote/rest_connection.ts @@ -98,7 +98,13 @@ export abstract class RestConnection implements Connection { }; this.modifyHeadersForRequest(headers, authToken, appCheckToken); - return this.performRPCRequest(rpcName, url, headers, req, this.databaseInfo.isUsingEmulator).then( + return this.performRPCRequest( + rpcName, + url, + headers, + req, + this.databaseInfo.isUsingEmulator + ).then( response => { logDebug(LOG_TAG, `Received RPC '${rpcName}' ${streamId}: `, response); return response; diff --git a/packages/firestore/test/integration/util/internal_helpers.ts b/packages/firestore/test/integration/util/internal_helpers.ts index 768b85df816..e5e64b5fbf4 100644 --- a/packages/firestore/test/integration/util/internal_helpers.ts +++ b/packages/firestore/test/integration/util/internal_helpers.ts @@ -62,7 +62,7 @@ export function getDefaultDatabaseInfo(): DatabaseInfo { DEFAULT_SETTINGS.experimentalLongPollingOptions ?? {} ), /*use FetchStreams= */ false, - /*isUsingEmulator=*/false + /*isUsingEmulator=*/ false ); } From f5930ab84935b4f3a1b8fa73a4c2fbdca897229f Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 25 Apr 2025 13:40:30 -0700 Subject: [PATCH 43/63] WIP --- config/.eslintrc.js | 16 +++++----- packages/auth/src/core/auth/emulator.test.ts | 32 ++++++++++++++++++- packages/auth/src/core/util/fetch_provider.ts | 1 + 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/config/.eslintrc.js b/config/.eslintrc.js index 57243a3e2a4..589dbf4cccd 100644 --- a/config/.eslintrc.js +++ b/config/.eslintrc.js @@ -98,18 +98,18 @@ module.exports = { 'object': 'it', 'property': 'skip' }, - { - 'object': 'it', - 'property': 'only' - }, + // { + // 'object': 'it', + // 'property': 'only' + // }, { 'object': 'describe', 'property': 'skip' }, - { - 'object': 'describe', - 'property': 'only' - }, + // { + // 'object': 'describe', + // 'property': 'only' + // }, { 'object': 'xit' } diff --git a/packages/auth/src/core/auth/emulator.test.ts b/packages/auth/src/core/auth/emulator.test.ts index 47c5d927c44..35f82249ab2 100644 --- a/packages/auth/src/core/auth/emulator.test.ts +++ b/packages/auth/src/core/auth/emulator.test.ts @@ -29,18 +29,21 @@ import { Endpoint } from '../../api'; import { UserInternal } from '../../model/user'; import { _castAuth } from './auth_impl'; import { connectAuthEmulator } from './emulator'; +import { FetchProvider } from '../util/fetch_provider'; use(sinonChai); use(chaiAsPromised); -describe('core/auth/emulator', () => { +describe.only('core/auth/emulator', () => { let auth: TestAuth; let user: UserInternal; let normalEndpoint: fetch.Route; let emulatorEndpoint: fetch.Route; + let spy: sinon.SinonSpy; beforeEach(async () => { auth = await testAuth(); + spy = sinon.spy(FetchProvider.fetch()); user = testUser(_castAuth(auth), 'uid', 'email', true); fetch.setUp(); normalEndpoint = mockEndpoint(Endpoint.DELETE_ACCOUNT, {}); @@ -93,6 +96,16 @@ describe('core/auth/emulator', () => { 'auth/emulator-config-failed' ); }); + it.only('sends the proper value', async () => { + expect(() => connectAuthEmulator(auth, 'http://127.0.0.1:2020')).to.not + .throw; + await user.delete(); + expect(spy).to.have.been.called; + expect(() => connectAuthEmulator(auth, 'http://127.0.0.1:2021')).to.throw( + FirebaseError, + 'auth/emulator-config-failed' + ); + }); it('subsequent calls update the endpoint appropriately', async () => { connectAuthEmulator(auth, 'http://127.0.0.1:2021'); @@ -111,6 +124,23 @@ describe('core/auth/emulator', () => { }); }); + it('subsequent calls update the endpoint appropriately', async () => { + connectAuthEmulator(auth, 'http://127.0.0.1:2021'); + expect(auth.emulatorConfig).to.eql({ + protocol: 'http', + host: '127.0.0.1', + port: 2021, + options: { disableWarnings: false } + }); + connectAuthEmulator(auth, 'http://127.0.0.1:2020'); + expect(auth.emulatorConfig).to.eql({ + protocol: 'http', + host: '127.0.0.1', + port: 2020, + options: { disableWarnings: false } + }); + }); + it('updates the endpoint appropriately', async () => { connectAuthEmulator(auth, 'http://127.0.0.1:2020'); await user.delete(); diff --git a/packages/auth/src/core/util/fetch_provider.ts b/packages/auth/src/core/util/fetch_provider.ts index 14433d6eacb..6a481630eed 100644 --- a/packages/auth/src/core/util/fetch_provider.ts +++ b/packages/auth/src/core/util/fetch_provider.ts @@ -37,6 +37,7 @@ export class FetchProvider { } static fetch(): typeof fetch { + console.log('fetch!'); if (this.fetchImpl) { return this.fetchImpl; } From b486cd7ad0687427ceaafd92130872cb53872aad Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 15:23:45 -0700 Subject: [PATCH 44/63] WIP --- packages/auth/src/api/index.test.ts | 28 ++++++++++--------- packages/auth/src/core/util/fetch_provider.ts | 1 - 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/auth/src/api/index.test.ts b/packages/auth/src/api/index.test.ts index ea11af59d01..8443d74070f 100644 --- a/packages/auth/src/api/index.test.ts +++ b/packages/auth/src/api/index.test.ts @@ -41,6 +41,7 @@ import { import { ServerError } from './errors'; import { SDK_VERSION } from '@firebase/app'; import { _getBrowserName } from '../core/util/browser'; +import { FetchProvider } from '../../internal'; use(sinonChai); use(chaiAsPromised); @@ -56,30 +57,31 @@ describe('api/_performApiRequest', () => { let auth: TestAuth; + let fetchSpy: sinon.SinonSpy; + beforeEach(async () => { auth = await testAuth(); }); - context('with regular requests', () => { - beforeEach(mockFetch.setUp); + afterEach(() => { + sinon.restore(); + }) + + context.only('with regular requests', () => { + + beforeEach(() => { + mockFetch.setUp(); + fetchSpy = sinon.spy(FetchProvider.fetch()); + }) afterEach(mockFetch.tearDown); - it('should set the correct request, method and HTTP Headers', async () => { + it.only('should set the correct request, method and HTTP Headers', async () => { const mock = mockEndpoint(Endpoint.SIGN_UP, serverResponse); const response = await _performApiRequest< typeof request, typeof serverResponse >(auth, HttpMethod.POST, Endpoint.SIGN_UP, request); - expect(response).to.eql(serverResponse); - expect(mock.calls.length).to.eq(1); - expect(mock.calls[0].method).to.eq(HttpMethod.POST); - expect(mock.calls[0].request).to.eql(request); - expect(mock.calls[0].headers!.get(HttpHeader.CONTENT_TYPE)).to.eq( - 'application/json' - ); - expect(mock.calls[0].headers!.get(HttpHeader.X_CLIENT_VERSION)).to.eq( - 'testSDK/0.0.0' - ); + expect(fetchSpy).to.have.been.called; }); it('should set the device language if available', async () => { diff --git a/packages/auth/src/core/util/fetch_provider.ts b/packages/auth/src/core/util/fetch_provider.ts index 6a481630eed..14433d6eacb 100644 --- a/packages/auth/src/core/util/fetch_provider.ts +++ b/packages/auth/src/core/util/fetch_provider.ts @@ -37,7 +37,6 @@ export class FetchProvider { } static fetch(): typeof fetch { - console.log('fetch!'); if (this.fetchImpl) { return this.fetchImpl; } From 79ea2d0276507fd8098fb07958b5e72788d61e5f Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 15:40:26 -0700 Subject: [PATCH 45/63] Got tests to work --- packages/auth/src/api/index.test.ts | 17 ++++++++++++----- packages/auth/src/core/auth/emulator.test.ts | 13 +------------ packages/auth/test/helpers/mock_fetch.ts | 4 +++- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/packages/auth/src/api/index.test.ts b/packages/auth/src/api/index.test.ts index 8443d74070f..0e9aa11028e 100644 --- a/packages/auth/src/api/index.test.ts +++ b/packages/auth/src/api/index.test.ts @@ -41,7 +41,7 @@ import { import { ServerError } from './errors'; import { SDK_VERSION } from '@firebase/app'; import { _getBrowserName } from '../core/util/browser'; -import { FetchProvider } from '../../internal'; +import { connectAuthEmulator, FetchProvider } from '../../internal'; use(sinonChai); use(chaiAsPromised); @@ -65,23 +65,30 @@ describe('api/_performApiRequest', () => { afterEach(() => { sinon.restore(); - }) + }); context.only('with regular requests', () => { - beforeEach(() => { mockFetch.setUp(); fetchSpy = sinon.spy(FetchProvider.fetch()); - }) + }); afterEach(mockFetch.tearDown); it.only('should set the correct request, method and HTTP Headers', async () => { const mock = mockEndpoint(Endpoint.SIGN_UP, serverResponse); + auth.emulatorConfig = { + host: 'https://something.cloudworkstations.dev', + protocol: '', + port: 8, + options: { + disableWarnings: false + } + }; const response = await _performApiRequest< typeof request, typeof serverResponse >(auth, HttpMethod.POST, Endpoint.SIGN_UP, request); - expect(fetchSpy).to.have.been.called; + expect(mock.calls[0].fullRequest?.credentials).to.eq('include'); }); it('should set the device language if available', async () => { diff --git a/packages/auth/src/core/auth/emulator.test.ts b/packages/auth/src/core/auth/emulator.test.ts index 35f82249ab2..3d84bc0c3aa 100644 --- a/packages/auth/src/core/auth/emulator.test.ts +++ b/packages/auth/src/core/auth/emulator.test.ts @@ -43,7 +43,6 @@ describe.only('core/auth/emulator', () => { beforeEach(async () => { auth = await testAuth(); - spy = sinon.spy(FetchProvider.fetch()); user = testUser(_castAuth(auth), 'uid', 'email', true); fetch.setUp(); normalEndpoint = mockEndpoint(Endpoint.DELETE_ACCOUNT, {}); @@ -96,16 +95,6 @@ describe.only('core/auth/emulator', () => { 'auth/emulator-config-failed' ); }); - it.only('sends the proper value', async () => { - expect(() => connectAuthEmulator(auth, 'http://127.0.0.1:2020')).to.not - .throw; - await user.delete(); - expect(spy).to.have.been.called; - expect(() => connectAuthEmulator(auth, 'http://127.0.0.1:2021')).to.throw( - FirebaseError, - 'auth/emulator-config-failed' - ); - }); it('subsequent calls update the endpoint appropriately', async () => { connectAuthEmulator(auth, 'http://127.0.0.1:2021'); @@ -124,7 +113,7 @@ describe.only('core/auth/emulator', () => { }); }); - it('subsequent calls update the endpoint appropriately', async () => { + it('subsequent calls update the endpoint appropriately', async () => { connectAuthEmulator(auth, 'http://127.0.0.1:2021'); expect(auth.emulatorConfig).to.eql({ protocol: 'http', diff --git a/packages/auth/test/helpers/mock_fetch.ts b/packages/auth/test/helpers/mock_fetch.ts index 2d5794b7327..49fa79966f9 100644 --- a/packages/auth/test/helpers/mock_fetch.ts +++ b/packages/auth/test/helpers/mock_fetch.ts @@ -22,6 +22,7 @@ export interface Call { request?: object | string; method?: string; headers: Headers; + fullRequest?: RequestInit; } export interface Route { @@ -59,7 +60,8 @@ const fakeFetch: typeof fetch = ( calls.push({ request: requestBody, method: request?.method, - headers + headers, + fullRequest: request }); return Promise.resolve( From cdb502ce5f68f8da15ae795c0b850787c4cfbe72 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 15:54:14 -0700 Subject: [PATCH 46/63] Fixed up tests --- packages/auth/src/api/index.test.ts | 23 ++++++++++++++++++-- packages/auth/src/core/auth/emulator.test.ts | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/auth/src/api/index.test.ts b/packages/auth/src/api/index.test.ts index 0e9aa11028e..45ee19dbecb 100644 --- a/packages/auth/src/api/index.test.ts +++ b/packages/auth/src/api/index.test.ts @@ -74,7 +74,26 @@ describe('api/_performApiRequest', () => { }); afterEach(mockFetch.tearDown); - it.only('should set the correct request, method and HTTP Headers', async () => { + it('should set the correct request, method and HTTP Headers', async () => { + const mock = mockEndpoint(Endpoint.SIGN_UP, serverResponse); + const response = await _performApiRequest< + typeof request, + typeof serverResponse + >(auth, HttpMethod.POST, Endpoint.SIGN_UP, request); + expect(response).to.eql(serverResponse); + expect(mock.calls.length).to.eq(1); + expect(mock.calls[0].method).to.eq(HttpMethod.POST); + expect(mock.calls[0].request).to.eql(request); + expect(mock.calls[0].headers!.get(HttpHeader.CONTENT_TYPE)).to.eq( + 'application/json' + ); + expect(mock.calls[0].headers!.get(HttpHeader.X_CLIENT_VERSION)).to.eq( + 'testSDK/0.0.0' + ); + expect(mock.calls[0].fullRequest?.credentials).to.be.undefined; + }); + + it('should set credentials to "include" when using IDX and emulator', async () => { const mock = mockEndpoint(Endpoint.SIGN_UP, serverResponse); auth.emulatorConfig = { host: 'https://something.cloudworkstations.dev', @@ -84,7 +103,7 @@ describe('api/_performApiRequest', () => { disableWarnings: false } }; - const response = await _performApiRequest< + await _performApiRequest< typeof request, typeof serverResponse >(auth, HttpMethod.POST, Endpoint.SIGN_UP, request); diff --git a/packages/auth/src/core/auth/emulator.test.ts b/packages/auth/src/core/auth/emulator.test.ts index 3d84bc0c3aa..553c7cc8be1 100644 --- a/packages/auth/src/core/auth/emulator.test.ts +++ b/packages/auth/src/core/auth/emulator.test.ts @@ -184,7 +184,7 @@ describe.only('core/auth/emulator', () => { ); }); - it('skips console info and has no banner if warnings disabled', () => { + it.only('skips console info and has no banner if warnings disabled', () => { sinon.stub(console, 'info'); connectAuthEmulator(auth, 'http://127.0.0.1:2020', { disableWarnings: true From c58a2897a34e2e76c35afc01d4eea6102845648c Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Mon, 28 Apr 2025 15:58:45 -0700 Subject: [PATCH 47/63] Fixed formatting --- packages/auth/src/api/index.test.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/auth/src/api/index.test.ts b/packages/auth/src/api/index.test.ts index 45ee19dbecb..6dde18ee849 100644 --- a/packages/auth/src/api/index.test.ts +++ b/packages/auth/src/api/index.test.ts @@ -103,10 +103,12 @@ describe('api/_performApiRequest', () => { disableWarnings: false } }; - await _performApiRequest< - typeof request, - typeof serverResponse - >(auth, HttpMethod.POST, Endpoint.SIGN_UP, request); + await _performApiRequest( + auth, + HttpMethod.POST, + Endpoint.SIGN_UP, + request + ); expect(mock.calls[0].fullRequest?.credentials).to.eq('include'); }); From 80f29d48da918a561e3b2469658179fa945fc0c1 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 11:29:09 -0700 Subject: [PATCH 48/63] Added data connect test for fetches --- config/.eslintrc.js | 16 ++++++------ packages/data-connect/test/unit/fetch.test.ts | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/config/.eslintrc.js b/config/.eslintrc.js index 589dbf4cccd..57243a3e2a4 100644 --- a/config/.eslintrc.js +++ b/config/.eslintrc.js @@ -98,18 +98,18 @@ module.exports = { 'object': 'it', 'property': 'skip' }, - // { - // 'object': 'it', - // 'property': 'only' - // }, + { + 'object': 'it', + 'property': 'only' + }, { 'object': 'describe', 'property': 'skip' }, - // { - // 'object': 'describe', - // 'property': 'only' - // }, + { + 'object': 'describe', + 'property': 'only' + }, { 'object': 'xit' } diff --git a/packages/data-connect/test/unit/fetch.test.ts b/packages/data-connect/test/unit/fetch.test.ts index 11bc8d03818..76bd0f3f272 100644 --- a/packages/data-connect/test/unit/fetch.test.ts +++ b/packages/data-connect/test/unit/fetch.test.ts @@ -220,4 +220,30 @@ describe('fetch', () => { } } }); + it('should call credentials include if using emulator on cloud workstation', async () => { + const json = { + code: 200, + message1: 'success' + }; + const fakeFetchImpl = mockFetch(json, false); + await dcFetch( + 'https://abc.cloudworkstations.dev', + { + name: 'n', + operationName: 'n', + variables: {} + }, + {} as AbortController, + null, + null, + null, + true, // _isUsingGen is true + CallerSdkTypeEnum.Base, + true + ); + expect(fakeFetchImpl).to.have.been.calledWithMatch( + 'https://abc.cloudworkstations.dev', + { credentials: 'include' } + ); + }); }); From 9d76cb3d91f0a53b4665e982e8f2114b04010fd4 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 11:29:51 -0700 Subject: [PATCH 49/63] Cleaned up auth tests --- packages/auth/src/api/index.test.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/auth/src/api/index.test.ts b/packages/auth/src/api/index.test.ts index 6dde18ee849..3398c550fab 100644 --- a/packages/auth/src/api/index.test.ts +++ b/packages/auth/src/api/index.test.ts @@ -41,7 +41,7 @@ import { import { ServerError } from './errors'; import { SDK_VERSION } from '@firebase/app'; import { _getBrowserName } from '../core/util/browser'; -import { connectAuthEmulator, FetchProvider } from '../../internal'; +import { FetchProvider } from '../../internal'; use(sinonChai); use(chaiAsPromised); @@ -57,8 +57,6 @@ describe('api/_performApiRequest', () => { let auth: TestAuth; - let fetchSpy: sinon.SinonSpy; - beforeEach(async () => { auth = await testAuth(); }); @@ -68,10 +66,7 @@ describe('api/_performApiRequest', () => { }); context.only('with regular requests', () => { - beforeEach(() => { - mockFetch.setUp(); - fetchSpy = sinon.spy(FetchProvider.fetch()); - }); + beforeEach(mockFetch.setUp); afterEach(mockFetch.tearDown); it('should set the correct request, method and HTTP Headers', async () => { From 2893ee24fbe9f0322abbd3c798fc1208099764e3 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 11:30:07 -0700 Subject: [PATCH 50/63] Removed only from auth test --- packages/auth/src/api/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth/src/api/index.test.ts b/packages/auth/src/api/index.test.ts index 3398c550fab..66d30c4e753 100644 --- a/packages/auth/src/api/index.test.ts +++ b/packages/auth/src/api/index.test.ts @@ -65,7 +65,7 @@ describe('api/_performApiRequest', () => { sinon.restore(); }); - context.only('with regular requests', () => { + context('with regular requests', () => { beforeEach(mockFetch.setUp); afterEach(mockFetch.tearDown); From 9d77dbb1d7508fdb4c33537935635185dded233b Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 11:31:33 -0700 Subject: [PATCH 51/63] More test cleanup --- packages/auth/src/core/auth/emulator.test.ts | 21 ++------------------ 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/packages/auth/src/core/auth/emulator.test.ts b/packages/auth/src/core/auth/emulator.test.ts index 553c7cc8be1..c2948918546 100644 --- a/packages/auth/src/core/auth/emulator.test.ts +++ b/packages/auth/src/core/auth/emulator.test.ts @@ -34,7 +34,7 @@ import { FetchProvider } from '../util/fetch_provider'; use(sinonChai); use(chaiAsPromised); -describe.only('core/auth/emulator', () => { +describe('core/auth/emulator', () => { let auth: TestAuth; let user: UserInternal; let normalEndpoint: fetch.Route; @@ -113,23 +113,6 @@ describe.only('core/auth/emulator', () => { }); }); - it('subsequent calls update the endpoint appropriately', async () => { - connectAuthEmulator(auth, 'http://127.0.0.1:2021'); - expect(auth.emulatorConfig).to.eql({ - protocol: 'http', - host: '127.0.0.1', - port: 2021, - options: { disableWarnings: false } - }); - connectAuthEmulator(auth, 'http://127.0.0.1:2020'); - expect(auth.emulatorConfig).to.eql({ - protocol: 'http', - host: '127.0.0.1', - port: 2020, - options: { disableWarnings: false } - }); - }); - it('updates the endpoint appropriately', async () => { connectAuthEmulator(auth, 'http://127.0.0.1:2020'); await user.delete(); @@ -184,7 +167,7 @@ describe.only('core/auth/emulator', () => { ); }); - it.only('skips console info and has no banner if warnings disabled', () => { + it('skips console info and has no banner if warnings disabled', () => { sinon.stub(console, 'info'); connectAuthEmulator(auth, 'http://127.0.0.1:2020', { disableWarnings: true From 862fb91d60332a90fba3bc40351e79310fbf3f99 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 13:37:57 -0700 Subject: [PATCH 52/63] Added test for storage --- .../storage/src/platform/node/connection.ts | 11 ++++-- packages/storage/test/unit/service.test.ts | 36 +++++++++++++++++-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/packages/storage/src/platform/node/connection.ts b/packages/storage/src/platform/node/connection.ts index e201ce8ffba..3b0964f6c0a 100644 --- a/packages/storage/src/platform/node/connection.ts +++ b/packages/storage/src/platform/node/connection.ts @@ -157,7 +157,8 @@ export class FetchStreamConnection extends FetchConnection< url: string, method: string, body?: NodeJS.ArrayBufferView | Blob | string, - headers?: Record + headers?: Record, + isUsingEmulator?: boolean ): Promise { if (this.sent_) { throw internalError('cannot .send() more than once'); @@ -165,7 +166,13 @@ export class FetchStreamConnection extends FetchConnection< this.sent_ = true; try { - const response = await newFetch(url, method, headers, body); + const response = await newFetch( + url, + method, + headers, + body, + isUsingEmulator + ); this.headers_ = response.headers; this.statusCode_ = response.status; this.errorCode_ = ErrorCode.NO_ERROR; diff --git a/packages/storage/test/unit/service.test.ts b/packages/storage/test/unit/service.test.ts index bc443c60a03..9d21f8ab63a 100644 --- a/packages/storage/test/unit/service.test.ts +++ b/packages/storage/test/unit/service.test.ts @@ -14,7 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { expect } from 'chai'; +import { expect, use } from 'chai'; +import * as sinon from 'sinon'; import { TaskEvent } from '../../src/implementation/taskenums'; import { Headers } from '../../src/implementation/connection'; import { @@ -34,19 +35,22 @@ import { import { Location } from '../../src/implementation/location'; import { newTestConnection, TestingConnection } from './connection'; import { injectTestConnection } from '../../src/platform/connection'; +import { newTextConnection } from '../../src/platform/node/connection'; +import sinonChai from 'sinon-chai'; const fakeAppGs = testShared.makeFakeApp('gs://mybucket'); const fakeAppGsEndingSlash = testShared.makeFakeApp('gs://mybucket/'); const fakeAppInvalidGs = testShared.makeFakeApp('gs://mybucket/hello'); const testLocation = new Location('bucket', 'object'); +use(sinonChai); function makeGsUrl(child: string = ''): string { return 'gs://' + testShared.bucket + '/' + child; } describe('Firebase Storage > Service', () => { - before(() => injectTestConnection(newTestConnection)); - after(() => injectTestConnection(null)); + // before(() => injectTestConnection(newTestConnection)); + // after(() => injectTestConnection(null)); describe('simple constructor', () => { const service = new FirebaseStorageImpl( @@ -227,6 +231,13 @@ GOOG4-RSA-SHA256` }); }); describe('connectStorageEmulator(service, host, port, options)', () => { + let sandbox: sinon.SinonSandbox; + beforeEach(() => { + sandbox = sinon.createSandbox(); + }); + afterEach(() => { + sandbox.restore(); + }); it('sets emulator host correctly', done => { function newSend(connection: TestingConnection, url: string): void { // Expect emulator host to be in url of storage operations requests, @@ -270,6 +281,25 @@ GOOG4-RSA-SHA256` expect(service._protocol).to.equal('https'); void getDownloadURL(ref(service, 'test.png')); }); + it('sets the credentials', () => { + const stub = sandbox.stub(globalThis, 'fetch').resolves(); + const textConnection = newTextConnection(); + textConnection.send( + 'http://something.cloudworkstations.dev', + 'POST', + undefined, + undefined, + true + ); + expect(stub).to.have.been.called; + expect(stub).to.have.been.calledWithMatch( + 'http://something.cloudworkstations.dev', + { + credentials: 'include' + } + ); + stub.restore(); + }); it('sets mock user token string if specified', done => { const mockUserToken = 'my-mock-user-token'; function newSend( From 6d630736a104585b03b60b02e772823e88f4b287 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 13:46:35 -0700 Subject: [PATCH 53/63] Make param required --- .../storage/src/implementation/connection.ts | 4 ++-- .../storage/src/platform/node/connection.ts | 20 +++++++++---------- packages/storage/src/service.ts | 3 ++- packages/storage/test/node/connection.test.ts | 2 +- packages/storage/test/unit/connection.ts | 1 + packages/storage/test/unit/service.test.ts | 4 ++-- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/packages/storage/src/implementation/connection.ts b/packages/storage/src/implementation/connection.ts index ec65ace3c00..f7630e59708 100644 --- a/packages/storage/src/implementation/connection.ts +++ b/packages/storage/src/implementation/connection.ts @@ -42,9 +42,9 @@ export interface Connection { send( url: string, method: string, + isUsingEmulator: boolean, body?: ArrayBufferView | Blob | string | null, - headers?: Headers, - isUsingEmulator?: boolean + headers?: Headers ): Promise; getErrorCode(): ErrorCode; diff --git a/packages/storage/src/platform/node/connection.ts b/packages/storage/src/platform/node/connection.ts index 3b0964f6c0a..2dd869eb2f0 100644 --- a/packages/storage/src/platform/node/connection.ts +++ b/packages/storage/src/platform/node/connection.ts @@ -49,9 +49,9 @@ abstract class FetchConnection async send( url: string, method: string, + isUsingEmulator: boolean, body?: NodeJS.ArrayBufferView | Blob | string, - headers?: Record, - isUsingEmulator?: boolean + headers?: Record ): Promise { if (this.sent_) { throw internalError('cannot .send() more than once'); @@ -62,9 +62,9 @@ abstract class FetchConnection const response = await newFetch( url, method, + isUsingEmulator, headers, - body, - isUsingEmulator + body ); this.headers_ = response.headers; this.statusCode_ = response.status; @@ -156,9 +156,9 @@ export class FetchStreamConnection extends FetchConnection< async send( url: string, method: string, + isUsingEmulator: boolean, body?: NodeJS.ArrayBufferView | Blob | string, - headers?: Record, - isUsingEmulator?: boolean + headers?: Record ): Promise { if (this.sent_) { throw internalError('cannot .send() more than once'); @@ -169,9 +169,9 @@ export class FetchStreamConnection extends FetchConnection< const response = await newFetch( url, method, + isUsingEmulator, headers, - body, - isUsingEmulator + body ); this.headers_ = response.headers; this.statusCode_ = response.status; @@ -196,9 +196,9 @@ export class FetchStreamConnection extends FetchConnection< function newFetch( url: string, method: string, + isUsingEmulator: boolean, headers?: Record, - body?: NodeJS.ArrayBufferView | Blob | string, - isUsingEmulator?: boolean + body?: NodeJS.ArrayBufferView | Blob | string ): Promise { const fetchArgs: RequestInit = { method, diff --git a/packages/storage/src/service.ts b/packages/storage/src/service.ts index f7b35219849..8ad31ecb13c 100644 --- a/packages/storage/src/service.ts +++ b/packages/storage/src/service.ts @@ -146,6 +146,7 @@ export function connectStorageEmulator( ): void { storage.host = `${host}:${port}`; const useSsl = isCloudWorkstation(host); + storage._isUsingEmulator = true; storage._protocol = useSsl ? 'https' : 'http'; const { mockUserToken } = options; if (mockUserToken) { @@ -193,7 +194,7 @@ export class FirebaseStorageImpl implements FirebaseStorage { */ readonly _url?: string, readonly _firebaseVersion?: string, - readonly _isUsingEmulator = false + public _isUsingEmulator = false ) { this._maxOperationRetryTime = DEFAULT_MAX_OPERATION_RETRY_TIME; this._maxUploadRetryTime = DEFAULT_MAX_UPLOAD_RETRY_TIME; diff --git a/packages/storage/test/node/connection.test.ts b/packages/storage/test/node/connection.test.ts index 925d1f8f7dc..af37e183755 100644 --- a/packages/storage/test/node/connection.test.ts +++ b/packages/storage/test/node/connection.test.ts @@ -25,7 +25,7 @@ describe('Connections', () => { const connection = new FetchBytesConnection(); const fetchStub = stub(globalThis, 'fetch').rejects(); - await connection.send('testurl', 'GET'); + await connection.send('testurl', 'GET', false); expect(connection.getErrorCode()).to.equal(ErrorCode.NETWORK_ERROR); fetchStub.restore(); }); diff --git a/packages/storage/test/unit/connection.ts b/packages/storage/test/unit/connection.ts index 6b800a17f91..a2f0ca58750 100644 --- a/packages/storage/test/unit/connection.ts +++ b/packages/storage/test/unit/connection.ts @@ -60,6 +60,7 @@ export class TestingConnection implements Connection { send( url: string, method: string, + _isUsingEmulator: boolean, body?: ArrayBufferView | Blob | string | null, headers?: Headers ): Promise { diff --git a/packages/storage/test/unit/service.test.ts b/packages/storage/test/unit/service.test.ts index 9d21f8ab63a..9df66a17cb5 100644 --- a/packages/storage/test/unit/service.test.ts +++ b/packages/storage/test/unit/service.test.ts @@ -287,9 +287,9 @@ GOOG4-RSA-SHA256` textConnection.send( 'http://something.cloudworkstations.dev', 'POST', + true, undefined, - undefined, - true + undefined ); expect(stub).to.have.been.called; expect(stub).to.have.been.calledWithMatch( From 48d56ed32837d72ccdee3196108f86ad0a23c29c Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 15:16:00 -0700 Subject: [PATCH 54/63] Added test for fetch for firestore --- common/api-review/storage.api.md | 4 +- packages/data-connect/test/unit/fetch.test.ts | 2 + packages/firestore/src/lite-api/components.ts | 3 +- packages/firestore/src/lite-api/settings.ts | 3 + .../platform/browser_lite/fetch_connection.ts | 2 +- .../test/unit/remote/fetch_connection.test.ts | 79 +++++++++++++++++++ .../storage/src/implementation/request.ts | 4 +- .../src/platform/browser/connection.ts | 4 +- .../storage/test/browser/connection.test.ts | 18 ++++- packages/storage/test/node/connection.test.ts | 19 +++++ packages/storage/test/unit/service.test.ts | 19 ----- 11 files changed, 129 insertions(+), 28 deletions(-) create mode 100644 packages/firestore/test/unit/remote/fetch_connection.test.ts diff --git a/common/api-review/storage.api.md b/common/api-review/storage.api.md index 4964aa40af7..f5302d2d5c5 100644 --- a/common/api-review/storage.api.md +++ b/common/api-review/storage.api.md @@ -58,7 +58,7 @@ export class _FirebaseStorageImpl implements FirebaseStorage { constructor( app: FirebaseApp, _authProvider: Provider, _appCheckProvider: Provider, - _url?: string | undefined, _firebaseVersion?: string | undefined); + _url?: string | undefined, _firebaseVersion?: string | undefined, _isUsingEmulator?: boolean); readonly app: FirebaseApp; // (undocumented) readonly _appCheckProvider: Provider; @@ -77,6 +77,8 @@ export class _FirebaseStorageImpl implements FirebaseStorage { _getAuthToken(): Promise; get host(): string; set host(host: string); + // (undocumented) + _isUsingEmulator: boolean; // Warning: (ae-forgotten-export) The symbol "ConnectionType" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "RequestInfo" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "Connection" needs to be exported by the entry point index.d.ts diff --git a/packages/data-connect/test/unit/fetch.test.ts b/packages/data-connect/test/unit/fetch.test.ts index 76bd0f3f272..be45695190f 100644 --- a/packages/data-connect/test/unit/fetch.test.ts +++ b/packages/data-connect/test/unit/fetch.test.ts @@ -18,10 +18,12 @@ import { expect, use } from 'chai'; import chaiAsPromised from 'chai-as-promised'; import * as sinon from 'sinon'; +import sinonChai from 'sinon-chai'; import { dcFetch, initializeFetch } from '../../src/network/fetch'; import { CallerSdkType, CallerSdkTypeEnum } from '../../src/network/transport'; use(chaiAsPromised); +use(sinonChai); function mockFetch(json: object, reject: boolean): sinon.SinonStub { const fakeFetchImpl = sinon.stub().returns( Promise.resolve({ diff --git a/packages/firestore/src/lite-api/components.ts b/packages/firestore/src/lite-api/components.ts index a51e451dcac..6d4a161259f 100644 --- a/packages/firestore/src/lite-api/components.ts +++ b/packages/firestore/src/lite-api/components.ts @@ -110,7 +110,6 @@ export function makeDatabaseInfo( persistenceKey: string, settings: FirestoreSettingsImpl ): DatabaseInfo { - const privateSettings = settings as PrivateSettings; return new DatabaseInfo( databaseId, appId, @@ -121,6 +120,6 @@ export function makeDatabaseInfo( settings.experimentalAutoDetectLongPolling, cloneLongPollingOptions(settings.experimentalLongPollingOptions), settings.useFetchStreams, - privateSettings.emulatorOptions !== undefined + settings.isUsingEmulator ); } diff --git a/packages/firestore/src/lite-api/settings.ts b/packages/firestore/src/lite-api/settings.ts index a1bba373d13..56c99e7ccea 100644 --- a/packages/firestore/src/lite-api/settings.ts +++ b/packages/firestore/src/lite-api/settings.ts @@ -112,6 +112,8 @@ export class FirestoreSettingsImpl { readonly useFetchStreams: boolean; readonly localCache?: FirestoreLocalCache; + readonly isUsingEmulator: boolean; + // Can be a google-auth-library or gapi client. // eslint-disable-next-line @typescript-eslint/no-explicit-any credentials?: any; @@ -130,6 +132,7 @@ export class FirestoreSettingsImpl { this.host = settings.host; this.ssl = settings.ssl ?? DEFAULT_SSL; } + this.isUsingEmulator = settings.emulatorOptions !== undefined; this.credentials = settings.credentials; this.ignoreUndefinedProperties = !!settings.ignoreUndefinedProperties; diff --git a/packages/firestore/src/platform/browser_lite/fetch_connection.ts b/packages/firestore/src/platform/browser_lite/fetch_connection.ts index 580c83c99ff..1404d7f9523 100644 --- a/packages/firestore/src/platform/browser_lite/fetch_connection.ts +++ b/packages/firestore/src/platform/browser_lite/fetch_connection.ts @@ -52,7 +52,7 @@ export class FetchConnection extends RestConnection { headers, body: requestJson }; - if (isCloudWorkstation(url) && isUsingEmulator) { + if (isCloudWorkstation(new URL(url).host) && isUsingEmulator) { fetchArgs.credentials = 'include'; } response = await fetch(url, fetchArgs); diff --git a/packages/firestore/test/unit/remote/fetch_connection.test.ts b/packages/firestore/test/unit/remote/fetch_connection.test.ts new file mode 100644 index 00000000000..2663de459bd --- /dev/null +++ b/packages/firestore/test/unit/remote/fetch_connection.test.ts @@ -0,0 +1,79 @@ +/** + * @license + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as sinon from 'sinon'; +import { expect, use } from 'chai'; +import { DatabaseId } from '../../../src/core/database_info'; +import { makeDatabaseInfo } from '../../../src/lite-api/components'; +import { + FirestoreSettingsImpl, + PrivateSettings +} from '../../../src/lite-api/settings'; +import { ResourcePath } from '../../../src/model/path'; +import { FetchConnection } from '../../../src/platform/browser_lite/fetch_connection'; +import sinonChai from 'sinon-chai'; +import chaiAsPromised from 'chai-as-promised'; + +use(sinonChai); +use(chaiAsPromised); + +describe('Fetch Connection', () => { + it('should pass in credentials if using emulator and cloud workstation', async () => { + const privateSettings: PrivateSettings = { + emulatorOptions: {}, + host: 'abc.cloudworkstations.dev' + }; + console.log( + makeDatabaseInfo( + DatabaseId.empty(), + '', + '', + new FirestoreSettingsImpl(privateSettings) + ) + ); + const stub = sinon.stub(globalThis, 'fetch'); + stub.resolves({ + ok: true, + json() { + return Promise.resolve(); + } + } as Response); + const fetchConnection = new FetchConnection( + makeDatabaseInfo( + DatabaseId.empty(), + '', + '', + new FirestoreSettingsImpl({ + host: 'abc.cloudworkstations.dev', + emulatorOptions: {} + }) + ) + ); + await fetchConnection.invokeRPC( + 'Commit', + new ResourcePath([]), + {}, + null, + null + ); + expect(stub).to.have.been.calledWithMatch( + 'https://abc.cloudworkstations.dev/v1/:commit', + { credentials: 'include' } + ); + stub.restore(); + }); +}); diff --git a/packages/storage/src/implementation/request.ts b/packages/storage/src/implementation/request.ts index 7433cd53955..adfda6e4460 100644 --- a/packages/storage/src/implementation/request.ts +++ b/packages/storage/src/implementation/request.ts @@ -115,9 +115,9 @@ class NetworkRequest implements Request { .send( this.url_, this.method_, + this.isUsingEmulator, this.body_, - this.headers_, - this.isUsingEmulator + this.headers_ ) .then(() => { if (this.progressCallback_ !== null) { diff --git a/packages/storage/src/platform/browser/connection.ts b/packages/storage/src/platform/browser/connection.ts index fcbd5db0c2a..77a2e42809b 100644 --- a/packages/storage/src/platform/browser/connection.ts +++ b/packages/storage/src/platform/browser/connection.ts @@ -63,9 +63,9 @@ abstract class XhrConnection send( url: string, method: string, + isUsingEmulator: boolean, body?: ArrayBufferView | Blob | string, - headers?: Headers, - isUsingEmulator?: boolean + headers?: Headers ): Promise { if (this.sent_) { throw internalError('cannot .send() more than once'); diff --git a/packages/storage/test/browser/connection.test.ts b/packages/storage/test/browser/connection.test.ts index b869c9ee31b..2a0320d0c02 100644 --- a/packages/storage/test/browser/connection.test.ts +++ b/packages/storage/test/browser/connection.test.ts @@ -24,11 +24,27 @@ describe('Connections', () => { it('XhrConnection.send() should not reject on network errors', async () => { const fakeXHR = useFakeXMLHttpRequest(); const connection = new XhrBytesConnection(); - const sendPromise = connection.send('testurl', 'GET'); + const sendPromise = connection.send('testurl', 'GET', false); // simulate a network error ((connection as any).xhr_ as SinonFakeXMLHttpRequest).error(); await sendPromise; expect(connection.getErrorCode()).to.equal(ErrorCode.NETWORK_ERROR); fakeXHR.restore(); }); + it('XhrConnection.send() should send credentials when using cloud workstation', async () => { + const fakeXHR = useFakeXMLHttpRequest(); + const connection = new XhrBytesConnection(); + const sendPromise = connection.send( + 'https://abc.cloudworkstations.dev', + 'GET', + true + ); + // simulate a network error + ((connection as any).xhr_ as SinonFakeXMLHttpRequest).error(); + await sendPromise; + expect( + ((connection as any).xhr_ as SinonFakeXMLHttpRequest).withCredentials + ).to.be.true; + fakeXHR.restore(); + }); }); diff --git a/packages/storage/test/node/connection.test.ts b/packages/storage/test/node/connection.test.ts index af37e183755..5c9f2efe41d 100644 --- a/packages/storage/test/node/connection.test.ts +++ b/packages/storage/test/node/connection.test.ts @@ -27,6 +27,25 @@ describe('Connections', () => { const fetchStub = stub(globalThis, 'fetch').rejects(); await connection.send('testurl', 'GET', false); expect(connection.getErrorCode()).to.equal(ErrorCode.NETWORK_ERROR); + + fetchStub.restore(); + }); + it('FetchConnection.send() should send credentials on cloud workstations', async () => { + const connection = new FetchBytesConnection(); + + const fetchStub = stub(globalThis, 'fetch').rejects(); + await connection.send( + 'http://something.cloudworkstations.dev', + 'GET', + true + ); + expect(connection.getErrorCode()).to.equal(ErrorCode.NETWORK_ERROR); + expect(fetchStub).to.have.been.calledWithMatch( + 'http://something.cloudworkstations.dev', + { + credentials: 'include' + } + ); fetchStub.restore(); }); }); diff --git a/packages/storage/test/unit/service.test.ts b/packages/storage/test/unit/service.test.ts index 9df66a17cb5..f0b544c698a 100644 --- a/packages/storage/test/unit/service.test.ts +++ b/packages/storage/test/unit/service.test.ts @@ -281,25 +281,6 @@ GOOG4-RSA-SHA256` expect(service._protocol).to.equal('https'); void getDownloadURL(ref(service, 'test.png')); }); - it('sets the credentials', () => { - const stub = sandbox.stub(globalThis, 'fetch').resolves(); - const textConnection = newTextConnection(); - textConnection.send( - 'http://something.cloudworkstations.dev', - 'POST', - true, - undefined, - undefined - ); - expect(stub).to.have.been.called; - expect(stub).to.have.been.calledWithMatch( - 'http://something.cloudworkstations.dev', - { - credentials: 'include' - } - ); - stub.restore(); - }); it('sets mock user token string if specified', done => { const mockUserToken = 'my-mock-user-token'; function newSend( From 7449c0190c2278e55b0834c14bfa8ce18c46bcbd Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 15:18:51 -0700 Subject: [PATCH 55/63] Fixed linting --- packages/auth/src/api/index.test.ts | 1 - packages/auth/src/core/auth/emulator.test.ts | 2 -- 2 files changed, 3 deletions(-) diff --git a/packages/auth/src/api/index.test.ts b/packages/auth/src/api/index.test.ts index 66d30c4e753..02042fce429 100644 --- a/packages/auth/src/api/index.test.ts +++ b/packages/auth/src/api/index.test.ts @@ -41,7 +41,6 @@ import { import { ServerError } from './errors'; import { SDK_VERSION } from '@firebase/app'; import { _getBrowserName } from '../core/util/browser'; -import { FetchProvider } from '../../internal'; use(sinonChai); use(chaiAsPromised); diff --git a/packages/auth/src/core/auth/emulator.test.ts b/packages/auth/src/core/auth/emulator.test.ts index c2948918546..47c5d927c44 100644 --- a/packages/auth/src/core/auth/emulator.test.ts +++ b/packages/auth/src/core/auth/emulator.test.ts @@ -29,7 +29,6 @@ import { Endpoint } from '../../api'; import { UserInternal } from '../../model/user'; import { _castAuth } from './auth_impl'; import { connectAuthEmulator } from './emulator'; -import { FetchProvider } from '../util/fetch_provider'; use(sinonChai); use(chaiAsPromised); @@ -39,7 +38,6 @@ describe('core/auth/emulator', () => { let user: UserInternal; let normalEndpoint: fetch.Route; let emulatorEndpoint: fetch.Route; - let spy: sinon.SinonSpy; beforeEach(async () => { auth = await testAuth(); From 11a6004413f966dc2149f7eb30af0d7956b1db9a Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 15:24:32 -0700 Subject: [PATCH 56/63] Really fix linting --- packages/firestore/src/lite-api/components.ts | 2 +- .../test/unit/remote/fetch_connection.test.ts | 24 ++++--------------- packages/storage/test/unit/service.test.ts | 1 - 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/packages/firestore/src/lite-api/components.ts b/packages/firestore/src/lite-api/components.ts index 6d4a161259f..52c3b3729ee 100644 --- a/packages/firestore/src/lite-api/components.ts +++ b/packages/firestore/src/lite-api/components.ts @@ -28,7 +28,7 @@ import { Datastore, newDatastore } from '../remote/datastore'; import { Code, FirestoreError } from '../util/error'; import { logDebug } from '../util/log'; -import { FirestoreSettingsImpl, PrivateSettings } from './settings'; +import { FirestoreSettingsImpl } from './settings'; export const LOG_TAG = 'ComponentProvider'; diff --git a/packages/firestore/test/unit/remote/fetch_connection.test.ts b/packages/firestore/test/unit/remote/fetch_connection.test.ts index 2663de459bd..528223e2d32 100644 --- a/packages/firestore/test/unit/remote/fetch_connection.test.ts +++ b/packages/firestore/test/unit/remote/fetch_connection.test.ts @@ -15,36 +15,22 @@ * limitations under the License. */ -import * as sinon from 'sinon'; import { expect, use } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import * as sinon from 'sinon'; +import sinonChai from 'sinon-chai'; + import { DatabaseId } from '../../../src/core/database_info'; import { makeDatabaseInfo } from '../../../src/lite-api/components'; -import { - FirestoreSettingsImpl, - PrivateSettings -} from '../../../src/lite-api/settings'; +import { FirestoreSettingsImpl } from '../../../src/lite-api/settings'; import { ResourcePath } from '../../../src/model/path'; import { FetchConnection } from '../../../src/platform/browser_lite/fetch_connection'; -import sinonChai from 'sinon-chai'; -import chaiAsPromised from 'chai-as-promised'; use(sinonChai); use(chaiAsPromised); describe('Fetch Connection', () => { it('should pass in credentials if using emulator and cloud workstation', async () => { - const privateSettings: PrivateSettings = { - emulatorOptions: {}, - host: 'abc.cloudworkstations.dev' - }; - console.log( - makeDatabaseInfo( - DatabaseId.empty(), - '', - '', - new FirestoreSettingsImpl(privateSettings) - ) - ); const stub = sinon.stub(globalThis, 'fetch'); stub.resolves({ ok: true, diff --git a/packages/storage/test/unit/service.test.ts b/packages/storage/test/unit/service.test.ts index f0b544c698a..9237b2b81a6 100644 --- a/packages/storage/test/unit/service.test.ts +++ b/packages/storage/test/unit/service.test.ts @@ -35,7 +35,6 @@ import { import { Location } from '../../src/implementation/location'; import { newTestConnection, TestingConnection } from './connection'; import { injectTestConnection } from '../../src/platform/connection'; -import { newTextConnection } from '../../src/platform/node/connection'; import sinonChai from 'sinon-chai'; const fakeAppGs = testShared.makeFakeApp('gs://mybucket'); From 28f80533c45c807c4f3b18cdfa1411dff45bc88f Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Tue, 29 Apr 2025 16:31:11 -0700 Subject: [PATCH 57/63] Brought back uncommented code --- packages/storage/test/unit/service.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/storage/test/unit/service.test.ts b/packages/storage/test/unit/service.test.ts index 9237b2b81a6..b37e624e3d1 100644 --- a/packages/storage/test/unit/service.test.ts +++ b/packages/storage/test/unit/service.test.ts @@ -48,8 +48,8 @@ function makeGsUrl(child: string = ''): string { } describe('Firebase Storage > Service', () => { - // before(() => injectTestConnection(newTestConnection)); - // after(() => injectTestConnection(null)); + before(() => injectTestConnection(newTestConnection)); + after(() => injectTestConnection(null)); describe('simple constructor', () => { const service = new FirebaseStorageImpl( From 2646d94fdf2dc6b186ad767d32ff49914ce783d7 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 30 Apr 2025 09:36:37 -0700 Subject: [PATCH 58/63] Removed app check changes --- packages/app-check/src/client.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/app-check/src/client.ts b/packages/app-check/src/client.ts index e8223675ae3..1861383174d 100644 --- a/packages/app-check/src/client.ts +++ b/packages/app-check/src/client.ts @@ -25,7 +25,6 @@ import { FirebaseApp } from '@firebase/app'; import { ERROR_FACTORY, AppCheckError } from './errors'; import { Provider } from '@firebase/component'; import { AppCheckTokenInternal } from './types'; -import { isCloudWorkstation } from '@firebase/util'; /** * Response JSON returned from AppCheck server endpoint. @@ -63,9 +62,6 @@ export async function exchangeToken( body: JSON.stringify(body), headers }; - if (isCloudWorkstation(url)) { - options.credentials = 'include'; - } let response; try { response = await fetch(url, options); From c282b7c3670b6f1e80c28016cf945c0457c7c623 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 30 Apr 2025 10:37:40 -0700 Subject: [PATCH 59/63] Moved emulator calculation to rest connection --- .../src/platform/browser/webchannel_connection.ts | 2 +- .../src/platform/browser_lite/fetch_connection.ts | 4 ++-- packages/firestore/src/remote/rest_connection.ts | 8 ++++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/firestore/src/platform/browser/webchannel_connection.ts b/packages/firestore/src/platform/browser/webchannel_connection.ts index a2d540b0e85..9a69164457e 100644 --- a/packages/firestore/src/platform/browser/webchannel_connection.ts +++ b/packages/firestore/src/platform/browser/webchannel_connection.ts @@ -72,7 +72,7 @@ export class WebChannelConnection extends RestConnection { url: string, headers: StringMap, body: Req, - _isUsingEmulator: boolean + _forwardCredentials: boolean ): Promise { const streamId = generateUniqueDebugId(); return new Promise((resolve: Resolver, reject: Rejecter) => { diff --git a/packages/firestore/src/platform/browser_lite/fetch_connection.ts b/packages/firestore/src/platform/browser_lite/fetch_connection.ts index 1404d7f9523..6d36490f926 100644 --- a/packages/firestore/src/platform/browser_lite/fetch_connection.ts +++ b/packages/firestore/src/platform/browser_lite/fetch_connection.ts @@ -41,7 +41,7 @@ export class FetchConnection extends RestConnection { url: string, headers: StringMap, body: Req, - isUsingEmulator: boolean + forwardCredentials: boolean ): Promise { const requestJson = JSON.stringify(body); let response: Response; @@ -52,7 +52,7 @@ export class FetchConnection extends RestConnection { headers, body: requestJson }; - if (isCloudWorkstation(new URL(url).host) && isUsingEmulator) { + if (forwardCredentials) { fetchArgs.credentials = 'include'; } response = await fetch(url, fetchArgs); diff --git a/packages/firestore/src/remote/rest_connection.ts b/packages/firestore/src/remote/rest_connection.ts index 60d4af5c1af..715ab631f93 100644 --- a/packages/firestore/src/remote/rest_connection.ts +++ b/packages/firestore/src/remote/rest_connection.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { isCloudWorkstation } from '@firebase/util'; import { SDK_VERSION } from '../../src/core/version'; import { Token } from '../api/credentials'; import { @@ -98,12 +99,15 @@ export abstract class RestConnection implements Connection { }; this.modifyHeadersForRequest(headers, authToken, appCheckToken); + const { host } = new URL(url); + const forwardCredentials = + isCloudWorkstation(host) && this.databaseInfo.isUsingEmulator; return this.performRPCRequest( rpcName, url, headers, req, - this.databaseInfo.isUsingEmulator + forwardCredentials ).then( response => { logDebug(LOG_TAG, `Received RPC '${rpcName}' ${streamId}: `, response); @@ -186,7 +190,7 @@ export abstract class RestConnection implements Connection { url: string, headers: StringMap, body: Req, - isUsingEmulator: boolean + _forwardCredentials: boolean ): Promise; private makeUrl(rpcName: string, path: string): string { From e61c6579563b17b916faa441a9a9fa0bcfa5cadf Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 30 Apr 2025 10:45:08 -0700 Subject: [PATCH 60/63] Fixed linting --- .../firestore/src/platform/browser_lite/fetch_connection.ts | 2 -- packages/firestore/src/remote/rest_connection.ts | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/firestore/src/platform/browser_lite/fetch_connection.ts b/packages/firestore/src/platform/browser_lite/fetch_connection.ts index 6d36490f926..227322153e9 100644 --- a/packages/firestore/src/platform/browser_lite/fetch_connection.ts +++ b/packages/firestore/src/platform/browser_lite/fetch_connection.ts @@ -15,8 +15,6 @@ * limitations under the License. */ -import { isCloudWorkstation } from '@firebase/util'; - import { Token } from '../../api/credentials'; import { Stream } from '../../remote/connection'; import { RestConnection } from '../../remote/rest_connection'; diff --git a/packages/firestore/src/remote/rest_connection.ts b/packages/firestore/src/remote/rest_connection.ts index 715ab631f93..49957bd5b13 100644 --- a/packages/firestore/src/remote/rest_connection.ts +++ b/packages/firestore/src/remote/rest_connection.ts @@ -16,6 +16,7 @@ */ import { isCloudWorkstation } from '@firebase/util'; + import { SDK_VERSION } from '../../src/core/version'; import { Token } from '../api/credentials'; import { From 840dc60fb7f516889bc61f24c76829a32573ba71 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 30 Apr 2025 11:39:22 -0700 Subject: [PATCH 61/63] Removed isEmulator check --- packages/firestore/src/remote/rest_connection.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/firestore/src/remote/rest_connection.ts b/packages/firestore/src/remote/rest_connection.ts index 49957bd5b13..2d6889dac3b 100644 --- a/packages/firestore/src/remote/rest_connection.ts +++ b/packages/firestore/src/remote/rest_connection.ts @@ -101,8 +101,7 @@ export abstract class RestConnection implements Connection { this.modifyHeadersForRequest(headers, authToken, appCheckToken); const { host } = new URL(url); - const forwardCredentials = - isCloudWorkstation(host) && this.databaseInfo.isUsingEmulator; + const forwardCredentials = isCloudWorkstation(host); return this.performRPCRequest( rpcName, url, From e422e05667c92642e70fff7a7b385f0f76607f35 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 30 Apr 2025 11:52:08 -0700 Subject: [PATCH 62/63] Updated fetch connection check --- packages/firestore/test/unit/remote/fetch_connection.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/firestore/test/unit/remote/fetch_connection.test.ts b/packages/firestore/test/unit/remote/fetch_connection.test.ts index 528223e2d32..5a9aa67436f 100644 --- a/packages/firestore/test/unit/remote/fetch_connection.test.ts +++ b/packages/firestore/test/unit/remote/fetch_connection.test.ts @@ -44,8 +44,7 @@ describe('Fetch Connection', () => { '', '', new FirestoreSettingsImpl({ - host: 'abc.cloudworkstations.dev', - emulatorOptions: {} + host: 'abc.cloudworkstations.dev' }) ) ); From 6d0b75eb457cab65b2ffa8b388bf83d7a60cf460 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 30 Apr 2025 11:53:07 -0700 Subject: [PATCH 63/63] Removed unnecessary package change --- .changeset/nine-pugs-crash.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/nine-pugs-crash.md b/.changeset/nine-pugs-crash.md index c3542b35d54..b4a654a484f 100644 --- a/.changeset/nine-pugs-crash.md +++ b/.changeset/nine-pugs-crash.md @@ -1,5 +1,4 @@ --- -"@firebase/app-check": patch "@firebase/auth": patch "@firebase/data-connect": patch "@firebase/database-compat": patch