@jebcode-dev/jebcode-tunnel 1.0.0 → 1.0.4
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/LICENSE +9 -9
- package/README.md +71 -71
- package/bin.js +47 -47
- package/index.js +249 -249
- package/package.json +8 -2
- package/.github/workflows/publicar.yml +0 -20
- package/editora.md +0 -40
- package/img/image copy.png +0 -0
- package/img/image.png +0 -0
package/LICENSE
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Licença MIT
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 JEBCODE SOFTWARE E TECNOLOGIA LTDA
|
|
4
|
-
|
|
5
|
-
A permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma cópia deste software e dos arquivos de documentação associados (o "Software"), para lidar com o Software sem restrições, incluindo, sem limitação, os direitos de usar, copiar, modificar, mesclar, publicar, distribuir, sublicenciar e/ou vender cópias do Software, e permitir que as pessoas a quem o Software é fornecido o façam, sujeito às seguintes condições:
|
|
6
|
-
|
|
7
|
-
O aviso de copyright acima e este aviso de permissão devem ser incluídos em todas as cópias ou partes substanciais do Software.
|
|
8
|
-
|
|
9
|
-
O SOFTWARE É FORNECIDO "COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO ÀS GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UM DETERMINADO FIM E NÃO VIOLAÇÃO. EM NENHUM CASO OS AUTORES OU DETENTORES DE DIREITOS DE AUTOR SERÃO RESPONSÁVEIS POR QUALQUER RECLAMAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM UMA AÇÃO DE CONTRATO, ILÍCITO OU DE OUTRA FORMA, DECORRENTE DE, FORA DE OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTRAS NEGOCIAÇÕES NO SOFTWARE.
|
|
1
|
+
Licença MIT
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JEBCODE SOFTWARE E TECNOLOGIA LTDA
|
|
4
|
+
|
|
5
|
+
A permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma cópia deste software e dos arquivos de documentação associados (o "Software"), para lidar com o Software sem restrições, incluindo, sem limitação, os direitos de usar, copiar, modificar, mesclar, publicar, distribuir, sublicenciar e/ou vender cópias do Software, e permitir que as pessoas a quem o Software é fornecido o façam, sujeito às seguintes condições:
|
|
6
|
+
|
|
7
|
+
O aviso de copyright acima e este aviso de permissão devem ser incluídos em todas as cópias ou partes substanciais do Software.
|
|
8
|
+
|
|
9
|
+
O SOFTWARE É FORNECIDO "COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO ÀS GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UM DETERMINADO FIM E NÃO VIOLAÇÃO. EM NENHUM CASO OS AUTORES OU DETENTORES DE DIREITOS DE AUTOR SERÃO RESPONSÁVEIS POR QUALQUER RECLAMAÇÃO, DANOS OU OUTRA RESPONSABILIDADE, SEJA EM UMA AÇÃO DE CONTRATO, ILÍCITO OU DE OUTRA FORMA, DECORRENTE DE, FORA DE OU EM CONEXÃO COM O SOFTWARE OU O USO OU OUTRAS NEGOCIAÇÕES NO SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,71 +1,71 @@
|
|
|
1
|
-
```text
|
|
2
|
-
██╗███████╗██████╗ ██████╗ ██████╗ ██████╗ ███████╗
|
|
3
|
-
██║██╔════╝██╔══██╗██╔════╝ ██╔═══██╗██╔══██╗██╔════╝
|
|
4
|
-
██║█████╗ ██████╔╝██║ ██║ ██║██║ ██║█████╗
|
|
5
|
-
██╗ ██║██╔══╝ ██╔══██╗██║ ██║ ██║██║ ██║██╔══╝
|
|
6
|
-
╚██████╔╝███████╗██████╔╝╚██████╗ ╚██████╔╝██████╔╝███████╗ ®
|
|
7
|
-
╚═════╝ ╚══════╝╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
|
8
|
-
Infraestrutura de Tunelamento de Alta Performance
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
# 🚀 JebCode Tunnel CLI
|
|
12
|
-
|
|
13
|
-
Interface de linha de comando oficial da **JebCode Software e Tecnologia LTDA** para expor seus serviços locais ao mundo.
|
|
14
|
-
|
|
15
|
-
## 💾 Instalação
|
|
16
|
-
|
|
17
|
-
Para utilizar o CLI em qualquer lugar do seu sistema:
|
|
18
|
-
```bash
|
|
19
|
-
npm install -g "@jebcode-dev/jebcode-tunnel"
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## 🛠️ Comandos Principais
|
|
23
|
-
|
|
24
|
-
### 1. Login
|
|
25
|
-
Autenticação interativa com e-mail e senha.
|
|
26
|
-
```bash
|
|
27
|
-
jebcode-tunnel login
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### 2. Authtoken (Manual)
|
|
31
|
-
Configura seu token manualmente se preferir.
|
|
32
|
-
```bash
|
|
33
|
-
jebcode-tunnel authtoken <seu_token>
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### 3. Inicializar Túnel
|
|
37
|
-
Inicia o encaminhamento de tráfego para uma porta local.
|
|
38
|
-
```bash
|
|
39
|
-
jebcode-tunnel http 3000
|
|
40
|
-
```
|
|
41
|
-
*Dica: Use `--subdomain projeto-x` para usar um subdomínio específico.*
|
|
42
|
-
|
|
43
|
-
### 4. Verificar Status
|
|
44
|
-
Visualize sua versão, estado de autenticação e servidor.
|
|
45
|
-
```bash
|
|
46
|
-
jebcode-tunnel status
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### 5. Logout
|
|
50
|
-
Remove as credenciais e encerra a sessão local.
|
|
51
|
-
```bash
|
|
52
|
-
jebcode-tunnel logout
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## 📦 Desenvolvimento
|
|
58
|
-
|
|
59
|
-
Para instalar as dependências:
|
|
60
|
-
```bash
|
|
61
|
-
npm install
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Para vincular o comando globalmente durante o desenvolvimento:
|
|
65
|
-
```bash
|
|
66
|
-
npm link
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
© 2026 JEBCODE SOFTWARE E TECNOLOGIA LTDA.
|
|
71
|
-
**JebCode Infrastructure v1.0.
|
|
1
|
+
```text
|
|
2
|
+
██╗███████╗██████╗ ██████╗ ██████╗ ██████╗ ███████╗
|
|
3
|
+
██║██╔════╝██╔══██╗██╔════╝ ██╔═══██╗██╔══██╗██╔════╝
|
|
4
|
+
██║█████╗ ██████╔╝██║ ██║ ██║██║ ██║█████╗
|
|
5
|
+
██╗ ██║██╔══╝ ██╔══██╗██║ ██║ ██║██║ ██║██╔══╝
|
|
6
|
+
╚██████╔╝███████╗██████╔╝╚██████╗ ╚██████╔╝██████╔╝███████╗ ®
|
|
7
|
+
╚═════╝ ╚══════╝╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
|
8
|
+
Infraestrutura de Tunelamento de Alta Performance
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
# 🚀 JebCode Tunnel CLI
|
|
12
|
+
|
|
13
|
+
Interface de linha de comando oficial da **JebCode Software e Tecnologia LTDA** para expor seus serviços locais ao mundo.
|
|
14
|
+
|
|
15
|
+
## 💾 Instalação
|
|
16
|
+
|
|
17
|
+
Para utilizar o CLI em qualquer lugar do seu sistema:
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g "@jebcode-dev/jebcode-tunnel"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 🛠️ Comandos Principais
|
|
23
|
+
|
|
24
|
+
### 1. Login
|
|
25
|
+
Autenticação interativa com e-mail e senha.
|
|
26
|
+
```bash
|
|
27
|
+
jebcode-tunnel login
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 2. Authtoken (Manual)
|
|
31
|
+
Configura seu token manualmente se preferir.
|
|
32
|
+
```bash
|
|
33
|
+
jebcode-tunnel authtoken <seu_token>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 3. Inicializar Túnel
|
|
37
|
+
Inicia o encaminhamento de tráfego para uma porta local.
|
|
38
|
+
```bash
|
|
39
|
+
jebcode-tunnel http 3000
|
|
40
|
+
```
|
|
41
|
+
*Dica: Use `--subdomain projeto-x` para usar um subdomínio específico.*
|
|
42
|
+
|
|
43
|
+
### 4. Verificar Status
|
|
44
|
+
Visualize sua versão, estado de autenticação e servidor.
|
|
45
|
+
```bash
|
|
46
|
+
jebcode-tunnel status
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 5. Logout
|
|
50
|
+
Remove as credenciais e encerra a sessão local.
|
|
51
|
+
```bash
|
|
52
|
+
jebcode-tunnel logout
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 📦 Desenvolvimento
|
|
58
|
+
|
|
59
|
+
Para instalar as dependências:
|
|
60
|
+
```bash
|
|
61
|
+
npm install
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Para vincular o comando globalmente durante o desenvolvimento:
|
|
65
|
+
```bash
|
|
66
|
+
npm link
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
© 2026 JEBCODE SOFTWARE E TECNOLOGIA LTDA.
|
|
71
|
+
**JebCode Infrastructure v1.0.3**
|
package/bin.js
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const { program } = require("commander");
|
|
4
|
-
const { version } = require("./package.json");
|
|
5
|
-
const { authtoken, startTunnel, showStatus, login, logout } = require("./index");
|
|
6
|
-
|
|
7
|
-
program
|
|
8
|
-
.name("jebcode-tunnel")
|
|
9
|
-
.description("CLI para expor seu serviço local ao mundo via JebCode Tunnel")
|
|
10
|
-
.version(version);
|
|
11
|
-
|
|
12
|
-
program
|
|
13
|
-
.command("login")
|
|
14
|
-
.description("Realiza login com e-mail e senha")
|
|
15
|
-
.action(login);
|
|
16
|
-
|
|
17
|
-
program
|
|
18
|
-
.command("logout")
|
|
19
|
-
.description("Remove as credenciais locais")
|
|
20
|
-
.action(logout);
|
|
21
|
-
|
|
22
|
-
program
|
|
23
|
-
.command("authtoken")
|
|
24
|
-
.description("Salva sua API Key do JebCode Tunnel localmente")
|
|
25
|
-
.argument("<token>", "Sua API Key encontrada no Dashboard")
|
|
26
|
-
.action(authtoken);
|
|
27
|
-
|
|
28
|
-
program
|
|
29
|
-
.command("status")
|
|
30
|
-
.description("Exibe o status atual da configuração e autenticação")
|
|
31
|
-
.action(showStatus);
|
|
32
|
-
|
|
33
|
-
program
|
|
34
|
-
.command("http")
|
|
35
|
-
.description("Inicia um túnel HTTP para uma porta local")
|
|
36
|
-
.argument("<port>", "Porta local (ex: 3000)")
|
|
37
|
-
.option("-s, --subdomain <name>", "Subdomínio customizado já criado no Dashboard")
|
|
38
|
-
.option("-i, --insecure", "Ignorar verificação de certificado SSL (útil para testes locais)", false)
|
|
39
|
-
.action((port, options) => {
|
|
40
|
-
startTunnel(port, options);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// Handle global help if no command is provided
|
|
44
|
-
if (!process.argv.slice(2).length) {
|
|
45
|
-
program.outputHelp();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
program.parse();
|
|
2
|
+
|
|
3
|
+
const { program } = require("commander");
|
|
4
|
+
const { version } = require("./package.json");
|
|
5
|
+
const { authtoken, startTunnel, showStatus, login, logout } = require("./index");
|
|
6
|
+
|
|
7
|
+
program
|
|
8
|
+
.name("jebcode-tunnel")
|
|
9
|
+
.description("CLI para expor seu serviço local ao mundo via JebCode Tunnel")
|
|
10
|
+
.version(version);
|
|
11
|
+
|
|
12
|
+
program
|
|
13
|
+
.command("login")
|
|
14
|
+
.description("Realiza login com e-mail e senha")
|
|
15
|
+
.action(login);
|
|
16
|
+
|
|
17
|
+
program
|
|
18
|
+
.command("logout")
|
|
19
|
+
.description("Remove as credenciais locais")
|
|
20
|
+
.action(logout);
|
|
21
|
+
|
|
22
|
+
program
|
|
23
|
+
.command("authtoken")
|
|
24
|
+
.description("Salva sua API Key do JebCode Tunnel localmente")
|
|
25
|
+
.argument("<token>", "Sua API Key encontrada no Dashboard")
|
|
26
|
+
.action(authtoken);
|
|
27
|
+
|
|
28
|
+
program
|
|
29
|
+
.command("status")
|
|
30
|
+
.description("Exibe o status atual da configuração e autenticação")
|
|
31
|
+
.action(showStatus);
|
|
32
|
+
|
|
33
|
+
program
|
|
34
|
+
.command("http")
|
|
35
|
+
.description("Inicia um túnel HTTP para uma porta local")
|
|
36
|
+
.argument("<port>", "Porta local (ex: 3000)")
|
|
37
|
+
.option("-s, --subdomain <name>", "Subdomínio customizado já criado no Dashboard")
|
|
38
|
+
.option("-i, --insecure", "Ignorar verificação de certificado SSL (útil para testes locais)", false)
|
|
39
|
+
.action((port, options) => {
|
|
40
|
+
startTunnel(port, options);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Handle global help if no command is provided
|
|
44
|
+
if (!process.argv.slice(2).length) {
|
|
45
|
+
program.outputHelp();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
program.parse();
|
package/index.js
CHANGED
|
@@ -1,249 +1,249 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
const os = require("os");
|
|
4
|
-
const io = require("socket.io-client");
|
|
5
|
-
const axios = require("axios");
|
|
6
|
-
const chalk = require("chalk");
|
|
7
|
-
const inquirer = require("inquirer");
|
|
8
|
-
const { version } = require("./package.json");
|
|
9
|
-
|
|
10
|
-
const CONFIG_PATH = path.join(os.homedir(), ".jebcode-tunnel");
|
|
11
|
-
const SERVER_URL = process.env.JEB_SERVER_URL || "https://jebcodetunnel.com";
|
|
12
|
-
|
|
13
|
-
function getHeader() {
|
|
14
|
-
return chalk.bold.blue(`
|
|
15
|
-
██╗███████╗██████╗ ██████╗ ██████╗ ██████╗ ███████╗
|
|
16
|
-
██║██╔════╝██╔══██╗██╔════╝ ██╔═══██╗██╔══██╗██╔════╝
|
|
17
|
-
██║█████╗ ██████╔╝██║ ██║ ██║██║ ██║█████╗
|
|
18
|
-
██╗ ██║██╔══╝ ██╔══██╗██║ ██║ ██║██║ ██║██╔══╝
|
|
19
|
-
╚██████╔╝███████╗██████╔╝╚██████╗ ╚██████╔╝██████╔╝███████╗ ®
|
|
20
|
-
╚═════╝ ╚══════╝╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
|
21
|
-
${chalk.italic("Infraestrutura de Tunelamento de Alta Performance")}
|
|
22
|
-
`);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async function login() {
|
|
26
|
-
console.log(getHeader());
|
|
27
|
-
console.log(chalk.white(" ENTRAR NA SUA CONTA JEBCODE:\n"));
|
|
28
|
-
|
|
29
|
-
const answers = await inquirer.prompt([
|
|
30
|
-
{
|
|
31
|
-
type: "input",
|
|
32
|
-
name: "email",
|
|
33
|
-
message: "E-mail:",
|
|
34
|
-
validate: (input) => input.includes("@") || "Por favor, insira um e-mail válido."
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
type: "password",
|
|
38
|
-
name: "password",
|
|
39
|
-
message: "Senha:",
|
|
40
|
-
mask: "*"
|
|
41
|
-
}
|
|
42
|
-
]);
|
|
43
|
-
|
|
44
|
-
process.stdout.write(chalk.blue("\n ☁ Autenticando... "));
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
const response = await axios.post(`${SERVER_URL}/api/cli/login`, {
|
|
48
|
-
email: answers.email,
|
|
49
|
-
password: answers.password
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const { api_key } = response.data;
|
|
53
|
-
process.stdout.write(chalk.green("OK\n"));
|
|
54
|
-
|
|
55
|
-
fs.writeFileSync(CONFIG_PATH, JSON.stringify({ token: api_key }));
|
|
56
|
-
console.log(chalk.green("\n ✔ Login realizado com sucesso!"));
|
|
57
|
-
console.log(chalk.gray(` Token salvo e pronto para uso.\n`));
|
|
58
|
-
} catch (err) {
|
|
59
|
-
process.stdout.write(chalk.red("FALHOU\n"));
|
|
60
|
-
const errorMsg = err.response?.data?.error || err.message;
|
|
61
|
-
console.error(chalk.red(" ✖ Erro:"), errorMsg);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function logout() {
|
|
66
|
-
if (fs.existsSync(CONFIG_PATH)) {
|
|
67
|
-
fs.unlinkSync(CONFIG_PATH);
|
|
68
|
-
console.log(getHeader());
|
|
69
|
-
console.log(chalk.green("\n ✔ Logout realizado com sucesso. Até logo!"));
|
|
70
|
-
console.log(chalk.gray(" Configurações locais removidas.\n"));
|
|
71
|
-
} else {
|
|
72
|
-
console.log(chalk.yellow("\n ⚠ Você não está logado atualmente."));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function authtoken(token) {
|
|
77
|
-
try {
|
|
78
|
-
fs.writeFileSync(CONFIG_PATH, JSON.stringify({ token }));
|
|
79
|
-
console.log("\n" + getHeader());
|
|
80
|
-
console.log(chalk.green(" ✔ Authtoken salvo com sucesso!"));
|
|
81
|
-
console.log(chalk.gray(` Configurado em: ${CONFIG_PATH}\n`));
|
|
82
|
-
} catch (err) {
|
|
83
|
-
console.error(chalk.red(" ✖ Erro ao salvar authtoken:"), err.message);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function showStatus() {
|
|
88
|
-
console.log(getHeader());
|
|
89
|
-
|
|
90
|
-
if (fs.existsSync(CONFIG_PATH)) {
|
|
91
|
-
try {
|
|
92
|
-
const config = JSON.parse(fs.readFileSync(CONFIG_PATH));
|
|
93
|
-
if (config.token) {
|
|
94
|
-
const maskedToken = config.token.substring(0, 8) + "•".repeat(24);
|
|
95
|
-
console.log(chalk.white("\n STATUS DA CONEXÃO"));
|
|
96
|
-
console.log(chalk.blue(" ▪"), chalk.bold("Versão: "), chalk.yellow(`v${version}`));
|
|
97
|
-
console.log(chalk.blue(" ▪"), chalk.bold("Autenticado:"), chalk.green("SIM"));
|
|
98
|
-
console.log(chalk.blue(" ▪"), chalk.bold("Token: "), chalk.gray(maskedToken));
|
|
99
|
-
console.log(chalk.blue(" ▪"), chalk.bold("Servidor: "), chalk.cyan(SERVER_URL));
|
|
100
|
-
console.log(chalk.blue(" ▪"), chalk.bold("Config: "), chalk.gray(CONFIG_PATH));
|
|
101
|
-
console.log(chalk.gray("\n © 2026 JEBCODE SOFTWARE E TECNOLOGIA LTDA\n"));
|
|
102
|
-
} else {
|
|
103
|
-
console.log(chalk.yellow("\n ⚠ Token não encontrado no arquivo de configuração."));
|
|
104
|
-
}
|
|
105
|
-
} catch (e) {
|
|
106
|
-
console.error(chalk.red("\n ✖ Erro ao ler configuração:"), e.message);
|
|
107
|
-
}
|
|
108
|
-
} else {
|
|
109
|
-
console.log(chalk.white("\n STATUS DA CONEXÃO"));
|
|
110
|
-
console.log(chalk.blue(" ▪"), chalk.bold("Autenticado:"), chalk.red("NÃO"));
|
|
111
|
-
console.log(chalk.gray("\n Use 'jebcode-tunnel login' or 'jebcode-tunnel authtoken <token>' para começar.\n"));
|
|
112
|
-
console.log(chalk.gray(" © 2026 JEBCODE SOFTWARE E TECNOLOGIA LTDA\n"));
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function startTunnel(port, options = {}) {
|
|
117
|
-
let config = {};
|
|
118
|
-
if (fs.existsSync(CONFIG_PATH)) {
|
|
119
|
-
try {
|
|
120
|
-
config = JSON.parse(fs.readFileSync(CONFIG_PATH));
|
|
121
|
-
} catch (e) {
|
|
122
|
-
console.error(chalk.red(" ✖ Erro no arquivo de config:"), e.message);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (!config.token) {
|
|
127
|
-
console.log(getHeader());
|
|
128
|
-
console.error(chalk.red(" ✖ Erro: Authtoken não configurado."));
|
|
129
|
-
console.log(chalk.gray(" Obtenha seu token no Dashboard: https://jebcodetunnel.com/dashboard"));
|
|
130
|
-
console.log(chalk.gray(`\n Use: ${chalk.bold("jebcode-tunnel login")} ou ${chalk.bold("jebcode-tunnel authtoken <token>")}\n`));
|
|
131
|
-
process.exit(1);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const subdomain = options.subdomain || "dev";
|
|
135
|
-
const insecure = options.insecure || false;
|
|
136
|
-
|
|
137
|
-
process.stdout.write(chalk.blue(" ☁ Conectando à infraestrutura JebCode... "));
|
|
138
|
-
|
|
139
|
-
const socket = io(SERVER_URL, {
|
|
140
|
-
transports: ["websocket", "polling"],
|
|
141
|
-
reconnectionAttempts: 10,
|
|
142
|
-
timeout: 15000,
|
|
143
|
-
rejectUnauthorized: !insecure,
|
|
144
|
-
pingInterval: 10000,
|
|
145
|
-
pingTimeout: 5000
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
socket.on("connect", () => {
|
|
149
|
-
process.stdout.write(chalk.green("OK\n"));
|
|
150
|
-
socket.emit("authenticate", { token: config.token, subdomain });
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
socket.on("auth_result", (result) => {
|
|
154
|
-
if (result.success) {
|
|
155
|
-
console.clear();
|
|
156
|
-
console.log(getHeader());
|
|
157
|
-
console.log(chalk.white(" STATUS DO TÚNEL ATIVO"));
|
|
158
|
-
console.log(chalk.blue(" ▪"), chalk.bold("URL Pública: "), chalk.yellow(`https://${subdomain}.jebcodetunnel.com`));
|
|
159
|
-
console.log(chalk.blue(" ▪"), chalk.bold("Encaminhando:"), chalk.white(`http://localhost:${port}`), chalk.gray("➔"), chalk.cyan("jeb-gateway"));
|
|
160
|
-
console.log(chalk.blue(" ▪"), chalk.bold("Dashboard: "), chalk.gray(`${SERVER_URL}/dashboard`));
|
|
161
|
-
|
|
162
|
-
console.log(chalk.gray("\n Pressione CTRL+C para encerrar o túnel"));
|
|
163
|
-
console.log(chalk.white("\n LOGS DE TRÁFEGO EM TEMPO REAL:"));
|
|
164
|
-
console.log(chalk.gray(" " + "─".repeat(60)));
|
|
165
|
-
} else {
|
|
166
|
-
console.log(chalk.red("\n ✖ Falha na Autenticação:"), chalk.bold(result.message));
|
|
167
|
-
console.log(chalk.gray(" Verifique seu token e se o subdomínio foi criado no dashboard.\n"));
|
|
168
|
-
process.exit(1);
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
socket.on("heartbeat_ping", () => {
|
|
173
|
-
socket.emit("heartbeat_pong");
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
socket.on("incoming_request", async (reqData) => {
|
|
177
|
-
const timestamp = new Date().toLocaleTimeString();
|
|
178
|
-
const methodColor = reqData.method === "GET" ? chalk.green : reqData.method === "POST" ? chalk.blue : chalk.yellow;
|
|
179
|
-
|
|
180
|
-
// Log imediato para feedback instantâneo no terminal
|
|
181
|
-
const startLog = `${chalk.gray(` [${timestamp}]`)} ${methodColor(reqData.method.padEnd(7))} ${chalk.white(reqData.path.substring(0, 30).padEnd(30))} ${chalk.yellow("PROCESSANDO...")}`;
|
|
182
|
-
process.stdout.write(startLog);
|
|
183
|
-
|
|
184
|
-
const startTime = Date.now();
|
|
185
|
-
try {
|
|
186
|
-
const response = await axios({
|
|
187
|
-
method: reqData.method,
|
|
188
|
-
url: `http://localhost:${port}${reqData.path}`,
|
|
189
|
-
headers: { ...reqData.headers, host: `localhost:${port}` },
|
|
190
|
-
data: reqData.body ? Buffer.from(reqData.body, "base64") : undefined,
|
|
191
|
-
responseType: "arraybuffer",
|
|
192
|
-
validateStatus: () => true,
|
|
193
|
-
timeout: 10000
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
const duration = Date.now() - startTime;
|
|
197
|
-
const statusColor = response.status < 300 ? chalk.green : response.status < 400 ? chalk.cyan : chalk.red;
|
|
198
|
-
|
|
199
|
-
// Limpa a linha atual e sobrescreve com o log final
|
|
200
|
-
if (process.stdout.isTTY) {
|
|
201
|
-
process.stdout.clearLine(0);
|
|
202
|
-
process.stdout.cursorTo(0);
|
|
203
|
-
} else {
|
|
204
|
-
process.stdout.write("\n");
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const logLine = [
|
|
208
|
-
chalk.gray(` [${timestamp}]`),
|
|
209
|
-
methodColor(reqData.method.padEnd(7)),
|
|
210
|
-
chalk.white(reqData.path.substring(0, 30).padEnd(30)),
|
|
211
|
-
statusColor(response.status.toString().padStart(3)),
|
|
212
|
-
chalk.gray(`${duration.toString().padStart(5)}ms`)
|
|
213
|
-
].join(" ");
|
|
214
|
-
|
|
215
|
-
console.log(logLine);
|
|
216
|
-
|
|
217
|
-
socket.emit(`response_${reqData.id}`, {
|
|
218
|
-
status: response.status,
|
|
219
|
-
headers: response.headers,
|
|
220
|
-
body: Buffer.from(response.data).toString("base64"),
|
|
221
|
-
});
|
|
222
|
-
} catch (err) {
|
|
223
|
-
const duration = Date.now() - startTime;
|
|
224
|
-
if (process.stdout.isTTY) {
|
|
225
|
-
process.stdout.clearLine(0);
|
|
226
|
-
process.stdout.cursorTo(0);
|
|
227
|
-
} else {
|
|
228
|
-
process.stdout.write("\n");
|
|
229
|
-
}
|
|
230
|
-
console.log(`${chalk.gray(` [${timestamp}]`)} ${methodColor(reqData.method.padEnd(7))} ${chalk.white(reqData.path.substring(0, 30).padEnd(30))} ${chalk.red("FALHOU")} ${chalk.gray(`${duration}ms`)}`);
|
|
231
|
-
|
|
232
|
-
socket.emit(`response_${reqData.id}`, {
|
|
233
|
-
status: 502,
|
|
234
|
-
headers: { "Content-Type": "text/plain" },
|
|
235
|
-
body: Buffer.from(`JebCode Gateway Error: Erro ao conectar no localhost:${port}. O serviço está rodando?`).toString("base64"),
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
socket.on("disconnect", () => {
|
|
241
|
-
console.log(chalk.yellow("\n ⚠ Conexão perdida. Tentando reconectar..."));
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
socket.on("connect_error", (err) => {
|
|
245
|
-
console.error(chalk.red("\n ✖ Erro Crítico de Conexão:"), err.message);
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
module.exports = { authtoken, startTunnel, showStatus, login, logout };
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const os = require("os");
|
|
4
|
+
const io = require("socket.io-client");
|
|
5
|
+
const axios = require("axios");
|
|
6
|
+
const chalk = require("chalk");
|
|
7
|
+
const inquirer = require("inquirer");
|
|
8
|
+
const { version } = require("./package.json");
|
|
9
|
+
|
|
10
|
+
const CONFIG_PATH = path.join(os.homedir(), ".jebcode-tunnel");
|
|
11
|
+
const SERVER_URL = process.env.JEB_SERVER_URL || "https://jebcodetunnel.com";
|
|
12
|
+
|
|
13
|
+
function getHeader() {
|
|
14
|
+
return chalk.bold.blue(`
|
|
15
|
+
██╗███████╗██████╗ ██████╗ ██████╗ ██████╗ ███████╗
|
|
16
|
+
██║██╔════╝██╔══██╗██╔════╝ ██╔═══██╗██╔══██╗██╔════╝
|
|
17
|
+
██║█████╗ ██████╔╝██║ ██║ ██║██║ ██║█████╗
|
|
18
|
+
██╗ ██║██╔══╝ ██╔══██╗██║ ██║ ██║██║ ██║██╔══╝
|
|
19
|
+
╚██████╔╝███████╗██████╔╝╚██████╗ ╚██████╔╝██████╔╝███████╗ ®
|
|
20
|
+
╚═════╝ ╚══════╝╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
|
21
|
+
${chalk.italic("Infraestrutura de Tunelamento de Alta Performance")}
|
|
22
|
+
`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function login() {
|
|
26
|
+
console.log(getHeader());
|
|
27
|
+
console.log(chalk.white(" ENTRAR NA SUA CONTA JEBCODE:\n"));
|
|
28
|
+
|
|
29
|
+
const answers = await inquirer.prompt([
|
|
30
|
+
{
|
|
31
|
+
type: "input",
|
|
32
|
+
name: "email",
|
|
33
|
+
message: "E-mail:",
|
|
34
|
+
validate: (input) => input.includes("@") || "Por favor, insira um e-mail válido."
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: "password",
|
|
38
|
+
name: "password",
|
|
39
|
+
message: "Senha:",
|
|
40
|
+
mask: "*"
|
|
41
|
+
}
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
process.stdout.write(chalk.blue("\n ☁ Autenticando... "));
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const response = await axios.post(`${SERVER_URL}/api/cli/login`, {
|
|
48
|
+
email: answers.email,
|
|
49
|
+
password: answers.password
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const { api_key } = response.data;
|
|
53
|
+
process.stdout.write(chalk.green("OK\n"));
|
|
54
|
+
|
|
55
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify({ token: api_key }));
|
|
56
|
+
console.log(chalk.green("\n ✔ Login realizado com sucesso!"));
|
|
57
|
+
console.log(chalk.gray(` Token salvo e pronto para uso.\n`));
|
|
58
|
+
} catch (err) {
|
|
59
|
+
process.stdout.write(chalk.red("FALHOU\n"));
|
|
60
|
+
const errorMsg = err.response?.data?.error || err.message;
|
|
61
|
+
console.error(chalk.red(" ✖ Erro:"), errorMsg);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function logout() {
|
|
66
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
67
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
68
|
+
console.log(getHeader());
|
|
69
|
+
console.log(chalk.green("\n ✔ Logout realizado com sucesso. Até logo!"));
|
|
70
|
+
console.log(chalk.gray(" Configurações locais removidas.\n"));
|
|
71
|
+
} else {
|
|
72
|
+
console.log(chalk.yellow("\n ⚠ Você não está logado atualmente."));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function authtoken(token) {
|
|
77
|
+
try {
|
|
78
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify({ token }));
|
|
79
|
+
console.log("\n" + getHeader());
|
|
80
|
+
console.log(chalk.green(" ✔ Authtoken salvo com sucesso!"));
|
|
81
|
+
console.log(chalk.gray(` Configurado em: ${CONFIG_PATH}\n`));
|
|
82
|
+
} catch (err) {
|
|
83
|
+
console.error(chalk.red(" ✖ Erro ao salvar authtoken:"), err.message);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function showStatus() {
|
|
88
|
+
console.log(getHeader());
|
|
89
|
+
|
|
90
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
91
|
+
try {
|
|
92
|
+
const config = JSON.parse(fs.readFileSync(CONFIG_PATH));
|
|
93
|
+
if (config.token) {
|
|
94
|
+
const maskedToken = config.token.substring(0, 8) + "•".repeat(24);
|
|
95
|
+
console.log(chalk.white("\n STATUS DA CONEXÃO"));
|
|
96
|
+
console.log(chalk.blue(" ▪"), chalk.bold("Versão: "), chalk.yellow(`v${version}`));
|
|
97
|
+
console.log(chalk.blue(" ▪"), chalk.bold("Autenticado:"), chalk.green("SIM"));
|
|
98
|
+
console.log(chalk.blue(" ▪"), chalk.bold("Token: "), chalk.gray(maskedToken));
|
|
99
|
+
console.log(chalk.blue(" ▪"), chalk.bold("Servidor: "), chalk.cyan(SERVER_URL));
|
|
100
|
+
console.log(chalk.blue(" ▪"), chalk.bold("Config: "), chalk.gray(CONFIG_PATH));
|
|
101
|
+
console.log(chalk.gray("\n © 2026 JEBCODE SOFTWARE E TECNOLOGIA LTDA\n"));
|
|
102
|
+
} else {
|
|
103
|
+
console.log(chalk.yellow("\n ⚠ Token não encontrado no arquivo de configuração."));
|
|
104
|
+
}
|
|
105
|
+
} catch (e) {
|
|
106
|
+
console.error(chalk.red("\n ✖ Erro ao ler configuração:"), e.message);
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
console.log(chalk.white("\n STATUS DA CONEXÃO"));
|
|
110
|
+
console.log(chalk.blue(" ▪"), chalk.bold("Autenticado:"), chalk.red("NÃO"));
|
|
111
|
+
console.log(chalk.gray("\n Use 'jebcode-tunnel login' or 'jebcode-tunnel authtoken <token>' para começar.\n"));
|
|
112
|
+
console.log(chalk.gray(" © 2026 JEBCODE SOFTWARE E TECNOLOGIA LTDA\n"));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function startTunnel(port, options = {}) {
|
|
117
|
+
let config = {};
|
|
118
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
119
|
+
try {
|
|
120
|
+
config = JSON.parse(fs.readFileSync(CONFIG_PATH));
|
|
121
|
+
} catch (e) {
|
|
122
|
+
console.error(chalk.red(" ✖ Erro no arquivo de config:"), e.message);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!config.token) {
|
|
127
|
+
console.log(getHeader());
|
|
128
|
+
console.error(chalk.red(" ✖ Erro: Authtoken não configurado."));
|
|
129
|
+
console.log(chalk.gray(" Obtenha seu token no Dashboard: https://jebcodetunnel.com/dashboard"));
|
|
130
|
+
console.log(chalk.gray(`\n Use: ${chalk.bold("jebcode-tunnel login")} ou ${chalk.bold("jebcode-tunnel authtoken <token>")}\n`));
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const subdomain = options.subdomain || "dev";
|
|
135
|
+
const insecure = options.insecure || false;
|
|
136
|
+
|
|
137
|
+
process.stdout.write(chalk.blue(" ☁ Conectando à infraestrutura JebCode... "));
|
|
138
|
+
|
|
139
|
+
const socket = io(SERVER_URL, {
|
|
140
|
+
transports: ["websocket", "polling"],
|
|
141
|
+
reconnectionAttempts: 10,
|
|
142
|
+
timeout: 15000,
|
|
143
|
+
rejectUnauthorized: !insecure,
|
|
144
|
+
pingInterval: 10000,
|
|
145
|
+
pingTimeout: 5000
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
socket.on("connect", () => {
|
|
149
|
+
process.stdout.write(chalk.green("OK\n"));
|
|
150
|
+
socket.emit("authenticate", { token: config.token, subdomain });
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
socket.on("auth_result", (result) => {
|
|
154
|
+
if (result.success) {
|
|
155
|
+
console.clear();
|
|
156
|
+
console.log(getHeader());
|
|
157
|
+
console.log(chalk.white(" STATUS DO TÚNEL ATIVO"));
|
|
158
|
+
console.log(chalk.blue(" ▪"), chalk.bold("URL Pública: "), chalk.yellow(`https://${subdomain}.jebcodetunnel.com`));
|
|
159
|
+
console.log(chalk.blue(" ▪"), chalk.bold("Encaminhando:"), chalk.white(`http://localhost:${port}`), chalk.gray("➔"), chalk.cyan("jeb-gateway"));
|
|
160
|
+
console.log(chalk.blue(" ▪"), chalk.bold("Dashboard: "), chalk.gray(`${SERVER_URL}/dashboard`));
|
|
161
|
+
|
|
162
|
+
console.log(chalk.gray("\n Pressione CTRL+C para encerrar o túnel"));
|
|
163
|
+
console.log(chalk.white("\n LOGS DE TRÁFEGO EM TEMPO REAL:"));
|
|
164
|
+
console.log(chalk.gray(" " + "─".repeat(60)));
|
|
165
|
+
} else {
|
|
166
|
+
console.log(chalk.red("\n ✖ Falha na Autenticação:"), chalk.bold(result.message));
|
|
167
|
+
console.log(chalk.gray(" Verifique seu token e se o subdomínio foi criado no dashboard.\n"));
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
socket.on("heartbeat_ping", () => {
|
|
173
|
+
socket.emit("heartbeat_pong");
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
socket.on("incoming_request", async (reqData) => {
|
|
177
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
178
|
+
const methodColor = reqData.method === "GET" ? chalk.green : reqData.method === "POST" ? chalk.blue : chalk.yellow;
|
|
179
|
+
|
|
180
|
+
// Log imediato para feedback instantâneo no terminal
|
|
181
|
+
const startLog = `${chalk.gray(` [${timestamp}]`)} ${methodColor(reqData.method.padEnd(7))} ${chalk.white(reqData.path.substring(0, 30).padEnd(30))} ${chalk.yellow("PROCESSANDO...")}`;
|
|
182
|
+
process.stdout.write(startLog);
|
|
183
|
+
|
|
184
|
+
const startTime = Date.now();
|
|
185
|
+
try {
|
|
186
|
+
const response = await axios({
|
|
187
|
+
method: reqData.method,
|
|
188
|
+
url: `http://localhost:${port}${reqData.path}`,
|
|
189
|
+
headers: { ...reqData.headers, host: `localhost:${port}` },
|
|
190
|
+
data: reqData.body ? Buffer.from(reqData.body, "base64") : undefined,
|
|
191
|
+
responseType: "arraybuffer",
|
|
192
|
+
validateStatus: () => true,
|
|
193
|
+
timeout: 10000
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const duration = Date.now() - startTime;
|
|
197
|
+
const statusColor = response.status < 300 ? chalk.green : response.status < 400 ? chalk.cyan : chalk.red;
|
|
198
|
+
|
|
199
|
+
// Limpa a linha atual e sobrescreve com o log final
|
|
200
|
+
if (process.stdout.isTTY) {
|
|
201
|
+
process.stdout.clearLine(0);
|
|
202
|
+
process.stdout.cursorTo(0);
|
|
203
|
+
} else {
|
|
204
|
+
process.stdout.write("\n");
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const logLine = [
|
|
208
|
+
chalk.gray(` [${timestamp}]`),
|
|
209
|
+
methodColor(reqData.method.padEnd(7)),
|
|
210
|
+
chalk.white(reqData.path.substring(0, 30).padEnd(30)),
|
|
211
|
+
statusColor(response.status.toString().padStart(3)),
|
|
212
|
+
chalk.gray(`${duration.toString().padStart(5)}ms`)
|
|
213
|
+
].join(" ");
|
|
214
|
+
|
|
215
|
+
console.log(logLine);
|
|
216
|
+
|
|
217
|
+
socket.emit(`response_${reqData.id}`, {
|
|
218
|
+
status: response.status,
|
|
219
|
+
headers: response.headers,
|
|
220
|
+
body: Buffer.from(response.data).toString("base64"),
|
|
221
|
+
});
|
|
222
|
+
} catch (err) {
|
|
223
|
+
const duration = Date.now() - startTime;
|
|
224
|
+
if (process.stdout.isTTY) {
|
|
225
|
+
process.stdout.clearLine(0);
|
|
226
|
+
process.stdout.cursorTo(0);
|
|
227
|
+
} else {
|
|
228
|
+
process.stdout.write("\n");
|
|
229
|
+
}
|
|
230
|
+
console.log(`${chalk.gray(` [${timestamp}]`)} ${methodColor(reqData.method.padEnd(7))} ${chalk.white(reqData.path.substring(0, 30).padEnd(30))} ${chalk.red("FALHOU")} ${chalk.gray(`${duration}ms`)}`);
|
|
231
|
+
|
|
232
|
+
socket.emit(`response_${reqData.id}`, {
|
|
233
|
+
status: 502,
|
|
234
|
+
headers: { "Content-Type": "text/plain" },
|
|
235
|
+
body: Buffer.from(`JebCode Gateway Error: Erro ao conectar no localhost:${port}. O serviço está rodando?`).toString("base64"),
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
socket.on("disconnect", () => {
|
|
241
|
+
console.log(chalk.yellow("\n ⚠ Conexão perdida. Tentando reconectar..."));
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
socket.on("connect_error", (err) => {
|
|
245
|
+
console.error(chalk.red("\n ✖ Erro Crítico de Conexão:"), err.message);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
module.exports = { authtoken, startTunnel, showStatus, login, logout };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jebcode-dev/jebcode-tunnel",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "CLI do JebCode Tunnel",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -22,6 +22,12 @@
|
|
|
22
22
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
23
23
|
"release": "npm version patch && npm link"
|
|
24
24
|
},
|
|
25
|
+
"files": [
|
|
26
|
+
"index.js",
|
|
27
|
+
"bin.js",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE"
|
|
30
|
+
],
|
|
25
31
|
"dependencies": {
|
|
26
32
|
"axios": "^1.7.9",
|
|
27
33
|
"chalk": "^4.1.2",
|
|
@@ -29,4 +35,4 @@
|
|
|
29
35
|
"inquirer": "^8.2.7",
|
|
30
36
|
"socket.io-client": "^4.8.1"
|
|
31
37
|
}
|
|
32
|
-
}
|
|
38
|
+
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
name: Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- 'v*'
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
publish:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
permissions:
|
|
12
|
-
id-token: write # Essencial para OIDC / Trusted Publishing
|
|
13
|
-
contents: read
|
|
14
|
-
steps:
|
|
15
|
-
- uses: actions/checkout@v4
|
|
16
|
-
- uses: actions/setup-node@v4
|
|
17
|
-
with:
|
|
18
|
-
node-version: "24"
|
|
19
|
-
- run: npm install
|
|
20
|
-
- run: npm publish --access public
|
package/editora.md
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# 🚀 Configuração da Editora de Confiança (npm + GitHub)
|
|
2
|
-
|
|
3
|
-
Para configurar o **Trusted Publishing**, preencha os campos no npm exatamente assim:
|
|
4
|
-
|
|
5
|
-
| Campo | Valor |
|
|
6
|
-
| :--- | :--- |
|
|
7
|
-
| **Organização ou usuário** | `JonathanBoza` |
|
|
8
|
-
| **Repositório** | `cli-jebcode-tunnel` |
|
|
9
|
-
| **Nome do arquivo do workflow** | `publish.yml` |
|
|
10
|
-
| **Nome do ambiente** | (Deixe vazio) |
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## 🛠️ O que fazer agora:
|
|
15
|
-
|
|
16
|
-
1. Eu já criei o arquivo `.github/workflows/publish.yml` na sua pasta `cli`.
|
|
17
|
-
2. Você precisa fazer o **Push** desse arquivo para o seu GitHub:
|
|
18
|
-
```powershell
|
|
19
|
-
git add .
|
|
20
|
-
git commit -m "Add npm publish workflow"
|
|
21
|
-
git push origin main
|
|
22
|
-
```
|
|
23
|
-
3. No site do npm, clique em **"Configurar conexão"**.
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## 📦 Como publicar uma nova versão:
|
|
28
|
-
|
|
29
|
-
Agora você não precisa mais rodar `npm publish` na sua máquina. Basta:
|
|
30
|
-
|
|
31
|
-
1. Alterar a versão no `package.json`.
|
|
32
|
-
2. Criar uma **Tag** ou uma **Release** no GitHub (ex: `v1.0.1`).
|
|
33
|
-
3. O GitHub vai publicar sozinho para você! 😊
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
# 1. Altera para a versão 1.0.7 no package.json (ou deixa eu fazer se preferir)
|
|
37
|
-
# 2. Cria a tag de versão
|
|
38
|
-
git tag v1.0.1
|
|
39
|
-
# 3. Envia a tag para o GitHub
|
|
40
|
-
git push origin v1.0.1
|
package/img/image copy.png
DELETED
|
Binary file
|
package/img/image.png
DELETED
|
Binary file
|