conductor-node 3.0.1 → 3.1.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
@@ -1,6 +1,6 @@
1
1
  # Conductor Node.js Library
2
2
 
3
- The Conductor Node.js library provides convenient access to the Conductor API from applications written in server-side JavaScript. Zero dependencies.
3
+ The Conductor Node.js library provides convenient access to the Conductor API from applications written in server-side JavaScript.
4
4
 
5
5
  ## Requirements
6
6
 
@@ -17,14 +17,14 @@ yarn add conductor-node
17
17
 
18
18
  Instantiate `Conductor` with your account's secret key, which is available from Danny.
19
19
 
20
- The `Conductor` instance can execute _any_ read or write [QuickBooks Desktop API](https://developer.intuit.com/app/developer/qbdesktop/docs/api-reference/qbdesktop) through TypeScript and receive a fully-typed response. Each request requires the user-id of a specific QuickBooks Desktop user.
20
+ The `Conductor` instance can execute _any_ read or write [QuickBooks Desktop API](https://developer.intuit.com/app/developer/qbdesktop/docs/api-reference/qbdesktop) through TypeScript and receive a fully-typed response. Each request requires the integration-user-connection id of a specific QuickBooks Desktop user.
21
21
 
22
22
  ```ts
23
23
  import Conductor from "conductor-node";
24
24
  const conductor = new Conductor("sk_test_...");
25
25
 
26
- const mockQBDUserId = "1";
27
- const newAccount = await conductor.qbd.account.add(mockQBDUserId, {
26
+ const mockQbdUserConnectionId = "1";
27
+ const newAccount = await conductor.qbd.account.add(mockQbdUserConnectionId, {
28
28
  Name: "Test Account",
29
29
  AccountType: "Bank",
30
30
  OpenBalance: "100",
@@ -1,16 +1,5 @@
1
- import type { Environment } from "./environment";
2
- export interface BaseClientOptions {
3
- verbose?: boolean;
4
- environment?: Environment;
5
- }
6
- export interface RequestParams {
7
- integrationUserConnectionId: string;
8
- requestObj: object;
9
- }
1
+ import type Client from "./Client";
10
2
  export default class BaseClient {
11
- protected readonly apiKey: string;
12
- protected readonly verbose: boolean;
13
- protected readonly serverURL: string;
14
- constructor(apiKey: string, { verbose, environment }: BaseClientOptions);
15
- protected sendAPIRequest(apiPath: string, requestParams: RequestParams): Promise<object>;
3
+ protected readonly root: Client;
4
+ constructor(client: Client);
16
5
  }
@@ -1,43 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const environment_1 = require("./environment");
4
- // Store properties via superclass `BaseClient` instead of on `Client` passed to
5
- // the integration clients (e.g., `ClientQbd`) to hide these properties from the
6
- // dev user while still allowing the integration clients to access them.
7
- //
8
- // Downside: These values are stored in each subclass instead of sharing a
9
- // single store (e.g., `Client`).
10
3
  class BaseClient {
11
- apiKey;
12
- verbose;
13
- serverURL;
14
- constructor(apiKey, { verbose = false, environment = "staging" }) {
15
- this.apiKey = apiKey;
16
- this.verbose = verbose;
17
- this.serverURL = (0, environment_1.envToBaseServerURL)(environment);
18
- }
19
- async sendAPIRequest(apiPath, requestParams) {
20
- const apiServerURL = `${this.serverURL}/${apiPath}`;
21
- if (this.verbose) {
22
- console.log(`Client sent request to ${apiServerURL} for ${apiPath} user ${requestParams.integrationUserConnectionId}:`, JSON.stringify(requestParams.requestObj, null, 2));
23
- }
24
- const response = await fetch(apiServerURL, {
25
- body: JSON.stringify(requestParams),
26
- headers: {
27
- "Content-Type": "application/json",
28
- Authorization: `Bearer ${this.apiKey}`,
29
- },
30
- method: "POST",
31
- });
32
- if (response.status >= 400) {
33
- const errorMessage = (await response.text()) || response.statusText;
34
- throw new Error(`Request to ${apiServerURL} failed with status ${response.status}: ${errorMessage}`);
35
- }
36
- const responseObj = (await response.json());
37
- if (this.verbose) {
38
- console.log(`Client received response for ${apiPath} user ${requestParams.integrationUserConnectionId}:`, JSON.stringify(responseObj, null, 2));
39
- }
40
- return responseObj;
4
+ root;
5
+ constructor(client) {
6
+ this.root = client;
41
7
  }
42
8
  }
43
9
  exports.default = BaseClient;
@@ -1,7 +1,21 @@
1
- import type { BaseClientOptions } from "./BaseClient";
1
+ import type { Environment } from "./environment";
2
2
  import ClientQbd from "./qbd/ClientQbd";
3
+ export interface ClientOptions {
4
+ /** Log the each request and response. */
5
+ verbose?: boolean;
6
+ environment?: Environment;
7
+ }
8
+ export interface IntegrationRequestParams {
9
+ integrationUserConnectionId: string;
10
+ requestObject: object;
11
+ }
3
12
  export default class Client {
4
13
  /** QuickBooks Desktop integration. */
5
14
  readonly qbd: ClientQbd;
6
- constructor(apiKey: string, options?: BaseClientOptions);
15
+ private readonly serverURL;
16
+ private readonly gqlClient;
17
+ private readonly verbose;
18
+ constructor(apiKey: string, { verbose, environment }?: ClientOptions);
19
+ integrationUserConnections(): Promise<object[]>;
20
+ integrationRequest(integrationRequestParams: IntegrationRequestParams): Promise<object>;
7
21
  }
@@ -3,12 +3,60 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const environment_1 = require("./environment");
6
7
  const ClientQbd_1 = __importDefault(require("./qbd/ClientQbd"));
8
+ const graphql_request_1 = require("graphql-request");
7
9
  class Client {
8
10
  /** QuickBooks Desktop integration. */
9
11
  qbd;
10
- constructor(apiKey, options = {}) {
11
- this.qbd = new ClientQbd_1.default(apiKey, options);
12
+ serverURL;
13
+ gqlClient;
14
+ verbose;
15
+ constructor(apiKey, { verbose = false, environment = "staging" } = {}) {
16
+ this.verbose = verbose;
17
+ this.serverURL = (0, environment_1.envToBaseServerURL)(environment);
18
+ this.gqlClient = new graphql_request_1.GraphQLClient(`${this.serverURL}/graphql`, {
19
+ headers: {
20
+ authorization: `Bearer ${apiKey}`,
21
+ },
22
+ });
23
+ this.qbd = new ClientQbd_1.default(this);
24
+ }
25
+ async integrationUserConnections() {
26
+ const data = await this.gqlClient.request(`#graphql
27
+ query {
28
+ integrationUserConnections {
29
+ id
30
+ integration {
31
+ id
32
+ name
33
+ }
34
+ username
35
+ }
36
+ }
37
+ `);
38
+ // @ts-expect-error - This will pass after we integrate GQL codegen.
39
+ return data.integrationUserConnections;
40
+ }
41
+ // TODO: Hide this method from the dev user while still allowing the
42
+ // integration clients to access it.
43
+ async integrationRequest(integrationRequestParams) {
44
+ if (this.verbose) {
45
+ console.log(`Client sent request to ${this.serverURL}:`, JSON.stringify(integrationRequestParams, null, 2));
46
+ console.time("Request time");
47
+ }
48
+ const response = await this.gqlClient.request(`#graphql
49
+ query IntegrationRequest($integrationRequestParams: IntegrationRequestParams!) {
50
+ integrationRequest(integrationRequestParams: $integrationRequestParams)
51
+ }
52
+ `, { integrationRequestParams });
53
+ // @ts-expect-error - This will pass after we integrate GQL codegen.
54
+ const responseBody = response.integrationRequest;
55
+ if (this.verbose) {
56
+ console.timeEnd("Request time");
57
+ console.log(`Client received response from ${this.serverURL}:`, JSON.stringify(responseBody, null, 2));
58
+ }
59
+ return responseBody;
12
60
  }
13
61
  }
14
62
  exports.default = Client;
@@ -247,6 +247,6 @@ export default class ClientQbd extends BaseClient {
247
247
  * Available APIs:
248
248
  * https://developer.intuit.com/app/developer/qbdesktop/docs/api-reference/qbdesktop
249
249
  */
250
- sendRequest(integrationUserConnectionId: string, requestObj: object): Promise<object>;
250
+ sendRequest(integrationUserConnectionId: string, requestObject: object): Promise<object>;
251
251
  private sendRequestBase;
252
252
  }
@@ -251,10 +251,10 @@ class ClientQbd extends BaseClient_1.default {
251
251
  * Available APIs:
252
252
  * https://developer.intuit.com/app/developer/qbdesktop/docs/api-reference/qbdesktop
253
253
  */
254
- async sendRequest(integrationUserConnectionId, requestObj) {
255
- return this.sendAPIRequest("qbd", {
254
+ async sendRequest(integrationUserConnectionId, requestObject) {
255
+ return this.root.integrationRequest({
256
256
  integrationUserConnectionId,
257
- requestObj,
257
+ requestObject,
258
258
  });
259
259
  }
260
260
  async sendRequestBase(integrationUserConnectionId, params, responseKey, responseBodyKey) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "conductor-node",
3
- "version": "3.0.1",
3
+ "version": "3.1.1",
4
4
  "description": "Conductor API wrapper",
5
5
  "author": "Danny Nemer <hi@DannyNemer.com>",
6
6
  "license": "MIT",
@@ -12,9 +12,14 @@
12
12
  ],
13
13
  "scripts": {
14
14
  "prepack": "yarn tsc && yarn tsc-alias",
15
- "postpack": "rm -rf dist"
15
+ "postpack": "rm -rf dist",
16
+ "test-staging": "yarn ts-node ./test/sendMockRequest"
16
17
  },
17
18
  "devDependencies": {
18
19
  "tsc-alias": "^1.7.0"
20
+ },
21
+ "dependencies": {
22
+ "graphql": "^16.6.0",
23
+ "graphql-request": "^5.0.0"
19
24
  }
20
25
  }