@linkly-link-shortener/n8n-nodes-linkly 1.0.3 → 2.0.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.
package/README.md CHANGED
@@ -5,7 +5,9 @@
5
5
 
6
6
  Linkly Link Shortener node for [n8n](https://n8n.io/) - Create short links, QR codes, track clicks, and automate your URL management workflows.
7
7
 
8
- [Linkly](https://linklyhq.com) is a powerful link shortener and click tracking platform with custom domains, retargeting pixels, UTM parameters, and real-time analytics.
8
+ ## About Linkly
9
+
10
+ [Linkly](https://linklyhq.com) is a powerful link management platform that lets you create branded short links, track clicks in real-time, and optimize your marketing campaigns. Features include custom domains, UTM parameters, retargeting pixels, QR codes, and detailed analytics.
9
11
 
10
12
  ## Features
11
13
 
@@ -0,0 +1,8 @@
1
+ import type { ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class LinklyOAuth2Api implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ extends: string[];
7
+ properties: INodeProperties[];
8
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LinklyOAuth2Api = void 0;
4
+ class LinklyOAuth2Api {
5
+ name = 'linklyOAuth2Api';
6
+ displayName = 'Linkly OAuth2 API';
7
+ documentationUrl = 'https://linklyhq.com/support/api';
8
+ extends = ['oAuth2Api'];
9
+ properties = [
10
+ {
11
+ displayName: 'Grant Type',
12
+ name: 'grantType',
13
+ type: 'hidden',
14
+ default: 'authorizationCode',
15
+ },
16
+ {
17
+ displayName: 'Authorization URL',
18
+ name: 'authUrl',
19
+ type: 'hidden',
20
+ default: 'https://app.linklyhq.com/oauth/authorize',
21
+ },
22
+ {
23
+ displayName: 'Access Token URL',
24
+ name: 'accessTokenUrl',
25
+ type: 'hidden',
26
+ default: 'https://app.linklyhq.com/oauth/token',
27
+ },
28
+ {
29
+ displayName: 'Client ID',
30
+ name: 'clientId',
31
+ type: 'hidden',
32
+ default: 'linkly_n8n_25316062113802ac',
33
+ },
34
+ {
35
+ displayName: 'Client Secret',
36
+ name: 'clientSecret',
37
+ type: 'hidden',
38
+ default: '3ecREEKyGHGnTaZlt_HLCEeKNsm97G2kqgJOPVAS',
39
+ },
40
+ {
41
+ displayName: 'Authentication',
42
+ name: 'authentication',
43
+ type: 'hidden',
44
+ default: 'body',
45
+ },
46
+ {
47
+ displayName: 'Auth URI Query Parameters',
48
+ name: 'authQueryParameters',
49
+ type: 'hidden',
50
+ default: '',
51
+ },
52
+ {
53
+ displayName: 'Scope',
54
+ name: 'scope',
55
+ type: 'hidden',
56
+ default: '',
57
+ },
58
+ ];
59
+ }
60
+ exports.LinklyOAuth2Api = LinklyOAuth2Api;
@@ -6,14 +6,15 @@ exports.removeEmptyFields = removeEmptyFields;
6
6
  const n8n_workflow_1 = require("n8n-workflow");
7
7
  const BASE_URL = 'https://app.linklyhq.com';
8
8
  async function linklyApiRequest(method, endpoint, body = {}, query = {}) {
9
- const credentials = await this.getCredentials('linklyApi');
9
+ const credentials = await this.getCredentials('linklyOAuth2Api');
10
+ const tokenData = credentials.oauthTokenData;
11
+ const accessToken = tokenData.access_token;
10
12
  const options = {
11
13
  method,
12
14
  headers: {
13
15
  'Content-Type': 'application/json',
14
16
  Accept: 'application/json',
15
- 'X-API-KEY': credentials.apiKey,
16
- 'X-WORKSPACE-ID': credentials.workspaceId,
17
+ Authorization: `Bearer ${accessToken}`,
17
18
  },
18
19
  qs: query,
19
20
  uri: `${BASE_URL}${endpoint}`,
@@ -19,7 +19,7 @@ class Linkly {
19
19
  outputs: ['main'],
20
20
  credentials: [
21
21
  {
22
- name: 'linklyApi',
22
+ name: 'linklyOAuth2Api',
23
23
  required: true,
24
24
  },
25
25
  ],
@@ -164,6 +164,13 @@ class Linkly {
164
164
  default: '',
165
165
  description: 'When the link should expire',
166
166
  },
167
+ {
168
+ displayName: 'Expiry Click Limit',
169
+ name: 'expiry_clicks',
170
+ type: 'number',
171
+ default: 0,
172
+ description: 'Number of clicks after which the link expires (0 = no limit)',
173
+ },
167
174
  {
168
175
  displayName: 'Expiry Destination',
169
176
  name: 'expiry_destination',
@@ -418,6 +425,13 @@ class Linkly {
418
425
  default: '',
419
426
  description: 'When the link should expire',
420
427
  },
428
+ {
429
+ displayName: 'Expiry Click Limit',
430
+ name: 'expiry_clicks',
431
+ type: 'number',
432
+ default: 0,
433
+ description: 'Number of clicks after which the link expires (0 = no limit)',
434
+ },
421
435
  {
422
436
  displayName: 'Expiry Destination',
423
437
  name: 'expiry_destination',
@@ -19,7 +19,7 @@ class LinklyTrigger {
19
19
  outputs: ['main'],
20
20
  credentials: [
21
21
  {
22
- name: 'linklyApi',
22
+ name: 'linklyOAuth2Api',
23
23
  required: true,
24
24
  },
25
25
  ],
@@ -86,14 +86,14 @@ class LinklyTrigger {
86
86
  const webhookUrl = this.getNodeWebhookUrl('default');
87
87
  const webhookData = this.getWorkflowStaticData('node');
88
88
  const event = this.getNodeParameter('event');
89
- const credentials = await this.getCredentials('linklyApi');
90
- const workspaceId = credentials.workspaceId;
91
89
  let endpoint;
92
90
  if (event === 'linkClick') {
93
91
  const linkId = this.getNodeParameter('linkId');
94
92
  endpoint = `/api/v1/link/${linkId}/webhooks`;
95
93
  }
96
94
  else {
95
+ const testResponse = await GenericFunctions_1.linklyApiRequest.call(this, 'POST', '/zapier/test');
96
+ const workspaceId = testResponse.workspace_id;
97
97
  endpoint = `/api/v1/workspace/${workspaceId}/webhooks`;
98
98
  }
99
99
  try {
@@ -113,8 +113,6 @@ class LinklyTrigger {
113
113
  const webhookUrl = this.getNodeWebhookUrl('default');
114
114
  const webhookData = this.getWorkflowStaticData('node');
115
115
  const event = this.getNodeParameter('event');
116
- const credentials = await this.getCredentials('linklyApi');
117
- const workspaceId = credentials.workspaceId;
118
116
  let endpoint;
119
117
  if (event === 'linkClick') {
120
118
  const linkId = this.getNodeParameter('linkId');
@@ -122,6 +120,8 @@ class LinklyTrigger {
122
120
  webhookData.linkId = linkId;
123
121
  }
124
122
  else {
123
+ const testResponse = await GenericFunctions_1.linklyApiRequest.call(this, 'POST', '/zapier/test');
124
+ const workspaceId = testResponse.workspace_id;
125
125
  endpoint = `/api/v1/workspace/${workspaceId}/webhooks`;
126
126
  }
127
127
  const body = {
@@ -139,8 +139,6 @@ class LinklyTrigger {
139
139
  async delete() {
140
140
  const webhookData = this.getWorkflowStaticData('node');
141
141
  const event = this.getNodeParameter('event');
142
- const credentials = await this.getCredentials('linklyApi');
143
- const workspaceId = credentials.workspaceId;
144
142
  if (!webhookData.webhookId) {
145
143
  return true;
146
144
  }
@@ -151,6 +149,8 @@ class LinklyTrigger {
151
149
  endpoint = `/api/v1/link/${linkId}/webhooks/${hookId}`;
152
150
  }
153
151
  else {
152
+ const testResponse = await GenericFunctions_1.linklyApiRequest.call(this, 'POST', '/zapier/test');
153
+ const workspaceId = testResponse.workspace_id;
154
154
  endpoint = `/api/v1/workspace/${workspaceId}/webhooks/${hookId}`;
155
155
  }
156
156
  try {
@@ -1,14 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
1
2
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
2
- <rect width="64" height="64" rx="8" fill="#6366F1"/>
3
- <g transform="translate(14, 18) scale(2.5)">
4
- <path fill="white" d="M10,13.239c-1.342,0-2.685-0.511-3.707-1.532c-1.266-1.265-3.323-1.264-4.586,0
5
- c-0.391,0.391-1.023,0.391-1.414,0s-0.391-1.023,0-1.414c2.043-2.043,5.369-2.043,7.414,0c1.265,1.264,3.322,1.263,4.586,0
6
- c0.391-0.391,1.023-0.391,1.414,0c0.391,0.391,0.391,1.023,0,1.414C12.686,12.728,11.343,13.239,10,13.239z"/>
7
- <path fill="white" d="M10,9.239c-1.342,0-2.685-0.511-3.707-1.532c-1.266-1.265-3.323-1.264-4.586,0
8
- c-0.391,0.391-1.023,0.391-1.414,0c-0.391-0.391-0.391-1.023,0-1.414c2.043-2.043,5.369-2.043,7.414,0
9
- c1.265,1.264,3.322,1.263,4.586,0c0.391-0.391,1.023-0.391,1.414,0s0.391,1.023,0,1.414C12.686,8.728,11.343,9.239,10,9.239z"/>
10
- <path fill="white" d="M10,5.239c-1.342,0-2.685-0.511-3.707-1.532c-1.266-1.265-3.323-1.264-4.586,0
11
- c-0.391,0.391-1.023,0.391-1.414,0s-0.391-1.023,0-1.414c2.043-2.042,5.369-2.044,7.414,0c1.265,1.264,3.322,1.263,4.586,0
12
- c0.391-0.391,1.023-0.391,1.414,0s0.391,1.023,0,1.414C12.686,4.728,11.343,5.239,10,5.239z"/>
3
+ <rect width="64" height="64" rx="8" fill="#ffffff"/>
4
+ <g transform="translate(8, 8) scale(0.293)">
5
+ <rect fill="#ffa200" x="0" y="0" width="79.21" height="79.21"/>
6
+ <rect fill="#009eff" x="79.22" y="79.21" width="79.21" height="79.21"/>
7
+ <polygon fill="#f40" points="79.22 79.21 0 79.21 79.22 158.42 79.22 79.21"/>
13
8
  </g>
14
9
  </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linkly-link-shortener/n8n-nodes-linkly",
3
- "version": "1.0.3",
3
+ "version": "2.0.0",
4
4
  "description": "Linkly Link Shortener for n8n - Create short links, track clicks, UTM parameters, retargeting pixels, and automate URL management",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "repository": {
28
28
  "type": "git",
29
- "url": "https://github.com/linklyhq/n8n-nodes-linkly.git"
29
+ "url": "https://github.com/Linkly-HQ/n8n-nodes-linkly.git"
30
30
  },
31
31
  "main": "index.js",
32
32
  "scripts": {
@@ -44,7 +44,8 @@
44
44
  "n8n": {
45
45
  "n8nNodesApiVersion": 1,
46
46
  "credentials": [
47
- "dist/credentials/LinklyApi.credentials.js"
47
+ "dist/credentials/LinklyApi.credentials.js",
48
+ "dist/credentials/LinklyOAuth2Api.credentials.js"
48
49
  ],
49
50
  "nodes": [
50
51
  "dist/nodes/Linkly/Linkly.node.js",