conductor-node 8.4.1 → 8.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -164,15 +164,19 @@ The `ConductorError` and its subclasses have the following properties:
164
164
  {
165
165
  // The error type.
166
166
  type: string;
167
- // The unique error code. This is useful for adding special handling for
168
- // specific errors.
167
+ // The unique error code. This is useful for adding special handling
168
+ // for specific errors.
169
169
  code: string;
170
- // The error message for your logs.
170
+ // The developer error message for your logs.
171
171
  message: string;
172
172
  // The end-user-friendly error message to display in your app.
173
173
  endUserMessage: string;
174
- // The HTTP status code.
175
- statusCode: number | undefined;
174
+ // The HTTP status code of the response that included the error.
175
+ httpStatusCode: number | undefined;
176
+ // The error code provided by the third-party integration when `type`
177
+ // is `ConductorIntegrationError`. This is useful for adding special
178
+ // handling for specific errors from the third-party integration.
179
+ integrationCode: string | undefined;
176
180
  }
177
181
  ```
178
182
 
@@ -180,13 +184,13 @@ The `ConductorError` and its subclasses have the following properties:
180
184
 
181
185
  The error object you receive will have one of the following error types:
182
186
 
183
- | Type | Description |
184
- | ------------------------------ | ------------------------------------------------------------------------------------------------ |
185
- | `ConductorIntegrationError` | An error occurred on the third-party integration's end while processing your end-user's request. |
186
- | `ConductorInvalidRequestError` | You made an API call with the wrong parameters, in the wrong state, or in an invalid way. |
187
- | `ConductorAuthenticationError` | Conductor cannot authenticate you with the credentials you provided. E.g., an incorrect API key. |
188
- | `ConductorConnectionError` | There was a network problem between the client (on your server) and Conductor's servers. |
189
- | `ConductorInternalError` | Something went wrong on Conductor's end. (These are rare.) |
187
+ | Type | Description |
188
+ | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
189
+ | `ConductorIntegrationError` | An error occurred on the third-party integration's end while processing your end-user's request. E.g., cannot connect to QuickBooks Desktop on your end-user's computer. |
190
+ | `ConductorInvalidRequestError` | You made an API call with the wrong parameters, in the wrong state, or in an invalid way. |
191
+ | `ConductorAuthenticationError` | Conductor cannot authenticate you with the credentials you provided. E.g., an incorrect API key. |
192
+ | `ConductorConnectionError` | There was a network problem between the client (on your server) and Conductor's servers. |
193
+ | `ConductorInternalError` | Something went wrong on Conductor's end. (These are rare.) |
190
194
 
191
195
  ### Example
192
196
 
@@ -201,7 +205,14 @@ try {
201
205
  });
202
206
  } catch (error) {
203
207
  if (error instanceof ConductorError) {
204
- // Update your app's UI to display `error.endUserMessage`.
208
+ // TODO: Update your app's UI to display `error.endUserMessage`.
209
+
210
+ // RECOMMENDED: Send a *warning* to Sentry for integration-errors, which are
211
+ // your end-user's fault (e.g., cannot connect to QBD on your end-user's
212
+ // computer) or an *error* for other errors (e.g., invalid API key).
213
+ Sentry.captureException(error, {
214
+ level: error instanceof ConductorIntegrationError ? "warning" : "error",
215
+ });
205
216
  }
206
217
  // ...
207
218
  }
@@ -221,7 +232,8 @@ conductor.qbd.account
221
232
  })
222
233
  .catch((error) => {
223
234
  if (error instanceof ConductorError) {
224
- // Update your app's UI to display `error.endUserMessage`.
235
+ // TODO: Update your app's UI to display `error.endUserMessage`.
236
+ // ...
225
237
  }
226
238
  // ...
227
239
  });
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conductor-node",
3
- "version": "8.4.1",
3
+ "version": "8.5.1",
4
4
  "description": "Easily integrate with the entire QuickBooks Desktop API with fully-typed async TypeScript",
5
5
  "author": "Danny Nemer <hi@DannyNemer.com>",
6
6
  "license": "MIT",
@@ -1,10 +1,11 @@
1
1
  export declare const DEFAULT_END_USER_MESSAGE = "An internal server error occurred. Please try again later.";
2
2
  export interface ConductorErrorOptions {
3
- readonly type: string;
3
+ readonly rawType: string;
4
4
  readonly code: string;
5
5
  readonly message: string;
6
6
  readonly endUserMessage?: string;
7
- readonly statusCode?: number;
7
+ readonly httpStatusCode?: number;
8
+ readonly integrationCode?: string;
8
9
  }
9
10
  /**
10
11
  * The base error from which all other more specific Conductor errors derive.
@@ -24,6 +25,11 @@ export declare class ConductorError extends Error {
24
25
  * for specific errors.
25
26
  */
26
27
  readonly code: string;
28
+ /**
29
+ * The developer-friendly error message for your logs.
30
+ *
31
+ * (Defined in the base class but documented here for completeness.)
32
+ */
27
33
  /**
28
34
  * The end-user-friendly error message to display in your app.
29
35
  */
@@ -31,43 +37,65 @@ export declare class ConductorError extends Error {
31
37
  /**
32
38
  * The HTTP status code of the response that included the error.
33
39
  */
34
- readonly statusCode: number | undefined;
35
- constructor(options: ConductorErrorOptions);
40
+ readonly httpStatusCode: number | undefined;
41
+ /**
42
+ * The error code provided by the third-party integration when `type` is
43
+ * `ConductorIntegrationError`. This is useful for adding special handling for
44
+ * specific errors from the third-party integration.
45
+ *
46
+ * The third-party integration's error codes are not standardized, so you
47
+ * should not rely on this code to be the same across integrations.
48
+ */
49
+ readonly integrationCode: string | undefined;
50
+ protected constructor(options: ConductorErrorOptions);
36
51
  }
52
+ type ConductorErrorOptionsWithoutRawType = Omit<ConductorErrorOptions, "rawType">;
37
53
  /**
38
54
  * Raised when an error occurs on the third-party integration's end while
39
- * processing your end-user's request. E.g., QBWC failed to connect to
40
- * QuickBooks Desktop on the end-user's computer.
55
+ * processing your end-user's request. E.g., cannot connect to QuickBooks
56
+ * Desktop on the end-user's computer.
41
57
  */
42
58
  export declare class ConductorIntegrationError extends ConductorError {
59
+ static readonly rawType: string;
60
+ constructor(options: ConductorErrorOptionsWithoutRawType);
43
61
  }
44
62
  /**
45
63
  * Raised when you make an API call with the wrong parameters, in the wrong
46
64
  * state, or in an invalid way.
47
65
  */
48
66
  export declare class ConductorInvalidRequestError extends ConductorError {
67
+ static readonly rawType = "INVALID_REQUEST_ERROR";
68
+ constructor(options: ConductorErrorOptionsWithoutRawType);
49
69
  }
50
70
  /**
51
71
  * Raised when Conductor cannot authenticate you with the credentials you
52
72
  * provided. E.g., an incorrect API key.
53
73
  */
54
74
  export declare class ConductorAuthenticationError extends ConductorError {
75
+ static readonly rawType = "AUTHENTICATION_ERROR";
76
+ constructor(options: ConductorErrorOptionsWithoutRawType);
55
77
  }
56
78
  /**
57
79
  * Raised when there is a network problem between the client (on your server)
58
80
  * and Conductor's servers. E.g., a downed network or a bad TLS certificate.
59
81
  */
60
82
  export declare class ConductorConnectionError extends ConductorError {
83
+ static readonly rawType = "CONNECTION_ERROR";
84
+ constructor(options: ConductorErrorOptionsWithoutRawType);
61
85
  }
62
86
  /**
63
87
  * Raised when something goes wrong on Conductor's end. (These are rare.)
64
88
  */
65
89
  export declare class ConductorInternalError extends ConductorError {
90
+ static readonly rawType = "INTERNAL_ERROR";
91
+ constructor(options: ConductorErrorOptionsWithoutRawType);
66
92
  }
67
93
  /**
68
94
  * Raised as a fallback for any other error from Conductor that no other error
69
95
  * type captures.
70
96
  */
71
97
  export declare class ConductorUnknownError extends ConductorError {
98
+ constructor(options: ConductorErrorOptions);
72
99
  }
73
- export declare function generateConductorError(rawConductorError: ConductorErrorOptions): ConductorError;
100
+ export declare function generateConductorErrorFromType(options: ConductorErrorOptions): ConductorError;
101
+ export {};
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateConductorError = exports.ConductorUnknownError = exports.ConductorInternalError = exports.ConductorConnectionError = exports.ConductorAuthenticationError = exports.ConductorInvalidRequestError = exports.ConductorIntegrationError = exports.ConductorError = exports.DEFAULT_END_USER_MESSAGE = void 0;
4
- /* eslint-disable max-classes-per-file -- Keep the error classes together */
3
+ exports.generateConductorErrorFromType = exports.ConductorUnknownError = exports.ConductorInternalError = exports.ConductorConnectionError = exports.ConductorAuthenticationError = exports.ConductorInvalidRequestError = exports.ConductorIntegrationError = exports.ConductorError = exports.DEFAULT_END_USER_MESSAGE = void 0;
4
+ /* eslint-disable max-classes-per-file -- Use one module for all error classes. */
5
5
  exports.DEFAULT_END_USER_MESSAGE = "An internal server error occurred. Please try again later.";
6
6
  /**
7
7
  * The base error from which all other more specific Conductor errors derive.
@@ -21,6 +21,12 @@ class ConductorError extends Error {
21
21
  * for specific errors.
22
22
  */
23
23
  code;
24
+ /**
25
+ * The developer-friendly error message for your logs.
26
+ *
27
+ * (Defined in the base class but documented here for completeness.)
28
+ */
29
+ // public readonly message: string;
24
30
  /**
25
31
  * The end-user-friendly error message to display in your app.
26
32
  */
@@ -28,7 +34,16 @@ class ConductorError extends Error {
28
34
  /**
29
35
  * The HTTP status code of the response that included the error.
30
36
  */
31
- statusCode;
37
+ httpStatusCode;
38
+ /**
39
+ * The error code provided by the third-party integration when `type` is
40
+ * `ConductorIntegrationError`. This is useful for adding special handling for
41
+ * specific errors from the third-party integration.
42
+ *
43
+ * The third-party integration's error codes are not standardized, so you
44
+ * should not rely on this code to be the same across integrations.
45
+ */
46
+ integrationCode;
32
47
  constructor(options) {
33
48
  super(options.message);
34
49
  // Set `name` to the constructor name so that the error appears in logs as
@@ -41,19 +56,24 @@ class ConductorError extends Error {
41
56
  // `ConductorError` always have the correct `type` even if they are
42
57
  // instantiated with the wrong options.
43
58
  this.type = this.constructor.name;
44
- this.rawType = options.type;
59
+ this.rawType = options.rawType;
45
60
  this.code = options.code;
46
61
  this.endUserMessage = options.endUserMessage ?? exports.DEFAULT_END_USER_MESSAGE;
47
- this.statusCode = options.statusCode;
62
+ this.httpStatusCode = options.httpStatusCode;
63
+ this.integrationCode = options.integrationCode;
48
64
  }
49
65
  }
50
66
  exports.ConductorError = ConductorError;
51
67
  /**
52
68
  * Raised when an error occurs on the third-party integration's end while
53
- * processing your end-user's request. E.g., QBWC failed to connect to
54
- * QuickBooks Desktop on the end-user's computer.
69
+ * processing your end-user's request. E.g., cannot connect to QuickBooks
70
+ * Desktop on the end-user's computer.
55
71
  */
56
72
  class ConductorIntegrationError extends ConductorError {
73
+ static rawType = "INTEGRATION_ERROR";
74
+ constructor(options) {
75
+ super({ ...options, rawType: ConductorIntegrationError.rawType });
76
+ }
57
77
  }
58
78
  exports.ConductorIntegrationError = ConductorIntegrationError;
59
79
  /**
@@ -61,6 +81,10 @@ exports.ConductorIntegrationError = ConductorIntegrationError;
61
81
  * state, or in an invalid way.
62
82
  */
63
83
  class ConductorInvalidRequestError extends ConductorError {
84
+ static rawType = "INVALID_REQUEST_ERROR";
85
+ constructor(options) {
86
+ super({ ...options, rawType: ConductorInvalidRequestError.rawType });
87
+ }
64
88
  }
65
89
  exports.ConductorInvalidRequestError = ConductorInvalidRequestError;
66
90
  /**
@@ -68,6 +92,10 @@ exports.ConductorInvalidRequestError = ConductorInvalidRequestError;
68
92
  * provided. E.g., an incorrect API key.
69
93
  */
70
94
  class ConductorAuthenticationError extends ConductorError {
95
+ static rawType = "AUTHENTICATION_ERROR";
96
+ constructor(options) {
97
+ super({ ...options, rawType: ConductorAuthenticationError.rawType });
98
+ }
71
99
  }
72
100
  exports.ConductorAuthenticationError = ConductorAuthenticationError;
73
101
  /**
@@ -75,12 +103,20 @@ exports.ConductorAuthenticationError = ConductorAuthenticationError;
75
103
  * and Conductor's servers. E.g., a downed network or a bad TLS certificate.
76
104
  */
77
105
  class ConductorConnectionError extends ConductorError {
106
+ static rawType = "CONNECTION_ERROR";
107
+ constructor(options) {
108
+ super({ ...options, rawType: ConductorConnectionError.rawType });
109
+ }
78
110
  }
79
111
  exports.ConductorConnectionError = ConductorConnectionError;
80
112
  /**
81
113
  * Raised when something goes wrong on Conductor's end. (These are rare.)
82
114
  */
83
115
  class ConductorInternalError extends ConductorError {
116
+ static rawType = "INTERNAL_ERROR";
117
+ constructor(options) {
118
+ super({ ...options, rawType: ConductorInternalError.rawType });
119
+ }
84
120
  }
85
121
  exports.ConductorInternalError = ConductorInternalError;
86
122
  /**
@@ -88,28 +124,33 @@ exports.ConductorInternalError = ConductorInternalError;
88
124
  * type captures.
89
125
  */
90
126
  class ConductorUnknownError extends ConductorError {
127
+ // Override the `protected` constructor in the base class even though we are
128
+ // not overriding `rawType`.
129
+ constructor(options) {
130
+ super(options);
131
+ }
91
132
  }
92
133
  exports.ConductorUnknownError = ConductorUnknownError;
93
- function generateConductorError(rawConductorError) {
94
- switch (rawConductorError.type) {
95
- case "INTEGRATION_ERROR": {
96
- return new ConductorIntegrationError(rawConductorError);
134
+ function generateConductorErrorFromType(options) {
135
+ switch (options.rawType) {
136
+ case ConductorIntegrationError.rawType: {
137
+ return new ConductorIntegrationError(options);
97
138
  }
98
- case "INVALID_REQUEST_ERROR": {
99
- return new ConductorInvalidRequestError(rawConductorError);
139
+ case ConductorInvalidRequestError.rawType: {
140
+ return new ConductorInvalidRequestError(options);
100
141
  }
101
- case "AUTHENTICATION_ERROR": {
102
- return new ConductorAuthenticationError(rawConductorError);
142
+ case ConductorAuthenticationError.rawType: {
143
+ return new ConductorAuthenticationError(options);
103
144
  }
104
- case "CONNECTION_ERROR": {
105
- return new ConductorConnectionError(rawConductorError);
145
+ case ConductorConnectionError.rawType: {
146
+ return new ConductorConnectionError(options);
106
147
  }
107
- case "INTERNAL_ERROR": {
108
- return new ConductorInternalError(rawConductorError);
148
+ case ConductorInternalError.rawType: {
149
+ return new ConductorInternalError(options);
109
150
  }
110
151
  default: {
111
- return new ConductorUnknownError(rawConductorError);
152
+ return new ConductorUnknownError(options);
112
153
  }
113
154
  }
114
155
  }
115
- exports.generateConductorError = generateConductorError;
156
+ exports.generateConductorErrorFromType = generateConductorErrorFromType;
@@ -59,45 +59,42 @@ async function graphqlOperationWrapper(operationName, variables, operation, verb
59
59
  }
60
60
  }
61
61
  exports.graphqlOperationWrapper = graphqlOperationWrapper;
62
+ function getDurationString(startTime) {
63
+ const duration = Date.now() - startTime;
64
+ return `${Math.round(duration / 10) / 100}s`;
65
+ }
62
66
  function wrapError(error) {
63
67
  if (error instanceof graphql_request_1.ClientError) {
64
68
  const { response } = error;
65
69
  if ([404, 502, 503].includes(response.status)) {
66
- return (0, errors_1.generateConductorError)({
67
- type: "CONNECTION_ERROR",
70
+ return new errors_1.ConductorConnectionError({
68
71
  code: "SERVER_UNAVAILABLE",
69
72
  message: `The Conductor server returned a ${response.status} error, which may indicate that the server is unavailable. Please alert the Conductor team if this error persists.`,
70
- statusCode: response.status,
73
+ httpStatusCode: response.status,
71
74
  });
72
75
  }
73
76
  const nestedError = response.errors?.[0];
74
77
  const errorExtensions = nestedError?.extensions;
75
78
  if (errorExtensions) {
76
79
  if (errorExtensions["code"] === "GRAPHQL_VALIDATION_FAILED") {
77
- return (0, errors_1.generateConductorError)({
78
- type: "INVALID_REQUEST_ERROR",
80
+ return new errors_1.ConductorInvalidRequestError({
79
81
  code: "CLIENT_OUTDATED",
80
82
  message: `Your version of "${package_json_1.default.name}" is not longer compatible with the Conductor server. Please run "yarn upgrade ${package_json_1.default.name} --latest" to update.`,
81
- statusCode: response.status,
83
+ httpStatusCode: response.status,
82
84
  });
83
85
  }
84
- return (0, errors_1.generateConductorError)({
85
- type: errorExtensions["type"],
86
+ return (0, errors_1.generateConductorErrorFromType)({
87
+ rawType: errorExtensions["type"],
86
88
  code: errorExtensions["code"],
87
89
  message: nestedError.message,
88
90
  endUserMessage: errorExtensions["endUserMessage"],
89
- statusCode: response.status,
91
+ httpStatusCode: response.status,
90
92
  });
91
93
  }
92
94
  }
93
- return (0, errors_1.generateConductorError)({
94
- type: "INTERNAL_ERROR",
95
+ return new errors_1.ConductorInternalError({
95
96
  code: "INVALID_JSON_RESPONSE",
96
97
  message: "Invalid JSON received from the Conductor API.",
97
98
  });
98
99
  }
99
100
  exports.wrapError = wrapError;
100
- function getDurationString(startTime) {
101
- const duration = Date.now() - startTime;
102
- return `${Math.round(duration / 10) / 100}s`;
103
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conductor-node",
3
- "version": "8.4.1",
3
+ "version": "8.5.1",
4
4
  "description": "Easily integrate with the entire QuickBooks Desktop API with fully-typed async TypeScript",
5
5
  "author": "Danny Nemer <hi@DannyNemer.com>",
6
6
  "license": "MIT",