conductor-node 3.8.5 → 4.0.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
- # Conductor Node.js Library
1
+ # Conductor - QuickBooks Desktop Integration
2
2
 
3
- The Conductor Node.js library provides convenient access to the Conductor API from applications written in server-side JavaScript.
3
+ Execute _any_ read or write [QuickBooks Desktop API](https://developer.intuit.com/app/developer/qbdesktop/docs/api-reference/qbdesktop) through async TypeScript and receive a fully-typed response.
4
4
 
5
5
  ## Requirements
6
6
 
@@ -15,16 +15,17 @@ yarn add conductor-node
15
15
 
16
16
  ## Usage
17
17
 
18
- Instantiate `Conductor` with your account's secret key, which is available from Danny.
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 integration-user-connection id of a specific QuickBooks Desktop user.
21
-
22
18
  ```ts
23
19
  import Conductor from "conductor-node";
20
+
21
+ // Instantiate `Conductor` with your account's secret key.
24
22
  const conductor = new Conductor("sk_test_...");
25
23
 
26
- const mockQbdUserConnectionId = "1";
27
- const newAccount = await conductor.qbd.account.add(mockQbdUserConnectionId, {
24
+ // Fetch all authorized integration-user-connections.
25
+ const qbdConnections = await client.getIntegrationUserConnections();
26
+
27
+ // Execute any QBD API against your QBD connection id.
28
+ const newAccount = await conductor.qbd.account.add(qbdConnections[0].id, {
28
29
  Name: "Test Account",
29
30
  AccountType: "Bank",
30
31
  OpenBalance: "100",
package/dist/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "conductor-node",
3
- "version": "3.8.5",
4
- "description": "Conductor API wrapper",
3
+ "version": "4.0.1",
4
+ "description": "Easily integrate with the entire QuickBooks Desktop API with fully-type async TypeScript",
5
5
  "author": "Danny Nemer <hi@DannyNemer.com>",
6
6
  "license": "MIT",
7
7
  "type": "commonjs",
@@ -24,6 +24,7 @@
24
24
  "tsc-alias": "^1.7.0"
25
25
  },
26
26
  "dependencies": {
27
+ "chalk": "^4",
27
28
  "graphql": "^16.6.0",
28
29
  "graphql-request": "^5.0.0"
29
30
  }
@@ -1,9 +1,9 @@
1
1
  import type { Environment } from "./environment";
2
2
  import QbdIntegration from "./integrations/qbd/QbdIntegration";
3
3
  export interface ClientOptions {
4
- /** Log the each request and response. */
4
+ /** Log each request and response. */
5
5
  verbose?: boolean;
6
- environment?: Environment;
6
+ serverEnvironment?: Environment;
7
7
  }
8
8
  export interface IntegrationRequestParams {
9
9
  integrationUserConnectionId: string;
@@ -15,8 +15,9 @@ export default class Client {
15
15
  private readonly serverURL;
16
16
  private readonly gqlClient;
17
17
  private readonly verbose;
18
- constructor(apiKey: string, { verbose, environment }?: ClientOptions);
19
- integrationUserConnections(): Promise<object[]>;
18
+ constructor(apiKey: string, { verbose, serverEnvironment }?: ClientOptions);
19
+ getIntegrationUserConnection(integrationUserConnectionId: string): Promise<object>;
20
+ getIntegrationUserConnections(): Promise<object[]>;
20
21
  integrationRequest(integrationRequestParams: IntegrationRequestParams): Promise<object>;
21
22
  private request;
22
23
  private checkForUpdates;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const package_json_1 = __importDefault(require("./../package.json"));
7
7
  const environment_1 = require("./environment");
8
8
  const QbdIntegration_1 = __importDefault(require("./integrations/qbd/QbdIntegration"));
9
+ const chalk_1 = __importDefault(require("chalk"));
9
10
  const graphql_request_1 = require("graphql-request");
10
11
  const node_child_process_1 = require("node:child_process");
11
12
  class Client {
@@ -14,10 +15,10 @@ class Client {
14
15
  serverURL;
15
16
  gqlClient;
16
17
  verbose;
17
- constructor(apiKey, { verbose = false, environment = "staging" } = {}) {
18
+ constructor(apiKey, { verbose = false, serverEnvironment = "staging" } = {}) {
18
19
  this.checkForUpdates();
19
20
  this.verbose = verbose;
20
- this.serverURL = (0, environment_1.envToBaseServerURL)(environment);
21
+ this.serverURL = (0, environment_1.envToBaseServerURL)(serverEnvironment);
21
22
  this.gqlClient = new graphql_request_1.GraphQLClient(`${this.serverURL}/graphql`, {
22
23
  headers: {
23
24
  Authorization: `Bearer ${apiKey}`,
@@ -26,7 +27,24 @@ class Client {
26
27
  });
27
28
  this.qbd = new QbdIntegration_1.default(this);
28
29
  }
29
- async integrationUserConnections() {
30
+ async getIntegrationUserConnection(integrationUserConnectionId) {
31
+ const data = await this.request(`#graphql
32
+ query GetIntegrationUserConnection($integrationUserConnectionId: ID!) {
33
+ integrationUserConnection(id: $integrationUserConnectionId) {
34
+ id
35
+ integration {
36
+ id
37
+ name
38
+ }
39
+ qbwcUsername
40
+ lastHeartbeatAt
41
+ }
42
+ }
43
+ `, { integrationUserConnectionId });
44
+ // @ts-expect-error - This will pass after we integrate GQL codegen.
45
+ return data.integrationUserConnection;
46
+ }
47
+ async getIntegrationUserConnections() {
30
48
  const data = await this.request(`#graphql
31
49
  query {
32
50
  integrationUserConnections {
@@ -35,7 +53,8 @@ class Client {
35
53
  id
36
54
  name
37
55
  }
38
- username
56
+ qbwcUsername
57
+ lastHeartbeatAt
39
58
  }
40
59
  }
41
60
  `);
@@ -45,34 +64,35 @@ class Client {
45
64
  // TODO: Hide this method from the dev user while still allowing the
46
65
  // integration clients to access it.
47
66
  async integrationRequest(integrationRequestParams) {
48
- if (this.verbose) {
49
- console.log(`Client sent request to ${this.serverURL}:`, JSON.stringify(integrationRequestParams, undefined, 2));
50
- console.time("Request time");
51
- }
52
67
  const response = await this.request(`#graphql
53
68
  query IntegrationRequest($integrationRequestParams: IntegrationRequestParams!) {
54
69
  integrationRequest(integrationRequestParams: $integrationRequestParams)
55
70
  }
56
71
  `, { integrationRequestParams });
57
72
  // @ts-expect-error - This will pass after we integrate GQL codegen.
58
- const responseBody = response.integrationRequest;
73
+ return response.integrationRequest;
74
+ }
75
+ async request(gqlQuery, variables) {
59
76
  if (this.verbose) {
60
- console.timeEnd("Request time");
61
- console.log(`Client received response from ${this.serverURL}:`, JSON.stringify(responseBody, undefined, 2));
77
+ console.log(`Client sent request to ${this.serverURL}:`, JSON.stringify(gqlQuery, undefined, 2));
78
+ console.time("Request time");
62
79
  }
63
- return responseBody;
64
- }
65
- async request(document, variables) {
66
80
  try {
67
- return await this.gqlClient.request(document, variables);
81
+ const response = await this.gqlClient.request(gqlQuery, variables);
82
+ if (this.verbose) {
83
+ console.timeEnd("Request time");
84
+ console.log(`Client received response from ${this.serverURL}:`, JSON.stringify(response, undefined, 2));
85
+ }
86
+ return response;
68
87
  }
69
88
  catch (error) {
70
89
  if (this.verbose) {
90
+ console.timeEnd("Request time");
71
91
  console.log(JSON.stringify(error, undefined, 2));
72
92
  }
73
93
  if (error instanceof graphql_request_1.ClientError) {
74
94
  const errorMessage = error.response.errors?.[0]?.message ??
75
- // Though property `ClientError.response.error` does *not* exist,
95
+ // Though the property `ClientError.response.error` does *not* exist,
76
96
  // we've seen it occur (e.g., attempting to access `development`
77
97
  // environment when `ngrok` is not running locally).
78
98
  error.response["error"];
@@ -84,12 +104,15 @@ class Client {
84
104
  }
85
105
  }
86
106
  checkForUpdates() {
107
+ if (environment_1.currentEnvironment.isTest) {
108
+ return;
109
+ }
87
110
  const currentVersion = package_json_1.default.version;
88
111
  const latestVersion = (0, node_child_process_1.execSync)(`yarn info ${package_json_1.default.name} version`)
89
112
  .toString()
90
113
  .trim();
91
114
  if (currentVersion !== latestVersion) {
92
- console.warn(`A new version of Conductor is available! You are using ${package_json_1.default.name} version ${currentVersion} but the latest version is ${latestVersion}. Please run "yarn add ${package_json_1.default.name}@latest" to update.`);
115
+ console.warn(chalk_1.default.yellow(`⚠️ A new version of Conductor is available! You are using ${package_json_1.default.name} version ${currentVersion} but the latest version is ${latestVersion}. Please run "yarn add ${package_json_1.default.name}@latest" to update.`));
93
116
  }
94
117
  }
95
118
  }
@@ -1,2 +1,9 @@
1
- export declare type Environment = "development" | "staging";
1
+ export declare type Environment = "development" | "production" | "staging" | "test";
2
2
  export declare function envToBaseServerURL(environment: Environment): string;
3
+ export declare const currentEnvironment: {
4
+ name: string;
5
+ isTest: boolean;
6
+ isDevelopment: boolean;
7
+ isStaging: boolean;
8
+ isProduction: boolean;
9
+ };
@@ -1,15 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.envToBaseServerURL = void 0;
4
- const STAGING_BASE_URL = "https://staging.api.conductor.is";
5
- const DEVELOPMENT_BASE_URL = "https://conductor.ngrok.io";
3
+ exports.currentEnvironment = exports.envToBaseServerURL = void 0;
6
4
  function envToBaseServerURL(environment) {
7
5
  switch (environment) {
6
+ case "development": {
7
+ return "https://conductor.ngrok.io";
8
+ }
8
9
  case "staging": {
9
- return STAGING_BASE_URL;
10
+ return "https://staging.api.conductor.is";
10
11
  }
11
- case "development": {
12
- return DEVELOPMENT_BASE_URL;
12
+ case "production": {
13
+ return "https://production.api.conductor.is";
13
14
  }
14
15
  default: {
15
16
  throw new Error("Invalid environment");
@@ -17,3 +18,11 @@ function envToBaseServerURL(environment) {
17
18
  }
18
19
  }
19
20
  exports.envToBaseServerURL = envToBaseServerURL;
21
+ const currentEnvironmentName = process.env["NODE_ENV"] ?? "development";
22
+ exports.currentEnvironment = {
23
+ name: currentEnvironmentName,
24
+ isTest: currentEnvironmentName === "test",
25
+ isDevelopment: currentEnvironmentName === "development",
26
+ isStaging: currentEnvironmentName === "staging",
27
+ isProduction: currentEnvironmentName === "production",
28
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "conductor-node",
3
- "version": "3.8.5",
4
- "description": "Conductor API wrapper",
3
+ "version": "4.0.1",
4
+ "description": "Easily integrate with the entire QuickBooks Desktop API with fully-type async TypeScript",
5
5
  "author": "Danny Nemer <hi@DannyNemer.com>",
6
6
  "license": "MIT",
7
7
  "type": "commonjs",
@@ -24,6 +24,7 @@
24
24
  "tsc-alias": "^1.7.0"
25
25
  },
26
26
  "dependencies": {
27
+ "chalk": "^4",
27
28
  "graphql": "^16.6.0",
28
29
  "graphql-request": "^5.0.0"
29
30
  }