From 7d0ba34f52022e96179a8ae9f246849480048bf0 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 2 Apr 2025 11:24:27 -0700 Subject: [PATCH 01/12] WIP --- packages/data-connect/src/api/DataConnect.ts | 20 ++++++++++--------- .../src/network/transport/index.ts | 2 +- .../test/unit/dataconnect.test.ts | 20 ++++++++++++++++++- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/data-connect/src/api/DataConnect.ts b/packages/data-connect/src/api/DataConnect.ts index dc170809143..b737976dd75 100644 --- a/packages/data-connect/src/api/DataConnect.ts +++ b/packages/data-connect/src/api/DataConnect.ts @@ -58,7 +58,6 @@ export interface ConnectorConfig { export interface TransportOptions { host: string; sslEnabled?: boolean; - port?: number; } const FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR = @@ -71,11 +70,15 @@ const FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR = * @internal */ export function parseOptions(fullHost: string): TransportOptions { - const [protocol, hostName] = fullHost.split('://'); - const isSecure = protocol === 'https'; - const [host, portAsString] = hostName.split(':'); - const port = Number(portAsString); - return { host, port, sslEnabled: isSecure }; + if (fullHost.startsWith('http://') || fullHost.startsWith('https://')) { + const [protocol, host] = fullHost.split('://'); + const isSecure = protocol === 'https'; + return { host, sslEnabled: isSecure }; + } + return { + host: fullHost, + sslEnabled: false + }; } /** * DataConnectOptions including project id @@ -182,7 +185,6 @@ export class DataConnect { if (this._transportOptions) { this._transport.useEmulator( this._transportOptions.host, - this._transportOptions.port, this._transportOptions.sslEnabled ); } @@ -219,7 +221,6 @@ export function areTransportOptionsEqual( ): boolean { return ( transportOptions1.host === transportOptions2.host && - transportOptions1.port === transportOptions2.port && transportOptions1.sslEnabled === transportOptions2.sslEnabled ); } @@ -237,7 +238,8 @@ export function connectDataConnectEmulator( port?: number, sslEnabled = false ): void { - dc.enableEmulator({ host, port, sslEnabled }); + const hostWithPort = port ? `${host}:${port}` : host; + dc.enableEmulator({ host: hostWithPort, sslEnabled }); } /** diff --git a/packages/data-connect/src/network/transport/index.ts b/packages/data-connect/src/network/transport/index.ts index 8b106b4d636..6470d205410 100644 --- a/packages/data-connect/src/network/transport/index.ts +++ b/packages/data-connect/src/network/transport/index.ts @@ -51,7 +51,7 @@ export interface DataConnectTransport { queryName: string, body?: U ): Promise<{ data: T; errors: Error[] }>; - useEmulator(host: string, port?: number, sslEnabled?: boolean): void; + useEmulator(host: string, sslEnabled?: boolean): void; onTokenChanged: (token: string | null) => void; _setCallerSdkType(callerSdkType: CallerSdkType): void; } diff --git a/packages/data-connect/test/unit/dataconnect.test.ts b/packages/data-connect/test/unit/dataconnect.test.ts index 76d04e3b502..6da7b82b3c5 100644 --- a/packages/data-connect/test/unit/dataconnect.test.ts +++ b/packages/data-connect/test/unit/dataconnect.test.ts @@ -18,7 +18,7 @@ import { deleteApp, initializeApp } from '@firebase/app'; import { expect } from 'chai'; -import { getDataConnect } from '../../src'; +import { getDataConnect, parseOptions } from '../../src'; describe('Data Connect Test', () => { beforeEach(() => {}); @@ -60,4 +60,22 @@ describe('Data Connect Test', () => { expect(dc.app.options.projectId).to.eq(projectId); await deleteApp(customApp); }); + it('should parse env var correctly with http://', async () => { + const parsedHost = parseOptions('http://localhost'); + expect(parsedHost.host).to.eq('localhost'); + expect(parsedHost.port).to.be.undefined; + expect(parsedHost.sslEnabled).to.be.false; + }); + it('should parse env var correctly with port', async () => { + const parsedHost = parseOptions('localhost:8080'); + expect(parsedHost.host).to.eq('localhost'); + expect(parsedHost.port).to.eq(8080); + expect(parsedHost.sslEnabled).to.be.false; + }); +it('should parse env var correctly with https://', async () => { + const parsedHost = parseOptions('https://localhost'); + expect(parsedHost.host).to.eq('localhost'); + expect(parsedHost.port).to.be.undefined; + expect(parsedHost.sslEnabled).to.be.true; + }); }); From 8c7f285bfe484413526766ab6c943e6e4673c7c9 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 2 Apr 2025 11:46:24 -0700 Subject: [PATCH 02/12] Fixed parsing --- .../data-connect/src/core/QueryManager.ts | 3 -- .../src/network/transport/rest.ts | 11 +---- packages/data-connect/src/util/url.ts | 15 +----- .../test/dataconnect/index.esm.js | 47 ------------------- .../dataconnect/logAddMovieVariables.json | 1 - .../dataconnect/logListAllMoviesMovies.json | 1 - .../dataconnect/logListMovieIdsMovies.json | 1 - .../test/dataconnect/movies.tools.json | 6 --- .../test/dataconnect/test.tools.json | 6 --- .../test/unit/dataconnect.test.ts | 5 +- .../test/unit/transportoptions.test.ts | 4 -- 11 files changed, 5 insertions(+), 95 deletions(-) delete mode 100644 packages/data-connect/test/dataconnect/index.esm.js delete mode 100644 packages/data-connect/test/dataconnect/logAddMovieVariables.json delete mode 100644 packages/data-connect/test/dataconnect/logListAllMoviesMovies.json delete mode 100644 packages/data-connect/test/dataconnect/logListMovieIdsMovies.json delete mode 100644 packages/data-connect/test/dataconnect/movies.tools.json delete mode 100644 packages/data-connect/test/dataconnect/test.tools.json diff --git a/packages/data-connect/src/core/QueryManager.ts b/packages/data-connect/src/core/QueryManager.ts index 8b7c59aea85..e8997614a6d 100644 --- a/packages/data-connect/src/core/QueryManager.ts +++ b/packages/data-connect/src/core/QueryManager.ts @@ -221,9 +221,6 @@ export class QueryManager { return newR; } - enableEmulator(host: string, port: number): void { - this.transport.useEmulator(host, port); - } } function compareDates(str1: string, str2: string): boolean { const date1 = new Date(str1); diff --git a/packages/data-connect/src/network/transport/rest.ts b/packages/data-connect/src/network/transport/rest.ts index 0663bc026db..26b04b82683 100644 --- a/packages/data-connect/src/network/transport/rest.ts +++ b/packages/data-connect/src/network/transport/rest.ts @@ -27,7 +27,6 @@ import { CallerSdkType, CallerSdkTypeEnum, DataConnectTransport } from '.'; export class RESTTransport implements DataConnectTransport { private _host = ''; - private _port: number | undefined; private _location = 'l'; private _connectorName = ''; private _secure = true; @@ -47,9 +46,6 @@ export class RESTTransport implements DataConnectTransport { private _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base ) { if (transportOptions) { - if (typeof transportOptions.port === 'number') { - this._port = transportOptions.port; - } if (typeof transportOptions.sslEnabled !== 'undefined') { this._secure = transportOptions.sslEnabled; } @@ -88,14 +84,11 @@ export class RESTTransport implements DataConnectTransport { projectId: this._project, service: this._serviceName }, - { host: this._host, sslEnabled: this._secure, port: this._port } + { host: this._host, sslEnabled: this._secure } ); } - useEmulator(host: string, port?: number, isSecure?: boolean): void { + useEmulator(host: string, isSecure?: boolean): void { this._host = host; - if (typeof port === 'number') { - this._port = port; - } if (typeof isSecure !== 'undefined') { this._secure = isSecure; } diff --git a/packages/data-connect/src/util/url.ts b/packages/data-connect/src/util/url.ts index 50630582761..5cd66cd6a01 100644 --- a/packages/data-connect/src/util/url.ts +++ b/packages/data-connect/src/util/url.ts @@ -16,27 +16,16 @@ */ import { DataConnectOptions, TransportOptions } from '../api/DataConnect'; -import { Code, DataConnectError } from '../core/error'; -import { logError } from '../logger'; export function urlBuilder( projectConfig: DataConnectOptions, transportOptions: TransportOptions ): string { const { connector, location, projectId: project, service } = projectConfig; - const { host, sslEnabled, port } = transportOptions; + const { host, sslEnabled } = transportOptions; const protocol = sslEnabled ? 'https' : 'http'; const realHost = host || `firebasedataconnect.googleapis.com`; - let baseUrl = `${protocol}://${realHost}`; - if (typeof port === 'number') { - baseUrl += `:${port}`; - } else if (typeof port !== 'undefined') { - logError('Port type is of an invalid type'); - throw new DataConnectError( - Code.INVALID_ARGUMENT, - 'Incorrect type for port passed in!' - ); - } + const baseUrl = `${protocol}://${realHost}`; return `${baseUrl}/v1/projects/${project}/locations/${location}/services/${service}/connectors/${connector}`; } export function addToken(url: string, apiKey?: string): string { diff --git a/packages/data-connect/test/dataconnect/index.esm.js b/packages/data-connect/test/dataconnect/index.esm.js deleted file mode 100644 index 6c7c8f8a49a..00000000000 --- a/packages/data-connect/test/dataconnect/index.esm.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @license - * Copyright 2024 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 { - getDataConnect, - queryRef, - mutationRef, - executeQuery, - executeMutation -} from 'firebase/data-connect'; - -export const connectorConfig = { - connector: 'test', - service: 'dataconnect', - location: 'us-central1' -}; - -function validateArgs(dcOrVars, vars, validateVars) { - let dcInstance; - let realVars; - // TODO(mtewani); Check what happens if this is undefined. - if (dcOrVars && 'dataConnectOptions' in dcOrVars) { - dcInstance = dcOrVars; - realVars = vars; - } else { - dcInstance = getDataConnect(connectorConfig); - realVars = dcOrVars; - } - if (!dcInstance || (!realVars && validateVars)) { - throw new Error('You didn\t pass in the vars!'); - } - return { dc: dcInstance, vars: realVars }; -} diff --git a/packages/data-connect/test/dataconnect/logAddMovieVariables.json b/packages/data-connect/test/dataconnect/logAddMovieVariables.json deleted file mode 100644 index 92e237b649f..00000000000 --- a/packages/data-connect/test/dataconnect/logAddMovieVariables.json +++ /dev/null @@ -1 +0,0 @@ -{"Name":"addMovie","Kind":"mutation","Variables":[{"Name":"id","TypeName":"String","TypeInfo":{"Name":"String","Kind":"NativeScalar","Fields":null,"KeyTypeInfo":null,"HasPrimaryKeyFields":false,"Description":""},"FullTypeInfo":null,"Attribute":"NonNull","DefaultValue":null,"Description":""},{"Name":"name","TypeName":"String","TypeInfo":{"Name":"String","Kind":"NativeScalar","Fields":null,"KeyTypeInfo":null,"HasPrimaryKeyFields":false,"Description":""},"FullTypeInfo":null,"Attribute":"NonNull","DefaultValue":null,"Description":""},{"Name":"genre","TypeName":"String","TypeInfo":{"Name":"String","Kind":"NativeScalar","Fields":null,"KeyTypeInfo":null,"HasPrimaryKeyFields":false,"Description":""},"FullTypeInfo":null,"Attribute":"NonNull","DefaultValue":null,"Description":""},{"Name":"description","TypeName":"String","TypeInfo":{"Name":"String","Kind":"NativeScalar","Fields":null,"KeyTypeInfo":null,"HasPrimaryKeyFields":false,"Description":""},"FullTypeInfo":null,"Attribute":"NonNull","DefaultValue":null,"Description":""}],"Response":[{"Name":"movie_insert","TypeName":"Movie_Key","TypeInfo":{"Name":"Movie_Key","Kind":"TypeKey","Fields":[{"Name":"id","TypeName":"String","TypeInfo":{"Name":"String","Kind":"NativeScalar","Fields":null,"KeyTypeInfo":null,"HasPrimaryKeyFields":false,"Description":""},"FullTypeInfo":null,"Attribute":"NonNull","DefaultValue":null,"Description":""}],"KeyTypeInfo":null,"HasPrimaryKeyFields":false,"Description":""},"FullTypeInfo":{"Name":"Movie_Key","Kind":"TypeKey","Fields":[{"Name":"id","TypeName":"String","TypeInfo":{"Name":"String","Kind":"NativeScalar","Fields":null,"KeyTypeInfo":null,"HasPrimaryKeyFields":false,"Description":""},"FullTypeInfo":null,"Attribute":"NonNull","DefaultValue":null,"Description":""}],"KeyTypeInfo":null,"HasPrimaryKeyFields":false,"Description":""},"Attribute":"NonNull","DefaultValue":null,"Description":""}],"Description":"# Example mutations\n# TODO: Replace with a really good illustrative example from devrel!\nmutation createOrder($name: String!) {\n order_insert(data : {name: $name})\n}"} \ No newline at end of file diff --git a/packages/data-connect/test/dataconnect/logListAllMoviesMovies.json b/packages/data-connect/test/dataconnect/logListAllMoviesMovies.json deleted file mode 100644 index ec747fa47dd..00000000000 --- a/packages/data-connect/test/dataconnect/logListAllMoviesMovies.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/packages/data-connect/test/dataconnect/logListMovieIdsMovies.json b/packages/data-connect/test/dataconnect/logListMovieIdsMovies.json deleted file mode 100644 index ec747fa47dd..00000000000 --- a/packages/data-connect/test/dataconnect/logListMovieIdsMovies.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/packages/data-connect/test/dataconnect/movies.tools.json b/packages/data-connect/test/dataconnect/movies.tools.json deleted file mode 100644 index f6938f8c163..00000000000 --- a/packages/data-connect/test/dataconnect/movies.tools.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "connector": "movies", - "location": "us-central1", - "service": "dataconnect", - "tools": [] -} \ No newline at end of file diff --git a/packages/data-connect/test/dataconnect/test.tools.json b/packages/data-connect/test/dataconnect/test.tools.json deleted file mode 100644 index a048e8da310..00000000000 --- a/packages/data-connect/test/dataconnect/test.tools.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "connector": "test", - "location": "us-central1", - "service": "dataconnect", - "tools": [] -} \ No newline at end of file diff --git a/packages/data-connect/test/unit/dataconnect.test.ts b/packages/data-connect/test/unit/dataconnect.test.ts index 6da7b82b3c5..5c3370308e9 100644 --- a/packages/data-connect/test/unit/dataconnect.test.ts +++ b/packages/data-connect/test/unit/dataconnect.test.ts @@ -63,19 +63,16 @@ describe('Data Connect Test', () => { it('should parse env var correctly with http://', async () => { const parsedHost = parseOptions('http://localhost'); expect(parsedHost.host).to.eq('localhost'); - expect(parsedHost.port).to.be.undefined; expect(parsedHost.sslEnabled).to.be.false; }); it('should parse env var correctly with port', async () => { const parsedHost = parseOptions('localhost:8080'); - expect(parsedHost.host).to.eq('localhost'); - expect(parsedHost.port).to.eq(8080); + expect(parsedHost.host).to.eq('localhost:8080'); expect(parsedHost.sslEnabled).to.be.false; }); it('should parse env var correctly with https://', async () => { const parsedHost = parseOptions('https://localhost'); expect(parsedHost.host).to.eq('localhost'); - expect(parsedHost.port).to.be.undefined; expect(parsedHost.sslEnabled).to.be.true; }); }); diff --git a/packages/data-connect/test/unit/transportoptions.test.ts b/packages/data-connect/test/unit/transportoptions.test.ts index a7136b5c408..bcddd6fc63d 100644 --- a/packages/data-connect/test/unit/transportoptions.test.ts +++ b/packages/data-connect/test/unit/transportoptions.test.ts @@ -29,12 +29,10 @@ describe('Transport Options', () => { it('should return false if transport options are not equal', () => { const transportOptions1: TransportOptions = { host: 'h', - port: 1, sslEnabled: false }; const transportOptions2: TransportOptions = { host: 'h2', - port: 2, sslEnabled: false }; expect( @@ -44,11 +42,9 @@ describe('Transport Options', () => { it('should return true if transport options are equal', () => { const transportOptions1: TransportOptions = { host: 'h', - port: 1, sslEnabled: false }; const transportOptions2: TransportOptions = { - port: 1, host: 'h', sslEnabled: false }; From ba0b1bd4b730de9e120123917d25b3faeb03dae6 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 2 Apr 2025 11:47:03 -0700 Subject: [PATCH 03/12] Fixed formatting --- packages/data-connect/src/api/DataConnect.ts | 2 +- packages/data-connect/test/unit/dataconnect.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/data-connect/src/api/DataConnect.ts b/packages/data-connect/src/api/DataConnect.ts index b737976dd75..958d5d7cf9a 100644 --- a/packages/data-connect/src/api/DataConnect.ts +++ b/packages/data-connect/src/api/DataConnect.ts @@ -238,7 +238,7 @@ export function connectDataConnectEmulator( port?: number, sslEnabled = false ): void { - const hostWithPort = port ? `${host}:${port}` : host; + const hostWithPort = port ? `${host}:${port}` : host; dc.enableEmulator({ host: hostWithPort, sslEnabled }); } diff --git a/packages/data-connect/test/unit/dataconnect.test.ts b/packages/data-connect/test/unit/dataconnect.test.ts index 5c3370308e9..5555b4f605f 100644 --- a/packages/data-connect/test/unit/dataconnect.test.ts +++ b/packages/data-connect/test/unit/dataconnect.test.ts @@ -70,7 +70,7 @@ describe('Data Connect Test', () => { expect(parsedHost.host).to.eq('localhost:8080'); expect(parsedHost.sslEnabled).to.be.false; }); -it('should parse env var correctly with https://', async () => { + it('should parse env var correctly with https://', async () => { const parsedHost = parseOptions('https://localhost'); expect(parsedHost.host).to.eq('localhost'); expect(parsedHost.sslEnabled).to.be.true; From f3b826a01338fa441e15c0e91fa39ad27533b4f3 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 2 Apr 2025 11:48:33 -0700 Subject: [PATCH 04/12] Included ipv6 parsing --- packages/data-connect/test/unit/dataconnect.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/data-connect/test/unit/dataconnect.test.ts b/packages/data-connect/test/unit/dataconnect.test.ts index 5555b4f605f..08637bf45e8 100644 --- a/packages/data-connect/test/unit/dataconnect.test.ts +++ b/packages/data-connect/test/unit/dataconnect.test.ts @@ -75,4 +75,11 @@ describe('Data Connect Test', () => { expect(parsedHost.host).to.eq('localhost'); expect(parsedHost.sslEnabled).to.be.true; }); + it('should parse ipv6 addresses correctly', async () => { + const host = '2001:0db8:85a3:0000:0000:8a2e:0370:7334'; + const parsedHost = parseOptions(host); + expect(parsedHost.host).to.eq(host); + expect(parsedHost.sslEnabled).to.be.false; + }); }); + From 5db3e15e02caea2083d9455368f2d94b7a3f3e6d Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 2 Apr 2025 11:52:07 -0700 Subject: [PATCH 05/12] Updated api changes --- common/api-review/data-connect.api.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/api-review/data-connect.api.md b/common/api-review/data-connect.api.md index 786714361af..f2e03755bd5 100644 --- a/common/api-review/data-connect.api.md +++ b/common/api-review/data-connect.api.md @@ -259,8 +259,6 @@ export interface TransportOptions { // (undocumented) host: string; // (undocumented) - port?: number; - // (undocumented) sslEnabled?: boolean; } From cb29de0379a07ace0d02ddf91359f0d9fe216e90 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 2 Apr 2025 11:55:14 -0700 Subject: [PATCH 06/12] Added back port usage --- common/api-review/data-connect.api.md | 2 ++ packages/data-connect/src/api/DataConnect.ts | 2 ++ packages/data-connect/src/network/transport/index.ts | 2 +- packages/data-connect/src/network/transport/rest.ts | 11 +++++++++-- packages/data-connect/test/unit/dataconnect.test.ts | 1 - 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/common/api-review/data-connect.api.md b/common/api-review/data-connect.api.md index f2e03755bd5..786714361af 100644 --- a/common/api-review/data-connect.api.md +++ b/common/api-review/data-connect.api.md @@ -259,6 +259,8 @@ export interface TransportOptions { // (undocumented) host: string; // (undocumented) + port?: number; + // (undocumented) sslEnabled?: boolean; } diff --git a/packages/data-connect/src/api/DataConnect.ts b/packages/data-connect/src/api/DataConnect.ts index 958d5d7cf9a..1f4e3b024ab 100644 --- a/packages/data-connect/src/api/DataConnect.ts +++ b/packages/data-connect/src/api/DataConnect.ts @@ -57,6 +57,7 @@ export interface ConnectorConfig { */ export interface TransportOptions { host: string; + port?: number; sslEnabled?: boolean; } @@ -185,6 +186,7 @@ export class DataConnect { if (this._transportOptions) { this._transport.useEmulator( this._transportOptions.host, + this._transportOptions.port, this._transportOptions.sslEnabled ); } diff --git a/packages/data-connect/src/network/transport/index.ts b/packages/data-connect/src/network/transport/index.ts index 6470d205410..0079d18ec72 100644 --- a/packages/data-connect/src/network/transport/index.ts +++ b/packages/data-connect/src/network/transport/index.ts @@ -51,7 +51,7 @@ export interface DataConnectTransport { queryName: string, body?: U ): Promise<{ data: T; errors: Error[] }>; - useEmulator(host: string, sslEnabled?: boolean): void; + useEmulator(host: string, port: number, sslEnabled?: boolean): void; onTokenChanged: (token: string | null) => void; _setCallerSdkType(callerSdkType: CallerSdkType): void; } diff --git a/packages/data-connect/src/network/transport/rest.ts b/packages/data-connect/src/network/transport/rest.ts index 26b04b82683..0663bc026db 100644 --- a/packages/data-connect/src/network/transport/rest.ts +++ b/packages/data-connect/src/network/transport/rest.ts @@ -27,6 +27,7 @@ import { CallerSdkType, CallerSdkTypeEnum, DataConnectTransport } from '.'; export class RESTTransport implements DataConnectTransport { private _host = ''; + private _port: number | undefined; private _location = 'l'; private _connectorName = ''; private _secure = true; @@ -46,6 +47,9 @@ export class RESTTransport implements DataConnectTransport { private _callerSdkType: CallerSdkType = CallerSdkTypeEnum.Base ) { if (transportOptions) { + if (typeof transportOptions.port === 'number') { + this._port = transportOptions.port; + } if (typeof transportOptions.sslEnabled !== 'undefined') { this._secure = transportOptions.sslEnabled; } @@ -84,11 +88,14 @@ export class RESTTransport implements DataConnectTransport { projectId: this._project, service: this._serviceName }, - { host: this._host, sslEnabled: this._secure } + { host: this._host, sslEnabled: this._secure, port: this._port } ); } - useEmulator(host: string, isSecure?: boolean): void { + useEmulator(host: string, port?: number, isSecure?: boolean): void { this._host = host; + if (typeof port === 'number') { + this._port = port; + } if (typeof isSecure !== 'undefined') { this._secure = isSecure; } diff --git a/packages/data-connect/test/unit/dataconnect.test.ts b/packages/data-connect/test/unit/dataconnect.test.ts index 08637bf45e8..475b2aecd1b 100644 --- a/packages/data-connect/test/unit/dataconnect.test.ts +++ b/packages/data-connect/test/unit/dataconnect.test.ts @@ -82,4 +82,3 @@ describe('Data Connect Test', () => { expect(parsedHost.sslEnabled).to.be.false; }); }); - From 2a02c9e04c2953cec86cc33ec312e96fde1f994d Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 2 Apr 2025 11:57:53 -0700 Subject: [PATCH 07/12] Added back tests --- packages/data-connect/src/api/DataConnect.ts | 1 + packages/data-connect/test/unit/transportoptions.test.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/packages/data-connect/src/api/DataConnect.ts b/packages/data-connect/src/api/DataConnect.ts index 1f4e3b024ab..5e39e2454bb 100644 --- a/packages/data-connect/src/api/DataConnect.ts +++ b/packages/data-connect/src/api/DataConnect.ts @@ -223,6 +223,7 @@ export function areTransportOptionsEqual( ): boolean { return ( transportOptions1.host === transportOptions2.host && + transportOptions1.port === transportOptions2.port && transportOptions1.sslEnabled === transportOptions2.sslEnabled ); } diff --git a/packages/data-connect/test/unit/transportoptions.test.ts b/packages/data-connect/test/unit/transportoptions.test.ts index bcddd6fc63d..a7136b5c408 100644 --- a/packages/data-connect/test/unit/transportoptions.test.ts +++ b/packages/data-connect/test/unit/transportoptions.test.ts @@ -29,10 +29,12 @@ describe('Transport Options', () => { it('should return false if transport options are not equal', () => { const transportOptions1: TransportOptions = { host: 'h', + port: 1, sslEnabled: false }; const transportOptions2: TransportOptions = { host: 'h2', + port: 2, sslEnabled: false }; expect( @@ -42,9 +44,11 @@ describe('Transport Options', () => { it('should return true if transport options are equal', () => { const transportOptions1: TransportOptions = { host: 'h', + port: 1, sslEnabled: false }; const transportOptions2: TransportOptions = { + port: 1, host: 'h', sslEnabled: false }; From bb812d7c5222c4f9396bf103ad012ec1ae4d7630 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 2 Apr 2025 11:58:55 -0700 Subject: [PATCH 08/12] Trimmed hostname --- packages/data-connect/src/api/DataConnect.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/data-connect/src/api/DataConnect.ts b/packages/data-connect/src/api/DataConnect.ts index 5e39e2454bb..8c6bdfc75ae 100644 --- a/packages/data-connect/src/api/DataConnect.ts +++ b/packages/data-connect/src/api/DataConnect.ts @@ -71,13 +71,14 @@ const FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR = * @internal */ export function parseOptions(fullHost: string): TransportOptions { - if (fullHost.startsWith('http://') || fullHost.startsWith('https://')) { - const [protocol, host] = fullHost.split('://'); + const trimmedHost = fullHost.trim(); + if (trimmedHost.startsWith('http://') || trimmedHost.startsWith('https://')) { + const [protocol, host] = trimmedHost.split('://'); const isSecure = protocol === 'https'; return { host, sslEnabled: isSecure }; } return { - host: fullHost, + host: trimmedHost, sslEnabled: false }; } From a89fc0428fd8144197b57134a4ce2d5ffb592dd3 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 2 Apr 2025 13:33:20 -0700 Subject: [PATCH 09/12] Updated signature --- packages/data-connect/src/network/transport/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/data-connect/src/network/transport/index.ts b/packages/data-connect/src/network/transport/index.ts index 0079d18ec72..8b106b4d636 100644 --- a/packages/data-connect/src/network/transport/index.ts +++ b/packages/data-connect/src/network/transport/index.ts @@ -51,7 +51,7 @@ export interface DataConnectTransport { queryName: string, body?: U ): Promise<{ data: T; errors: Error[] }>; - useEmulator(host: string, port: number, sslEnabled?: boolean): void; + useEmulator(host: string, port?: number, sslEnabled?: boolean): void; onTokenChanged: (token: string | null) => void; _setCallerSdkType(callerSdkType: CallerSdkType): void; } From f7d65ba75b204869efaf2e410e029565e21fa8d1 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 2 Apr 2025 14:32:36 -0700 Subject: [PATCH 10/12] Fixed non-http protocols --- packages/data-connect/src/api/DataConnect.ts | 8 +++++++- packages/data-connect/test/unit/dataconnect.test.ts | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/data-connect/src/api/DataConnect.ts b/packages/data-connect/src/api/DataConnect.ts index 8c6bdfc75ae..b03613d1171 100644 --- a/packages/data-connect/src/api/DataConnect.ts +++ b/packages/data-connect/src/api/DataConnect.ts @@ -72,8 +72,14 @@ const FIREBASE_DATA_CONNECT_EMULATOR_HOST_VAR = */ export function parseOptions(fullHost: string): TransportOptions { const trimmedHost = fullHost.trim(); - if (trimmedHost.startsWith('http://') || trimmedHost.startsWith('https://')) { + if (fullHost.includes('://')) { const [protocol, host] = trimmedHost.split('://'); + if (protocol !== 'http' && protocol !== 'https') { + throw new DataConnectError( + Code.INVALID_ARGUMENT, + `Protocol ${protocol} is not supported. Use 'http' or 'https' instead.` + ); + } const isSecure = protocol === 'https'; return { host, sslEnabled: isSecure }; } diff --git a/packages/data-connect/test/unit/dataconnect.test.ts b/packages/data-connect/test/unit/dataconnect.test.ts index 475b2aecd1b..a04a62c29cb 100644 --- a/packages/data-connect/test/unit/dataconnect.test.ts +++ b/packages/data-connect/test/unit/dataconnect.test.ts @@ -81,4 +81,10 @@ describe('Data Connect Test', () => { expect(parsedHost.host).to.eq(host); expect(parsedHost.sslEnabled).to.be.false; }); + it('should throw for non-http protocols', async () => { + const host = 'ftp://localhost'; + expect(() => parseOptions(host)).to.throw( + "Protocol ftp is not supported. Use 'http' or 'https' instead." + ); + }); }); From 55502d9ec78bcd064b8769c00fac7a8b8ef53b05 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 2 Apr 2025 14:33:46 -0700 Subject: [PATCH 11/12] Create hip-chefs-attack.md --- .changeset/hip-chefs-attack.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/hip-chefs-attack.md diff --git a/.changeset/hip-chefs-attack.md b/.changeset/hip-chefs-attack.md new file mode 100644 index 00000000000..84d7f6ea05b --- /dev/null +++ b/.changeset/hip-chefs-attack.md @@ -0,0 +1,5 @@ +--- +"@firebase/data-connect": patch +--- + +Fix issue where ipv6 addresses weren't getting parsed correctly when setting FIREBASE_DATA_CONNECT_EMULATOR_HOST From 8e6d81a8febb40a83731fc821dbc1769ff654812 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 4 Apr 2025 11:45:36 -0700 Subject: [PATCH 12/12] Added extra test --- packages/data-connect/test/unit/dataconnect.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/data-connect/test/unit/dataconnect.test.ts b/packages/data-connect/test/unit/dataconnect.test.ts index a04a62c29cb..b53be406dbd 100644 --- a/packages/data-connect/test/unit/dataconnect.test.ts +++ b/packages/data-connect/test/unit/dataconnect.test.ts @@ -81,6 +81,12 @@ describe('Data Connect Test', () => { expect(parsedHost.host).to.eq(host); expect(parsedHost.sslEnabled).to.be.false; }); + it('should parse ipv6 localhost addresses correctly', async () => { + const host = '[::1]:8080'; + const parsedHost = parseOptions(host); + expect(parsedHost.host).to.eq(host); + expect(parsedHost.sslEnabled).to.be.false; + }); it('should throw for non-http protocols', async () => { const host = 'ftp://localhost'; expect(() => parseOptions(host)).to.throw(