n8n-nodes-qlik-cloud 1.0.17 → 1.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.
@@ -3,6 +3,33 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.assistantDescription = exports.assistantsInvokeThreadDescription = exports.assistantsStreamThreadDescription = exports.assistantsCreateThreadDescription = exports.assistantsListThreadsDescription = exports.assistantsCreateStarterDescription = exports.assistantsListStartersDescription = exports.assistantsDeleteDescription = exports.assistantsBulkSearchSourcesDescription = exports.assistantsGetFeedbackDescription = exports.assistantsSearchDescription = exports.assistantsUpdateDescription = exports.assistantsCreateDescription = exports.assistantsGetDescription = exports.assistantsGetAllDescription = void 0;
4
4
  // Get All Assistants
5
5
  exports.assistantsGetAllDescription = [
6
+ {
7
+ displayName: 'Return All',
8
+ name: 'returnAll',
9
+ type: 'boolean',
10
+ default: false,
11
+ displayOptions: {
12
+ show: {
13
+ resource: ['assistants'],
14
+ operation: ['getAll'],
15
+ },
16
+ },
17
+ description: 'Whether to return all assistants',
18
+ },
19
+ {
20
+ displayName: 'Limit',
21
+ name: 'limit',
22
+ type: 'number',
23
+ default: 50,
24
+ displayOptions: {
25
+ show: {
26
+ resource: ['assistants'],
27
+ operation: ['getAll'],
28
+ returnAll: [false],
29
+ },
30
+ },
31
+ description: 'The number of assistants to get',
32
+ },
6
33
  {
7
34
  displayName: 'Options',
8
35
  name: 'options',
@@ -16,13 +43,6 @@ exports.assistantsGetAllDescription = [
16
43
  },
17
44
  },
18
45
  options: [
19
- {
20
- displayName: 'Limit',
21
- name: 'limit',
22
- type: 'number',
23
- default: 50,
24
- description: 'The number of assistants to get',
25
- },
26
46
  {
27
47
  displayName: 'Next Page',
28
48
  name: 'next',
@@ -1,2 +1,2 @@
1
- import type { IExecuteFunctions, IHttpRequestMethods } from 'n8n-workflow';
2
- export declare function qlikApiRequest(this: IExecuteFunctions, method: IHttpRequestMethods, endpoint: string, body?: Record<string, any>, qs?: Record<string, any>): Promise<Record<string, any>>;
1
+ import type { IExecuteFunctions, IHttpRequestMethods, IHttpRequestOptions } from 'n8n-workflow';
2
+ export declare function qlikApiRequest(this: IExecuteFunctions, method: IHttpRequestMethods, endpoint: string, body?: any, qs?: Record<string, any>, returnFullResponse?: boolean, extraOptions?: Partial<IHttpRequestOptions>): Promise<any>;
@@ -2,23 +2,29 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.qlikApiRequest = qlikApiRequest;
4
4
  const n8n_workflow_1 = require("n8n-workflow");
5
- async function qlikApiRequest(method, endpoint, body, qs) {
5
+ async function qlikApiRequest(method, endpoint, body, qs, returnFullResponse = false, extraOptions = {}) {
6
6
  const credentials = await this.getCredentials('qlikCloudApi');
7
7
  if (!credentials) {
8
8
  throw new n8n_workflow_1.NodeApiError(this.getNode(), {
9
9
  message: 'No credentials found for Qlik Cloud API',
10
10
  });
11
11
  }
12
- const baseUrl = credentials.baseUrl;
12
+ const baseUrl = credentials.baseUrl.replace(/\/+$/, '');
13
13
  const accessToken = credentials.accessToken;
14
+ const url = `${baseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;
15
+ const headers = {
16
+ Authorization: `Bearer ${accessToken}`,
17
+ 'Content-Type': 'application/json',
18
+ ...(extraOptions.headers || {}),
19
+ };
14
20
  const options = {
15
- headers: {
16
- Authorization: `Bearer ${accessToken}`,
17
- 'Content-Type': 'application/json',
18
- },
19
21
  method,
20
- url: `${baseUrl}${endpoint}`,
22
+ url,
21
23
  qs,
24
+ json: extraOptions.json ?? true,
25
+ returnFullResponse,
26
+ ...extraOptions,
27
+ headers,
22
28
  };
23
29
  if (body !== undefined) {
24
30
  options.body = body;
@@ -27,8 +33,9 @@ async function qlikApiRequest(method, endpoint, body, qs) {
27
33
  return await this.helpers.httpRequest(options);
28
34
  }
29
35
  catch (error) {
30
- throw new n8n_workflow_1.NodeApiError(this.getNode(), {
31
- message: error.message,
36
+ const errMessage = error instanceof Error ? error.message : typeof error === 'string' ? error : JSON.stringify(error);
37
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), { message: errMessage }, {
38
+ message: 'Qlik Cloud API request failed',
32
39
  });
33
40
  }
34
41
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-qlik-cloud",
3
- "version": "1.0.17",
3
+ "version": "1.1.0",
4
4
  "description": "n8n node for Qlik Cloud REST APIs integration",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,8 +10,7 @@
10
10
  "dev": "tsc --watch",
11
11
  "lint": "eslint src/",
12
12
  "test": "jest",
13
- "publish": "npm run build && npm version patch && npm publish",
14
- "prepublishOnly": "npm run build"
13
+ "publish-patch": "npm run build && npm version patch && npm publish"
15
14
  },
16
15
  "n8n": {
17
16
  "nodes": [
@@ -1,11 +1,6 @@
1
- import type {
2
- ICredentialType,
3
- INodeProperties,
4
- } from 'n8n-workflow';
1
+ import type { ICredentialType, INodeProperties } from 'n8n-workflow';
5
2
 
6
- const scopes = [
7
- 'https://analysis.windows.net/powerbi/api/.default',
8
- ];
3
+ const DEFAULT_SCOPES = ['openid', 'profile', 'email', 'offline_access'];
9
4
 
10
5
  export class QlikCloudOAuth2Api implements ICredentialType {
11
6
  name = 'qlikCloudOAuth2Api';
@@ -28,21 +23,19 @@ export class QlikCloudOAuth2Api implements ICredentialType {
28
23
  name: 'authUrl',
29
24
  type: 'hidden',
30
25
  default: '',
31
- required: true,
32
26
  },
33
27
  {
34
28
  displayName: 'Access Token URL',
35
29
  name: 'accessTokenUrl',
36
30
  type: 'hidden',
37
31
  default: '',
38
- required: true,
39
32
  },
40
33
  {
41
34
  displayName: 'Scope',
42
35
  name: 'scope',
43
- type: 'hidden',
44
- default: scopes.join(' '),
45
- description: 'OAuth2 scopes required for Qlik Cloud API access',
36
+ type: 'string',
37
+ default: DEFAULT_SCOPES.join(' '),
38
+ description: 'OAuth2 scopes requested from Qlik Cloud (space-separated)',
46
39
  },
47
40
  {
48
41
  displayName: 'Authentication',
@@ -54,27 +47,31 @@ export class QlikCloudOAuth2Api implements ICredentialType {
54
47
 
55
48
  async preAuthentication(this: any, credentials: any) {
56
49
  const baseUrl = credentials.baseUrl as string;
57
-
58
- // Extract tenant and region from base URL
59
- // Expected format: https://tenant.region.qlikcloud.com
60
- const urlParts = new URL(baseUrl);
61
- const hostname = urlParts.hostname;
62
- const parts = hostname.split('.');
63
-
64
- if (parts.length < 3) {
50
+ let parsed: URL;
51
+
52
+ try {
53
+ parsed = new URL(baseUrl);
54
+ } catch (error) {
65
55
  throw new Error('Invalid Qlik Cloud tenant URL format');
66
56
  }
67
57
 
68
- const tenant = parts[0];
69
- const region = parts[1];
58
+ if (parsed.protocol !== 'https:') {
59
+ throw new Error('Qlik Cloud tenant URL must use HTTPS');
60
+ }
70
61
 
71
- // Construct OAuth endpoints
72
- const authEndpoint = `https://auth.${region}.qlikcloud.com/oauth/authorize`;
73
- const tokenEndpoint = `https://auth.${region}.qlikcloud.com/oauth/token`;
62
+ if (!parsed.hostname.endsWith('.qlikcloud.com')) {
63
+ throw new Error('Tenant URL must end with .qlikcloud.com');
64
+ }
65
+
66
+ const oauthBase = `${parsed.origin}/oauth`;
67
+
68
+ credentials.authUrl = `${oauthBase}/authorize`;
69
+ credentials.accessTokenUrl = `${oauthBase}/token`;
70
+
71
+ if (!credentials.scope) {
72
+ credentials.scope = DEFAULT_SCOPES.join(' ');
73
+ }
74
74
 
75
- credentials.authUrl = authEndpoint;
76
- credentials.accessTokenUrl = tokenEndpoint;
77
-
78
75
  return credentials;
79
76
  }
80
77
  }