@batistafull/deploy-server 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -15
- package/lib/deploy.js +66 -23
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @batistafull/deploy-server
|
|
2
2
|
|
|
3
|
-
Herramienta CLI de despliegue dirigida por configuración. Ejecuta los comandos de build de tu proyecto y copia las carpetas
|
|
3
|
+
Herramienta CLI de despliegue dirigida por configuración. Ejecuta los comandos de build de tu proyecto y copia las carpetas, archivos o globs que indiques a la carpeta destino, con opción de subir el resultado por FTP/FTPS.
|
|
4
4
|
|
|
5
5
|
## Instalación
|
|
6
6
|
|
|
@@ -52,10 +52,9 @@ Crea `deploy.config.json` en la raíz de tu proyecto. **Este archivo lo creas t
|
|
|
52
52
|
```json
|
|
53
53
|
{
|
|
54
54
|
"output": "C:/inetpub/app.host",
|
|
55
|
-
"
|
|
56
|
-
"server": "api",
|
|
55
|
+
"sources": ["dist/", "api/", "robots.txt"],
|
|
57
56
|
"buildCommand": ["npm install", "npm run build"],
|
|
58
|
-
"exclude": ["
|
|
57
|
+
"exclude": ["dist/.htaccess", "api/node_modules"],
|
|
59
58
|
"ftp": {
|
|
60
59
|
"enabled": false,
|
|
61
60
|
"host": "ftp.example.com",
|
|
@@ -67,18 +66,36 @@ Crea `deploy.config.json` en la raíz de tu proyecto. **Este archivo lo creas t
|
|
|
67
66
|
|
|
68
67
|
### Campos
|
|
69
68
|
|
|
70
|
-
| Campo | Tipo | Descripción
|
|
71
|
-
| -------------- | --------------------- |
|
|
72
|
-
| `output` | `string` | Ruta destino del deploy (ver nota abajo).
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `ftp` | `object` | (Opcional) Configuración de subida por FTP/FTPS. Ver abajo. |
|
|
69
|
+
| Campo | Tipo | Descripción |
|
|
70
|
+
| -------------- | --------------------- | ----------------------------------------------------------- |
|
|
71
|
+
| `output` | `string` | Ruta destino del deploy (ver nota abajo). |
|
|
72
|
+
| `sources` | `string[]` | Carpetas, archivos o globs a copiar (ver abajo). |
|
|
73
|
+
| `buildCommand` | `string` o `string[]` | Comando(s) de build. Si es un array, se ejecutan en orden. |
|
|
74
|
+
| `exclude` | `string[]` | Rutas a excluir, relativas al proyecto (ver abajo). |
|
|
75
|
+
| `ftp` | `object` | (Opcional) Configuración de subida por FTP/FTPS. Ver abajo. |
|
|
78
76
|
|
|
79
77
|
> **`output`:** si es una ruta **absoluta** se usa tal cual (ej: `C:/inetpub/app.host`);
|
|
80
78
|
> si es **relativa** se resuelve desde la raíz del proyecto (ej: `../deploy/app.host`).
|
|
81
79
|
|
|
80
|
+
### `sources` — qué se copia
|
|
81
|
+
|
|
82
|
+
Cada entrada es una carpeta, un archivo o un glob, relativo a la raíz del proyecto:
|
|
83
|
+
|
|
84
|
+
| Entrada | Significado |
|
|
85
|
+
| ------------ | -------------------------------------------------------------------------------- |
|
|
86
|
+
| `dist/` | Carpeta completa (recursivo). Su contenido se copia a la raíz del output. |
|
|
87
|
+
| `dist/*.css` | Glob: solo los `.css` del primer nivel de `dist`, copiados a la raíz del output. |
|
|
88
|
+
| `robots.txt` | Un archivo suelto, copiado por su nombre a la raíz del output. |
|
|
89
|
+
|
|
90
|
+
En todos los casos el contenido se copia a la **raíz del output** (se quita la carpeta base). Las carpetas se indican con `/` al final.
|
|
91
|
+
|
|
92
|
+
### `exclude` — qué se omite
|
|
93
|
+
|
|
94
|
+
Cada entrada es una ruta **relativa al proyecto** (no un nombre suelto), scopeada a la carpeta de origen:
|
|
95
|
+
|
|
96
|
+
- `"dist/.htaccess"` → omite ese archivo concreto dentro de `dist`.
|
|
97
|
+
- `"api/node_modules"` → omite esa carpeta entera (y su contenido) dentro de `api`.
|
|
98
|
+
|
|
82
99
|
### FTP / FTPS
|
|
83
100
|
|
|
84
101
|
La subida por FTP está desactivada salvo que pongas `ftp.enabled: true`.
|
|
@@ -111,9 +128,8 @@ Si el FTP está habilitado y faltan `FTP_HOST`, `FTP_USER` o `FTP_PASSWORD` (y t
|
|
|
111
128
|
1. Carga el `deploy.config.json`.
|
|
112
129
|
2. Si se pasa `--clean`, borra la carpeta de salida.
|
|
113
130
|
3. Ejecuta el/los `buildCommand`.
|
|
114
|
-
4. Copia `
|
|
115
|
-
5.
|
|
116
|
-
6. Si `ftp.enabled`, sube la carpeta de salida por FTP/FTPS.
|
|
131
|
+
4. Copia cada entrada de `sources` → `<output>` (aplicando `exclude`).
|
|
132
|
+
5. Si `ftp.enabled`, sube la carpeta de salida por FTP/FTPS.
|
|
117
133
|
|
|
118
134
|
## Licencia
|
|
119
135
|
|
package/lib/deploy.js
CHANGED
|
@@ -3,6 +3,7 @@ const fs = require("fs-extra");
|
|
|
3
3
|
const chalk = require("chalk");
|
|
4
4
|
const { execSync } = require("child_process");
|
|
5
5
|
const ftp = require("basic-ftp");
|
|
6
|
+
const fg = require("fast-glob");
|
|
6
7
|
|
|
7
8
|
// Ejecuta una lista de comandos de build en orden
|
|
8
9
|
function runBuildCommands(commands, cwd) {
|
|
@@ -12,23 +13,67 @@ function runBuildCommands(commands, cwd) {
|
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
// Dado un patrón (con "/"), calcula el patrón glob y la carpeta base a "quitar"
|
|
17
|
+
// al copiar hacia el output.
|
|
18
|
+
// "dist/" -> { glob: "dist/**/*", base: "dist" } (carpeta completa)
|
|
19
|
+
// "dist/*.css" -> { glob: "dist/*.css", base: "dist" } (glob dentro de dist)
|
|
20
|
+
// "dist/app.js" -> { glob: "dist/app.js", base: "dist" } (archivo suelto)
|
|
21
|
+
function resolveSource(raw) {
|
|
22
|
+
const source = raw.replace(/\\/g, "/");
|
|
23
|
+
const hasGlob = (s) => /[*?[\]{}!()]/.test(s);
|
|
24
|
+
|
|
25
|
+
if (source.endsWith("/")) {
|
|
26
|
+
const dir = source.replace(/\/+$/, "");
|
|
27
|
+
return { glob: `${dir}/**/*`, base: dir };
|
|
20
28
|
}
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
(pattern) => name === pattern || relative.split(path.sep).includes(pattern)
|
|
29
|
-
);
|
|
30
|
+
if (hasGlob(source)) {
|
|
31
|
+
// base = prefijo estático anterior al primer segmento con comodines
|
|
32
|
+
const baseSegs = [];
|
|
33
|
+
for (const seg of source.split("/")) {
|
|
34
|
+
if (hasGlob(seg)) break;
|
|
35
|
+
baseSegs.push(seg);
|
|
30
36
|
}
|
|
37
|
+
return { glob: source, base: baseSegs.join("/") || "." };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// archivo (o carpeta sin "/") suelto: se copia bajo su nombre
|
|
41
|
+
return { glob: source, base: path.posix.dirname(source) };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Copia cada 'source' al output. Los 'exclude' son rutas relativas al proyecto
|
|
45
|
+
// (ej: "dist/.htaccess") y se aplican como patrones ignorados.
|
|
46
|
+
async function copySources(sources, outputPath, exclude, projectRoot) {
|
|
47
|
+
// Para excluir una carpeta entera basta con nombrarla; añadimos "/**" para
|
|
48
|
+
// cubrir también su contenido.
|
|
49
|
+
const ignore = exclude.flatMap((e) => {
|
|
50
|
+
const p = e.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
51
|
+
return [p, `${p}/**`];
|
|
31
52
|
});
|
|
53
|
+
|
|
54
|
+
for (const raw of sources) {
|
|
55
|
+
const { glob, base } = resolveSource(raw);
|
|
56
|
+
|
|
57
|
+
const matches = await fg(glob, {
|
|
58
|
+
cwd: projectRoot,
|
|
59
|
+
dot: true,
|
|
60
|
+
onlyFiles: true,
|
|
61
|
+
ignore
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (matches.length === 0) {
|
|
65
|
+
console.log(chalk.yellow(`⚠️ Sin coincidencias, se omite: ${raw}`));
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log(chalk.blue(`📦 Copiando ${raw} (${matches.length} archivo(s))...`));
|
|
70
|
+
for (const rel of matches) {
|
|
71
|
+
const from = path.join(projectRoot, rel);
|
|
72
|
+
const dest = path.join(outputPath, path.relative(base, rel));
|
|
73
|
+
await fs.ensureDir(path.dirname(dest));
|
|
74
|
+
await fs.copy(from, dest);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
32
77
|
}
|
|
33
78
|
|
|
34
79
|
module.exports = async function deploy(options) {
|
|
@@ -40,13 +85,16 @@ module.exports = async function deploy(options) {
|
|
|
40
85
|
throw new Error("Falta 'output' en el config: indica la carpeta destino del deploy.");
|
|
41
86
|
}
|
|
42
87
|
|
|
88
|
+
if (!Array.isArray(config.sources) || config.sources.length === 0) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
"Falta 'sources' en el config: indica un array de carpetas/archivos a copiar (ej: [\"dist/\", \"api/\"])."
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
43
94
|
// 'output' es la ruta destino. Si es absoluta se usa tal cual;
|
|
44
95
|
// si es relativa se resuelve desde la raíz del proyecto.
|
|
45
96
|
const outputPath = path.resolve(projectRoot, config.output);
|
|
46
97
|
|
|
47
|
-
const distPath = path.join(projectRoot, config.dist);
|
|
48
|
-
const serverPath = path.join(projectRoot, config.server);
|
|
49
|
-
|
|
50
98
|
// Clean
|
|
51
99
|
if (options.clean) {
|
|
52
100
|
console.log(chalk.gray("🧹 Cleaning output..."));
|
|
@@ -65,13 +113,8 @@ module.exports = async function deploy(options) {
|
|
|
65
113
|
});
|
|
66
114
|
}
|
|
67
115
|
|
|
68
|
-
// COPY
|
|
69
|
-
|
|
70
|
-
await copyFiltered(distPath, outputPath, config.exclude || []);
|
|
71
|
-
|
|
72
|
-
// COPY SERVER
|
|
73
|
-
console.log(chalk.blue("📦 Copying server..."));
|
|
74
|
-
await copyFiltered(serverPath, outputPath, config.exclude || []);
|
|
116
|
+
// COPY SOURCES
|
|
117
|
+
await copySources(config.sources, outputPath, config.exclude || [], projectRoot);
|
|
75
118
|
|
|
76
119
|
// FTP (opcional)
|
|
77
120
|
if (config.ftp?.enabled) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@batistafull/deploy-server",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Config-driven deploy tool that builds and copies folders, files or globs to a target path, with optional FTP/FTPS upload",
|
|
5
5
|
"main": "bin/deploy-server.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"deploy-server": "bin/deploy-server.js"
|
|
@@ -10,7 +10,11 @@
|
|
|
10
10
|
"bin/",
|
|
11
11
|
"lib/"
|
|
12
12
|
],
|
|
13
|
-
"keywords": [
|
|
13
|
+
"keywords": [
|
|
14
|
+
"deploy",
|
|
15
|
+
"cli",
|
|
16
|
+
"nodejs"
|
|
17
|
+
],
|
|
14
18
|
"author": "batistafull",
|
|
15
19
|
"license": "MIT",
|
|
16
20
|
"type": "commonjs",
|
|
@@ -21,6 +25,7 @@
|
|
|
21
25
|
"basic-ftp": "^5.0.5",
|
|
22
26
|
"chalk": "^4.1.2",
|
|
23
27
|
"commander": "^12.1.0",
|
|
28
|
+
"fast-glob": "^3.3.3",
|
|
24
29
|
"fs-extra": "^11.2.0"
|
|
25
30
|
}
|
|
26
|
-
}
|
|
31
|
+
}
|