From f63d34d2c1c3c40e167631906eda7b3323614b28 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 26 Feb 2025 13:34:27 -0500 Subject: [PATCH 01/16] Add API for partial errors --- packages/data-connect/src/api/index.ts | 8 ++++ packages/data-connect/src/core/error.ts | 62 ++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/packages/data-connect/src/api/index.ts b/packages/data-connect/src/api/index.ts index 885dac5a923..71bd95557dc 100644 --- a/packages/data-connect/src/api/index.ts +++ b/packages/data-connect/src/api/index.ts @@ -22,3 +22,11 @@ export * from './Mutation'; export * from './query'; export { setLogLevel } from '../logger'; export { validateArgs } from '../util/validateArgs'; + +export { DataConnectError, DataConnectOperationError } from '../core/error'; + +export type { + DataConnectErrorCode, + DataConnectOperationResponse, + DataConnectOperationErrorInfo +} from '../core/error'; diff --git a/packages/data-connect/src/core/error.ts b/packages/data-connect/src/core/error.ts index f0beb128afa..6aed2d4bb0f 100644 --- a/packages/data-connect/src/core/error.ts +++ b/packages/data-connect/src/core/error.ts @@ -40,8 +40,8 @@ export const Code = { /** An error returned by a DataConnect operation. */ export class DataConnectError extends FirebaseError { - /** The stack of the error. */ - readonly stack?: string; + /** The custom name for DataConnectError. */ + readonly name: string = 'DataConnectError'; /** @hideconstructor */ constructor( @@ -56,9 +56,59 @@ export class DataConnectError extends FirebaseError { ) { super(code, message); - // HACK: We write a toString property directly because Error is not a real - // class and so inheritance does not work correctly. We could alternatively - // do the same "back-door inheritance" trick that FirebaseError does. - this.toString = () => `${this.name}: [code=${this.code}]: ${this.message}`; + // Ensure the instanceof operator works as expected on subclasses of Error. + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#custom_error_types + // and https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget + Object.setPrototypeOf(this, new.target.prototype); } + + toString(): string { + return `${this.name}[code=${this.code}]: ${this.message}`; + } +} + +/** An error returned by a DataConnect operation. */ +export class DataConnectOperationError extends DataConnectError { + /** The custom name for DataConnectOperationError. */ + readonly name: string = 'DataConnectOperationError'; + + /** The response received from the backend. */ + readonly response: DataConnectOperationResponse; + + /** @hideconstructor */ + constructor(message: string, response: DataConnectOperationResponse) { + super('partial-error', message); + this.response = response; + + // Ensure the instanceof operator works as expected on subclasses of Error. + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#custom_error_types + // and https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget + Object.setPrototypeOf(this, new.target.prototype); + } +} + +export interface DataConnectOperationResponse { + // The "data" provided by the backend in the response message. + // + // Will be `undefined` if no "data" was provided in the response message. + // Otherwise, will be `null` if `null` was explicitly specified as the "data" + // in the response message. Otherwise, will be the value of the "data" + // specified as the "data" in the response message + readonly data?: Record | null; + + // The list of errors provided by the backend in the response message. + readonly errors: DataConnectOperationErrorInfo[]; +} + +// Information about the error, as provided in the response from the backend. +// See https://spec.graphql.org/draft/#sec-Errors +export interface DataConnectOperationErrorInfo { + // The error message. + readonly message: string; + + // The path of the field in the response data to which this error relates. + // String values in this array refer to field names. Numeric values in this + // array always satisfy `Number.isInteger()` and refer to the index in an + // array. + readonly path: Array; } From 6032daff7f2a52af3cca234344a85555cfddb96b Mon Sep 17 00:00:00 2001 From: dconeybe Date: Wed, 26 Feb 2025 18:43:58 +0000 Subject: [PATCH 02/16] Update API reports --- common/api-review/data-connect.api.md | 38 +++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/common/api-review/data-connect.api.md b/common/api-review/data-connect.api.md index 1a698c229b4..833a988bfb9 100644 --- a/common/api-review/data-connect.api.md +++ b/common/api-review/data-connect.api.md @@ -52,6 +52,40 @@ export class DataConnect { setInitialized(): void; } +// @public +export class DataConnectError extends FirebaseError { + readonly code: DataConnectErrorCode; + readonly message: string; + readonly name: string; + // (undocumented) + toString(): string; +} + +// @public (undocumented) +export type DataConnectErrorCode = 'other' | 'already-initialized' | 'not-initialized' | 'not-supported' | 'invalid-argument' | 'partial-error' | 'unauthorized'; + +// @public +export class DataConnectOperationError extends DataConnectError { + readonly name: string; + readonly response: DataConnectOperationResponse; +} + +// @public (undocumented) +export interface DataConnectOperationErrorInfo { + // (undocumented) + readonly message: string; + // (undocumented) + readonly path: Array; +} + +// @public (undocumented) +export interface DataConnectOperationResponse { + // (undocumented) + readonly data?: Record | null; + // (undocumented) + readonly errors: DataConnectOperationErrorInfo[]; +} + // @public export interface DataConnectOptions extends ConnectorConfig { // (undocumented) @@ -67,7 +101,7 @@ export interface DataConnectResult extends OpResult { // @public export interface DataConnectSubscription { // (undocumented) - errCallback?: (e?: FirebaseError) => void; + errCallback?: (e?: DataConnectError) => void; // (undocumented) unsubscribe: () => void; // (undocumented) @@ -118,7 +152,7 @@ export interface MutationResult extends DataConnectResult void; // @public -export type OnErrorSubscription = (err?: FirebaseError) => void; +export type OnErrorSubscription = (err?: DataConnectError) => void; // @public export type OnResultSubscription = (res: QueryResult) => void; From c5d38292bf7ba4798aa3dd37ba7fa28c38825557 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 26 Feb 2025 13:58:53 -0500 Subject: [PATCH 03/16] src/core/error.ts: cleanups --- packages/data-connect/src/core/error.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/data-connect/src/core/error.ts b/packages/data-connect/src/core/error.ts index 6aed2d4bb0f..3c817f616c3 100644 --- a/packages/data-connect/src/core/error.ts +++ b/packages/data-connect/src/core/error.ts @@ -40,7 +40,7 @@ export const Code = { /** An error returned by a DataConnect operation. */ export class DataConnectError extends FirebaseError { - /** The custom name for DataConnectError. */ + /** @internal */ readonly name: string = 'DataConnectError'; /** @hideconstructor */ @@ -52,7 +52,7 @@ export class DataConnectError extends FirebaseError { /** * A custom error description. */ - readonly message: string + message: string ) { super(code, message); @@ -62,6 +62,7 @@ export class DataConnectError extends FirebaseError { Object.setPrototypeOf(this, new.target.prototype); } + /** @internal */ toString(): string { return `${this.name}[code=${this.code}]: ${this.message}`; } @@ -69,7 +70,7 @@ export class DataConnectError extends FirebaseError { /** An error returned by a DataConnect operation. */ export class DataConnectOperationError extends DataConnectError { - /** The custom name for DataConnectOperationError. */ + /** @internal */ readonly name: string = 'DataConnectOperationError'; /** The response received from the backend. */ From 8a33180826a6ac273ff19424a6c05a3c899173d8 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Wed, 26 Feb 2025 14:00:27 -0500 Subject: [PATCH 04/16] data-connect.api.md: updated --- common/api-review/data-connect.api.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/common/api-review/data-connect.api.md b/common/api-review/data-connect.api.md index 833a988bfb9..1b93be0e9c3 100644 --- a/common/api-review/data-connect.api.md +++ b/common/api-review/data-connect.api.md @@ -55,10 +55,6 @@ export class DataConnect { // @public export class DataConnectError extends FirebaseError { readonly code: DataConnectErrorCode; - readonly message: string; - readonly name: string; - // (undocumented) - toString(): string; } // @public (undocumented) @@ -66,7 +62,7 @@ export type DataConnectErrorCode = 'other' | 'already-initialized' | 'not-initia // @public export class DataConnectOperationError extends DataConnectError { - readonly name: string; + /* Excluded from this release type: name */ readonly response: DataConnectOperationResponse; } From 9f535fba730e89d30a6cb0d3a11252e913e77fa7 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 28 Feb 2025 15:34:36 -0800 Subject: [PATCH 05/16] Implemented partial error --- packages/data-connect/src/network/fetch.ts | 18 ++++++++-- packages/data-connect/test/unit/fetch.test.ts | 36 ++++++++++++++++++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/packages/data-connect/src/network/fetch.ts b/packages/data-connect/src/network/fetch.ts index 166422ca14c..eb1d22b6a3f 100644 --- a/packages/data-connect/src/network/fetch.ts +++ b/packages/data-connect/src/network/fetch.ts @@ -15,7 +15,12 @@ * limitations under the License. */ -import { Code, DataConnectError } from '../core/error'; +import { + Code, + DataConnectError, + DataConnectOperationError, + DataConnectOperationResponse +} from '../core/error'; import { SDK_VERSION } from '../core/version'; import { logDebug, logError } from '../logger'; @@ -106,10 +111,17 @@ export function dcFetch( return jsonResponse; }) .then(res => { + console.log(res.errors); if (res.errors && res.errors.length) { const stringified = JSON.stringify(res.errors); - logError('DataConnect error while performing request: ' + stringified); - throw new DataConnectError(Code.OTHER, stringified); + const response: DataConnectOperationResponse = { + errors: res.errors, + data: res.data + }; + throw new DataConnectOperationError( + 'DataConnect error while performing request: ' + stringified, + response + ); } return res; }); diff --git a/packages/data-connect/test/unit/fetch.test.ts b/packages/data-connect/test/unit/fetch.test.ts index 599260f8b10..688886934d7 100644 --- a/packages/data-connect/test/unit/fetch.test.ts +++ b/packages/data-connect/test/unit/fetch.test.ts @@ -34,7 +34,7 @@ function mockFetch(json: object, reject: boolean): sinon.SinonStub { initializeFetch(fakeFetchImpl); return fakeFetchImpl; } -describe('fetch', () => { +describe.only('fetch', () => { it('should throw an error with just the message when the server responds with an error with a message property in the body', async () => { const message = 'Failed to connect to Postgres instance'; mockFetch( @@ -85,6 +85,40 @@ describe('fetch', () => { ) ).to.eventually.be.rejectedWith(JSON.stringify(json)); }); + it.only('should throw a stringified message when the server responds with an error without a message property in the body', async () => { + const json = { + 'data': { 'abc': 'def' }, + 'errors': [ + { + 'message': + 'SQL query error: pq: duplicate key value violates unique constraint movie_pkey', + 'locations': [], + 'path': ['the_matrix'], + 'extensions': null + } + ] + }; + mockFetch(json, false); + await expect( + dcFetch( + 'http://localhost', + { + name: 'n', + operationName: 'n', + variables: {} + }, + {} as AbortController, + null, + null, + null, + false, + CallerSdkTypeEnum.Base + ) + ).to.eventually.be.rejected.then(error => { + expect(error.response.data).to.eq(json.data); + expect(error.response.errors).to.eq(json.errors); + }); + }); it('should assign different values to custom headers based on the _callerSdkType argument (_isUsingGen is false)', async () => { const json = { code: 200, From 763dcd3f32cb43d2382b8452fbb683c7af20808d Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 28 Feb 2025 15:38:12 -0800 Subject: [PATCH 06/16] Removed only --- packages/data-connect/test/unit/fetch.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/data-connect/test/unit/fetch.test.ts b/packages/data-connect/test/unit/fetch.test.ts index 688886934d7..6cf2750d50d 100644 --- a/packages/data-connect/test/unit/fetch.test.ts +++ b/packages/data-connect/test/unit/fetch.test.ts @@ -34,7 +34,7 @@ function mockFetch(json: object, reject: boolean): sinon.SinonStub { initializeFetch(fakeFetchImpl); return fakeFetchImpl; } -describe.only('fetch', () => { +describe('fetch', () => { it('should throw an error with just the message when the server responds with an error with a message property in the body', async () => { const message = 'Failed to connect to Postgres instance'; mockFetch( @@ -85,7 +85,7 @@ describe.only('fetch', () => { ) ).to.eventually.be.rejectedWith(JSON.stringify(json)); }); - it.only('should throw a stringified message when the server responds with an error without a message property in the body', async () => { + it('should throw a stringified message when the server responds with an error without a message property in the body', async () => { const json = { 'data': { 'abc': 'def' }, 'errors': [ From 8978a654e3efc7845565b7876648ed537c8ddd3f Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 28 Feb 2025 15:41:03 -0800 Subject: [PATCH 07/16] Removed only --- packages/data-connect/src/network/fetch.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/data-connect/src/network/fetch.ts b/packages/data-connect/src/network/fetch.ts index eb1d22b6a3f..abcb4966d70 100644 --- a/packages/data-connect/src/network/fetch.ts +++ b/packages/data-connect/src/network/fetch.ts @@ -111,7 +111,6 @@ export function dcFetch( return jsonResponse; }) .then(res => { - console.log(res.errors); if (res.errors && res.errors.length) { const stringified = JSON.stringify(res.errors); const response: DataConnectOperationResponse = { From 1ce98e6ed1026222036dee03ed7dea13e876f391 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 19 Mar 2025 14:42:35 -0700 Subject: [PATCH 08/16] Updated error type name --- packages/data-connect/src/core/error.ts | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/packages/data-connect/src/core/error.ts b/packages/data-connect/src/core/error.ts index 3c817f616c3..87e9160f0de 100644 --- a/packages/data-connect/src/core/error.ts +++ b/packages/data-connect/src/core/error.ts @@ -44,22 +44,13 @@ export class DataConnectError extends FirebaseError { readonly name: string = 'DataConnectError'; /** @hideconstructor */ - constructor( - /** - * The backend error code associated with this error. - */ - readonly code: DataConnectErrorCode, - /** - * A custom error description. - */ - message: string - ) { + constructor(code: Code, message: string) { super(code, message); // Ensure the instanceof operator works as expected on subclasses of Error. // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#custom_error_types // and https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget - Object.setPrototypeOf(this, new.target.prototype); + Object.setPrototypeOf(this, DataConnectError.prototype); } /** @internal */ @@ -78,13 +69,8 @@ export class DataConnectOperationError extends DataConnectError { /** @hideconstructor */ constructor(message: string, response: DataConnectOperationResponse) { - super('partial-error', message); + super(Code.PARTIAL_ERROR, message); this.response = response; - - // Ensure the instanceof operator works as expected on subclasses of Error. - // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#custom_error_types - // and https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget - Object.setPrototypeOf(this, new.target.prototype); } } From c61652841da66418763e030578147fef8e4273b1 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 19 Mar 2025 14:44:06 -0700 Subject: [PATCH 09/16] Updated data connect API --- common/api-review/data-connect.api.md | 41 ++++++--------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/common/api-review/data-connect.api.md b/common/api-review/data-connect.api.md index 1b93be0e9c3..383d1ae33e1 100644 --- a/common/api-review/data-connect.api.md +++ b/common/api-review/data-connect.api.md @@ -52,36 +52,6 @@ export class DataConnect { setInitialized(): void; } -// @public -export class DataConnectError extends FirebaseError { - readonly code: DataConnectErrorCode; -} - -// @public (undocumented) -export type DataConnectErrorCode = 'other' | 'already-initialized' | 'not-initialized' | 'not-supported' | 'invalid-argument' | 'partial-error' | 'unauthorized'; - -// @public -export class DataConnectOperationError extends DataConnectError { - /* Excluded from this release type: name */ - readonly response: DataConnectOperationResponse; -} - -// @public (undocumented) -export interface DataConnectOperationErrorInfo { - // (undocumented) - readonly message: string; - // (undocumented) - readonly path: Array; -} - -// @public (undocumented) -export interface DataConnectOperationResponse { - // (undocumented) - readonly data?: Record | null; - // (undocumented) - readonly errors: DataConnectOperationErrorInfo[]; -} - // @public export interface DataConnectOptions extends ConnectorConfig { // (undocumented) @@ -97,7 +67,7 @@ export interface DataConnectResult extends OpResult { // @public export interface DataConnectSubscription { // (undocumented) - errCallback?: (e?: DataConnectError) => void; + errCallback?: (e?: FirebaseError) => void; // (undocumented) unsubscribe: () => void; // (undocumented) @@ -113,6 +83,9 @@ export function executeMutation(mutationRef: MutationRef(queryRef: QueryRef): QueryPromise; +// @public (undocumented) +export const fdcSymbol: unique symbol; + // @public export function getDataConnect(options: ConnectorConfig): DataConnect; @@ -148,13 +121,15 @@ export interface MutationResult extends DataConnectResult void; // @public -export type OnErrorSubscription = (err?: DataConnectError) => void; +export type OnErrorSubscription = (err?: FirebaseError) => void; // @public export type OnResultSubscription = (res: QueryResult) => void; // @public (undocumented) -export interface OperationRef<_Data, Variables> { +export interface OperationRef { + // (undocumented) + [fdcSymbol]?: Data; // (undocumented) dataConnect: DataConnect; // (undocumented) From 1f5fa0305607cac1d43174512f1f8f5dc002c62d Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 19 Mar 2025 14:56:12 -0700 Subject: [PATCH 10/16] Updated typings --- common/api-review/data-connect.api.md | 40 ++++++++++++++++++++------ packages/data-connect/src/api/index.ts | 2 +- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/common/api-review/data-connect.api.md b/common/api-review/data-connect.api.md index 383d1ae33e1..0652d07820f 100644 --- a/common/api-review/data-connect.api.md +++ b/common/api-review/data-connect.api.md @@ -52,6 +52,35 @@ export class DataConnect { setInitialized(): void; } +// @public +export class DataConnectError extends FirebaseError { + } + +// @public (undocumented) +export type DataConnectErrorCode = 'other' | 'already-initialized' | 'not-initialized' | 'not-supported' | 'invalid-argument' | 'partial-error' | 'unauthorized'; + +// @public +export class DataConnectOperationError extends DataConnectError { + /* Excluded from this release type: name */ + readonly response: DataConnectOperationResponse; +} + +// @public (undocumented) +export interface DataConnectOperationErrorInfo { + // (undocumented) + readonly message: string; + // (undocumented) + readonly path: Array; +} + +// @public (undocumented) +export interface DataConnectOperationResponse { + // (undocumented) + readonly data?: Record | null; + // (undocumented) + readonly errors: DataConnectOperationErrorInfo[]; +} + // @public export interface DataConnectOptions extends ConnectorConfig { // (undocumented) @@ -67,7 +96,7 @@ export interface DataConnectResult extends OpResult { // @public export interface DataConnectSubscription { // (undocumented) - errCallback?: (e?: FirebaseError) => void; + errCallback?: (e?: DataConnectError) => void; // (undocumented) unsubscribe: () => void; // (undocumented) @@ -83,9 +112,6 @@ export function executeMutation(mutationRef: MutationRef(queryRef: QueryRef): QueryPromise; -// @public (undocumented) -export const fdcSymbol: unique symbol; - // @public export function getDataConnect(options: ConnectorConfig): DataConnect; @@ -121,15 +147,13 @@ export interface MutationResult extends DataConnectResult void; // @public -export type OnErrorSubscription = (err?: FirebaseError) => void; +export type OnErrorSubscription = (err?: DataConnectError) => void; // @public export type OnResultSubscription = (res: QueryResult) => void; // @public (undocumented) -export interface OperationRef { - // (undocumented) - [fdcSymbol]?: Data; +export interface OperationRef<_Data, Variables> { // (undocumented) dataConnect: DataConnect; // (undocumented) diff --git a/packages/data-connect/src/api/index.ts b/packages/data-connect/src/api/index.ts index 71bd95557dc..8f84e23bdaf 100644 --- a/packages/data-connect/src/api/index.ts +++ b/packages/data-connect/src/api/index.ts @@ -25,7 +25,7 @@ export { validateArgs } from '../util/validateArgs'; export { DataConnectError, DataConnectOperationError } from '../core/error'; -export type { +export { DataConnectErrorCode, DataConnectOperationResponse, DataConnectOperationErrorInfo From a41d2ef0da76c583a0ae2d2ad2e513d7080b8dc4 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 19 Mar 2025 14:57:53 -0700 Subject: [PATCH 11/16] Create sharp-nails-glow.md --- .changeset/sharp-nails-glow.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sharp-nails-glow.md diff --git a/.changeset/sharp-nails-glow.md b/.changeset/sharp-nails-glow.md new file mode 100644 index 00000000000..68c5e68c39d --- /dev/null +++ b/.changeset/sharp-nails-glow.md @@ -0,0 +1,5 @@ +--- +"@firebase/data-connect": patch +--- + +Expose partial errors to the user. From 23b7845015fe45e5caba9820c1afb9266cfe8a61 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 19 Mar 2025 15:46:23 -0700 Subject: [PATCH 12/16] Addressed comments --- packages/data-connect/src/api/index.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/data-connect/src/api/index.ts b/packages/data-connect/src/api/index.ts index 8f84e23bdaf..cf3f6fd5d47 100644 --- a/packages/data-connect/src/api/index.ts +++ b/packages/data-connect/src/api/index.ts @@ -22,11 +22,10 @@ export * from './Mutation'; export * from './query'; export { setLogLevel } from '../logger'; export { validateArgs } from '../util/validateArgs'; - -export { DataConnectError, DataConnectOperationError } from '../core/error'; - export { DataConnectErrorCode, + DataConnectError, + DataConnectOperationError, DataConnectOperationResponse, DataConnectOperationErrorInfo } from '../core/error'; From 12ce1bd7494e1094e35dac2c543188e38c3bdffd Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Thu, 20 Mar 2025 09:32:35 -0700 Subject: [PATCH 13/16] Addressed comments --- packages/data-connect/src/api/index.ts | 4 ++-- packages/data-connect/src/core/error.ts | 10 +++++----- packages/data-connect/src/network/fetch.ts | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/data-connect/src/api/index.ts b/packages/data-connect/src/api/index.ts index cf3f6fd5d47..dcd48485571 100644 --- a/packages/data-connect/src/api/index.ts +++ b/packages/data-connect/src/api/index.ts @@ -26,6 +26,6 @@ export { DataConnectErrorCode, DataConnectError, DataConnectOperationError, - DataConnectOperationResponse, - DataConnectOperationErrorInfo + DataConnectOperationFailureResponse, + DataConnectOperationFailureResponseErrorInfo } from '../core/error'; diff --git a/packages/data-connect/src/core/error.ts b/packages/data-connect/src/core/error.ts index 87e9160f0de..b1246969e48 100644 --- a/packages/data-connect/src/core/error.ts +++ b/packages/data-connect/src/core/error.ts @@ -65,16 +65,16 @@ export class DataConnectOperationError extends DataConnectError { readonly name: string = 'DataConnectOperationError'; /** The response received from the backend. */ - readonly response: DataConnectOperationResponse; + readonly response: DataConnectOperationFailureResponse; /** @hideconstructor */ - constructor(message: string, response: DataConnectOperationResponse) { + constructor(message: string, response: DataConnectOperationFailureResponse) { super(Code.PARTIAL_ERROR, message); this.response = response; } } -export interface DataConnectOperationResponse { +export interface DataConnectOperationFailureResponse { // The "data" provided by the backend in the response message. // // Will be `undefined` if no "data" was provided in the response message. @@ -84,12 +84,12 @@ export interface DataConnectOperationResponse { readonly data?: Record | null; // The list of errors provided by the backend in the response message. - readonly errors: DataConnectOperationErrorInfo[]; + readonly errors: DataConnectOperationFailureResponseErrorInfo[]; } // Information about the error, as provided in the response from the backend. // See https://spec.graphql.org/draft/#sec-Errors -export interface DataConnectOperationErrorInfo { +export interface DataConnectOperationFailureResponseErrorInfo { // The error message. readonly message: string; diff --git a/packages/data-connect/src/network/fetch.ts b/packages/data-connect/src/network/fetch.ts index abcb4966d70..8353c6b99ab 100644 --- a/packages/data-connect/src/network/fetch.ts +++ b/packages/data-connect/src/network/fetch.ts @@ -19,7 +19,7 @@ import { Code, DataConnectError, DataConnectOperationError, - DataConnectOperationResponse + DataConnectOperationFailureResponse } from '../core/error'; import { SDK_VERSION } from '../core/version'; import { logDebug, logError } from '../logger'; @@ -113,7 +113,7 @@ export function dcFetch( .then(res => { if (res.errors && res.errors.length) { const stringified = JSON.stringify(res.errors); - const response: DataConnectOperationResponse = { + const response: DataConnectOperationFailureResponse = { errors: res.errors, data: res.data }; From d650f5d0710518d71774173ed24708a7ed7b551f Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Thu, 20 Mar 2025 10:14:14 -0700 Subject: [PATCH 14/16] Updated docgen --- common/api-review/data-connect.api.md | 14 +++++++------- .../test/dataconnect/connector/connector.yaml | 6 +++--- packages/data-connect/test/mutations.gql | 6 ------ 3 files changed, 10 insertions(+), 16 deletions(-) delete mode 100644 packages/data-connect/test/mutations.gql diff --git a/common/api-review/data-connect.api.md b/common/api-review/data-connect.api.md index 0652d07820f..786714361af 100644 --- a/common/api-review/data-connect.api.md +++ b/common/api-review/data-connect.api.md @@ -62,23 +62,23 @@ export type DataConnectErrorCode = 'other' | 'already-initialized' | 'not-initia // @public export class DataConnectOperationError extends DataConnectError { /* Excluded from this release type: name */ - readonly response: DataConnectOperationResponse; + readonly response: DataConnectOperationFailureResponse; } // @public (undocumented) -export interface DataConnectOperationErrorInfo { +export interface DataConnectOperationFailureResponse { // (undocumented) - readonly message: string; + readonly data?: Record | null; // (undocumented) - readonly path: Array; + readonly errors: DataConnectOperationFailureResponseErrorInfo[]; } // @public (undocumented) -export interface DataConnectOperationResponse { +export interface DataConnectOperationFailureResponseErrorInfo { // (undocumented) - readonly data?: Record | null; + readonly message: string; // (undocumented) - readonly errors: DataConnectOperationErrorInfo[]; + readonly path: Array; } // @public diff --git a/packages/data-connect/test/dataconnect/connector/connector.yaml b/packages/data-connect/test/dataconnect/connector/connector.yaml index e945b44b00c..e4cde271588 100644 --- a/packages/data-connect/test/dataconnect/connector/connector.yaml +++ b/packages/data-connect/test/dataconnect/connector/connector.yaml @@ -1,6 +1,6 @@ connectorId: "tests" authMode: "PUBLIC" generate: - javascriptSdk: - outputDir: "./gen/web" - package: "@test-app/tests" + javascriptSdk: + outputDir: "./gen/web" + package: "@test-app/tests" diff --git a/packages/data-connect/test/mutations.gql b/packages/data-connect/test/mutations.gql deleted file mode 100644 index a826a39529a..00000000000 --- a/packages/data-connect/test/mutations.gql +++ /dev/null @@ -1,6 +0,0 @@ -mutation seedDatabase($id: UUID!, $content: String!) @auth(level: PUBLIC) { - post: post_insert(data: {id: $id, content: $content}) -} -mutation removePost($id: UUID!) @auth(level: PUBLIC) { - post: post_delete(id: $id) -} \ No newline at end of file From e1f55338f00f4504259489864f5786cd297c02e2 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Thu, 20 Mar 2025 15:23:44 -0700 Subject: [PATCH 15/16] Bumped emulator version --- packages/data-connect/test/emulatorSeeder.ts | 68 ------------------- .../emulators/dataconnect-emulator.ts | 2 +- .../emulator-testing/emulators/emulator.ts | 5 +- 3 files changed, 5 insertions(+), 70 deletions(-) delete mode 100644 packages/data-connect/test/emulatorSeeder.ts diff --git a/packages/data-connect/test/emulatorSeeder.ts b/packages/data-connect/test/emulatorSeeder.ts deleted file mode 100644 index 1517deb90f8..00000000000 --- a/packages/data-connect/test/emulatorSeeder.ts +++ /dev/null @@ -1,68 +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 fs from 'fs'; -import * as path from 'path'; - -import { ReferenceType } from '../src'; - -import { EMULATOR_PORT } from './util'; - -export interface SeedInfo { - type: ReferenceType; - name: string; -} -export async function setupQueries( - schema: string, - seedInfoArray: SeedInfo[] -): Promise { - const schemaPath = path.resolve(__dirname, schema); - const schemaFileContents = fs.readFileSync(schemaPath).toString(); - const toWrite = { - 'service_id': 'l', - 'schema': { - 'files': [ - { - 'path': `schema/${schema}`, - 'content': schemaFileContents - } - ] - }, - 'connectors': { - 'c': { - 'files': seedInfoArray.map(seedInfo => { - const fileName = seedInfo.name + '.gql'; - const operationFilePath = path.resolve(__dirname, fileName); - const operationFileContents = fs - .readFileSync(operationFilePath) - .toString(); - return { - path: `operations/${seedInfo.name}.gql`, - content: operationFileContents - }; - }) - } - }, - // eslint-disable-next-line camelcase - connection_string: - 'postgresql://postgres:secretpassword@localhost:5432/postgres?sslmode=disable' - }; - return fetch(`http://localhost:${EMULATOR_PORT}/setupSchema`, { - method: 'POST', - body: JSON.stringify(toWrite) - }); -} diff --git a/scripts/emulator-testing/emulators/dataconnect-emulator.ts b/scripts/emulator-testing/emulators/dataconnect-emulator.ts index 5cea83b073b..9dc6add5df1 100644 --- a/scripts/emulator-testing/emulators/dataconnect-emulator.ts +++ b/scripts/emulator-testing/emulators/dataconnect-emulator.ts @@ -18,7 +18,7 @@ import { platform } from 'os'; import { Emulator } from './emulator'; -const DATACONNECT_EMULATOR_VERSION = '1.7.5'; +const DATACONNECT_EMULATOR_VERSION = '1.9.2'; export class DataConnectEmulator extends Emulator { constructor(port = 9399) { diff --git a/scripts/emulator-testing/emulators/emulator.ts b/scripts/emulator-testing/emulators/emulator.ts index 0eeb1ca88bd..b9bd81b2005 100644 --- a/scripts/emulator-testing/emulators/emulator.ts +++ b/scripts/emulator-testing/emulators/emulator.ts @@ -146,6 +146,7 @@ export abstract class Emulator { if (this.isDataConnect) { const dataConnectConfigDir = this.findDataConnectConfigDir(); promise = spawn(this.binaryPath, [ + '--logtostderr', '--v=2', 'dev', `--listen=127.0.0.1:${this.port},[::1]:${this.port}`, @@ -155,6 +156,9 @@ export abstract class Emulator { promise.childProcess.stderr?.on('data', res => console.log(res.toString()) ); + promise.childProcess.stderr?.on('error', res => + console.log(res.toString()) + ); } else { promise = spawn( 'java', @@ -174,7 +178,6 @@ export abstract class Emulator { promise.catch(reject); this.emulator = promise.childProcess; - console.log(`Waiting for emulator to start up ...`); // NOTE: Normally the emulator starts up within a few seconds. // However, our sdk test suite launches tests from 20+ packages in parallel, which slows // down the startup substantially. In such case for the emulator to start, it can take From c6955234c32611ab1b13a46bb1856240e2ecb476 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Thu, 20 Mar 2025 18:47:17 -0700 Subject: [PATCH 16/16] Brought back log --- scripts/emulator-testing/emulators/emulator.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/emulator-testing/emulators/emulator.ts b/scripts/emulator-testing/emulators/emulator.ts index b9bd81b2005..01fbe66fa13 100644 --- a/scripts/emulator-testing/emulators/emulator.ts +++ b/scripts/emulator-testing/emulators/emulator.ts @@ -178,6 +178,7 @@ export abstract class Emulator { promise.catch(reject); this.emulator = promise.childProcess; + console.log(`Waiting for emulator to start up ...`); // NOTE: Normally the emulator starts up within a few seconds. // However, our sdk test suite launches tests from 20+ packages in parallel, which slows // down the startup substantially. In such case for the emulator to start, it can take