n8n-nodes-salvia 0.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.
package/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # n8n-nodes-salvia
2
+
3
+ Nodes do **Salvia CRM** para o n8n: crie leads a partir de qualquer fluxo (formulário, planilha, anúncio, bot) com credencial própria e campos amigáveis.
4
+
5
+ ## Instalação (n8n self-hosted)
6
+
7
+ No terminal do container do n8n:
8
+
9
+ ```bash
10
+ mkdir -p ~/.n8n/nodes && cd ~/.n8n/nodes
11
+ npm install https://github.com/Projetos-Mov/n8n-nodes-salvia/archive/refs/heads/main.tar.gz
12
+ ```
13
+
14
+ Depois **reinicie o n8n**. O node "Salvia" aparece na busca de nodes.
15
+
16
+ ## Credencial
17
+
18
+ 1. No Salvia: **Ajustes → Central de Integrações → Desenvolvedores → Nova chave** (planos Pro e Clínica).
19
+ 2. No n8n: **Credentials → New → Salvia API**:
20
+ - **Base URL**: `https://salviacrm.com.br` (ou a URL do ambiente de teste)
21
+ - **API Key**: a chave gerada
22
+ 3. O botão de teste chama `GET /api/v1/me` e confirma a conexão.
23
+
24
+ ## Operações
25
+
26
+ ### Lead → Criar
27
+
28
+ `POST /api/v1/leads` — campos: Nome (obrigatório), Telefone, Email, Origem e opcionais (funil, etapa, dono, campos personalizados, UTMs, telefone duplicado). O lead cai na etapa de entrada do funil padrão quando funil/etapa não são informados.
29
+
30
+ A saída do node é o lead criado (id, nome, etapa etc.) pronto pra usar nos próximos passos do fluxo.
31
+
32
+ ## Desenvolvimento
33
+
34
+ ```bash
35
+ npm install
36
+ npm run build # tsc + cópia de ícones pro dist/
37
+ ```
38
+
39
+ O `dist/` fica commitado pra permitir instalação direta pelo tarball do GitHub, sem build no servidor.
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SalviaApi = void 0;
4
+ /**
5
+ * Credencial do Salvia CRM: chave da API (Ajustes → Central de Integrações →
6
+ * Desenvolvedores) enviada como Bearer token. A Base URL permite apontar pro
7
+ * ambiente de teste (preview) sem mexer nos fluxos.
8
+ */
9
+ class SalviaApi {
10
+ constructor() {
11
+ this.name = "salviaApi";
12
+ this.displayName = "Salvia API";
13
+ this.documentationUrl = "https://salviacrm.com.br";
14
+ this.properties = [
15
+ {
16
+ displayName: "Base URL",
17
+ name: "baseUrl",
18
+ type: "string",
19
+ default: "https://salviacrm.com.br",
20
+ description: "Endereço do Salvia. Pra testar, use a URL do ambiente de teste (preview).",
21
+ },
22
+ {
23
+ displayName: "API Key",
24
+ name: "apiKey",
25
+ type: "string",
26
+ typeOptions: { password: true },
27
+ default: "",
28
+ description: "Gerada no Salvia em Ajustes → Central de Integrações → Desenvolvedores.",
29
+ },
30
+ ];
31
+ this.authenticate = {
32
+ type: "generic",
33
+ properties: {
34
+ headers: {
35
+ Authorization: "=Bearer {{$credentials.apiKey}}",
36
+ },
37
+ },
38
+ };
39
+ this.test = {
40
+ request: {
41
+ baseURL: "={{$credentials.baseUrl}}",
42
+ url: "/api/v1/me",
43
+ },
44
+ };
45
+ }
46
+ }
47
+ exports.SalviaApi = SalviaApi;
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Salvia = void 0;
4
+ /**
5
+ * Node declarativo do Salvia CRM. Sem método execute: o roteamento REST fica
6
+ * todo na descrição — menos código, mesma robustez dos nodes oficiais.
7
+ *
8
+ * Operações:
9
+ * Lead → Criar (POST /api/v1/leads)
10
+ *
11
+ * A resposta da API vem em { data: {...} } — o postReceive desembrulha pro
12
+ * item de saída ser o lead direto.
13
+ */
14
+ class Salvia {
15
+ constructor() {
16
+ this.description = {
17
+ displayName: "Salvia",
18
+ name: "salvia",
19
+ icon: "file:salvia.svg",
20
+ group: ["transform"],
21
+ version: 1,
22
+ subtitle: '={{ $parameter["operation"] + ": " + $parameter["resource"] }}',
23
+ description: "Interage com o Salvia CRM (leads, funil, atendimento)",
24
+ defaults: {
25
+ name: "Salvia",
26
+ },
27
+ // Literal "main" compila em qualquer versão do n8n-workflow (o enum
28
+ // NodeConnectionType virou type-only em versões recentes).
29
+ inputs: ["main"],
30
+ outputs: ["main"],
31
+ usableAsTool: true,
32
+ credentials: [
33
+ {
34
+ name: "salviaApi",
35
+ required: true,
36
+ },
37
+ ],
38
+ requestDefaults: {
39
+ baseURL: "={{ $credentials.baseUrl }}",
40
+ headers: {
41
+ "Content-Type": "application/json",
42
+ },
43
+ },
44
+ properties: [
45
+ {
46
+ displayName: "Recurso",
47
+ name: "resource",
48
+ type: "options",
49
+ noDataExpression: true,
50
+ options: [{ name: "Lead", value: "lead" }],
51
+ default: "lead",
52
+ },
53
+ {
54
+ displayName: "Operação",
55
+ name: "operation",
56
+ type: "options",
57
+ noDataExpression: true,
58
+ displayOptions: { show: { resource: ["lead"] } },
59
+ options: [
60
+ {
61
+ name: "Criar",
62
+ value: "create",
63
+ action: "Criar um lead",
64
+ description: "Cria um lead no funil (etapa de entrada do funil padrão, salvo se você indicar outra)",
65
+ routing: {
66
+ request: {
67
+ method: "POST",
68
+ url: "/api/v1/leads",
69
+ },
70
+ output: {
71
+ postReceive: [
72
+ {
73
+ type: "rootProperty",
74
+ properties: { property: "data" },
75
+ },
76
+ ],
77
+ },
78
+ },
79
+ },
80
+ ],
81
+ default: "create",
82
+ },
83
+ // ── Campos do Criar Lead ──
84
+ {
85
+ displayName: "Nome",
86
+ name: "name",
87
+ type: "string",
88
+ required: true,
89
+ default: "",
90
+ placeholder: "Maria Souza",
91
+ displayOptions: { show: { resource: ["lead"], operation: ["create"] } },
92
+ routing: { send: { type: "body", property: "name" } },
93
+ },
94
+ {
95
+ displayName: "Telefone",
96
+ name: "phone",
97
+ type: "string",
98
+ default: "",
99
+ placeholder: "+55 71 99999-9999",
100
+ description: "Com DDD. Aceita formato nacional ou internacional.",
101
+ displayOptions: { show: { resource: ["lead"], operation: ["create"] } },
102
+ routing: { send: { type: "body", property: "phone" } },
103
+ },
104
+ {
105
+ displayName: "Email",
106
+ name: "email",
107
+ type: "string",
108
+ default: "",
109
+ placeholder: "maria@email.com",
110
+ displayOptions: { show: { resource: ["lead"], operation: ["create"] } },
111
+ routing: { send: { type: "body", property: "email" } },
112
+ },
113
+ {
114
+ displayName: "Origem",
115
+ name: "origin",
116
+ type: "string",
117
+ default: "",
118
+ placeholder: "instagram-ads",
119
+ description: "De onde o lead veio (aparece na ficha e nas métricas)",
120
+ displayOptions: { show: { resource: ["lead"], operation: ["create"] } },
121
+ routing: { send: { type: "body", property: "origin" } },
122
+ },
123
+ {
124
+ displayName: "Opções adicionais",
125
+ name: "additionalFields",
126
+ type: "collection",
127
+ placeholder: "Adicionar campo",
128
+ default: {},
129
+ displayOptions: { show: { resource: ["lead"], operation: ["create"] } },
130
+ options: [
131
+ {
132
+ displayName: "Funil (pipelineId)",
133
+ name: "pipelineId",
134
+ type: "string",
135
+ default: "",
136
+ description: "UUID do funil de destino (opcional)",
137
+ routing: { send: { type: "body", property: "pipelineId" } },
138
+ },
139
+ {
140
+ displayName: "Etapa (stageId)",
141
+ name: "stageId",
142
+ type: "string",
143
+ default: "",
144
+ description: "UUID da etapa de destino (opcional)",
145
+ routing: { send: { type: "body", property: "stageId" } },
146
+ },
147
+ {
148
+ displayName: "Dono (email do atendente)",
149
+ name: "ownerEmail",
150
+ type: "string",
151
+ default: "",
152
+ description: "Email de um usuário do Salvia que vira dono do lead",
153
+ routing: { send: { type: "body", property: "ownerEmail" } },
154
+ },
155
+ {
156
+ displayName: "Campos personalizados (JSON)",
157
+ name: "customFields",
158
+ type: "json",
159
+ default: "{}",
160
+ description: 'Ex.: {"convenio": "Unimed", "procedimento": "Botox"}',
161
+ routing: {
162
+ send: {
163
+ type: "body",
164
+ property: "customFields",
165
+ value: "={{ typeof $value === 'string' ? JSON.parse($value || '{}') : $value }}",
166
+ },
167
+ },
168
+ },
169
+ {
170
+ displayName: "UTM Source",
171
+ name: "utmSource",
172
+ type: "string",
173
+ default: "",
174
+ routing: { send: { type: "body", property: "utmSource" } },
175
+ },
176
+ {
177
+ displayName: "UTM Medium",
178
+ name: "utmMedium",
179
+ type: "string",
180
+ default: "",
181
+ routing: { send: { type: "body", property: "utmMedium" } },
182
+ },
183
+ {
184
+ displayName: "UTM Campaign",
185
+ name: "utmCampaign",
186
+ type: "string",
187
+ default: "",
188
+ routing: { send: { type: "body", property: "utmCampaign" } },
189
+ },
190
+ {
191
+ displayName: "Permitir telefone duplicado",
192
+ name: "forceDuplicate",
193
+ type: "boolean",
194
+ default: false,
195
+ description: "Se desligado (padrão), telefone já cadastrado devolve erro com o ID do lead existente",
196
+ routing: { send: { type: "body", property: "forceDuplicate" } },
197
+ },
198
+ ],
199
+ },
200
+ ],
201
+ };
202
+ }
203
+ }
204
+ exports.Salvia = Salvia;
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60">
2
+ <defs>
3
+ <linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
4
+ <stop offset="0" stop-color="#7C3AED"/>
5
+ <stop offset="1" stop-color="#A855F7"/>
6
+ </linearGradient>
7
+ </defs>
8
+ <rect width="60" height="60" rx="14" fill="#0B1220"/>
9
+ <path d="M30 10c8 6 12 13 12 21 0 8-5 15-12 19-7-4-12-11-12-19 0-8 4-15 12-21z" fill="url(#g)"/>
10
+ <path d="M30 14v32" stroke="#0B1220" stroke-width="2.4" stroke-linecap="round"/>
11
+ <path d="M30 24c-3-1-6-4-7-8M30 32c3-1 6-4 7-8" stroke="#0B1220" stroke-width="2.4" stroke-linecap="round" fill="none"/>
12
+ </svg>
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "n8n-nodes-salvia",
3
+ "version": "0.1.0",
4
+ "description": "Nodes do Salvia CRM para n8n — crie leads e integre sua clínica aos seus fluxos.",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "salvia",
8
+ "crm",
9
+ "whatsapp"
10
+ ],
11
+ "license": "MIT",
12
+ "author": "MovMed <pedro@grupomovmed.com.br>",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/Projetos-Mov/n8n-nodes-salvia.git"
16
+ },
17
+ "main": "index.js",
18
+ "scripts": {
19
+ "build": "tsc && node scripts/copy-assets.js"
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "n8n": {
25
+ "n8nNodesApiVersion": 1,
26
+ "credentials": [
27
+ "dist/credentials/SalviaApi.credentials.js"
28
+ ],
29
+ "nodes": [
30
+ "dist/nodes/Salvia/Salvia.node.js"
31
+ ]
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^20.14.0",
35
+ "n8n-workflow": "^1.70.0",
36
+ "typescript": "^5.5.0"
37
+ },
38
+ "peerDependencies": {
39
+ "n8n-workflow": "*"
40
+ }
41
+ }