Skip to content

Commit f63d34d

Browse files
committed
Add API for partial errors
1 parent 777f465 commit f63d34d

File tree

2 files changed

+64
-6
lines changed

2 files changed

+64
-6
lines changed

packages/data-connect/src/api/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,11 @@ export * from './Mutation';
2222
export * from './query';
2323
export { setLogLevel } from '../logger';
2424
export { validateArgs } from '../util/validateArgs';
25+
26+
export { DataConnectError, DataConnectOperationError } from '../core/error';
27+
28+
export type {
29+
DataConnectErrorCode,
30+
DataConnectOperationResponse,
31+
DataConnectOperationErrorInfo
32+
} from '../core/error';

packages/data-connect/src/core/error.ts

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ export const Code = {
4040

4141
/** An error returned by a DataConnect operation. */
4242
export class DataConnectError extends FirebaseError {
43-
/** The stack of the error. */
44-
readonly stack?: string;
43+
/** The custom name for DataConnectError. */
44+
readonly name: string = 'DataConnectError';
4545

4646
/** @hideconstructor */
4747
constructor(
@@ -56,9 +56,59 @@ export class DataConnectError extends FirebaseError {
5656
) {
5757
super(code, message);
5858

59-
// HACK: We write a toString property directly because Error is not a real
60-
// class and so inheritance does not work correctly. We could alternatively
61-
// do the same "back-door inheritance" trick that FirebaseError does.
62-
this.toString = () => `${this.name}: [code=${this.code}]: ${this.message}`;
59+
// Ensure the instanceof operator works as expected on subclasses of Error.
60+
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#custom_error_types
61+
// and https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget
62+
Object.setPrototypeOf(this, new.target.prototype);
6363
}
64+
65+
toString(): string {
66+
return `${this.name}[code=${this.code}]: ${this.message}`;
67+
}
68+
}
69+
70+
/** An error returned by a DataConnect operation. */
71+
export class DataConnectOperationError extends DataConnectError {
72+
/** The custom name for DataConnectOperationError. */
73+
readonly name: string = 'DataConnectOperationError';
74+
75+
/** The response received from the backend. */
76+
readonly response: DataConnectOperationResponse;
77+
78+
/** @hideconstructor */
79+
constructor(message: string, response: DataConnectOperationResponse) {
80+
super('partial-error', message);
81+
this.response = response;
82+
83+
// Ensure the instanceof operator works as expected on subclasses of Error.
84+
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#custom_error_types
85+
// and https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget
86+
Object.setPrototypeOf(this, new.target.prototype);
87+
}
88+
}
89+
90+
export interface DataConnectOperationResponse {
91+
// The "data" provided by the backend in the response message.
92+
//
93+
// Will be `undefined` if no "data" was provided in the response message.
94+
// Otherwise, will be `null` if `null` was explicitly specified as the "data"
95+
// in the response message. Otherwise, will be the value of the "data"
96+
// specified as the "data" in the response message
97+
readonly data?: Record<string, unknown> | null;
98+
99+
// The list of errors provided by the backend in the response message.
100+
readonly errors: DataConnectOperationErrorInfo[];
101+
}
102+
103+
// Information about the error, as provided in the response from the backend.
104+
// See https://spec.graphql.org/draft/#sec-Errors
105+
export interface DataConnectOperationErrorInfo {
106+
// The error message.
107+
readonly message: string;
108+
109+
// The path of the field in the response data to which this error relates.
110+
// String values in this array refer to field names. Numeric values in this
111+
// array always satisfy `Number.isInteger()` and refer to the index in an
112+
// array.
113+
readonly path: Array<string | number>;
64114
}

0 commit comments

Comments
 (0)