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 +9 -8
- package/dist/package.json +3 -2
- package/dist/src/Client.d.ts +5 -4
- package/dist/src/Client.js +40 -17
- package/dist/src/environment.d.ts +8 -1
- package/dist/src/environment.js +15 -6
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Conductor
|
|
1
|
+
# Conductor - QuickBooks Desktop Integration
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
27
|
-
const
|
|
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": "
|
|
4
|
-
"description": "
|
|
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
|
}
|
package/dist/src/Client.d.ts
CHANGED
|
@@ -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
|
|
4
|
+
/** Log each request and response. */
|
|
5
5
|
verbose?: boolean;
|
|
6
|
-
|
|
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,
|
|
19
|
-
|
|
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;
|
package/dist/src/Client.js
CHANGED
|
@@ -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,
|
|
18
|
+
constructor(apiKey, { verbose = false, serverEnvironment = "staging" } = {}) {
|
|
18
19
|
this.checkForUpdates();
|
|
19
20
|
this.verbose = verbose;
|
|
20
|
-
this.serverURL = (0, environment_1.envToBaseServerURL)(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
73
|
+
return response.integrationRequest;
|
|
74
|
+
}
|
|
75
|
+
async request(gqlQuery, variables) {
|
|
59
76
|
if (this.verbose) {
|
|
60
|
-
console.
|
|
61
|
-
console.
|
|
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
|
-
|
|
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(
|
|
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
|
+
};
|
package/dist/src/environment.js
CHANGED
|
@@ -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
|
|
10
|
+
return "https://staging.api.conductor.is";
|
|
10
11
|
}
|
|
11
|
-
case "
|
|
12
|
-
return
|
|
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": "
|
|
4
|
-
"description": "
|
|
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
|
}
|