@aiteza/n8n-nodes-aiteza 0.4.0 → 1.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.
@@ -178,7 +178,9 @@ class AitezaProgress {
178
178
  const callbackTokenOverride = options.callbackTokenOverride || '';
179
179
  const timeout = options.timeout ?? 5000;
180
180
  const failOnError = options.failOnError ?? false;
181
- const callbackUrl = (callbackUrlOverride || readTriggerBodyField(this, i, 'callbackUrl') || '').replace(/\/+$/, '');
181
+ const callbackUrl = (callbackUrlOverride ||
182
+ readTriggerBodyField(this, i, 'callbackUrl') ||
183
+ '').replace(/\/+$/, '');
182
184
  const executionId = executionIdOverride || readTriggerBodyField(this, i, 'executionId') || '';
183
185
  const callbackToken = callbackTokenOverride || readTriggerBodyField(this, i, 'callbackToken') || '';
184
186
  // Build payload
@@ -197,7 +199,10 @@ class AitezaProgress {
197
199
  }
198
200
  catch (err) {
199
201
  if (failOnError) {
200
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The 'Additional Fields' value is not valid JSON: ${err.message}`, { itemIndex: i, description: 'Please provide a valid JSON object in the \'Additional Fields\' parameter, e.g. { "percent": 42 }.' });
202
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The 'Additional Fields' value is not valid JSON: ${err.message}`, {
203
+ itemIndex: i,
204
+ description: 'Please provide a valid JSON object in the \'Additional Fields\' parameter, e.g. { "percent": 42 }.',
205
+ });
201
206
  }
202
207
  }
203
208
  }
@@ -219,7 +224,10 @@ class AitezaProgress {
219
224
  ? 'No callbackUrl on Aiteza Trigger body'
220
225
  : 'No executionId on Aiteza Trigger body';
221
226
  if (failOnError) {
222
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Cannot send progress report: ${reportMeta.reason}`, { itemIndex: i, description: 'Make sure this node is downstream of an Aiteza Trigger node that provides \'callbackUrl\' and \'executionId\' in its body.' });
227
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Cannot send progress report: ${reportMeta.reason}`, {
228
+ itemIndex: i,
229
+ description: "Make sure this node is downstream of an Aiteza Trigger node that provides 'callbackUrl' and 'executionId' in its body.",
230
+ });
223
231
  }
224
232
  returnData.push({
225
233
  json: { ...items[i].json, _progressReport: reportMeta },
@@ -247,7 +255,10 @@ class AitezaProgress {
247
255
  reportMeta.error =
248
256
  error?.message ?? error?.response?.statusText ?? 'The callback could not be delivered';
249
257
  if (failOnError) {
250
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Progress callback could not be delivered: ${reportMeta.error}`, { itemIndex: i, description: 'Check that the \'callbackUrl\' is reachable and the callback token is valid.' });
258
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Progress callback could not be delivered: ${reportMeta.error}`, {
259
+ itemIndex: i,
260
+ description: "Check that the 'callbackUrl' is reachable and the callback token is valid.",
261
+ });
251
262
  }
252
263
  }
253
264
  returnData.push({
@@ -8,7 +8,7 @@ class AitezaTrigger {
8
8
  icon: 'file:aiteza.svg',
9
9
  group: ['trigger'],
10
10
  version: 1,
11
- description: 'Starts the workflow when an Aiteza event is received via webhook. Forwards the calling user\'s token to downstream Aiteza nodes so they act on behalf of the triggering user.',
11
+ description: "Starts the workflow when an Aiteza event is received via webhook. Forwards the calling user's token to downstream Aiteza nodes so they act on behalf of the triggering user.",
12
12
  defaults: { name: 'AITEZA Trigger' },
13
13
  inputs: [],
14
14
  outputs: ['main'],
@@ -59,7 +59,7 @@ class AitezaTrigger {
59
59
  type: 'string',
60
60
  default: '',
61
61
  placeholder: 'e.g. https://aiteza.example.com',
62
- description: 'Optional. If set, this URL is forwarded to downstream Aiteza nodes as \'_baseUrl\' so they don\'t need to repeat it. Without trailing slash.',
62
+ description: "Optional. If set, this URL is forwarded to downstream Aiteza nodes as '_baseUrl' so they don't need to repeat it. Without trailing slash.",
63
63
  },
64
64
  ],
65
65
  };
@@ -167,7 +167,9 @@ class AitezaWorkflowResult {
167
167
  const callbackTokenOverride = options.callbackTokenOverride || '';
168
168
  const timeout = options.timeout ?? 10000;
169
169
  const failOnError = options.failOnError ?? true;
170
- const callbackUrl = (callbackUrlOverride || readTriggerBodyField(this, i, 'callbackUrl') || '').replace(/\/+$/, '');
170
+ const callbackUrl = (callbackUrlOverride ||
171
+ readTriggerBodyField(this, i, 'callbackUrl') ||
172
+ '').replace(/\/+$/, '');
171
173
  const executionId = executionIdOverride || readTriggerBodyField(this, i, 'executionId') || '';
172
174
  const callbackToken = callbackTokenOverride || readTriggerBodyField(this, i, 'callbackToken') || '';
173
175
  // Build result payload
@@ -182,7 +184,10 @@ class AitezaWorkflowResult {
182
184
  }
183
185
  catch (err) {
184
186
  if (failOnError) {
185
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The 'Result Data' value is not valid JSON: ${err.message}`, { itemIndex: i, description: 'Please provide a valid JSON object in the \'Result Data\' field, or use an expression like ={{ $json }}.' });
187
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The 'Result Data' value is not valid JSON: ${err.message}`, {
188
+ itemIndex: i,
189
+ description: "Please provide a valid JSON object in the 'Result Data' field, or use an expression like ={{ $json }}.",
190
+ });
186
191
  }
187
192
  resultPayload = { raw: resultDataRaw };
188
193
  }
@@ -208,7 +213,10 @@ class AitezaWorkflowResult {
208
213
  ? 'No callbackUrl on Aiteza Trigger body'
209
214
  : 'No executionId on Aiteza Trigger body';
210
215
  if (failOnError) {
211
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Cannot send workflow result: ${reportMeta.reason}`, { itemIndex: i, description: 'Make sure this node is downstream of an Aiteza Trigger node that provides \'callbackUrl\' and \'executionId\' in its body.' });
216
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Cannot send workflow result: ${reportMeta.reason}`, {
217
+ itemIndex: i,
218
+ description: "Make sure this node is downstream of an Aiteza Trigger node that provides 'callbackUrl' and 'executionId' in its body.",
219
+ });
212
220
  }
213
221
  returnData.push({
214
222
  json: { ...items[i].json, _workflowResult: reportMeta },
@@ -236,7 +244,10 @@ class AitezaWorkflowResult {
236
244
  reportMeta.error =
237
245
  error?.message ?? error?.response?.statusText ?? 'The callback could not be delivered';
238
246
  if (failOnError) {
239
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Workflow result could not be delivered: ${reportMeta.error}`, { itemIndex: i, description: 'Check that the \'callbackUrl\' is reachable and the callback token is valid.' });
247
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Workflow result could not be delivered: ${reportMeta.error}`, {
248
+ itemIndex: i,
249
+ description: "Check that the 'callbackUrl' is reachable and the callback token is valid.",
250
+ });
240
251
  }
241
252
  }
242
253
  returnData.push({
@@ -7,10 +7,6 @@ export declare function getUpstreamAuthToken(ef: IExecuteFunctions): string | un
7
7
  export declare function getUpstreamBaseUrl(ef: IExecuteFunctions): string | undefined;
8
8
  export declare function isJwtExpired(token: string | undefined, skewSeconds?: number): boolean;
9
9
  export declare function aitezaApiRequest(this: IExecuteFunctions | ILoadOptionsFunctions, method: IHttpRequestMethods, endpoint: string, body?: IDataObject | IDataObject[], qs?: IDataObject, extraOpts?: Partial<IHttpRequestOptions>, authCtx?: AitezaAuthContext): Promise<any>;
10
- export declare function aitezaApiRequestFullResponse(this: IExecuteFunctions, method: IHttpRequestMethods, endpoint: string, body?: IDataObject, qs?: IDataObject, extraOpts?: Partial<IHttpRequestOptions>, authCtx?: AitezaAuthContext): Promise<{
11
- body: any;
12
- headers: Record<string, string>;
13
- }>;
14
10
  export declare function loadDatarooms(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
15
11
  export declare function loadDataroomsOptional(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
16
12
  export declare function loadModels(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
@@ -4,7 +4,6 @@ exports.getUpstreamAuthToken = getUpstreamAuthToken;
4
4
  exports.getUpstreamBaseUrl = getUpstreamBaseUrl;
5
5
  exports.isJwtExpired = isJwtExpired;
6
6
  exports.aitezaApiRequest = aitezaApiRequest;
7
- exports.aitezaApiRequestFullResponse = aitezaApiRequestFullResponse;
8
7
  exports.loadDatarooms = loadDatarooms;
9
8
  exports.loadDataroomsOptional = loadDataroomsOptional;
10
9
  exports.loadModels = loadModels;
@@ -16,93 +15,74 @@ exports.loadStandaloneFiles = loadStandaloneFiles;
16
15
  exports.loadStandaloneImages = loadStandaloneImages;
17
16
  exports.validateRequiredField = validateRequiredField;
18
17
  const n8n_workflow_1 = require("n8n-workflow");
19
- function isAitezaTriggerType(type) {
20
- return typeof type === 'string' && /(^|\.)aitezaTrigger$/i.test(type);
21
- }
22
- function findAitezaTriggerParentName(ef) {
18
+ function readFromTriggerItems(ef, picker) {
23
19
  try {
24
20
  const currentNodeName = ef.getNode().name;
25
21
  const parents = ef.getParentNodes(currentNodeName);
26
- const trigger = parents.find((p) => isAitezaTriggerType(p.type) && !p.disabled);
27
- return trigger?.name;
28
- }
29
- catch {
30
- return undefined;
31
- }
32
- }
33
- function readFromTriggerItems(ef, picker) {
34
- const triggerName = findAitezaTriggerParentName(ef);
35
- if (!triggerName)
36
- return undefined;
37
- try {
22
+ const trigger = parents.find((p) => /(^|\.)aitezaTrigger$/i.test(p.type) && !p.disabled);
23
+ if (!trigger)
24
+ return undefined;
38
25
  const proxy = ef.getWorkflowDataProxy(0);
39
- const triggerItems = proxy.$items(triggerName) ?? [];
26
+ const triggerItems = proxy.$items(trigger.name) ?? [];
40
27
  for (const item of triggerItems) {
41
28
  const value = picker(item?.json);
42
29
  if (value !== undefined && value !== null && value !== '')
43
30
  return value;
44
31
  }
45
32
  }
46
- catch {
47
- }
33
+ catch { }
48
34
  return undefined;
49
35
  }
50
36
  function getUpstreamAuthToken(ef) {
51
37
  try {
52
- const items = ef.getInputData();
53
- for (const item of items) {
38
+ for (const item of ef.getInputData()) {
54
39
  const token = item.json?._authToken;
55
40
  if (token)
56
41
  return token;
57
42
  }
58
43
  }
59
- catch {
60
- }
44
+ catch { }
61
45
  return readFromTriggerItems(ef, (json) => json?._authToken);
62
46
  }
63
47
  function getUpstreamBaseUrl(ef) {
64
48
  try {
65
- const items = ef.getInputData();
66
- for (const item of items) {
49
+ for (const item of ef.getInputData()) {
67
50
  const url = item.json?._baseUrl;
68
51
  if (url)
69
52
  return url.replace(/\/+$/, '');
70
53
  }
71
54
  }
72
- catch {
73
- }
74
- const fromTrigger = readFromTriggerItems(ef, (json) => json?._baseUrl);
55
+ catch { }
56
+ const fromTrigger = readFromTriggerItems(ef, (json) => {
57
+ const explicit = json?._baseUrl;
58
+ if (explicit)
59
+ return explicit;
60
+ const body = json?.body ?? {};
61
+ return body?.callbackUrl;
62
+ });
75
63
  return fromTrigger ? fromTrigger.replace(/\/+$/, '') : undefined;
76
64
  }
77
- // JWT helpers
78
- function decodeJwtPayload(token) {
65
+ function isJwtExpired(token, skewSeconds = 30) {
66
+ if (!token)
67
+ return true;
79
68
  try {
80
69
  const payload = token.split('.')[1];
81
70
  if (!payload)
82
- return undefined;
71
+ return false;
83
72
  const normalized = payload.replace(/-/g, '+').replace(/_/g, '/');
84
73
  const padded = normalized + '='.repeat((4 - (normalized.length % 4)) % 4);
85
- const decoded = globalThis.atob
86
- ? globalThis.atob(padded)
87
- : '';
74
+ const decoded = globalThis.atob ? globalThis.atob(padded) : '';
88
75
  if (!decoded)
89
- return undefined;
90
- return JSON.parse(decoded);
76
+ return false;
77
+ const { exp } = JSON.parse(decoded);
78
+ if (!exp)
79
+ return false;
80
+ return exp <= Math.floor(Date.now() / 1000) + skewSeconds;
91
81
  }
92
82
  catch {
93
- return undefined;
94
- }
95
- }
96
- function isJwtExpired(token, skewSeconds = 30) {
97
- if (!token)
98
- return true;
99
- const payload = decodeJwtPayload(token);
100
- if (!payload?.exp)
101
83
  return false;
102
- const nowSeconds = Math.floor(Date.now() / 1000);
103
- return payload.exp <= nowSeconds + skewSeconds;
84
+ }
104
85
  }
105
- // Internal helpers
106
86
  async function resolveBaseUrl(ctx, authCtx) {
107
87
  if (authCtx?.baseUrl)
108
88
  return authCtx.baseUrl;
@@ -111,10 +91,7 @@ async function resolveBaseUrl(ctx, authCtx) {
111
91
  }
112
92
  async function executeRequest(ctx, options, authCtx) {
113
93
  if (authCtx?.triggerToken) {
114
- options.headers = {
115
- ...(options.headers ?? {}),
116
- Authorization: `Bearer ${authCtx.triggerToken}`,
117
- };
94
+ options.headers = { ...(options.headers ?? {}), Authorization: `Bearer ${authCtx.triggerToken}` };
118
95
  return ctx.helpers.httpRequest(options);
119
96
  }
120
97
  return ctx.helpers.httpRequestWithAuthentication.call(ctx, 'aitezaOAuth2Api', options);
@@ -126,9 +103,8 @@ function toOptions(items, nameField = 'name') {
126
103
  }));
127
104
  }
128
105
  function extractItems(data) {
129
- return Array.isArray(data) ? data : data?.content ?? [];
106
+ return Array.isArray(data) ? data : (data?.content ?? []);
130
107
  }
131
- // Generic authenticated request helper
132
108
  async function aitezaApiRequest(method, endpoint, body = {}, qs = {}, extraOpts = {}, authCtx) {
133
109
  const baseUrl = await resolveBaseUrl(this, authCtx);
134
110
  const options = {
@@ -137,14 +113,12 @@ async function aitezaApiRequest(method, endpoint, body = {}, qs = {}, extraOpts
137
113
  json: true,
138
114
  ...extraOpts,
139
115
  };
140
- if (Object.keys(qs).length > 0) {
116
+ if (Object.keys(qs).length > 0)
141
117
  options.qs = qs;
142
- }
143
- if (method !== 'GET' && method !== 'DELETE') {
144
- options.body = body;
145
- }
146
- else if (method === 'DELETE' && Object.keys(body).length > 0) {
147
- options.body = body;
118
+ if (method !== 'GET') {
119
+ const bodyObj = body;
120
+ if (method !== 'DELETE' || Object.keys(bodyObj).length > 0)
121
+ options.body = bodyObj;
148
122
  }
149
123
  try {
150
124
  return await executeRequest(this, options, authCtx);
@@ -161,28 +135,6 @@ async function aitezaApiRequest(method, endpoint, body = {}, qs = {}, extraOpts
161
135
  });
162
136
  }
163
137
  }
164
- // Full-response variant (gives access to response headers, e.g. X-Chat-Id)
165
- async function aitezaApiRequestFullResponse(method, endpoint, body = {}, qs = {}, extraOpts = {}, authCtx) {
166
- const baseUrl = await resolveBaseUrl(this, authCtx);
167
- const options = {
168
- method,
169
- url: `${baseUrl}${endpoint}`,
170
- qs,
171
- json: true,
172
- returnFullResponse: true,
173
- ...extraOpts,
174
- };
175
- if (method !== 'GET') {
176
- options.body = body;
177
- }
178
- try {
179
- return (await executeRequest(this, options, authCtx));
180
- }
181
- catch (error) {
182
- throw new n8n_workflow_1.NodeApiError(this.getNode(), error);
183
- }
184
- }
185
- // loadOptions helpers
186
138
  async function loadDatarooms() {
187
139
  try {
188
140
  const data = await aitezaApiRequest.call(this, 'GET', '/api/dataroom/search?q=&sortBy=recentlyUsed');
@@ -239,7 +191,6 @@ async function loadStandaloneImages() {
239
191
  const data = await aitezaApiRequest.call(this, 'GET', '/api/images', {}, { size: 100 });
240
192
  return toOptions(extractItems(data));
241
193
  }
242
- // Validation helper
243
194
  function validateRequiredField(ef, value, fieldName) {
244
195
  if (value === undefined || value === null || value === '') {
245
196
  throw new n8n_workflow_1.NodeOperationError(ef.getNode(), `The '${fieldName}' field is required but was not provided.`, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiteza/n8n-nodes-aiteza",
3
- "version": "0.4.0",
3
+ "version": "1.0.1",
4
4
  "description": "n8n Community Node for the AITEZA REST API (Datarooms, Files, Chat, Search, Workflows)",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",