diff --git a/.changeset/beige-roses-cross.md b/.changeset/beige-roses-cross.md new file mode 100644 index 00000000000..395abbb1909 --- /dev/null +++ b/.changeset/beige-roses-cross.md @@ -0,0 +1,5 @@ +--- +'@firebase/data-connect': patch +--- + +- Throw error when calling `executeQuery` with mutations \ No newline at end of file diff --git a/packages/data-connect/src/core/QueryManager.ts b/packages/data-connect/src/core/QueryManager.ts index c82e0fee903..8b7c59aea85 100644 --- a/packages/data-connect/src/core/QueryManager.ts +++ b/packages/data-connect/src/core/QueryManager.ts @@ -37,7 +37,7 @@ import { DataConnectTransport } from '../network'; import { encoderImpl } from '../util/encoder'; import { setIfNotExists } from '../util/map'; -import { DataConnectError } from './error'; +import { Code, DataConnectError } from './error'; interface TrackedQuery { ref: Omit, 'dataConnect'>; @@ -172,6 +172,12 @@ export class QueryManager { executeQuery( queryRef: QueryRef ): QueryPromise { + if (queryRef.refType !== QUERY_STR) { + throw new DataConnectError( + Code.INVALID_ARGUMENT, + `ExecuteQuery can only execute query operation` + ); + } const key = encoderImpl({ name: queryRef.name, variables: queryRef.variables, diff --git a/packages/data-connect/test/unit/QueryManager.test.ts b/packages/data-connect/test/unit/QueryManager.test.ts new file mode 100644 index 00000000000..9acc948d57c --- /dev/null +++ b/packages/data-connect/test/unit/QueryManager.test.ts @@ -0,0 +1,65 @@ +/** + * @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 { deleteApp, FirebaseApp, initializeApp } from '@firebase/app'; +import { expect } from 'chai'; +import * as chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import { + DataConnect, + executeQuery, + getDataConnect, + mutationRef, + queryRef +} from '../../src'; +import { Code, DataConnectError } from '../../src/core/error'; +chai.use(chaiAsPromised); + +describe('Query Manager Tests', () => { + let dc: DataConnect; + let app: FirebaseApp; + const APPID = 'MYAPPID'; + const APPNAME = 'MYAPPNAME'; + + beforeEach(() => { + app = initializeApp({ projectId: 'p', appId: APPID }, APPNAME); + dc = getDataConnect(app, { + connector: 'c', + location: 'l', + service: 's' + }); + }); + afterEach(async () => { + await dc._delete(); + await deleteApp(app); + }); + + it('should refuse to make requests to execute non-query operations', async () => { + const query = queryRef(dc, 'q'); + const mutation = mutationRef(dc, 'm'); + + const error = new DataConnectError( + Code.INVALID_ARGUMENT, + `ExecuteQuery can only execute query operation` + ); + + // @ts-ignore + expect(() => executeQuery(mutation)).to.throw(error.message); + expect(() => executeQuery(query)).to.not.throw(error.message); + }); +});