n8n-nodes-imis 0.1.0

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.
Files changed (39) hide show
  1. package/dist/credentials/ImisCrmApi.credentials.d.ts +7 -0
  2. package/dist/credentials/ImisCrmApi.credentials.js +42 -0
  3. package/dist/credentials/TdnWorkflowApi.credentials.d.ts +7 -0
  4. package/dist/credentials/TdnWorkflowApi.credentials.js +33 -0
  5. package/dist/nodes/ImisCrmIqa/3DN.png +0 -0
  6. package/dist/nodes/ImisCrmIqa/ImisCrmIqa.node.d.ts +5 -0
  7. package/dist/nodes/ImisCrmIqa/ImisCrmIqa.node.js +281 -0
  8. package/dist/nodes/ImisCrmIqa/helpers/ImisAuth.d.ts +17 -0
  9. package/dist/nodes/ImisCrmIqa/helpers/ImisAuth.js +88 -0
  10. package/dist/nodes/ImisCrmTrigger/ImisAuth.d.ts +17 -0
  11. package/dist/nodes/ImisCrmTrigger/ImisAuth.js +88 -0
  12. package/dist/nodes/ImisCrm_Unified/3DN.png +0 -0
  13. package/dist/nodes/ImisCrm_Unified/ImisCrm.node.d.ts +15 -0
  14. package/dist/nodes/ImisCrm_Unified/ImisCrm.node.js +1355 -0
  15. package/dist/nodes/ImisCrm_Unified/ImisCrmTrigger.node.d.ts +5 -0
  16. package/dist/nodes/ImisCrm_Unified/ImisCrmTrigger.node.js +509 -0
  17. package/dist/nodes/ImisCrm_Unified/ImisMemberProcess.node.d.ts +5 -0
  18. package/dist/nodes/ImisCrm_Unified/ImisMemberProcess.node.js +499 -0
  19. package/dist/nodes/ImisCrm_Unified/ImisSendEmail.node.d.ts +5 -0
  20. package/dist/nodes/ImisCrm_Unified/ImisSendEmail.node.js +228 -0
  21. package/dist/nodes/ImisCrm_Unified/helpers/ImisAuth.d.ts +17 -0
  22. package/dist/nodes/ImisCrm_Unified/helpers/ImisAuth.js +88 -0
  23. package/dist/nodes/ImisCrm_Unified/imis.png +0 -0
  24. package/dist/nodes/TdnWorkflowInput/3DN.png +0 -0
  25. package/dist/nodes/TdnWorkflowInput/TdnWorkflowInput.node.d.ts +10 -0
  26. package/dist/nodes/TdnWorkflowInput/TdnWorkflowInput.node.js +232 -0
  27. package/dist/nodes/TdnWorkflowTrigger/3DN.png +0 -0
  28. package/dist/nodes/TdnWorkflowTrigger/TdnWorkflowTrigger.node.d.ts +5 -0
  29. package/dist/nodes/TdnWorkflowTrigger/TdnWorkflowTrigger.node.js +99 -0
  30. package/dist/utils/CrmDeduplicationHelper.d.ts +30 -0
  31. package/dist/utils/CrmDeduplicationHelper.js +318 -0
  32. package/dist/utils/DeduplicationOptions.d.ts +5 -0
  33. package/dist/utils/DeduplicationOptions.js +63 -0
  34. package/dist/utils/DeduplicationStore.d.ts +37 -0
  35. package/dist/utils/DeduplicationStore.js +287 -0
  36. package/dist/utils/NodeDeduplicationHelper.d.ts +29 -0
  37. package/dist/utils/NodeDeduplicationHelper.js +153 -0
  38. package/index.js +2 -0
  39. package/package.json +64 -0
@@ -0,0 +1,7 @@
1
+ import { ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class ImisCrmApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImisCrmApi = void 0;
4
+ class ImisCrmApi {
5
+ constructor() {
6
+ this.name = 'imisCrmApi';
7
+ this.displayName = 'iMIS CRM API';
8
+ this.documentationUrl = 'https://developer.imis.com/';
9
+ this.properties = [
10
+ {
11
+ displayName: 'Host URL',
12
+ name: 'hostUrl',
13
+ type: 'string',
14
+ default: '',
15
+ placeholder: 'https://your-imis-instance.com',
16
+ required: true,
17
+ description: 'The base URL of your iMIS instance (without trailing slash)',
18
+ },
19
+ {
20
+ displayName: 'Username',
21
+ name: 'username',
22
+ type: 'string',
23
+ default: '',
24
+ required: true,
25
+ description: 'Your iMIS username',
26
+ },
27
+ {
28
+ displayName: 'Password',
29
+ name: 'password',
30
+ type: 'string',
31
+ typeOptions: {
32
+ password: true,
33
+ },
34
+ default: '',
35
+ required: true,
36
+ description: 'Your iMIS password',
37
+ },
38
+ ];
39
+ // Note: Credential testing will be handled by the authentication flow in the node
40
+ }
41
+ }
42
+ exports.ImisCrmApi = ImisCrmApi;
@@ -0,0 +1,7 @@
1
+ import { ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class TdnWorkflowApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TdnWorkflowApi = void 0;
4
+ class TdnWorkflowApi {
5
+ constructor() {
6
+ this.name = 'tdnWorkflowApi';
7
+ this.displayName = '3DN Workflow API';
8
+ this.documentationUrl = '';
9
+ this.properties = [
10
+ {
11
+ displayName: 'Base URL',
12
+ name: 'baseUrl',
13
+ type: 'string',
14
+ default: '',
15
+ placeholder: 'http://localhost:3000',
16
+ required: true,
17
+ description: 'The base URL of your 3DN Workflow instance (without trailing slash)',
18
+ },
19
+ {
20
+ displayName: 'API Key',
21
+ name: 'apiKey',
22
+ type: 'string',
23
+ typeOptions: {
24
+ password: true,
25
+ },
26
+ default: '',
27
+ required: true,
28
+ description: 'Your 3DN Workflow API key',
29
+ },
30
+ ];
31
+ }
32
+ }
33
+ exports.TdnWorkflowApi = TdnWorkflowApi;
Binary file
@@ -0,0 +1,5 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class ImisCrmIqa implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImisCrmIqa = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const ImisAuth_1 = require("./helpers/ImisAuth");
6
+ function transformImisData(rawData) {
7
+ const cleanObject = (obj) => {
8
+ if (obj === null || obj === undefined) {
9
+ return obj;
10
+ }
11
+ if (Array.isArray(obj)) {
12
+ return obj.map(item => cleanObject(item));
13
+ }
14
+ if (typeof obj === 'object') {
15
+ const cleaned = {};
16
+ for (const [key, value] of Object.entries(obj)) {
17
+ if (key === '$type') {
18
+ continue;
19
+ }
20
+ const cleanKey = key.startsWith('$') ? key.substring(1) : key;
21
+ cleaned[cleanKey] = cleanObject(value);
22
+ }
23
+ return cleaned;
24
+ }
25
+ return obj;
26
+ };
27
+ return cleanObject(rawData);
28
+ }
29
+ class ImisCrmIqa {
30
+ constructor() {
31
+ this.description = {
32
+ displayName: 'iMIS IQA Query',
33
+ name: 'imisCrmIqa',
34
+ icon: 'file:3DN.png',
35
+ group: ['transform'],
36
+ version: 1,
37
+ description: 'Execute iMIS IQA queries and return iterable JSON results',
38
+ defaults: {
39
+ name: 'iMIS IQA Query',
40
+ },
41
+ inputs: ['main'],
42
+ outputs: ['main'],
43
+ credentials: [
44
+ {
45
+ name: 'imisCrmApi',
46
+ required: true,
47
+ },
48
+ ],
49
+ properties: [
50
+ {
51
+ displayName: 'Operation',
52
+ name: 'operation',
53
+ type: 'options',
54
+ noDataExpression: true,
55
+ options: [
56
+ {
57
+ name: 'Execute Query',
58
+ value: 'executeQuery',
59
+ description: 'Execute an IQA query and return results',
60
+ },
61
+ ],
62
+ default: 'executeQuery',
63
+ required: true,
64
+ },
65
+ {
66
+ displayName: 'Query Name',
67
+ name: 'queryName',
68
+ type: 'string',
69
+ displayOptions: {
70
+ show: {
71
+ operation: ['executeQuery'],
72
+ },
73
+ },
74
+ default: '',
75
+ required: true,
76
+ description: 'The full path to the IQA query (e.g., $/Common/Queries/Value Lists/MemberTypeList)',
77
+ placeholder: '$/Common/Queries/Value Lists/MemberTypeList',
78
+ },
79
+ {
80
+ displayName: 'Split Results',
81
+ name: 'splitResults',
82
+ type: 'boolean',
83
+ displayOptions: {
84
+ show: {
85
+ operation: ['executeQuery'],
86
+ },
87
+ },
88
+ default: true,
89
+ description: 'Whether to split results into separate items (one per result row) or return all results as a single item',
90
+ },
91
+ {
92
+ displayName: 'Additional Options',
93
+ name: 'additionalOptions',
94
+ type: 'collection',
95
+ placeholder: 'Add Option',
96
+ default: {},
97
+ displayOptions: {
98
+ show: {
99
+ operation: ['executeQuery'],
100
+ },
101
+ },
102
+ options: [
103
+ {
104
+ displayName: 'Limit',
105
+ name: 'limit',
106
+ type: 'number',
107
+ default: 100,
108
+ description: 'Maximum number of results to return',
109
+ typeOptions: {
110
+ minValue: 1,
111
+ maxValue: 10000,
112
+ },
113
+ },
114
+ {
115
+ displayName: 'Offset',
116
+ name: 'offset',
117
+ type: 'number',
118
+ default: 0,
119
+ description: 'Number of results to skip (for pagination)',
120
+ typeOptions: {
121
+ minValue: 0,
122
+ },
123
+ },
124
+ {
125
+ displayName: 'Query Parameters',
126
+ name: 'queryParameters',
127
+ type: 'fixedCollection',
128
+ typeOptions: {
129
+ multipleValues: true,
130
+ },
131
+ default: {},
132
+ description: 'Query parameters to pass to the IQA query',
133
+ options: [
134
+ {
135
+ name: 'parameter',
136
+ displayName: 'Parameter',
137
+ values: [
138
+ {
139
+ displayName: 'Name',
140
+ name: 'name',
141
+ type: 'string',
142
+ default: '',
143
+ description: 'Parameter name (for reference - iMIS uses positional parameters)',
144
+ },
145
+ {
146
+ displayName: 'Value',
147
+ name: 'value',
148
+ type: 'string',
149
+ default: '',
150
+ description: 'Parameter value (must match order in IQA query definition)',
151
+ },
152
+ ],
153
+ },
154
+ ],
155
+ },
156
+ ],
157
+ },
158
+ ],
159
+ };
160
+ }
161
+ async execute() {
162
+ var _a, _b;
163
+ const items = this.getInputData();
164
+ const returnData = [];
165
+ const operation = this.getNodeParameter('operation', 0);
166
+ for (let i = 0; i < items.length; i++) {
167
+ try {
168
+ const credentials = await this.getCredentials('imisCrmApi');
169
+ const imisAuth = new ImisAuth_1.ImisAuth({
170
+ hostUrl: credentials.hostUrl,
171
+ username: credentials.username,
172
+ password: credentials.password,
173
+ });
174
+ if (operation === 'executeQuery') {
175
+ const queryName = this.getNodeParameter('queryName', i);
176
+ const splitResults = this.getNodeParameter('splitResults', i, true);
177
+ const additionalOptions = this.getNodeParameter('additionalOptions', i, {});
178
+ if (!queryName || queryName.trim() === '') {
179
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Query Name is required for item ${i}`);
180
+ }
181
+ // Build the query URL
182
+ let queryUrl = `${credentials.hostUrl}/api/IQA?QueryName=${encodeURIComponent(queryName.trim())}`;
183
+ // Add limit and offset if specified
184
+ if (additionalOptions.limit !== undefined) {
185
+ queryUrl += `&limit=${additionalOptions.limit}`;
186
+ }
187
+ if (additionalOptions.offset !== undefined) {
188
+ queryUrl += `&offset=${additionalOptions.offset}`;
189
+ }
190
+ // Add query parameters if specified
191
+ // iMIS IQA API requires parameters as &Parameter=value (repeated for each parameter in order)
192
+ // The parameter name is not included - only values, in the order defined in the IQA query
193
+ if ((_a = additionalOptions.queryParameters) === null || _a === void 0 ? void 0 : _a.parameter) {
194
+ const params = additionalOptions.queryParameters.parameter;
195
+ params.forEach(param => {
196
+ // Pass the value using &Parameter= format as required by iMIS IQA API
197
+ queryUrl += `&Parameter=${encodeURIComponent(param.value || '')}`;
198
+ });
199
+ }
200
+ // Execute the query
201
+ const response = await imisAuth.makeAuthenticatedRequest(this.helpers.httpRequest.bind(this.helpers), {
202
+ method: 'GET',
203
+ url: queryUrl,
204
+ });
205
+ // Extract items from response
206
+ // IQA returns: { Items: { $values: [...] } } or { $values: [...] }
207
+ const items = ((_b = response.Items) === null || _b === void 0 ? void 0 : _b.$values) || response.$values || [];
208
+ if (!Array.isArray(items)) {
209
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Expected array of results from IQA query, got: ${typeof items}`);
210
+ }
211
+ // Transform the data
212
+ const cleanedItems = items.map((item) => {
213
+ var _a;
214
+ // IQA returns data in Properties collection
215
+ const properties = ((_a = item.Properties) === null || _a === void 0 ? void 0 : _a.$values) || [];
216
+ // Convert properties array to object
217
+ const dataObject = {};
218
+ if (Array.isArray(properties)) {
219
+ properties.forEach((prop) => {
220
+ const name = prop.Name || prop.name;
221
+ const value = prop.Value !== undefined ? prop.Value : prop.value;
222
+ if (name) {
223
+ dataObject[name] = value;
224
+ }
225
+ });
226
+ }
227
+ // If no properties found, return the transformed item as-is
228
+ if (Object.keys(dataObject).length === 0) {
229
+ return transformImisData(item);
230
+ }
231
+ return dataObject;
232
+ });
233
+ const metadata = {
234
+ operation,
235
+ queryName: queryName.trim(),
236
+ resultCount: cleanedItems.length,
237
+ executedAt: new Date().toISOString(),
238
+ };
239
+ if (splitResults) {
240
+ // Return each result as a separate item
241
+ cleanedItems.forEach((item, index) => {
242
+ returnData.push({
243
+ json: item,
244
+ meta: {
245
+ ...metadata,
246
+ itemIndex: index,
247
+ },
248
+ });
249
+ });
250
+ }
251
+ else {
252
+ // Return all results as a single item
253
+ returnData.push({
254
+ json: {
255
+ results: cleanedItems,
256
+ metadata,
257
+ },
258
+ meta: metadata,
259
+ });
260
+ }
261
+ }
262
+ }
263
+ catch (error) {
264
+ if (this.continueOnFail()) {
265
+ returnData.push({
266
+ json: {
267
+ error: error.message,
268
+ },
269
+ meta: {
270
+ error: true,
271
+ },
272
+ });
273
+ continue;
274
+ }
275
+ throw error;
276
+ }
277
+ }
278
+ return [returnData];
279
+ }
280
+ }
281
+ exports.ImisCrmIqa = ImisCrmIqa;
@@ -0,0 +1,17 @@
1
+ import { IHttpRequestOptions } from 'n8n-workflow';
2
+ interface ImisCredentials {
3
+ hostUrl: string;
4
+ username: string;
5
+ password: string;
6
+ }
7
+ export declare class ImisAuth {
8
+ private accessToken;
9
+ private tokenExpiry;
10
+ private credentials;
11
+ constructor(credentials: ImisCredentials);
12
+ private requestNewToken;
13
+ private isTokenExpired;
14
+ getAccessToken(httpRequest: (options: IHttpRequestOptions) => Promise<any>): Promise<string>;
15
+ makeAuthenticatedRequest(httpRequest: (options: IHttpRequestOptions) => Promise<any>, requestOptions: IHttpRequestOptions): Promise<any>;
16
+ }
17
+ export {};
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImisAuth = void 0;
4
+ class ImisAuth {
5
+ constructor(credentials) {
6
+ this.accessToken = null;
7
+ this.tokenExpiry = null;
8
+ this.credentials = credentials;
9
+ }
10
+ async requestNewToken(httpRequest) {
11
+ var _a, _b;
12
+ const formData = `grant_type=password&username=${encodeURIComponent(this.credentials.username)}&password=${encodeURIComponent(this.credentials.password)}`;
13
+ // Clean URL - remove trailing slash
14
+ const cleanUrl = this.credentials.hostUrl.replace(/\/$/, '');
15
+ try {
16
+ const response = await httpRequest({
17
+ method: 'POST',
18
+ url: `${cleanUrl}/token`,
19
+ headers: {
20
+ 'Content-Type': 'application/x-www-form-urlencoded',
21
+ },
22
+ body: formData,
23
+ });
24
+ if (!response.access_token) {
25
+ throw new Error('Failed to obtain access token from iMIS - no access_token in response');
26
+ }
27
+ return response;
28
+ }
29
+ catch (error) {
30
+ if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 401) {
31
+ throw new Error('Invalid iMIS credentials - check username and password');
32
+ }
33
+ else if (((_b = error.response) === null || _b === void 0 ? void 0 : _b.status) === 404) {
34
+ throw new Error('iMIS token endpoint not found - check Host URL');
35
+ }
36
+ throw new Error(`Failed to obtain access token: ${error.message || 'Unknown error'}`);
37
+ }
38
+ }
39
+ isTokenExpired() {
40
+ if (!this.tokenExpiry) {
41
+ return true;
42
+ }
43
+ // Add 5 minute buffer before actual expiry
44
+ const bufferTime = 5 * 60 * 1000; // 5 minutes in milliseconds
45
+ return new Date().getTime() > (this.tokenExpiry.getTime() - bufferTime);
46
+ }
47
+ async getAccessToken(httpRequest) {
48
+ if (!this.accessToken || this.isTokenExpired()) {
49
+ const tokenResponse = await this.requestNewToken(httpRequest);
50
+ this.accessToken = tokenResponse.access_token;
51
+ // Calculate expiry time
52
+ const expiryTime = new Date();
53
+ expiryTime.setSeconds(expiryTime.getSeconds() + tokenResponse.expires_in);
54
+ this.tokenExpiry = expiryTime;
55
+ }
56
+ return this.accessToken;
57
+ }
58
+ async makeAuthenticatedRequest(httpRequest, requestOptions) {
59
+ var _a;
60
+ const token = await this.getAccessToken(httpRequest);
61
+ const authenticatedOptions = {
62
+ ...requestOptions,
63
+ headers: {
64
+ ...requestOptions.headers,
65
+ Authorization: `Bearer ${token}`,
66
+ },
67
+ };
68
+ try {
69
+ return await httpRequest(authenticatedOptions);
70
+ }
71
+ catch (error) {
72
+ // If we get a 401, token might be invalid, try refreshing once
73
+ if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 401) {
74
+ // Force token refresh
75
+ this.accessToken = null;
76
+ this.tokenExpiry = null;
77
+ const newToken = await this.getAccessToken(httpRequest);
78
+ authenticatedOptions.headers = {
79
+ ...authenticatedOptions.headers,
80
+ Authorization: `Bearer ${newToken}`,
81
+ };
82
+ return await httpRequest(authenticatedOptions);
83
+ }
84
+ throw error;
85
+ }
86
+ }
87
+ }
88
+ exports.ImisAuth = ImisAuth;
@@ -0,0 +1,17 @@
1
+ import { IHttpRequestOptions } from 'n8n-workflow';
2
+ interface ImisCredentials {
3
+ hostUrl: string;
4
+ username: string;
5
+ password: string;
6
+ }
7
+ export declare class ImisAuth {
8
+ private accessToken;
9
+ private tokenExpiry;
10
+ private credentials;
11
+ constructor(credentials: ImisCredentials);
12
+ private requestNewToken;
13
+ private isTokenExpired;
14
+ getAccessToken(httpRequest: (options: IHttpRequestOptions) => Promise<any>): Promise<string>;
15
+ makeAuthenticatedRequest(httpRequest: (options: IHttpRequestOptions) => Promise<any>, requestOptions: IHttpRequestOptions): Promise<any>;
16
+ }
17
+ export {};
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImisAuth = void 0;
4
+ class ImisAuth {
5
+ constructor(credentials) {
6
+ this.accessToken = null;
7
+ this.tokenExpiry = null;
8
+ this.credentials = credentials;
9
+ }
10
+ async requestNewToken(httpRequest) {
11
+ var _a, _b;
12
+ const formData = `grant_type=password&username=${encodeURIComponent(this.credentials.username)}&password=${encodeURIComponent(this.credentials.password)}`;
13
+ // Clean URL - remove trailing slash
14
+ const cleanUrl = this.credentials.hostUrl.replace(/\/$/, '');
15
+ try {
16
+ const response = await httpRequest({
17
+ method: 'POST',
18
+ url: `${cleanUrl}/token`,
19
+ headers: {
20
+ 'Content-Type': 'application/x-www-form-urlencoded',
21
+ },
22
+ body: formData,
23
+ });
24
+ if (!response.access_token) {
25
+ throw new Error('Failed to obtain access token from iMIS - no access_token in response');
26
+ }
27
+ return response;
28
+ }
29
+ catch (error) {
30
+ if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 401) {
31
+ throw new Error('Invalid iMIS credentials - check username and password');
32
+ }
33
+ else if (((_b = error.response) === null || _b === void 0 ? void 0 : _b.status) === 404) {
34
+ throw new Error('iMIS token endpoint not found - check Host URL');
35
+ }
36
+ throw new Error(`Failed to obtain access token: ${error.message || 'Unknown error'}`);
37
+ }
38
+ }
39
+ isTokenExpired() {
40
+ if (!this.tokenExpiry) {
41
+ return true;
42
+ }
43
+ // Add 5 minute buffer before actual expiry
44
+ const bufferTime = 5 * 60 * 1000; // 5 minutes in milliseconds
45
+ return new Date().getTime() > (this.tokenExpiry.getTime() - bufferTime);
46
+ }
47
+ async getAccessToken(httpRequest) {
48
+ if (!this.accessToken || this.isTokenExpired()) {
49
+ const tokenResponse = await this.requestNewToken(httpRequest);
50
+ this.accessToken = tokenResponse.access_token;
51
+ // Calculate expiry time
52
+ const expiryTime = new Date();
53
+ expiryTime.setSeconds(expiryTime.getSeconds() + tokenResponse.expires_in);
54
+ this.tokenExpiry = expiryTime;
55
+ }
56
+ return this.accessToken;
57
+ }
58
+ async makeAuthenticatedRequest(httpRequest, requestOptions) {
59
+ var _a;
60
+ const token = await this.getAccessToken(httpRequest);
61
+ const authenticatedOptions = {
62
+ ...requestOptions,
63
+ headers: {
64
+ ...requestOptions.headers,
65
+ Authorization: `Bearer ${token}`,
66
+ },
67
+ };
68
+ try {
69
+ return await httpRequest(authenticatedOptions);
70
+ }
71
+ catch (error) {
72
+ // If we get a 401, token might be invalid, try refreshing once
73
+ if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 401) {
74
+ // Force token refresh
75
+ this.accessToken = null;
76
+ this.tokenExpiry = null;
77
+ const newToken = await this.getAccessToken(httpRequest);
78
+ authenticatedOptions.headers = {
79
+ ...authenticatedOptions.headers,
80
+ Authorization: `Bearer ${newToken}`,
81
+ };
82
+ return await httpRequest(authenticatedOptions);
83
+ }
84
+ throw error;
85
+ }
86
+ }
87
+ }
88
+ exports.ImisAuth = ImisAuth;
@@ -0,0 +1,15 @@
1
+ import { IExecuteFunctions, ILoadOptionsFunctions, INodeExecutionData, INodePropertyOptions, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class ImisCrm implements INodeType {
3
+ description: INodeTypeDescription;
4
+ methods: {
5
+ loadOptions: {
6
+ getSalutations(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
7
+ getGenders(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
8
+ getMemberStatuses(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
9
+ getCategories(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
10
+ getMemberTypes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
11
+ getActivityTypes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
12
+ };
13
+ };
14
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
15
+ }