n8n-nodes-atendix 1.0.0 → 1.3.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/dist/credentials/TrayApiAuto.credentials.js +82 -100
- package/dist/nodes/Atendix/Atendix.node.js +254 -199
- package/index.js +6 -2
- package/package.json +33 -37
- package/dist/credentials/TrayApiAuto.credentials.d.ts +0 -16
- package/dist/icons/tray.svg +0 -21
- package/dist/nodes/Atendix/Atendix.node.d.ts +0 -11
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
/**
|
|
3
|
+
* n8n-nodes-atendix — Credenciais Tray Commerce
|
|
4
|
+
* v1.3.0 — CORREÇÃO CRÍTICA:
|
|
5
|
+
* URL: {store_id}.commercesuite.com.br/web_api (api.tray.com.br não existe)
|
|
6
|
+
* consumer_key/secret agora são campos de credencial (não env vars)
|
|
6
7
|
*/
|
|
7
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
9
|
exports.TrayApiAuto = void 0;
|
|
9
|
-
|
|
10
|
-
const CONSUMER_SECRET = process.env.TRAY_CONSUMER_SECRET;
|
|
10
|
+
|
|
11
11
|
class TrayApiAuto {
|
|
12
12
|
constructor() {
|
|
13
13
|
this.name = 'trayApiAuto';
|
|
@@ -19,150 +19,132 @@ class TrayApiAuto {
|
|
|
19
19
|
this.documentationUrl = 'https://developers.tray.com.br/docs/';
|
|
20
20
|
this.properties = [
|
|
21
21
|
{
|
|
22
|
-
displayName: '
|
|
23
|
-
name: '
|
|
22
|
+
displayName: 'Store ID',
|
|
23
|
+
name: 'storeId',
|
|
24
24
|
type: 'string',
|
|
25
|
-
default: '
|
|
25
|
+
default: '',
|
|
26
26
|
required: true,
|
|
27
|
-
|
|
27
|
+
placeholder: '1225878',
|
|
28
|
+
description: 'ID da sua loja Tray. A URL base (https://{storeId}.commercesuite.com.br/web_api) é gerada automaticamente.',
|
|
28
29
|
},
|
|
29
30
|
{
|
|
30
|
-
displayName: '
|
|
31
|
-
name: '
|
|
31
|
+
displayName: 'Consumer Key',
|
|
32
|
+
name: 'consumerKey',
|
|
32
33
|
type: 'string',
|
|
33
|
-
typeOptions: {
|
|
34
|
-
password: true,
|
|
35
|
-
},
|
|
36
34
|
default: '',
|
|
37
35
|
required: true,
|
|
38
|
-
|
|
39
|
-
description: 'Código de autorização único da loja (fornecido pela Tray)',
|
|
36
|
+
description: 'Consumer Key fornecida pela Tray no painel de apps',
|
|
40
37
|
},
|
|
41
38
|
{
|
|
42
|
-
displayName: '
|
|
43
|
-
name: '
|
|
44
|
-
type: '
|
|
45
|
-
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
displayName: 'Refresh Token',
|
|
49
|
-
name: 'refreshToken',
|
|
50
|
-
type: 'hidden',
|
|
51
|
-
default: '',
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
displayName: 'API Host',
|
|
55
|
-
name: 'apiHost',
|
|
56
|
-
type: 'hidden',
|
|
57
|
-
default: '',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
displayName: 'Token Expiration',
|
|
61
|
-
name: 'tokenExpiration',
|
|
62
|
-
type: 'hidden',
|
|
39
|
+
displayName: 'Consumer Secret',
|
|
40
|
+
name: 'consumerSecret',
|
|
41
|
+
type: 'string',
|
|
42
|
+
typeOptions: { password: true },
|
|
63
43
|
default: '',
|
|
44
|
+
required: true,
|
|
45
|
+
description: 'Consumer Secret fornecido pela Tray no painel de apps',
|
|
64
46
|
},
|
|
65
47
|
{
|
|
66
|
-
displayName: '
|
|
67
|
-
name: '
|
|
68
|
-
type: '
|
|
48
|
+
displayName: 'Authorization Code',
|
|
49
|
+
name: 'authCode',
|
|
50
|
+
type: 'string',
|
|
51
|
+
typeOptions: { password: true },
|
|
69
52
|
default: '',
|
|
53
|
+
required: true,
|
|
54
|
+
placeholder: 'a9777f8cdfe4cf41b0a72c295adef1f9c43a093052c9e6dd98d1e629a09f13f3',
|
|
55
|
+
description: 'Código de autorização único da loja (fornecido pela Tray)',
|
|
70
56
|
},
|
|
57
|
+
// Campos ocultos — cache interno de token
|
|
58
|
+
{ displayName: 'Access Token', name: 'accessToken', type: 'hidden', default: '' },
|
|
59
|
+
{ displayName: 'Refresh Token', name: 'refreshToken', type: 'hidden', default: '' },
|
|
60
|
+
{ displayName: 'Token Expiration',name: 'tokenExpiration',type: 'hidden', default: '' },
|
|
61
|
+
{ displayName: 'API Host', name: 'apiHost', type: 'hidden', default: '' },
|
|
71
62
|
];
|
|
72
|
-
// O segredo para o n8n injetar o token em todas as chamadas
|
|
73
63
|
this.authenticate = {
|
|
74
64
|
type: 'generic',
|
|
75
65
|
properties: {
|
|
76
|
-
qs: {
|
|
77
|
-
access_token: '={{$credentials.accessToken}}',
|
|
78
|
-
},
|
|
66
|
+
qs: { access_token: '={{$credentials.accessToken}}' },
|
|
79
67
|
},
|
|
80
68
|
};
|
|
81
69
|
this.test = {
|
|
82
70
|
request: {
|
|
83
|
-
|
|
84
|
-
baseURL: '={{$credentials.apiAddress}}',
|
|
71
|
+
baseURL: '={{`https://${$credentials.storeId}.commercesuite.com.br/web_api`}}',
|
|
85
72
|
url: '/auth',
|
|
86
73
|
method: 'POST',
|
|
87
74
|
body: {
|
|
88
|
-
consumer_key:
|
|
89
|
-
consumer_secret:
|
|
90
|
-
code:
|
|
75
|
+
consumer_key: '={{$credentials.consumerKey}}',
|
|
76
|
+
consumer_secret: '={{$credentials.consumerSecret}}',
|
|
77
|
+
code: '={{$credentials.authCode}}',
|
|
91
78
|
},
|
|
92
79
|
},
|
|
93
80
|
};
|
|
94
81
|
}
|
|
82
|
+
|
|
83
|
+
_buildBaseUrl(credentials) {
|
|
84
|
+
const storeId = (credentials.storeId || '').toString().trim();
|
|
85
|
+
if (!storeId) throw new Error('[Atendix] Store ID não configurado nas credenciais');
|
|
86
|
+
// v1.3.0 FIX: URL correta — api.tray.com.br não existe
|
|
87
|
+
return `https://${storeId}.commercesuite.com.br/web_api`;
|
|
88
|
+
}
|
|
89
|
+
|
|
95
90
|
async preAuthentication(credentials) {
|
|
96
91
|
const now = new Date();
|
|
97
92
|
const tokenExpiration = credentials.tokenExpiration
|
|
98
93
|
? new Date(credentials.tokenExpiration)
|
|
99
94
|
: null;
|
|
95
|
+
|
|
100
96
|
if (credentials.accessToken && tokenExpiration && tokenExpiration > now) {
|
|
101
|
-
return credentials;
|
|
97
|
+
return credentials; // Token válido em cache
|
|
102
98
|
}
|
|
103
99
|
if (credentials.refreshToken && tokenExpiration && tokenExpiration <= now) {
|
|
104
100
|
return await this._refreshTokenFlow(credentials);
|
|
105
101
|
}
|
|
106
102
|
return await this._authenticateFlow(credentials);
|
|
107
103
|
}
|
|
108
|
-
|
|
109
|
-
* Renomeado para evitar conflito com a propriedade 'authenticate' da interface
|
|
110
|
-
*/
|
|
104
|
+
|
|
111
105
|
async _authenticateFlow(credentials) {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
});
|
|
129
|
-
const data = (await response.json());
|
|
130
|
-
if (!response.ok) {
|
|
131
|
-
console.error(' Erro retornado pela Tray:', data);
|
|
132
|
-
throw new Error(data.message || 'Erro desconhecido na Tray');
|
|
133
|
-
}
|
|
134
|
-
console.log(' Autenticação com a Tray teve SUCESSO!');
|
|
135
|
-
return {
|
|
136
|
-
...credentials,
|
|
137
|
-
accessToken: data.access_token,
|
|
138
|
-
refreshToken: data.refresh_token,
|
|
139
|
-
apiHost: data.api_host, // Geralmente vem algo como "https://1225878.commercesuite.com.br"
|
|
140
|
-
storeId: data.store_id,
|
|
141
|
-
tokenExpiration: data.date_expiration_access_token,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
catch (error) {
|
|
145
|
-
console.error(' Erro Crítico no Flow de Autenticação:', error.message);
|
|
146
|
-
throw new Error(`Falha ao autenticar na Tray: ${error.message}`);
|
|
106
|
+
const baseUrl = this._buildBaseUrl(credentials);
|
|
107
|
+
console.log(`[Atendix v1.3.0] Autenticando em: ${baseUrl}/auth`);
|
|
108
|
+
|
|
109
|
+
const response = await fetch(`${baseUrl}/auth`, {
|
|
110
|
+
method: 'POST',
|
|
111
|
+
headers: { 'Content-Type': 'application/json' },
|
|
112
|
+
body: JSON.stringify({
|
|
113
|
+
consumer_key: credentials.consumerKey,
|
|
114
|
+
consumer_secret: credentials.consumerSecret,
|
|
115
|
+
code: credentials.authCode,
|
|
116
|
+
}),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const data = await response.json();
|
|
120
|
+
if (!response.ok) {
|
|
121
|
+
console.error('[Atendix] Erro na autenticação Tray:', data);
|
|
122
|
+
throw new Error(data.message || `Erro HTTP ${response.status} na autenticação Tray`);
|
|
147
123
|
}
|
|
124
|
+
|
|
125
|
+
console.log('[Atendix v1.3.0] Autenticação OK ✓');
|
|
126
|
+
return {
|
|
127
|
+
...credentials,
|
|
128
|
+
accessToken: data.access_token,
|
|
129
|
+
refreshToken: data.refresh_token,
|
|
130
|
+
apiHost: data.api_host,
|
|
131
|
+
tokenExpiration: data.date_expiration_access_token,
|
|
132
|
+
};
|
|
148
133
|
}
|
|
134
|
+
|
|
149
135
|
async _refreshTokenFlow(credentials) {
|
|
150
|
-
const
|
|
151
|
-
const refreshToken = credentials.refreshToken;
|
|
136
|
+
const baseUrl = this._buildBaseUrl(credentials);
|
|
152
137
|
try {
|
|
153
|
-
const response = await fetch(`${
|
|
154
|
-
const data =
|
|
155
|
-
if (!response.ok)
|
|
156
|
-
return await this._authenticateFlow(credentials);
|
|
157
|
-
}
|
|
138
|
+
const response = await fetch(`${baseUrl}/auth?refresh_token=${credentials.refreshToken}`);
|
|
139
|
+
const data = await response.json();
|
|
140
|
+
if (!response.ok) return await this._authenticateFlow(credentials);
|
|
158
141
|
return {
|
|
159
142
|
...credentials,
|
|
160
|
-
accessToken:
|
|
161
|
-
refreshToken:
|
|
143
|
+
accessToken: data.access_token,
|
|
144
|
+
refreshToken: data.refresh_token,
|
|
162
145
|
tokenExpiration: data.date_expiration_access_token,
|
|
163
146
|
};
|
|
164
|
-
}
|
|
165
|
-
catch (error) {
|
|
147
|
+
} catch {
|
|
166
148
|
return await this._authenticateFlow(credentials);
|
|
167
149
|
}
|
|
168
150
|
}
|
|
@@ -1,324 +1,379 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* n8n-nodes-atendix — Node Atendix Tray Commerce
|
|
4
|
+
* v1.3.0 — Correções críticas de homologação:
|
|
5
|
+
* - URL: {store_id}.commercesuite.com.br/web_api
|
|
6
|
+
* - Endpoints NF: GET /orders/:id/invoices (não /invoices?order_id=)
|
|
7
|
+
* - Recursos: Pedido, Nota Fiscal, Cliente, Rastreamento, Produto
|
|
7
8
|
*/
|
|
8
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
10
|
exports.Atendix = void 0;
|
|
10
11
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
12
|
+
|
|
13
|
+
const wait = (ms) => new Promise(res => setTimeout(res, ms));
|
|
14
|
+
|
|
11
15
|
class Atendix {
|
|
12
16
|
constructor() {
|
|
13
17
|
this.description = {
|
|
14
18
|
displayName: 'Atendix - Tray API',
|
|
15
19
|
name: 'atendix',
|
|
16
|
-
icon: {
|
|
17
|
-
light: 'file:tray.svg',
|
|
18
|
-
dark: 'file:tray.svg',
|
|
19
|
-
},
|
|
20
|
+
icon: { light: 'file:tray.svg', dark: 'file:tray.svg' },
|
|
20
21
|
group: ['transform'],
|
|
21
22
|
version: 1,
|
|
22
23
|
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
23
|
-
description: 'Integração com a
|
|
24
|
-
defaults: {
|
|
25
|
-
name: 'Atendix - Tray API',
|
|
26
|
-
},
|
|
24
|
+
description: 'Integração nativa com a Tray Commerce — v1.3.0',
|
|
25
|
+
defaults: { name: 'Atendix - Tray API' },
|
|
27
26
|
inputs: ['main'],
|
|
28
27
|
outputs: ['main'],
|
|
29
|
-
credentials: [
|
|
30
|
-
{
|
|
31
|
-
name: 'trayApiAuto',
|
|
32
|
-
required: true,
|
|
33
|
-
displayName: 'Atendix - Tray API',
|
|
34
|
-
},
|
|
35
|
-
],
|
|
28
|
+
credentials: [{ name: 'trayApiAuto', required: true, displayName: 'Atendix - Tray API' }],
|
|
36
29
|
properties: [
|
|
37
|
-
//
|
|
30
|
+
// ===== RESOURCE =====
|
|
38
31
|
{
|
|
39
|
-
displayName: 'Resource',
|
|
40
|
-
name: 'resource',
|
|
41
|
-
type: 'options',
|
|
32
|
+
displayName: 'Resource', name: 'resource', type: 'options',
|
|
42
33
|
noDataExpression: true,
|
|
43
34
|
options: [
|
|
44
|
-
{ name: 'Pedido',
|
|
45
|
-
{ name: '
|
|
46
|
-
{ name: '
|
|
35
|
+
{ name: 'Pedido', value: 'order' },
|
|
36
|
+
{ name: 'Nota Fiscal', value: 'invoice' },
|
|
37
|
+
{ name: 'Cliente', value: 'customer' },
|
|
38
|
+
{ name: 'Rastreamento', value: 'tracking' },
|
|
39
|
+
{ name: 'Produto', value: 'product' },
|
|
47
40
|
],
|
|
48
41
|
default: 'order',
|
|
49
42
|
},
|
|
50
|
-
|
|
43
|
+
|
|
44
|
+
// ===== PEDIDO — OPERATIONS =====
|
|
51
45
|
{
|
|
52
|
-
displayName: 'Operation',
|
|
53
|
-
name: 'operation',
|
|
54
|
-
type: 'options',
|
|
46
|
+
displayName: 'Operation', name: 'operation', type: 'options',
|
|
55
47
|
noDataExpression: true,
|
|
56
48
|
displayOptions: { show: { resource: ['order'] } },
|
|
57
49
|
options: [
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
action: 'Buscar um pedido',
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
name: 'Listar Pedidos',
|
|
66
|
-
value: 'list',
|
|
67
|
-
description: 'Lista pedidos com filtros opcionais',
|
|
68
|
-
action: 'Listar pedidos',
|
|
69
|
-
},
|
|
50
|
+
{ name: 'Buscar Pedido', value: 'get', action: 'Buscar pedido por ID' },
|
|
51
|
+
{ name: 'Dados Completos', value: 'getComplete', action: 'Buscar dados completos' },
|
|
52
|
+
{ name: 'Listar Pedidos', value: 'list', action: 'Listar pedidos com filtros' },
|
|
53
|
+
{ name: 'Atualizar Status', value: 'updateStatus', action: 'Atualizar status do pedido' },
|
|
70
54
|
],
|
|
71
55
|
default: 'get',
|
|
72
56
|
},
|
|
73
57
|
{
|
|
74
|
-
displayName: 'ID do Pedido',
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
required: true,
|
|
78
|
-
displayOptions: { show: { resource: ['order'], operation: ['get'] } },
|
|
79
|
-
default: '',
|
|
58
|
+
displayName: 'ID do Pedido', name: 'orderId', type: 'string', required: true,
|
|
59
|
+
displayOptions: { show: { resource: ['order'], operation: ['get', 'getComplete', 'updateStatus'] } },
|
|
60
|
+
default: '', placeholder: '9847',
|
|
80
61
|
},
|
|
81
62
|
{
|
|
82
|
-
displayName: '
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
63
|
+
displayName: 'Novo Status', name: 'orderStatus', type: 'options',
|
|
64
|
+
displayOptions: { show: { resource: ['order'], operation: ['updateStatus'] } },
|
|
65
|
+
options: [
|
|
66
|
+
{ name: 'Aprovado', value: 'approved' },
|
|
67
|
+
{ name: 'Em Preparação', value: 'preparing' },
|
|
68
|
+
{ name: 'Enviado', value: 'shipped' },
|
|
69
|
+
{ name: 'Entregue', value: 'delivered' },
|
|
70
|
+
{ name: 'Cancelado', value: 'cancelled' },
|
|
71
|
+
],
|
|
72
|
+
default: 'approved',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
displayName: 'Filtros', name: 'filters', type: 'collection',
|
|
76
|
+
placeholder: 'Adicionar Filtro', default: {},
|
|
87
77
|
displayOptions: { show: { resource: ['order'], operation: ['list'] } },
|
|
88
78
|
options: [
|
|
89
79
|
{
|
|
90
|
-
displayName: 'Status',
|
|
91
|
-
name: 'status',
|
|
92
|
-
type: 'options',
|
|
80
|
+
displayName: 'Status', name: 'status', type: 'options', default: '',
|
|
93
81
|
options: [
|
|
94
|
-
{ name: 'Pendente',
|
|
95
|
-
{ name: 'Aprovado',
|
|
96
|
-
{ name: 'Enviado',
|
|
97
|
-
{ name: 'Entregue',
|
|
82
|
+
{ name: 'Pendente', value: 'pending' },
|
|
83
|
+
{ name: 'Aprovado', value: 'approved' },
|
|
84
|
+
{ name: 'Enviado', value: 'shipped' },
|
|
85
|
+
{ name: 'Entregue', value: 'delivered' },
|
|
98
86
|
{ name: 'Cancelado', value: 'cancelled' },
|
|
99
87
|
],
|
|
100
|
-
default: '',
|
|
101
88
|
},
|
|
102
89
|
{ displayName: 'Limite', name: 'limit', type: 'number', default: 50 },
|
|
90
|
+
{ displayName: 'Página', name: 'page', type: 'number', default: 1 },
|
|
91
|
+
{ displayName: 'Data Início (YYYY-MM-DD)', name: 'dateFrom', type: 'string', default: '' },
|
|
92
|
+
{ displayName: 'Data Fim (YYYY-MM-DD)', name: 'dateTo', type: 'string', default: '' },
|
|
103
93
|
],
|
|
104
94
|
},
|
|
105
|
-
|
|
95
|
+
|
|
96
|
+
// ===== NOTA FISCAL — OPERATIONS =====
|
|
97
|
+
// v1.3.0 FIX: endpoints corretos são /orders/:id/invoices
|
|
106
98
|
{
|
|
107
|
-
displayName: 'Operation',
|
|
108
|
-
|
|
109
|
-
|
|
99
|
+
displayName: 'Operation', name: 'operation', type: 'options',
|
|
100
|
+
noDataExpression: true,
|
|
101
|
+
displayOptions: { show: { resource: ['invoice'] } },
|
|
102
|
+
options: [
|
|
103
|
+
{ name: 'Listar NFs do Pedido', value: 'list', action: 'GET /orders/:id/invoices' },
|
|
104
|
+
{ name: 'Buscar NF por ID', value: 'get', action: 'GET /orders/:id/invoices/:inv_id' },
|
|
105
|
+
{ name: 'Cadastrar NF', value: 'create', action: 'POST /invoices' },
|
|
106
|
+
],
|
|
107
|
+
default: 'list',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
displayName: 'ID do Pedido', name: 'orderId', type: 'string', required: true,
|
|
111
|
+
displayOptions: { show: { resource: ['invoice'], operation: ['list', 'get'] } },
|
|
112
|
+
default: '', placeholder: '9847',
|
|
113
|
+
description: 'ID do pedido Tray para buscar as NFs',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
displayName: 'ID da Nota Fiscal', name: 'invoiceId', type: 'string', required: true,
|
|
117
|
+
displayOptions: { show: { resource: ['invoice'], operation: ['get'] } },
|
|
118
|
+
default: '', placeholder: '1347',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
displayName: 'Dados da NF (JSON)', name: 'invoiceData', type: 'json',
|
|
122
|
+
displayOptions: { show: { resource: ['invoice'], operation: ['create'] } },
|
|
123
|
+
default: '{\n "order_id": "",\n "issue_date": "",\n "number": "",\n "serie": "",\n "value": "",\n "xml": "",\n "key": "",\n "link": ""\n}',
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
// ===== CLIENTES — OPERATIONS =====
|
|
127
|
+
{
|
|
128
|
+
displayName: 'Operation', name: 'operation', type: 'options',
|
|
110
129
|
noDataExpression: true,
|
|
111
130
|
displayOptions: { show: { resource: ['customer'] } },
|
|
112
131
|
options: [
|
|
113
|
-
{ name: 'Buscar
|
|
114
|
-
{ name: '
|
|
132
|
+
{ name: 'Buscar por ID', value: 'get', action: 'Buscar cliente por ID' },
|
|
133
|
+
{ name: 'Listar Clientes', value: 'list', action: 'Listar clientes paginado' },
|
|
134
|
+
{ name: 'Buscar por Tel/E-mail', value: 'search', action: 'Buscar por telefone ou email' },
|
|
115
135
|
],
|
|
116
136
|
default: 'get',
|
|
117
137
|
},
|
|
118
138
|
{
|
|
119
|
-
displayName: '
|
|
120
|
-
name: 'searchType',
|
|
121
|
-
type: 'options',
|
|
139
|
+
displayName: 'ID do Cliente', name: 'customerId', type: 'string', required: true,
|
|
122
140
|
displayOptions: { show: { resource: ['customer'], operation: ['get'] } },
|
|
141
|
+
default: '',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
displayName: 'Buscar Por', name: 'searchType', type: 'options',
|
|
145
|
+
displayOptions: { show: { resource: ['customer'], operation: ['search'] } },
|
|
123
146
|
options: [
|
|
124
|
-
{ name: 'E-mail',
|
|
125
|
-
{ name: '
|
|
147
|
+
{ name: 'E-mail', value: 'email' },
|
|
148
|
+
{ name: 'Telefone', value: 'phone' },
|
|
149
|
+
{ name: 'CPF/CNPJ', value: 'cpf_cnpj'},
|
|
126
150
|
],
|
|
127
151
|
default: 'email',
|
|
128
152
|
},
|
|
129
153
|
{
|
|
130
|
-
displayName: 'Valor',
|
|
131
|
-
|
|
132
|
-
type: 'string',
|
|
133
|
-
displayOptions: { show: { resource: ['customer'], operation: ['get'] } },
|
|
154
|
+
displayName: 'Valor de Busca', name: 'searchValue', type: 'string',
|
|
155
|
+
displayOptions: { show: { resource: ['customer'], operation: ['search'] } },
|
|
134
156
|
default: '',
|
|
135
157
|
},
|
|
136
|
-
// ==================== PRODUTOS - OPERATIONS ====================
|
|
137
158
|
{
|
|
138
|
-
displayName: '
|
|
139
|
-
|
|
140
|
-
|
|
159
|
+
displayName: 'Filtros', name: 'filters', type: 'collection',
|
|
160
|
+
placeholder: 'Adicionar Filtro', default: {},
|
|
161
|
+
displayOptions: { show: { resource: ['customer'], operation: ['list'] } },
|
|
162
|
+
options: [
|
|
163
|
+
{ displayName: 'Limite', name: 'limit', type: 'number', default: 50 },
|
|
164
|
+
{ displayName: 'Página', name: 'page', type: 'number', default: 1 },
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
// ===== RASTREAMENTO — OPERATIONS =====
|
|
169
|
+
{
|
|
170
|
+
displayName: 'Operation', name: 'operation', type: 'options',
|
|
171
|
+
noDataExpression: true,
|
|
172
|
+
displayOptions: { show: { resource: ['tracking'] } },
|
|
173
|
+
options: [
|
|
174
|
+
{ name: 'Código de Rastreio', value: 'getTracking', action: 'Obter código de rastreio do pedido' },
|
|
175
|
+
{ name: 'Formas de Envio', value: 'getShipping', action: 'Listar formas de envio disponíveis' },
|
|
176
|
+
],
|
|
177
|
+
default: 'getTracking',
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
displayName: 'ID do Pedido', name: 'orderId', type: 'string', required: true,
|
|
181
|
+
displayOptions: { show: { resource: ['tracking'], operation: ['getTracking'] } },
|
|
182
|
+
default: '', placeholder: '9847',
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
// ===== PRODUTO — OPERATIONS =====
|
|
186
|
+
{
|
|
187
|
+
displayName: 'Operation', name: 'operation', type: 'options',
|
|
141
188
|
noDataExpression: true,
|
|
142
189
|
displayOptions: { show: { resource: ['product'] } },
|
|
143
190
|
options: [
|
|
144
|
-
{ name: 'Buscar Produto',
|
|
145
|
-
{ name: 'Atualizar Estoque', value: 'updateStock', action: 'Atualizar estoque
|
|
191
|
+
{ name: 'Buscar Produto', value: 'get', action: 'Buscar produto por ID ou SKU' },
|
|
192
|
+
{ name: 'Atualizar Estoque', value: 'updateStock', action: 'Atualizar estoque' },
|
|
146
193
|
],
|
|
147
194
|
default: 'get',
|
|
148
195
|
},
|
|
149
196
|
{
|
|
150
|
-
displayName: 'Buscar Por',
|
|
151
|
-
name: 'searchType',
|
|
152
|
-
type: 'options',
|
|
197
|
+
displayName: 'Buscar Por', name: 'searchType', type: 'options',
|
|
153
198
|
displayOptions: { show: { resource: ['product'], operation: ['get'] } },
|
|
154
199
|
options: [
|
|
155
|
-
{ name: 'ID do Produto', value: 'id'
|
|
156
|
-
{ name: 'SKU',
|
|
200
|
+
{ name: 'ID do Produto', value: 'id' },
|
|
201
|
+
{ name: 'SKU', value: 'sku' },
|
|
157
202
|
],
|
|
158
203
|
default: 'id',
|
|
159
204
|
},
|
|
160
205
|
{
|
|
161
|
-
displayName: 'Valor',
|
|
162
|
-
name: 'searchValue',
|
|
163
|
-
type: 'string',
|
|
206
|
+
displayName: 'Valor', name: 'searchValue', type: 'string',
|
|
164
207
|
displayOptions: { show: { resource: ['product'], operation: ['get'] } },
|
|
165
208
|
default: '',
|
|
166
209
|
},
|
|
167
210
|
],
|
|
168
211
|
};
|
|
169
212
|
}
|
|
213
|
+
|
|
170
214
|
async execute() {
|
|
171
|
-
|
|
172
|
-
const items = this.getInputData();
|
|
215
|
+
const items = this.getInputData();
|
|
173
216
|
const returnData = [];
|
|
174
|
-
const resource
|
|
217
|
+
const resource = this.getNodeParameter('resource', 0);
|
|
175
218
|
const operation = this.getNodeParameter('operation', 0);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
console.error('❌ ATENDIX_AUTH_TOKEN não configurado nas variáveis de ambiente');
|
|
179
|
-
throw new Error('Configuração de validação Atendix incompleta. Entre em contato com o suporte.');
|
|
180
|
-
}
|
|
181
|
-
// 1. Get Credentials
|
|
219
|
+
|
|
220
|
+
// Credenciais (n8n chama preAuthentication automaticamente)
|
|
182
221
|
const credentials = await this.getCredentials('trayApiAuto');
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
try {
|
|
191
|
-
licenseCheck = await this.helpers.httpRequest({
|
|
192
|
-
method: 'POST',
|
|
193
|
-
url: 'https://n8n.mariapinho.com.br/webhook/valida-atendix',
|
|
194
|
-
headers: {
|
|
195
|
-
'Content-Type': 'application/json',
|
|
196
|
-
'Authorization': atendixAuthToken,
|
|
197
|
-
},
|
|
198
|
-
body: { url: storeBaseUrl },
|
|
199
|
-
json: true,
|
|
200
|
-
});
|
|
201
|
-
console.error('LICENSE CHECK RESPONSE: ' + licenseCheck.autorizado);
|
|
202
|
-
if (!licenseCheck || licenseCheck.autorizado !== true) {
|
|
203
|
-
console.error('Resposta inválida do servidor de licenças:', licenseCheck);
|
|
204
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Sua licença Atendix para a loja ${storeBaseUrl} não está ativa ou não pode ser validada. Para liberar seu acesso e automatizar sua operação, acesse https://atendix.com.br e assine um plano agora mesmo!`);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
catch (error) {
|
|
208
|
-
console.error('ATENDIX_AUTH_TOKEN:', atendixAuthToken);
|
|
209
|
-
console.error('STORE BASE URL:', storeBaseUrl);
|
|
210
|
-
console.error('LICENSECHECK:', licenseCheck);
|
|
211
|
-
console.error('Erro HTTP licença:', (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status);
|
|
212
|
-
console.error('Body licença:', (_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.data);
|
|
213
|
-
// Se for erro de acesso bloqueado, repassa. Se for erro de rede, avisa o usuário.
|
|
214
|
-
if (error instanceof n8n_workflow_1.NodeOperationError)
|
|
215
|
-
throw error;
|
|
216
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Erro crítico: Não foi possível validar a licença do Atendix no servidor MariaPinho.");
|
|
217
|
-
}
|
|
218
|
-
// 2. TOKEN MANAGER (Fallback)
|
|
219
|
-
let accessToken = credentials.accessToken;
|
|
220
|
-
if (!accessToken) {
|
|
221
|
-
try {
|
|
222
|
-
const authResponse = await this.helpers.httpRequest({
|
|
223
|
-
method: 'POST',
|
|
224
|
-
url: `${baseUrl}/auth`,
|
|
225
|
-
body: {
|
|
226
|
-
consumer_key: process.env.TRAY_CONSUMER_KEY,
|
|
227
|
-
consumer_secret: process.env.TRAY_CONSUMER_SECRET,
|
|
228
|
-
code: credentials.authCode,
|
|
229
|
-
},
|
|
230
|
-
json: true,
|
|
231
|
-
});
|
|
232
|
-
accessToken = authResponse.access_token;
|
|
233
|
-
}
|
|
234
|
-
catch (authError) {
|
|
235
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Falha na Autenticação Tray: ${authError.message}`);
|
|
236
|
-
}
|
|
222
|
+
const storeId = (credentials.storeId || '').toString().trim();
|
|
223
|
+
|
|
224
|
+
if (!storeId) {
|
|
225
|
+
throw new n8n_workflow_1.NodeOperationError(
|
|
226
|
+
this.getNode(),
|
|
227
|
+
'Store ID não configurado nas credenciais Atendix. Preencha o campo Store ID.',
|
|
228
|
+
);
|
|
237
229
|
}
|
|
230
|
+
|
|
231
|
+
// v1.3.0: URL derivada do store_id — nunca mais hardcoded
|
|
232
|
+
const baseUrl = `https://${storeId}.commercesuite.com.br/web_api`;
|
|
233
|
+
const accessToken = credentials.accessToken;
|
|
234
|
+
|
|
238
235
|
for (let i = 0; i < items.length; i++) {
|
|
239
236
|
try {
|
|
237
|
+
if (i > 0) await wait(500); // Rate-limit seguro: ~120 req/min (limite Tray: 180)
|
|
238
|
+
|
|
240
239
|
let responseData = {};
|
|
241
240
|
const qs = { access_token: accessToken };
|
|
242
|
-
|
|
241
|
+
|
|
242
|
+
// ===== PEDIDOS =====
|
|
243
243
|
if (resource === 'order') {
|
|
244
244
|
if (operation === 'get') {
|
|
245
245
|
const orderId = this.getNodeParameter('orderId', i);
|
|
246
246
|
responseData = await this.helpers.httpRequest({
|
|
247
|
-
method: 'GET',
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
247
|
+
method: 'GET', url: `${baseUrl}/orders/${orderId}`, qs, json: true,
|
|
248
|
+
});
|
|
249
|
+
} else if (operation === 'getComplete') {
|
|
250
|
+
const orderId = this.getNodeParameter('orderId', i);
|
|
251
|
+
responseData = await this.helpers.httpRequest({
|
|
252
|
+
method: 'GET', url: `${baseUrl}/orders/${orderId}/complete`, qs, json: true,
|
|
253
|
+
});
|
|
254
|
+
} else if (operation === 'list') {
|
|
255
|
+
const filters = this.getNodeParameter('filters', i, {});
|
|
256
|
+
if (filters.status) qs.status = filters.status;
|
|
257
|
+
if (filters.limit) qs.limit = filters.limit;
|
|
258
|
+
if (filters.page) qs.page = filters.page;
|
|
259
|
+
if (filters.dateFrom) qs.date_from = filters.dateFrom;
|
|
260
|
+
if (filters.dateTo) qs.date_to = filters.dateTo;
|
|
261
|
+
responseData = await this.helpers.httpRequest({
|
|
262
|
+
method: 'GET', url: `${baseUrl}/orders`, qs, json: true,
|
|
263
|
+
});
|
|
264
|
+
} else if (operation === 'updateStatus') {
|
|
265
|
+
const orderId = this.getNodeParameter('orderId', i);
|
|
266
|
+
const orderStatus = this.getNodeParameter('orderStatus', i);
|
|
267
|
+
responseData = await this.helpers.httpRequest({
|
|
268
|
+
method: 'PUT', url: `${baseUrl}/orders/${orderId}`,
|
|
269
|
+
qs, body: { status: orderStatus }, json: true,
|
|
251
270
|
});
|
|
252
271
|
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ===== NOTA FISCAL =====
|
|
275
|
+
// v1.3.0 FIX CRÍTICO: endpoints corretos são /orders/:id/invoices
|
|
276
|
+
else if (resource === 'invoice') {
|
|
253
277
|
if (operation === 'list') {
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
qs.status = filters.status;
|
|
257
|
-
if (filters.limit)
|
|
258
|
-
qs.limit = filters.limit;
|
|
278
|
+
const orderId = this.getNodeParameter('orderId', i);
|
|
279
|
+
// ✅ CORRETO: GET /orders/:order_id/invoices
|
|
259
280
|
responseData = await this.helpers.httpRequest({
|
|
260
|
-
method: 'GET',
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
281
|
+
method: 'GET', url: `${baseUrl}/orders/${orderId}/invoices`, qs, json: true,
|
|
282
|
+
});
|
|
283
|
+
} else if (operation === 'get') {
|
|
284
|
+
const orderId = this.getNodeParameter('orderId', i);
|
|
285
|
+
const invoiceId = this.getNodeParameter('invoiceId', i);
|
|
286
|
+
// ✅ CORRETO: GET /orders/:order_id/invoices/:invoice_id
|
|
287
|
+
responseData = await this.helpers.httpRequest({
|
|
288
|
+
method: 'GET', url: `${baseUrl}/orders/${orderId}/invoices/${invoiceId}`, qs, json: true,
|
|
289
|
+
});
|
|
290
|
+
} else if (operation === 'create') {
|
|
291
|
+
const invoiceData = JSON.parse(this.getNodeParameter('invoiceData', i));
|
|
292
|
+
responseData = await this.helpers.httpRequest({
|
|
293
|
+
method: 'POST', url: `${baseUrl}/invoices`, qs, body: invoiceData, json: true,
|
|
264
294
|
});
|
|
265
295
|
}
|
|
266
296
|
}
|
|
267
|
-
|
|
268
|
-
|
|
297
|
+
|
|
298
|
+
// ===== CLIENTES =====
|
|
299
|
+
else if (resource === 'customer') {
|
|
269
300
|
if (operation === 'get') {
|
|
270
|
-
const
|
|
301
|
+
const customerId = this.getNodeParameter('customerId', i);
|
|
302
|
+
responseData = await this.helpers.httpRequest({
|
|
303
|
+
method: 'GET', url: `${baseUrl}/customers/${customerId}`, qs, json: true,
|
|
304
|
+
});
|
|
305
|
+
} else if (operation === 'list') {
|
|
306
|
+
const filters = this.getNodeParameter('filters', i, {});
|
|
307
|
+
if (filters.limit) qs.limit = filters.limit;
|
|
308
|
+
if (filters.page) qs.page = filters.page;
|
|
309
|
+
responseData = await this.helpers.httpRequest({
|
|
310
|
+
method: 'GET', url: `${baseUrl}/customers`, qs, json: true,
|
|
311
|
+
});
|
|
312
|
+
} else if (operation === 'search') {
|
|
313
|
+
const searchType = this.getNodeParameter('searchType', i);
|
|
271
314
|
const searchValue = this.getNodeParameter('searchValue', i);
|
|
272
|
-
|
|
273
|
-
qs.email = searchValue;
|
|
274
|
-
else
|
|
275
|
-
qs.cpf_cnpj = searchValue;
|
|
315
|
+
qs[searchType] = searchValue;
|
|
276
316
|
responseData = await this.helpers.httpRequest({
|
|
277
|
-
method: 'GET',
|
|
278
|
-
url: `${baseUrl}/customers`,
|
|
279
|
-
qs,
|
|
280
|
-
json: true,
|
|
317
|
+
method: 'GET', url: `${baseUrl}/customers`, qs, json: true,
|
|
281
318
|
});
|
|
282
319
|
}
|
|
283
|
-
// Nota da Gerente: Se for adicionar UPSERT aqui, o código deve ser incluído abaixo
|
|
284
320
|
}
|
|
285
|
-
|
|
286
|
-
|
|
321
|
+
|
|
322
|
+
// ===== RASTREAMENTO =====
|
|
323
|
+
else if (resource === 'tracking') {
|
|
324
|
+
if (operation === 'getTracking') {
|
|
325
|
+
const orderId = this.getNodeParameter('orderId', i);
|
|
326
|
+
const orderRaw = await this.helpers.httpRequest({
|
|
327
|
+
method: 'GET', url: `${baseUrl}/orders/${orderId}`, qs, json: true,
|
|
328
|
+
});
|
|
329
|
+
const order = (orderRaw.Order || orderRaw);
|
|
330
|
+
responseData = {
|
|
331
|
+
order_id: orderId,
|
|
332
|
+
tracking_code: order.shipping_tracking_code || null,
|
|
333
|
+
shipping_carrier: order.shipping_carrier || null,
|
|
334
|
+
shipping_method: order.shipping_method_name || null,
|
|
335
|
+
};
|
|
336
|
+
} else if (operation === 'getShipping') {
|
|
337
|
+
responseData = await this.helpers.httpRequest({
|
|
338
|
+
method: 'GET', url: `${baseUrl}/shipping`, qs, json: true,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// ===== PRODUTO =====
|
|
344
|
+
else if (resource === 'product') {
|
|
287
345
|
if (operation === 'get') {
|
|
288
|
-
const searchType
|
|
346
|
+
const searchType = this.getNodeParameter('searchType', i);
|
|
289
347
|
const searchValue = this.getNodeParameter('searchValue', i);
|
|
290
348
|
if (searchType === 'id') {
|
|
291
349
|
responseData = await this.helpers.httpRequest({
|
|
292
|
-
method: 'GET',
|
|
293
|
-
url: `${baseUrl}/products/${searchValue}`,
|
|
294
|
-
qs,
|
|
295
|
-
json: true,
|
|
350
|
+
method: 'GET', url: `${baseUrl}/products/${searchValue}`, qs, json: true,
|
|
296
351
|
});
|
|
297
|
-
}
|
|
298
|
-
else {
|
|
352
|
+
} else {
|
|
299
353
|
qs.sku = searchValue;
|
|
300
354
|
responseData = await this.helpers.httpRequest({
|
|
301
|
-
method: 'GET',
|
|
302
|
-
url: `${baseUrl}/products`,
|
|
303
|
-
qs,
|
|
304
|
-
json: true,
|
|
355
|
+
method: 'GET', url: `${baseUrl}/products`, qs, json: true,
|
|
305
356
|
});
|
|
306
357
|
}
|
|
307
358
|
}
|
|
308
|
-
// Nota da Gerente: Se for adicionar UPDATE_STOCK aqui, o código deve ser incluído abaixo
|
|
309
359
|
}
|
|
310
|
-
|
|
360
|
+
|
|
361
|
+
const executionData = this.helpers.constructExecutionMetaData(
|
|
362
|
+
this.helpers.returnJsonArray(responseData),
|
|
363
|
+
{ itemData: { item: i } },
|
|
364
|
+
);
|
|
311
365
|
returnData.push(...executionData);
|
|
312
|
-
|
|
313
|
-
catch (error) {
|
|
314
|
-
const
|
|
366
|
+
|
|
367
|
+
} catch (error) {
|
|
368
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
315
369
|
if (this.continueOnFail()) {
|
|
316
|
-
returnData.push({ json: { error:
|
|
370
|
+
returnData.push({ json: { error: msg, resource, operation }, pairedItem: { item: i } });
|
|
317
371
|
continue;
|
|
318
372
|
}
|
|
319
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(),
|
|
373
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), msg, { itemIndex: i });
|
|
320
374
|
}
|
|
321
375
|
}
|
|
376
|
+
|
|
322
377
|
return [returnData];
|
|
323
378
|
}
|
|
324
379
|
}
|
package/index.js
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
var Atendix_node_1 = require("./dist/nodes/Atendix/Atendix.node");
|
|
4
|
+
Object.defineProperty(exports, "Atendix", { enumerable: true, get: function () { return Atendix_node_1.Atendix; } });
|
|
5
|
+
var TrayApiAuto_credentials_1 = require("./dist/credentials/TrayApiAuto.credentials");
|
|
6
|
+
Object.defineProperty(exports, "TrayApiAuto", { enumerable: true, get: function () { return TrayApiAuto_credentials_1.TrayApiAuto; } });
|
package/package.json
CHANGED
|
@@ -1,37 +1,33 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "n8n-nodes-atendix",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Conector Atendix para integração com Tray Commerce",
|
|
5
|
-
"keywords": ["n8n-community-node-package"],
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"homepage": "https://atendix.
|
|
8
|
-
"author": {
|
|
9
|
-
"name": "Atendix",
|
|
10
|
-
"email": "contato@atendix.
|
|
11
|
-
},
|
|
12
|
-
"main": "index.js",
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
],
|
|
21
|
-
"n8n": {
|
|
22
|
-
"n8nNodesApiVersion": 1,
|
|
23
|
-
"credentials": [
|
|
24
|
-
"dist/credentials/TrayApiAuto.credentials.js"
|
|
25
|
-
],
|
|
26
|
-
"nodes": [
|
|
27
|
-
"dist/nodes/Atendix/Atendix.node.js"
|
|
28
|
-
]
|
|
29
|
-
},
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"n8n-workflow": "^1.0.0"
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
"@types/node": "^18.0.0",
|
|
35
|
-
"typescript": "^5.0.0"
|
|
36
|
-
}
|
|
37
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "n8n-nodes-atendix",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Conector Atendix para integração nativa com a Tray Commerce",
|
|
5
|
+
"keywords": ["n8n-community-node-package"],
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://atendix.co",
|
|
8
|
+
"author": {
|
|
9
|
+
"name": "Atendix",
|
|
10
|
+
"email": "contato@atendix.co"
|
|
11
|
+
},
|
|
12
|
+
"main": "index.js",
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "echo 'v1.3.0 pre-compiled — no build needed'"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"icons",
|
|
19
|
+
"index.js"
|
|
20
|
+
],
|
|
21
|
+
"n8n": {
|
|
22
|
+
"n8nNodesApiVersion": 1,
|
|
23
|
+
"credentials": [
|
|
24
|
+
"dist/credentials/TrayApiAuto.credentials.js"
|
|
25
|
+
],
|
|
26
|
+
"nodes": [
|
|
27
|
+
"dist/nodes/Atendix/Atendix.node.js"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"n8n-workflow": "^1.0.0"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { IAuthenticateGeneric, ICredentialType, INodeProperties, ICredentialDataDecryptedObject, ICredentialTestRequest, Icon } from 'n8n-workflow';
|
|
2
|
-
export declare class TrayApiAuto implements ICredentialType {
|
|
3
|
-
name: string;
|
|
4
|
-
displayName: string;
|
|
5
|
-
icon: Icon;
|
|
6
|
-
documentationUrl: string;
|
|
7
|
-
properties: INodeProperties[];
|
|
8
|
-
authenticate: IAuthenticateGeneric;
|
|
9
|
-
preAuthentication(credentials: ICredentialDataDecryptedObject): Promise<ICredentialDataDecryptedObject>;
|
|
10
|
-
/**
|
|
11
|
-
* Renomeado para evitar conflito com a propriedade 'authenticate' da interface
|
|
12
|
-
*/
|
|
13
|
-
private _authenticateFlow;
|
|
14
|
-
private _refreshTokenFlow;
|
|
15
|
-
test: ICredentialTestRequest;
|
|
16
|
-
}
|
package/dist/icons/tray.svg
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg
|
|
3
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
4
|
-
viewBox="0 0 24 24"
|
|
5
|
-
fill="none"
|
|
6
|
-
stroke="#7D7D87"
|
|
7
|
-
stroke-width="1.3"
|
|
8
|
-
stroke-linecap="round"
|
|
9
|
-
stroke-linejoin="round"
|
|
10
|
-
>
|
|
11
|
-
<path d="M3 21 L3 6 C3 4.343 4.343 3 6 3 H18 C19.657 3 22 4.343 22 6 V14 C22 15.657 19.657 17 18 17 H8.5 L3 21 Z" />
|
|
12
|
-
|
|
13
|
-
<path d="M6.8 14V9.5" />
|
|
14
|
-
<circle cx="6.8" cy="8" r="1.5" />
|
|
15
|
-
|
|
16
|
-
<path d="M10.6 14V11.5L12.5 9" />
|
|
17
|
-
<circle cx="13.5" cy="7.8" r="1.5" />
|
|
18
|
-
|
|
19
|
-
<path d="M14 14V12.5C14 11.8 14.5 11.5 15.2 11.5H17" />
|
|
20
|
-
<circle cx="18.5" cy="11.5" r="1.5" />
|
|
21
|
-
</svg>
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Arquivo: n8n-nodes-atendix/nodes/Atendix/Atendix.node.ts
|
|
3
|
-
*
|
|
4
|
-
* Node oficial Atendix - Tray Commerce
|
|
5
|
-
* Versão 1.2.0 - Licenciamento SaaS + Full Operations
|
|
6
|
-
*/
|
|
7
|
-
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
8
|
-
export declare class Atendix implements INodeType {
|
|
9
|
-
description: INodeTypeDescription;
|
|
10
|
-
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
11
|
-
}
|