@mspcopilot/n8n-nodes-connectwise 0.2.1-beta.1 → 0.2.1-beta.3
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/{dist-community → dist-beta}/credentials/ConnectWisePsaApi.credentials.js +18 -4
- package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/ConnectWisePsa.node.js +14 -2
- package/dist-beta/nodes/ConnectWise/PSA/ConnectWisePsaTrigger.node.js +506 -0
- package/dist-beta/nodes/ConnectWise/PSA/IfSchedule.node.js +332 -0
- package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/descriptions/common.properties.js +17 -2
- package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/helpers/hint-collector.js +17 -3
- package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/methods/fieldOptions.js +1 -0
- package/dist-beta/nodes/ConnectWise/PSA/schema/resources/alert-consolidation.js +451 -0
- package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/custom.schema.js +38 -1
- package/dist-beta/nodes/ConnectWise/PSA/schema/resources/diagnostics.schema.js +103 -0
- package/dist-beta/nodes/ConnectWise/PSA/schema/resources/reports.schema.js +206 -0
- package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/ticket.schema.js +11 -1
- package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/transport/cache.js +84 -6
- package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/transport/client.js +46 -5
- package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/transport/version-check.js +7 -7
- package/package.json +7 -5
- package/dist-community/nodes/ConnectWise/PSA/schema/resources/alert-consolidation.js +0 -42
- /package/{dist-community → dist-beta}/LICENSE.md +0 -0
- /package/{dist-community → dist-beta}/credentials/connectwise-dark.svg +0 -0
- /package/{dist-community → dist-beta}/credentials/connectwise-light.svg +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/connectwise-dark.svg +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/connectwise-light.svg +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/descriptions/common.descriptions.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/descriptions/index.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/helpers/customFields.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/helpers/field-collector.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/helpers/field-conditions.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/helpers/index.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/helpers/logging.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/helpers/utils.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/methods/generated.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/methods/index.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/converter/index.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/converter/reference.generator.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/index.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/references.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/reports-descriptions.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/activity.schema.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/company.schema.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/contact.schema.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/index.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/members.schema.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/ticketNote.schema.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/ticketTask.schema.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/timeEntry.schema.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/static-fields.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/transformer.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/types/index.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/types/reference.types.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/types/resource.types.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/transport/access-key.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/transport/index.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/transport/operations.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/transport/response-transformer.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/types/n8n-augmentation.d.js +0 -0
- /package/{dist-community → dist-beta}/nodes/ConnectWisePsa.node.json +0 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
|
|
9
|
+
var __getProtoOf = Object.getPrototypeOf, __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all) __defProp(target, name, {
|
|
13
|
+
get: all[name],
|
|
14
|
+
enumerable: !0
|
|
15
|
+
});
|
|
16
|
+
}, __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from == "object" || typeof from == "function") for (let key of __getOwnPropNames(from)) !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, {
|
|
18
|
+
get: () => from[key],
|
|
19
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
20
|
+
});
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {},
|
|
25
|
+
__copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
26
|
+
value: mod,
|
|
27
|
+
enumerable: !0
|
|
28
|
+
}) : target, mod)), __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
29
|
+
value: !0
|
|
30
|
+
}), mod);
|
|
31
|
+
|
|
32
|
+
var reports_schema_exports = {};
|
|
33
|
+
|
|
34
|
+
__export(reports_schema_exports, {
|
|
35
|
+
execute: () => execute,
|
|
36
|
+
loadReportColumns: () => loadReportColumns,
|
|
37
|
+
reportsSchema: () => reportsSchema,
|
|
38
|
+
transformReportData: () => transformReportData
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
module.exports = __toCommonJS(reports_schema_exports);
|
|
42
|
+
|
|
43
|
+
var import_transport = require("../../transport"), import_utils = require("../../helpers/utils"), import_common = require("../../descriptions/common.properties");
|
|
44
|
+
|
|
45
|
+
function transformReportData(columnDefinitions, rowValues) {
|
|
46
|
+
if (process.env.MSPCOPILOT_BETA !== "true") return [];
|
|
47
|
+
const columnNames = columnDefinitions.map(def => Object.keys(def)[0]);
|
|
48
|
+
return rowValues.map(row => {
|
|
49
|
+
const obj = {};
|
|
50
|
+
return columnNames.forEach((col, index) => {
|
|
51
|
+
obj[col] = row[index];
|
|
52
|
+
}), obj;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function loadReportColumns() {
|
|
57
|
+
const reportName = this.getCurrentNodeParameter("reportName");
|
|
58
|
+
if (!reportName) return [];
|
|
59
|
+
try {
|
|
60
|
+
const sampleData = await import_transport.connectWiseApiRequest.call(this, "GET", `/system/reports/${reportName}`, {}, {
|
|
61
|
+
pageSize: 1
|
|
62
|
+
});
|
|
63
|
+
if (!sampleData.column_definitions) return [];
|
|
64
|
+
const columns = sampleData.column_definitions.map(def => {
|
|
65
|
+
const columnName = Object.keys(def)[0], columnInfo = def[columnName], details = [ columnInfo.type ];
|
|
66
|
+
for (const [key, value] of Object.entries(columnInfo)) if (key !== "type") {
|
|
67
|
+
if (typeof value == "boolean") {
|
|
68
|
+
if (value === !0) {
|
|
69
|
+
let displayKey = key.replace(/^is/, "").replace(/([A-Z])/g, " $1").trim();
|
|
70
|
+
displayKey = displayKey.charAt(0).toUpperCase() + displayKey.slice(1), details.push(displayKey);
|
|
71
|
+
}
|
|
72
|
+
} else if (value != null && value !== "") {
|
|
73
|
+
let displayKey = key.replace(/([A-Z])/g, " $1").trim();
|
|
74
|
+
displayKey = displayKey.charAt(0).toUpperCase() + displayKey.slice(1), details.push(`${displayKey}: ${value}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
name: columnName,
|
|
79
|
+
value: columnName,
|
|
80
|
+
description: details.join(", ")
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
return columns.unshift({
|
|
84
|
+
name: "All Fields (Override Selection)",
|
|
85
|
+
value: "__ALL_FIELDS_OVERRIDE__"
|
|
86
|
+
}), columns;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
return console.error("Error loading report columns:", error), [];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const reportsFields = [ {
|
|
93
|
+
displayName: "Operation",
|
|
94
|
+
name: "operation",
|
|
95
|
+
type: "options",
|
|
96
|
+
noDataExpression: !0,
|
|
97
|
+
displayOptions: {
|
|
98
|
+
show: {
|
|
99
|
+
resource: [ "reports" ]
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
options: [ {
|
|
103
|
+
name: "Get Report",
|
|
104
|
+
value: "getReport",
|
|
105
|
+
description: "Retrieve report data",
|
|
106
|
+
action: "Get a report"
|
|
107
|
+
} ],
|
|
108
|
+
default: "getReport"
|
|
109
|
+
}, {
|
|
110
|
+
displayName: "Report Name",
|
|
111
|
+
name: "reportName",
|
|
112
|
+
type: "options",
|
|
113
|
+
required: !0,
|
|
114
|
+
displayOptions: {
|
|
115
|
+
show: {
|
|
116
|
+
resource: [ "reports" ],
|
|
117
|
+
operation: [ "getReport" ]
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
typeOptions: {
|
|
121
|
+
loadOptionsMethod: "loadOptions_system_reports"
|
|
122
|
+
},
|
|
123
|
+
default: "",
|
|
124
|
+
description: "Select the report to retrieve"
|
|
125
|
+
}, {
|
|
126
|
+
displayName: "Transform Output",
|
|
127
|
+
name: "transformOutput",
|
|
128
|
+
type: "boolean",
|
|
129
|
+
displayOptions: {
|
|
130
|
+
show: {
|
|
131
|
+
resource: [ "reports" ],
|
|
132
|
+
operation: [ "getReport" ]
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
default: !0,
|
|
136
|
+
hint: "Transform matrix format (column_definitions + row_values) to array of objects"
|
|
137
|
+
}, ...(0, import_common.getCommonFields)({
|
|
138
|
+
overrides: {
|
|
139
|
+
fields: {
|
|
140
|
+
typeOptions: {
|
|
141
|
+
loadOptionsMethod: "loadReportColumns",
|
|
142
|
+
loadOptionsDependsOn: [ "reportName" ]
|
|
143
|
+
},
|
|
144
|
+
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>. Leave empty to return all columns.'
|
|
145
|
+
},
|
|
146
|
+
orderBy: {
|
|
147
|
+
type: "string",
|
|
148
|
+
typeOptions: void 0,
|
|
149
|
+
placeholder: "e.g., Date_Created or Company_Name",
|
|
150
|
+
hint: "Use exact column name from the report"
|
|
151
|
+
},
|
|
152
|
+
descending: {
|
|
153
|
+
displayOptions: {
|
|
154
|
+
show: {
|
|
155
|
+
operation: [ "getReport" ],
|
|
156
|
+
orderBy: [ {
|
|
157
|
+
_cnd: {
|
|
158
|
+
not: ""
|
|
159
|
+
}
|
|
160
|
+
} ]
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}) ], reportsSchema = {
|
|
166
|
+
resource: "reports",
|
|
167
|
+
displayName: "Report ✨",
|
|
168
|
+
pluralDisplayName: "Reports",
|
|
169
|
+
description: "Access ConnectWise system reports",
|
|
170
|
+
identifierField: "name",
|
|
171
|
+
nameField: "reportName",
|
|
172
|
+
endpoints: {
|
|
173
|
+
getReport: {
|
|
174
|
+
method: "GET",
|
|
175
|
+
path: params => `/system/reports/${params.reportName}`
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
fields: reportsFields
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
async function execute(operation, i) {
|
|
182
|
+
{
|
|
183
|
+
if (process.env.MSPCOPILOT_BETA !== "true") return (0, import_utils.returnProOnlyMessage)(this, i);
|
|
184
|
+
const {requireAccessKey: requireAccessKey} = await import("../../transport/access-key.js");
|
|
185
|
+
if (!await requireAccessKey(this, "beta")) return (0, import_utils.returnAccessKeyRequired)(this, i);
|
|
186
|
+
}
|
|
187
|
+
const reportName = this.getNodeParameter("reportName", i), transformOutput = this.getNodeParameter("transformOutput", i, !0), returnAll = this.getNodeParameter("returnAll", i, !1), limit = this.getNodeParameter("limit", i, 50), qs = (0,
|
|
188
|
+
import_utils.buildQueryOptions)(this, i, []), endpoint = `/system/reports/${reportName}`;
|
|
189
|
+
let result = await import_transport.connectWiseApiRequest.call(this, "GET", endpoint, {}, qs, {
|
|
190
|
+
returnAll: returnAll,
|
|
191
|
+
limit: returnAll ? void 0 : limit
|
|
192
|
+
});
|
|
193
|
+
return transformOutput && result && result.column_definitions && result.row_values && (result = transformReportData(result.column_definitions, result.row_values)),
|
|
194
|
+
this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(result), {
|
|
195
|
+
itemData: {
|
|
196
|
+
item: i
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
0 && (module.exports = {
|
|
202
|
+
execute: execute,
|
|
203
|
+
loadReportColumns: loadReportColumns,
|
|
204
|
+
reportsSchema: reportsSchema,
|
|
205
|
+
transformReportData: transformReportData
|
|
206
|
+
});
|
package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/ticket.schema.js
RENAMED
|
@@ -75,6 +75,11 @@ const ticketFields = [ {
|
|
|
75
75
|
value: "update",
|
|
76
76
|
description: "Update a ticket",
|
|
77
77
|
action: "Update a ticket"
|
|
78
|
+
}, {
|
|
79
|
+
name: "Smart Alert Consolidation ✨",
|
|
80
|
+
value: "smartAlertConsolidation",
|
|
81
|
+
description: "Create, update or close tickets with smart alert consolidation",
|
|
82
|
+
action: "Smart alert consolidation ✨"
|
|
78
83
|
} ],
|
|
79
84
|
default: "create"
|
|
80
85
|
}, {
|
|
@@ -90,6 +95,10 @@ const ticketFields = [ {
|
|
|
90
95
|
}, {
|
|
91
96
|
name: "Project Ticket",
|
|
92
97
|
value: "project"
|
|
98
|
+
}, {
|
|
99
|
+
name: "Auto ✨",
|
|
100
|
+
value: "auto",
|
|
101
|
+
description: "Automatically detect ticket type"
|
|
93
102
|
} ],
|
|
94
103
|
displayOptions: {
|
|
95
104
|
show: {
|
|
@@ -502,7 +511,8 @@ const ticketFields = [ {
|
|
|
502
511
|
ticketType: [ "project" ]
|
|
503
512
|
}
|
|
504
513
|
}
|
|
505
|
-
}, ...(0, import_common.
|
|
514
|
+
}, ...process.env.MSPCOPILOT_BETA === "true" ? [ (0, import_common.getCustomFieldsProperty)("service_tickets") ] : [], ...(0,
|
|
515
|
+
import_common.getCommonFields)(), {
|
|
506
516
|
displayName: `New to Smart Alert Consolidation? Start with the <a href="https://${import_common2.DOCURL_PREFIX}/smart-alert-consolidation${import_common2.DOCURL_SUFFIX}">setup guide</a> for a walkthrough of all options.`,
|
|
507
517
|
name: "smartAlertConsolidationNotice",
|
|
508
518
|
type: "notice",
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
|
|
1
3
|
var __defProp = Object.defineProperty;
|
|
2
4
|
|
|
3
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
6
|
|
|
5
7
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
8
|
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __getProtoOf = Object.getPrototypeOf, __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
10
|
|
|
9
11
|
var __export = (target, all) => {
|
|
10
12
|
for (var name in all) __defProp(target, name, {
|
|
@@ -19,7 +21,11 @@ var __export = (target, all) => {
|
|
|
19
21
|
return to;
|
|
20
22
|
};
|
|
21
23
|
|
|
22
|
-
var
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {},
|
|
25
|
+
__copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
26
|
+
value: mod,
|
|
27
|
+
enumerable: !0
|
|
28
|
+
}) : target, mod)), __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
23
29
|
value: !0
|
|
24
30
|
}), mod);
|
|
25
31
|
|
|
@@ -44,23 +50,95 @@ function getBestErrorMessage(operationError) {
|
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
async function getCacheClient() {
|
|
47
|
-
return null;
|
|
53
|
+
if (process.env.MSPCOPILOT_BETA !== "true") return null;
|
|
54
|
+
if (!Redis && process.env.MSPCOPILOT_BETA === "true") try {
|
|
55
|
+
Redis = (await import("ioredis")).default;
|
|
56
|
+
} catch (error) {
|
|
57
|
+
return console.error("Failed to load cache module:", error), null;
|
|
58
|
+
}
|
|
59
|
+
if (cacheClient && cacheClient.status === "ready") return cacheClient;
|
|
60
|
+
if (cacheClient && [ "end", "close" ].includes(cacheClient.status)) {
|
|
61
|
+
try {
|
|
62
|
+
cacheClient.disconnect(!1);
|
|
63
|
+
} catch {}
|
|
64
|
+
cacheClient = null;
|
|
65
|
+
}
|
|
66
|
+
if (!cacheClient && Redis) try {
|
|
67
|
+
cacheClient = new Redis({
|
|
68
|
+
host: process.env.QUEUE_BULL_REDIS_HOST || "localhost",
|
|
69
|
+
port: parseInt(process.env.QUEUE_BULL_REDIS_PORT || "6379"),
|
|
70
|
+
password: process.env.QUEUE_BULL_REDIS_PASSWORD || "",
|
|
71
|
+
db: 1,
|
|
72
|
+
retryStrategy: () => null,
|
|
73
|
+
lazyConnect: !0,
|
|
74
|
+
enableOfflineQueue: !1,
|
|
75
|
+
connectTimeout: 1e3
|
|
76
|
+
}), cacheClient.on("error", err => {
|
|
77
|
+
console.error("Cache connection error:", err.message), lastConnectionError = err.message;
|
|
78
|
+
});
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error("Failed to create cache client:", error), cacheClient = null;
|
|
81
|
+
}
|
|
82
|
+
return cacheClient;
|
|
48
83
|
}
|
|
49
84
|
|
|
50
85
|
async function getCached(key) {
|
|
51
|
-
return {
|
|
86
|
+
if (process.env.MSPCOPILOT_BETA !== "true") return {
|
|
52
87
|
data: null
|
|
53
88
|
};
|
|
89
|
+
const redis = await getCacheClient();
|
|
90
|
+
if (!redis) return {
|
|
91
|
+
data: null,
|
|
92
|
+
error: "Redis not available"
|
|
93
|
+
};
|
|
94
|
+
try {
|
|
95
|
+
const cached = await redis.get(key);
|
|
96
|
+
return cached !== null ? {
|
|
97
|
+
data: JSON.parse(cached)
|
|
98
|
+
} : {
|
|
99
|
+
data: null
|
|
100
|
+
};
|
|
101
|
+
} catch (error) {
|
|
102
|
+
return console.error("Cache get error:", error.message), {
|
|
103
|
+
data: null,
|
|
104
|
+
error: getBestErrorMessage(error.message)
|
|
105
|
+
};
|
|
106
|
+
}
|
|
54
107
|
}
|
|
55
108
|
|
|
56
109
|
async function setCached(key, data, ttl) {
|
|
57
|
-
return {
|
|
110
|
+
if (process.env.MSPCOPILOT_BETA !== "true") return {
|
|
111
|
+
success: !1
|
|
112
|
+
};
|
|
113
|
+
const redis = await getCacheClient();
|
|
114
|
+
if (!redis) return {
|
|
115
|
+
success: !1,
|
|
116
|
+
error: "Redis not available"
|
|
117
|
+
};
|
|
118
|
+
if (ttl <= 0) return {
|
|
58
119
|
success: !1
|
|
59
120
|
};
|
|
121
|
+
try {
|
|
122
|
+
return await redis.setex(key, ttl, JSON.stringify(data)), {
|
|
123
|
+
success: !0
|
|
124
|
+
};
|
|
125
|
+
} catch (error) {
|
|
126
|
+
return console.error("Cache set error:", error.message), {
|
|
127
|
+
success: !1,
|
|
128
|
+
error: getBestErrorMessage(error.message)
|
|
129
|
+
};
|
|
130
|
+
}
|
|
60
131
|
}
|
|
61
132
|
|
|
62
133
|
async function deleteCached(key) {
|
|
63
|
-
return !1;
|
|
134
|
+
if (process.env.MSPCOPILOT_BETA !== "true") return !1;
|
|
135
|
+
const redis = await getCacheClient();
|
|
136
|
+
if (!redis) return !1;
|
|
137
|
+
try {
|
|
138
|
+
return await redis.del(key) > 0;
|
|
139
|
+
} catch (error) {
|
|
140
|
+
return console.error("Cache del error:", error.message), !1;
|
|
141
|
+
}
|
|
64
142
|
}
|
|
65
143
|
|
|
66
144
|
async function clearAllCached() {
|
|
@@ -43,7 +43,7 @@ module.exports = __toCommonJS(client_exports);
|
|
|
43
43
|
|
|
44
44
|
var import_n8n_workflow = require("n8n-workflow"), import_logging = require("../helpers/logging"), import_hint_collector = require("../helpers/hint-collector");
|
|
45
45
|
|
|
46
|
-
const DEFAULT_API_PATH = "v4_6_release/apis/3.0";
|
|
46
|
+
const OPTIONS_CACHE_TTL = 120, DEFAULT_API_PATH = "v4_6_release/apis/3.0";
|
|
47
47
|
|
|
48
48
|
function extractApiError(error) {
|
|
49
49
|
let errorMessage = "Request failed";
|
|
@@ -91,10 +91,51 @@ async function connectWiseApiRequest(method, endpoint, body = {}, qs = {}, optio
|
|
|
91
91
|
} catch (error) {
|
|
92
92
|
console.warn("Version check module load failed:", error);
|
|
93
93
|
}
|
|
94
|
-
if (
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
if (process.env.MSPCOPILOT_BETA === "true") {
|
|
95
|
+
const {createHash: createHash} = await import("crypto"), {getCached: getCached, setCached: setCached, deleteCached: deleteCached, getCacheConfig: getCacheConfig} = await import("./cache.js");
|
|
96
|
+
let cacheConfig = {
|
|
97
|
+
enabled: !1,
|
|
98
|
+
ttl: 0
|
|
99
|
+
};
|
|
100
|
+
if ("getNodeParameter" in this && method === "GET") try {
|
|
101
|
+
cacheConfig = getCacheConfig(this, 0);
|
|
102
|
+
} catch {}
|
|
103
|
+
process.env.MSPCOPILOT_BETA === "true" && options.optionsCache === !0 && method === "GET" && (cacheConfig = {
|
|
104
|
+
enabled: !0,
|
|
105
|
+
ttl: OPTIONS_CACHE_TTL
|
|
106
|
+
});
|
|
107
|
+
let cacheKey;
|
|
108
|
+
if (cacheConfig.enabled) {
|
|
109
|
+
const credentials = await this.getCredentials("connectWisePsaApi"), cacheKeyData = {
|
|
110
|
+
endpoint: endpoint,
|
|
111
|
+
qs: qs,
|
|
112
|
+
options: options
|
|
113
|
+
}, hash = createHash("sha256").update(JSON.stringify(cacheKeyData)).digest("hex").substring(0, 16);
|
|
114
|
+
if (cacheKey = `cw:psa:${credentials.companyId}:${hash}`, cacheConfig.ttl === 0) await deleteCached(cacheKey),
|
|
115
|
+
console.log("🗑️ Cache invalidated for", endpoint), options.optionsCache || (0,
|
|
116
|
+
import_hint_collector.hint)(this, "cache_invalidated"); else {
|
|
117
|
+
const cacheResult = await getCached(cacheKey);
|
|
118
|
+
if (console.log(`💾 Cache lookup for ${endpoint}: ${cacheResult.data ? "✅ HIT" : "❌ MISS"}`, {
|
|
119
|
+
qs: qs,
|
|
120
|
+
options: options
|
|
121
|
+
}), cacheResult.error && !options.optionsCache && (0, import_hint_collector.hint)(this, "cache_error", cacheResult.error),
|
|
122
|
+
cacheResult.data) return options.optionsCache || (0, import_hint_collector.hint)(this, "cache_hit"),
|
|
123
|
+
cacheResult.data;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const response = await connectWiseHttpRequest.call(this, method, endpoint, body, qs, options);
|
|
127
|
+
if (cacheKey && cacheConfig.ttl > 0) {
|
|
128
|
+
const setResult = await setCached(cacheKey, response, cacheConfig.ttl);
|
|
129
|
+
if (console.log(`💾 Storing response in cache for ${endpoint} - TTL=${cacheConfig.ttl}s, Data=${Array.isArray(response) ? `${response.length} items` : "single item"}, Key=${cacheKey}`),
|
|
130
|
+
!options.optionsCache) {
|
|
131
|
+
if (setResult.error) (0, import_hint_collector.hint)(this, "cache_error", setResult.error); else if (setResult.success) {
|
|
132
|
+
const minutes = Math.floor(cacheConfig.ttl / 60), ttlMessage = minutes > 0 ? `${minutes} minutes` : `${cacheConfig.ttl} seconds`;
|
|
133
|
+
(0, import_hint_collector.hint)(this, "cache_stored", ttlMessage);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return response;
|
|
138
|
+
} else return await connectWiseHttpRequest.call(this, method, endpoint, body, qs, options);
|
|
98
139
|
}
|
|
99
140
|
|
|
100
141
|
async function connectWiseHttpRequest(method, endpoint, body = {}, qs = {}, options = {}) {
|
|
@@ -39,7 +39,7 @@ module.exports = __toCommonJS(version_check_exports);
|
|
|
39
39
|
|
|
40
40
|
var fs = __toESM(require("fs/promises")), path = __toESM(require("path")), os = __toESM(require("os")), import_common = require("../descriptions/common.descriptions"), import_hint_collector = require("../helpers/hint-collector");
|
|
41
41
|
|
|
42
|
-
const CACHE_FILE_PATH = path.join(os.tmpdir(), "connectwise-n8n-version-cache.json"), CURRENT_VERSION = "0.2.1-beta.
|
|
42
|
+
const CACHE_FILE_PATH = path.join(os.tmpdir(), "connectwise-n8n-version-cache.json"), CURRENT_VERSION = "0.2.1-beta.3";
|
|
43
43
|
|
|
44
44
|
let inMemoryCache = null, cacheLoadPromise = null, fetchInProgress = !1;
|
|
45
45
|
|
|
@@ -63,7 +63,7 @@ async function saveCache(versionInfo) {
|
|
|
63
63
|
};
|
|
64
64
|
try {
|
|
65
65
|
await fs.writeFile(CACHE_FILE_PATH, JSON.stringify(cacheEntry, null, 2), "utf-8"),
|
|
66
|
-
console.log("📦 Version check cache saved to disk (
|
|
66
|
+
console.log("📦 Version check cache saved to disk (beta build)");
|
|
67
67
|
} catch (error) {
|
|
68
68
|
console.warn("⚠️ Failed to save version check cache to disk:", error);
|
|
69
69
|
}
|
|
@@ -76,8 +76,8 @@ async function fetchLatestVersion(accessKey) {
|
|
|
76
76
|
lastChecked: Date.now()
|
|
77
77
|
};
|
|
78
78
|
try {
|
|
79
|
-
console.log(`🔍 Checking for updates (
|
|
80
|
-
const controller = new AbortController, timeoutId = setTimeout(() => controller.abort(), 5e3), url = `${import_common.VERSION_CHECK_URL}?version=${CURRENT_VERSION}&build=
|
|
79
|
+
console.log(`🔍 Checking for updates (beta v${CURRENT_VERSION})...`);
|
|
80
|
+
const controller = new AbortController, timeoutId = setTimeout(() => controller.abort(), 5e3), url = `${import_common.VERSION_CHECK_URL}?version=${CURRENT_VERSION}&build=beta`, headers = {
|
|
81
81
|
Accept: "application/json"
|
|
82
82
|
};
|
|
83
83
|
accessKey && (headers.Authorization = `Bearer ${accessKey}`);
|
|
@@ -91,7 +91,7 @@ async function fetchLatestVersion(accessKey) {
|
|
|
91
91
|
const data = await response.json();
|
|
92
92
|
if (data && typeof data.latest == "string" && (versionInfo.latest = data.latest,
|
|
93
93
|
versionInfo.updateAvailable = data.updateAvailable || !1, versionInfo.message = data.message,
|
|
94
|
-
console.log(`✅ Version check complete:
|
|
94
|
+
console.log(`✅ Version check complete: beta v${CURRENT_VERSION}, latest=${data.latest}, updateAvailable=${data.updateAvailable}`)),
|
|
95
95
|
data?.accessKeyInfo) {
|
|
96
96
|
versionInfo.accessKeyInfo = data.accessKeyInfo;
|
|
97
97
|
try {
|
|
@@ -122,8 +122,8 @@ function checkForUpdatesAsync(accessKey) {
|
|
|
122
122
|
|
|
123
123
|
async function checkAndNotifyUpdate(context) {
|
|
124
124
|
try {
|
|
125
|
-
const
|
|
126
|
-
if (
|
|
125
|
+
const accessKey = (await context.getCredentials("connectWisePsaApi")).accessKey;
|
|
126
|
+
if (!!0) return;
|
|
127
127
|
checkForUpdatesAsync(accessKey), inMemoryCache?.updateAvailable && (0, import_hint_collector.hint)(context, "version_update", {
|
|
128
128
|
version: inMemoryCache.latest,
|
|
129
129
|
message: inMemoryCache.message
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mspcopilot/n8n-nodes-connectwise",
|
|
3
|
-
"version": "0.2.1-beta.
|
|
3
|
+
"version": "0.2.1-beta.3",
|
|
4
4
|
"description": "n8n node to integrate with ConnectWise PSA",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package"
|
|
@@ -24,15 +24,16 @@
|
|
|
24
24
|
"postinstall": "echo 'ConnectWise PSA node installed successfully'"
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
|
-
"dist-
|
|
27
|
+
"dist-beta"
|
|
28
28
|
],
|
|
29
29
|
"n8n": {
|
|
30
30
|
"n8nNodesApiVersion": 1,
|
|
31
31
|
"credentials": [
|
|
32
|
-
"dist-
|
|
32
|
+
"dist-beta/credentials/ConnectWisePsaApi.credentials.js"
|
|
33
33
|
],
|
|
34
34
|
"nodes": [
|
|
35
|
-
"dist-
|
|
35
|
+
"dist-beta/nodes/ConnectWise/PSA/ConnectWisePsa.node.js",
|
|
36
|
+
"dist-beta/nodes/ConnectWise/PSA/IfSchedule.node.js"
|
|
36
37
|
]
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
@@ -61,7 +62,8 @@
|
|
|
61
62
|
"typescript": "^5.8.2"
|
|
62
63
|
},
|
|
63
64
|
"peerDependencies": {
|
|
64
|
-
"n8n-workflow": "*"
|
|
65
|
+
"n8n-workflow": "*",
|
|
66
|
+
"luxon": "*"
|
|
65
67
|
},
|
|
66
68
|
"publishConfig": {
|
|
67
69
|
"registry": "https://registry.npmjs.org",
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
|
|
9
|
-
var __export = (target, all) => {
|
|
10
|
-
for (var name in all) __defProp(target, name, {
|
|
11
|
-
get: all[name],
|
|
12
|
-
enumerable: !0
|
|
13
|
-
});
|
|
14
|
-
}, __copyProps = (to, from, except, desc) => {
|
|
15
|
-
if (from && typeof from == "object" || typeof from == "function") for (let key of __getOwnPropNames(from)) !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, {
|
|
16
|
-
get: () => from[key],
|
|
17
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
18
|
-
});
|
|
19
|
-
return to;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
|
|
23
|
-
value: !0
|
|
24
|
-
}), mod);
|
|
25
|
-
|
|
26
|
-
var alert_consolidation_exports = {};
|
|
27
|
-
|
|
28
|
-
__export(alert_consolidation_exports, {
|
|
29
|
-
executeSmartConsolidation: () => executeSmartConsolidation
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
module.exports = __toCommonJS(alert_consolidation_exports);
|
|
33
|
-
|
|
34
|
-
var import_n8n_workflow = require("n8n-workflow"), import_luxon = require("luxon"), import_crypto = require("crypto"), import_client = require("../../transport/client"), import_utils = require("../../helpers/utils");
|
|
35
|
-
|
|
36
|
-
const executeSmartConsolidationStub = async function(itemIndex) {
|
|
37
|
-
return (0, import_utils.returnProOnlyMessage)(this, itemIndex);
|
|
38
|
-
}, executeSmartConsolidation = executeSmartConsolidationStub;
|
|
39
|
-
|
|
40
|
-
0 && (module.exports = {
|
|
41
|
-
executeSmartConsolidation: executeSmartConsolidation
|
|
42
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/descriptions/common.descriptions.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/converter/reference.generator.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/activity.schema.js
RENAMED
|
File without changes
|
/package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/company.schema.js
RENAMED
|
File without changes
|
/package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/contact.schema.js
RENAMED
|
File without changes
|
|
File without changes
|
/package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/members.schema.js
RENAMED
|
File without changes
|
/package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/ticketNote.schema.js
RENAMED
|
File without changes
|
/package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/ticketTask.schema.js
RENAMED
|
File without changes
|
/package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/schema/resources/timeEntry.schema.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/{dist-community → dist-beta}/nodes/ConnectWise/PSA/transport/response-transformer.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|