n8n-nodes-tiendanube-alldo 1.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.
Files changed (28) hide show
  1. package/README.md +43 -0
  2. package/credentials/TiendanubeApi.credentials.ts +36 -0
  3. package/dist/credentials/TiendanubeApi.credentials.js +36 -0
  4. package/dist/credentials/TiendanubeApi.credentials.js.map +1 -0
  5. package/dist/nodes/Tiendanube/CustomerDescription.js +149 -0
  6. package/dist/nodes/Tiendanube/CustomerDescription.js.map +1 -0
  7. package/dist/nodes/Tiendanube/ExtraDescription.js +162 -0
  8. package/dist/nodes/Tiendanube/ExtraDescription.js.map +1 -0
  9. package/dist/nodes/Tiendanube/GenericFunctions.js +34 -0
  10. package/dist/nodes/Tiendanube/GenericFunctions.js.map +1 -0
  11. package/dist/nodes/Tiendanube/OrderDescription.js +129 -0
  12. package/dist/nodes/Tiendanube/OrderDescription.js.map +1 -0
  13. package/dist/nodes/Tiendanube/ProductDescription.js +138 -0
  14. package/dist/nodes/Tiendanube/ProductDescription.js.map +1 -0
  15. package/dist/nodes/Tiendanube/Tiendanube.node.js +244 -0
  16. package/dist/nodes/Tiendanube/Tiendanube.node.js.map +1 -0
  17. package/dist/nodes/TiendanubeTrigger/TiendanubeTrigger.node.js +133 -0
  18. package/dist/nodes/TiendanubeTrigger/TiendanubeTrigger.node.js.map +1 -0
  19. package/index.ts +4 -0
  20. package/nodes/Tiendanube/CustomerDescription.ts +150 -0
  21. package/nodes/Tiendanube/ExtraDescription.ts +163 -0
  22. package/nodes/Tiendanube/GenericFunctions.ts +53 -0
  23. package/nodes/Tiendanube/OrderDescription.ts +130 -0
  24. package/nodes/Tiendanube/ProductDescription.ts +139 -0
  25. package/nodes/Tiendanube/Tiendanube.node.ts +271 -0
  26. package/nodes/TiendanubeTrigger/TiendanubeTrigger.node.ts +144 -0
  27. package/package.json +47 -0
  28. package/tsconfig.json +34 -0
@@ -0,0 +1,271 @@
1
+ import {
2
+ IExecuteFunctions,
3
+ IDataObject,
4
+ INodeExecutionData,
5
+ INodeType,
6
+ INodeTypeDescription,
7
+ } from 'n8n-workflow';
8
+
9
+ import {
10
+ tiendanubeApiRequest,
11
+ } from './GenericFunctions';
12
+
13
+ import {
14
+ productFields,
15
+ productOperations,
16
+ } from './ProductDescription';
17
+
18
+ import {
19
+ orderFields,
20
+ orderOperations,
21
+ } from './OrderDescription';
22
+
23
+ import {
24
+ customerFields,
25
+ customerOperations,
26
+ } from './CustomerDescription';
27
+
28
+ import {
29
+ extraFields,
30
+ extraOperations,
31
+ } from './ExtraDescription';
32
+
33
+ export class Tiendanube implements INodeType {
34
+ description: INodeTypeDescription = {
35
+ displayName: 'Tiendanube',
36
+ name: 'tiendanube',
37
+ icon: 'file:tiendanube.svg',
38
+ group: ['transform'],
39
+ version: 1,
40
+ subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}',
41
+ description: 'Consume Tiendanube (Nuvemshop) API',
42
+ defaults: {
43
+ name: 'Tiendanube',
44
+ },
45
+ inputs: ['main'],
46
+ outputs: ['main'],
47
+ credentials: [
48
+ {
49
+ name: 'tiendanubeApi',
50
+ required: true,
51
+ },
52
+ ],
53
+ properties: [
54
+ {
55
+ displayName: 'Resource',
56
+ name: 'resource',
57
+ type: 'options',
58
+ noDataExpression: true,
59
+ options: [
60
+ {
61
+ name: 'Product',
62
+ value: 'product',
63
+ },
64
+ {
65
+ name: 'Order',
66
+ value: 'order',
67
+ },
68
+ {
69
+ name: 'Customer',
70
+ value: 'customer',
71
+ },
72
+ {
73
+ name: 'Category',
74
+ value: 'category',
75
+ },
76
+ {
77
+ name: 'Coupon',
78
+ value: 'coupon',
79
+ },
80
+ {
81
+ name: 'Product Image',
82
+ value: 'productImage',
83
+ },
84
+ {
85
+ name: 'Product Variant',
86
+ value: 'productVariant',
87
+ },
88
+ {
89
+ name: 'Abandoned Checkout',
90
+ value: 'checkout',
91
+ },
92
+ {
93
+ name: 'Location',
94
+ value: 'location',
95
+ },
96
+ {
97
+ name: 'Cart',
98
+ value: 'cart',
99
+ },
100
+ {
101
+ name: 'Page',
102
+ value: 'page',
103
+ },
104
+ ],
105
+ default: 'product',
106
+ },
107
+ ...productOperations,
108
+ ...productFields,
109
+ ...orderOperations,
110
+ ...orderFields,
111
+ ...customerOperations,
112
+ ...customerFields,
113
+ ...extraOperations,
114
+ ...extraFields,
115
+ ],
116
+ };
117
+
118
+ async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
119
+ const items = this.getInputData();
120
+ const returnData: INodeExecutionData[] = [];
121
+ const length = items.length;
122
+ let responseData;
123
+ const resource = this.getNodeParameter('resource', 0) as string;
124
+ const operation = this.getNodeParameter('operation', 0) as string;
125
+
126
+ for (let i = 0; i < length; i++) {
127
+ try {
128
+ if (resource === 'product') {
129
+ if (operation === 'create') {
130
+ const name = this.getNodeParameter('name', i) as string;
131
+ const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
132
+ const body: IDataObject = {
133
+ name,
134
+ ...additionalFields,
135
+ };
136
+ responseData = await tiendanubeApiRequest.call(this, 'POST', 'products', body);
137
+ }
138
+ if (operation === 'get') {
139
+ const productId = this.getNodeParameter('productId', i) as string;
140
+ responseData = await tiendanubeApiRequest.call(this, 'GET', `products/${productId}`);
141
+ }
142
+ if (operation === 'getAll') {
143
+ responseData = await tiendanubeApiRequest.call(this, 'GET', 'products');
144
+ }
145
+ if (operation === 'delete') {
146
+ const productId = this.getNodeParameter('productId', i) as string;
147
+ responseData = await tiendanubeApiRequest.call(this, 'DELETE', `products/${productId}`);
148
+ responseData = { success: true };
149
+ }
150
+ if (operation === 'update') {
151
+ const productId = this.getNodeParameter('productId', i) as string;
152
+ const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
153
+ const body: IDataObject = {
154
+ ...additionalFields,
155
+ };
156
+ responseData = await tiendanubeApiRequest.call(this, 'PUT', `products/${productId}`, body);
157
+ }
158
+ }
159
+ else if (resource === 'order') {
160
+ if (operation === 'get') {
161
+ const orderId = this.getNodeParameter('orderId', i) as string;
162
+ responseData = await tiendanubeApiRequest.call(this, 'GET', `orders/${orderId}`);
163
+ }
164
+ if (operation === 'getAll') {
165
+ const returnAll = this.getNodeParameter('returnAll', i) as boolean;
166
+ const qs: IDataObject = {};
167
+ if (!returnAll) {
168
+ qs.limit = this.getNodeParameter('limit', i) as number;
169
+ }
170
+ responseData = await tiendanubeApiRequest.call(this, 'GET', 'orders', {}, qs);
171
+ }
172
+ if (operation === 'update') {
173
+ const orderId = this.getNodeParameter('orderId', i) as string;
174
+ const body = {};
175
+ responseData = await tiendanubeApiRequest.call(this, 'PUT', `orders/${orderId}`, body);
176
+ }
177
+ if (['open', 'close', 'cancel'].includes(operation)) {
178
+ const orderId = this.getNodeParameter('orderId', i) as string;
179
+ responseData = await tiendanubeApiRequest.call(this, 'POST', `orders/${orderId}/${operation}`);
180
+ }
181
+ }
182
+ else if (resource === 'customer') {
183
+ if (operation === 'create') {
184
+ const name = this.getNodeParameter('name', i) as string;
185
+ const email = this.getNodeParameter('email', i) as string;
186
+ const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
187
+ const body: IDataObject = {
188
+ name,
189
+ email,
190
+ ...additionalFields,
191
+ };
192
+ responseData = await tiendanubeApiRequest.call(this, 'POST', 'customers', body);
193
+ }
194
+ if (operation === 'get') {
195
+ const customerId = this.getNodeParameter('customerId', i) as string;
196
+ responseData = await tiendanubeApiRequest.call(this, 'GET', `customers/${customerId}`);
197
+ }
198
+ if (operation === 'getAll') {
199
+ responseData = await tiendanubeApiRequest.call(this, 'GET', 'customers');
200
+ }
201
+ if (operation === 'delete') {
202
+ const customerId = this.getNodeParameter('customerId', i) as string;
203
+ responseData = await tiendanubeApiRequest.call(this, 'DELETE', `customers/${customerId}`);
204
+ responseData = { success: true };
205
+ }
206
+ if (operation === 'update') {
207
+ const customerId = this.getNodeParameter('customerId', i) as string;
208
+ const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
209
+ const body: IDataObject = {
210
+ ...additionalFields,
211
+ };
212
+ responseData = await tiendanubeApiRequest.call(this, 'PUT', `customers/${customerId}`, body);
213
+ }
214
+ }
215
+ else {
216
+ // Generic handler for 'extra' resources
217
+ const endpointMap: { [key: string]: string } = {
218
+ 'category': 'categories',
219
+ 'coupon': 'coupons',
220
+ 'productImage': 'products/{productId}/images',
221
+ 'productVariant': 'products/{productId}/variants',
222
+ 'checkout': 'checkouts',
223
+ 'location': 'shipping_carriers',
224
+ 'cart': 'carts',
225
+ 'page': 'pages',
226
+ };
227
+ let endpoint = endpointMap[resource];
228
+
229
+ const id = this.getNodeParameter('id', i, '') as string;
230
+ const jsonBody = this.getNodeParameter('jsonBody', i, {}) as IDataObject;
231
+ const productId = this.getNodeParameter('productId', i, '') as string;
232
+
233
+ if (endpoint.includes('{productId}')) {
234
+ endpoint = endpoint.replace('{productId}', productId);
235
+ }
236
+
237
+ if (operation === 'getAll') {
238
+ responseData = await tiendanubeApiRequest.call(this, 'GET', endpoint);
239
+ }
240
+ if (operation === 'get') {
241
+ responseData = await tiendanubeApiRequest.call(this, 'GET', `${endpoint}/${id}`);
242
+ }
243
+ if (operation === 'create') {
244
+ responseData = await tiendanubeApiRequest.call(this, 'POST', endpoint, jsonBody);
245
+ }
246
+ if (operation === 'update') {
247
+ responseData = await tiendanubeApiRequest.call(this, 'PUT', `${endpoint}/${id}`, jsonBody);
248
+ }
249
+ if (operation === 'delete') {
250
+ responseData = await tiendanubeApiRequest.call(this, 'DELETE', `${endpoint}/${id}`);
251
+ responseData = { success: true };
252
+ }
253
+ }
254
+
255
+ if (Array.isArray(responseData)) {
256
+ responseData.forEach((item) => returnData.push({ json: item }));
257
+ } else if (responseData !== undefined) {
258
+ returnData.push({ json: responseData as IDataObject });
259
+ }
260
+ } catch (error) {
261
+ if (this.continueOnFail()) {
262
+ returnData.push({ json: { error: (error as Error).message } });
263
+ continue;
264
+ }
265
+ throw error;
266
+ }
267
+ }
268
+
269
+ return [returnData];
270
+ }
271
+ }
@@ -0,0 +1,144 @@
1
+ import {
2
+ IHookFunctions,
3
+ IWebhookFunctions,
4
+ IDataObject,
5
+ INodeType,
6
+ INodeTypeDescription,
7
+ IWebhookResponseData,
8
+ } from 'n8n-workflow';
9
+
10
+ import {
11
+ tiendanubeApiRequest,
12
+ } from '../Tiendanube/GenericFunctions';
13
+
14
+ export class TiendanubeTrigger implements INodeType {
15
+ description: INodeTypeDescription = {
16
+ displayName: 'Tiendanube Trigger',
17
+ name: 'tiendanubeTrigger',
18
+ icon: 'file:tiendanube.svg',
19
+ group: ['trigger'],
20
+ version: 1,
21
+ description: 'Handle Tiendanube Webhooks',
22
+ defaults: {
23
+ name: 'Tiendanube Trigger',
24
+ },
25
+ inputs: [],
26
+ outputs: ['main'],
27
+ credentials: [
28
+ {
29
+ name: 'tiendanubeApi',
30
+ required: true,
31
+ },
32
+ ],
33
+ webhooks: [
34
+ {
35
+ name: 'default',
36
+ httpMethod: 'POST',
37
+ responseMode: 'onReceived',
38
+ path: 'webhook',
39
+ },
40
+ ],
41
+ properties: [
42
+ {
43
+ displayName: 'Event',
44
+ name: 'event',
45
+ type: 'options',
46
+ required: true,
47
+ default: 'order/created',
48
+ description: 'The event to listen to',
49
+ options: [
50
+ {
51
+ name: 'Order Created',
52
+ value: 'order/created',
53
+ },
54
+ {
55
+ name: 'Order Updated',
56
+ value: 'order/updated',
57
+ },
58
+ {
59
+ name: 'Product Created',
60
+ value: 'product/created',
61
+ },
62
+ {
63
+ name: 'Product Updated',
64
+ value: 'product/updated',
65
+ },
66
+ {
67
+ name: 'Product Deleted',
68
+ value: 'product/deleted',
69
+ },
70
+ {
71
+ name: 'Customer Created',
72
+ value: 'customer/created',
73
+ },
74
+ {
75
+ name: 'Customer Updated',
76
+ value: 'customer/updated',
77
+ },
78
+ {
79
+ name: 'Checkout Created',
80
+ value: 'checkout/created',
81
+ },
82
+ {
83
+ name: 'Checkout Updated',
84
+ value: 'checkout/updated',
85
+ },
86
+ ],
87
+ },
88
+ ],
89
+ };
90
+
91
+ webhookMethods = {
92
+ default: {
93
+ async checkExists(this: IHookFunctions): Promise<boolean> {
94
+ const webhookUrl = this.getNodeWebhookUrl('default');
95
+ const event = this.getNodeParameter('event') as string;
96
+ // Get all webhooks to check if ours exists
97
+ const webhooks = await tiendanubeApiRequest.call(this, 'GET', 'webhooks');
98
+
99
+ for (const webhook of webhooks) {
100
+ if (webhook.url === webhookUrl && webhook.event === event) {
101
+ return true;
102
+ }
103
+ }
104
+ return false;
105
+ },
106
+ async create(this: IHookFunctions): Promise<boolean> {
107
+ const webhookUrl = this.getNodeWebhookUrl('default');
108
+ const event = this.getNodeParameter('event') as string;
109
+ const body = {
110
+ url: webhookUrl,
111
+ event: event,
112
+ };
113
+ await tiendanubeApiRequest.call(this, 'POST', 'webhooks', body);
114
+ return true;
115
+ },
116
+ async delete(this: IHookFunctions): Promise<boolean> {
117
+ const webhookUrl = this.getNodeWebhookUrl('default');
118
+ const event = this.getNodeParameter('event') as string;
119
+ const webhooks = await tiendanubeApiRequest.call(this, 'GET', 'webhooks');
120
+
121
+ for (const webhook of webhooks) {
122
+ if (webhook.url === webhookUrl && webhook.event === event) {
123
+ await tiendanubeApiRequest.call(this, 'DELETE', `webhooks/${webhook.id}`);
124
+ return true;
125
+ }
126
+ }
127
+ return false;
128
+ },
129
+ },
130
+ };
131
+
132
+ async webhook(this: IWebhookFunctions): Promise<IWebhookResponseData> {
133
+ const req = this.getRequestObject();
134
+ return {
135
+ workflowData: [
136
+ [
137
+ {
138
+ json: req.body as IDataObject,
139
+ },
140
+ ],
141
+ ],
142
+ };
143
+ }
144
+ }
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "n8n-nodes-tiendanube-alldo",
3
+ "version": "1.0.0",
4
+ "description": "n8n nodes for Tiendanube (Nuvemshop) API integration",
5
+ "keywords": [
6
+ "n8n-community-node-package"
7
+ ],
8
+ "license": "MIT",
9
+ "homepage": "",
10
+ "author": {
11
+ "name": "Community",
12
+ "email": "community@n8n.io"
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "format": "prettier nodes/**/*.ts credentials/**/*.ts --write",
18
+ "lint": "tslint -p tsconfig.json -c tslint.json",
19
+ "test": "jest"
20
+ },
21
+ "main": "dist/index.js",
22
+ "n8n": {
23
+ "credentials": [
24
+ "dist/credentials/TiendanubeApi.credentials.js"
25
+ ],
26
+ "nodes": [
27
+ "dist/nodes/Tiendanube/Tiendanube.node.js",
28
+ "dist/nodes/TiendanubeTrigger/TiendanubeTrigger.node.js"
29
+ ]
30
+ },
31
+ "devDependencies": {
32
+ "@types/express": "^4.17.6",
33
+ "@types/ms": "^2.1.0",
34
+ "@types/node": "^25.0.9",
35
+ "@types/request-promise-native": "~1.0.15",
36
+ "@types/ssh2": "^1.15.5",
37
+ "gulp": "^4.0.2",
38
+ "n8n-workflow": "*",
39
+ "nock": "^14.0.10",
40
+ "prettier": "^2.1.2",
41
+ "tslint": "^6.1.2",
42
+ "typescript": "^5.3.3"
43
+ },
44
+ "dependencies": {
45
+ "n8n-core": "*"
46
+ }
47
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "commonjs",
5
+ "lib": [
6
+ "ES2022",
7
+ "dom"
8
+ ],
9
+ "sourceMap": true,
10
+ "outDir": "./dist",
11
+ "rootDir": "./",
12
+ "strict": true,
13
+ "noImplicitAny": true,
14
+ "strictNullChecks": true,
15
+ "strictFunctionTypes": true,
16
+ "strictBindCallApply": true,
17
+ "strictPropertyInitialization": true,
18
+ "noImplicitThis": true,
19
+ "alwaysStrict": true,
20
+ "esModuleInterop": true,
21
+ "types": [
22
+ "node"
23
+ ],
24
+ "skipLibCheck": true
25
+ },
26
+ "include": [
27
+ "nodes/**/*",
28
+ "credentials/**/*"
29
+ ],
30
+ "exclude": [
31
+ "node_modules",
32
+ "dist"
33
+ ]
34
+ }