codecrypto-cli 1.0.0 → 1.0.1

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/Dockerfile ADDED
@@ -0,0 +1,15 @@
1
+ FROM node:20-alpine
2
+ WORKDIR /app
3
+
4
+ ENV NODE_ENV=production
5
+ ENV PORT=3000
6
+
7
+ # 1. Copiamos el servidor standalone generado localmente
8
+ # Nota: La carpeta 'standalone' incluye un 'server.js'
9
+ COPY standalone/ .
10
+
11
+ # 2. Exponemos el puerto para Traefik
12
+ EXPOSE 3000
13
+
14
+ # 3. Arrancamos directamente con Node
15
+ CMD ["node", "server.js"]
@@ -0,0 +1,174 @@
1
+ #!/bin/bash
2
+
3
+ # Script para copiar build standalone y crear imagen Docker
4
+ # Uso: ./build-docker.sh <path-proyecto> <folder-destino>
5
+
6
+ set -e
7
+
8
+ # Colores para output
9
+ RED='\033[0;31m'
10
+ GREEN='\033[0;32m'
11
+ YELLOW='\033[1;33m'
12
+ NC='\033[0m' # No Color
13
+
14
+ # Verificar argumentos
15
+ if [ "$#" -ne 2 ]; then
16
+ echo -e "${RED}Error: Argumentos insuficientes${NC}"
17
+ echo "Uso: $0 <path-proyecto> <folder-destino>"
18
+ echo ""
19
+ echo "Ejemplo:"
20
+ echo " $0 /path/to/proyecto /path/to/destino"
21
+ exit 1
22
+ fi
23
+
24
+ PROJECT_PATH="$1"
25
+ DEST_FOLDER="$2"
26
+
27
+ # Verificar que el proyecto existe
28
+ if [ ! -d "$PROJECT_PATH" ]; then
29
+ echo -e "${RED}Error: El directorio del proyecto no existe: ${PROJECT_PATH}${NC}"
30
+ exit 1
31
+ fi
32
+
33
+ # Verificar que existe .next/standalone
34
+ if [ ! -d "$PROJECT_PATH/.next/standalone" ]; then
35
+ echo -e "${RED}Error: No se encontró .next/standalone en el proyecto${NC}"
36
+ echo "Asegúrate de haber ejecutado 'npm run build' con 'output: standalone'"
37
+ exit 1
38
+ fi
39
+
40
+ # Obtener el nombre del proyecto desde el path
41
+ PROJECT_NAME=$(basename "$PROJECT_PATH")
42
+ IMAGE_BASE="jviejo/${PROJECT_NAME}"
43
+
44
+ # Leer versión del package.json
45
+ VERSION="latest"
46
+ if [ -f "$PROJECT_PATH/package.json" ]; then
47
+ VERSION=$(node -p "require('$PROJECT_PATH/package.json').version" 2>/dev/null || echo "latest")
48
+ if [ "$VERSION" = "undefined" ] || [ -z "$VERSION" ]; then
49
+ VERSION="latest"
50
+ fi
51
+ else
52
+ echo -e "${YELLOW}Advertencia: No se encontró package.json, usando versión 'latest'${NC}"
53
+ fi
54
+
55
+ IMAGE_NAME="${IMAGE_BASE}:${VERSION}"
56
+ IMAGE_LATEST="${IMAGE_BASE}:latest"
57
+
58
+ echo -e "${GREEN}=== Construyendo imagen Docker para: ${PROJECT_NAME} ===${NC}"
59
+ echo -e "${GREEN} Versión: ${VERSION}${NC}"
60
+ echo -e "${GREEN} Tags: ${IMAGE_NAME}, ${IMAGE_LATEST}${NC}"
61
+
62
+ # Crear directorio destino si no existe
63
+ mkdir -p "$DEST_FOLDER"
64
+
65
+ # Paso 1: Encontrar y copiar el contenido de standalone (usando el patrón especificado)
66
+ echo -e "${YELLOW}Paso 1: Copiando contenido de standalone...${NC}"
67
+ STANDALONE_DEST="$DEST_FOLDER/standalone"
68
+ mkdir -p "$STANDALONE_DEST"
69
+
70
+ # Buscar el directorio .next dentro de standalone y copiar su contenido padre
71
+ NEXT_DIR=$(find "$PROJECT_PATH/.next/standalone" -name ".next" -type d | head -n 1)
72
+ if [ -n "$NEXT_DIR" ]; then
73
+ # Copiar el contenido del padre de .next (que es el contenido de standalone)
74
+ PARENT_DIR=$(dirname "$NEXT_DIR")
75
+ cp -r "$PARENT_DIR"/* "$STANDALONE_DEST/" 2>/dev/null || true
76
+ # También copiar archivos ocultos
77
+ cp -r "$PARENT_DIR"/.[!.]* "$STANDALONE_DEST/" 2>/dev/null || true
78
+ else
79
+ # Si no se encuentra .next, copiar todo standalone directamente
80
+ cp -r "$PROJECT_PATH/.next/standalone"/* "$STANDALONE_DEST/"
81
+ fi
82
+
83
+ # Paso 2: Copiar .next/static dentro de standalone/.next/static
84
+ echo -e "${YELLOW}Paso 2: Copiando .next/static...${NC}"
85
+ if [ -d "$PROJECT_PATH/.next/static" ]; then
86
+ mkdir -p "$STANDALONE_DEST/.next/static"
87
+ cp -r "$PROJECT_PATH/.next/static"/* "$STANDALONE_DEST/.next/static/"
88
+ else
89
+ echo -e "${YELLOW}Advertencia: No se encontró .next/static${NC}"
90
+ fi
91
+
92
+ # Paso 3: Copiar public dentro de standalone/public
93
+ echo -e "${YELLOW}Paso 3: Copiando public...${NC}"
94
+ if [ -d "$PROJECT_PATH/public" ]; then
95
+ mkdir -p "$STANDALONE_DEST/public"
96
+ cp -r "$PROJECT_PATH/public"/* "$STANDALONE_DEST/public/"
97
+ else
98
+ echo -e "${YELLOW}Advertencia: No se encontró public${NC}"
99
+ fi
100
+
101
+ # Paso 4: Crear Dockerfile en el destino
102
+ echo -e "${YELLOW}Paso 4: Creando Dockerfile...${NC}"
103
+ cat > "$DEST_FOLDER/Dockerfile" << 'EOF'
104
+ FROM node:20-alpine
105
+ WORKDIR /app
106
+
107
+ ENV NODE_ENV=production
108
+ ENV PORT=3000
109
+
110
+ # Copiamos el contenido de standalone
111
+ COPY standalone/ .
112
+
113
+ # Exponemos el puerto para Traefik
114
+ EXPOSE 3000
115
+
116
+ # Arrancamos directamente con Node
117
+ CMD ["node", "server.js"]
118
+ EOF
119
+
120
+ # Verificar que server.js existe en standalone
121
+ if [ ! -f "$STANDALONE_DEST/server.js" ]; then
122
+ echo -e "${RED}Error: No se encontró server.js en standalone${NC}"
123
+ exit 1
124
+ fi
125
+
126
+ # Paso 5: Verificar/crear builder multi-plataforma
127
+ echo -e "${YELLOW}Paso 5: Verificando builder multi-plataforma...${NC}"
128
+ BUILDER_NAME="multiarch-builder"
129
+ if ! docker buildx ls | grep -q "$BUILDER_NAME"; then
130
+ echo -e "${YELLOW}Creando builder multi-plataforma...${NC}"
131
+ docker buildx create --name "$BUILDER_NAME" --use --bootstrap
132
+ else
133
+ echo -e "${YELLOW}Usando builder existente...${NC}"
134
+ docker buildx use "$BUILDER_NAME" 2>/dev/null || docker buildx use "$BUILDER_NAME" --default
135
+ fi
136
+
137
+ # Paso 6: Verificar autenticación en Docker Hub
138
+ echo -e "${YELLOW}Paso 6: Verificando autenticación en Docker Hub...${NC}"
139
+ if ! docker info | grep -q "Username"; then
140
+ echo -e "${YELLOW}No se detectó sesión de Docker Hub. Intentando login...${NC}"
141
+ echo -e "${YELLOW}Si no estás autenticado, ejecuta: docker login${NC}"
142
+ fi
143
+
144
+ # Paso 7: Construir y hacer push de imagen Docker con buildx para múltiples plataformas
145
+ echo -e "${YELLOW}Paso 7: Construyendo y haciendo push de imagen Docker con buildx para múltiples plataformas...${NC}"
146
+ cd "$DEST_FOLDER"
147
+
148
+ # Construir para ambas plataformas y hacer push con múltiples tags
149
+ # Esto crea automáticamente un manifest multi-plataforma
150
+ docker buildx build \
151
+ --platform linux/amd64,linux/arm64 \
152
+ --tag "$IMAGE_NAME" \
153
+ --tag "$IMAGE_LATEST" \
154
+ --push \
155
+ --progress=plain \
156
+ .
157
+
158
+ BUILD_EXIT=$?
159
+
160
+ if [ $BUILD_EXIT -eq 0 ]; then
161
+ echo -e "${GREEN}✅ ¡Imagen construida y pusheada exitosamente para múltiples plataformas${NC}"
162
+ echo -e "${GREEN} Plataformas: linux/amd64, linux/arm64${NC}"
163
+ echo -e "${GREEN} Versión: ${VERSION}${NC}"
164
+ echo -e "${GREEN} Tags pusheados:${NC}"
165
+ echo -e "${GREEN} - ${IMAGE_NAME}${NC}"
166
+ echo -e "${GREEN} - ${IMAGE_LATEST}${NC}"
167
+ echo -e "${GREEN} Registry: Docker Hub${NC}"
168
+ echo -e "${GREEN} Imagen disponible en: https://hub.docker.com/r/${IMAGE_BASE}${NC}"
169
+ else
170
+ echo -e "${RED}❌ Error al construir o hacer push de la imagen Docker${NC}"
171
+ echo -e "${YELLOW}Verifica que estés autenticado con: docker login${NC}"
172
+ exit 1
173
+ fi
174
+
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,aAAa,SAwCtB,CAAC"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,aAAa,SA2LtB,CAAC"}
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
@@ -7,40 +40,217 @@ exports.deployCommand = void 0;
7
40
  const commander_1 = require("commander");
8
41
  const chalk_1 = __importDefault(require("chalk"));
9
42
  const ora_1 = __importDefault(require("ora"));
43
+ const child_process_1 = require("child_process");
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
10
46
  exports.deployCommand = new commander_1.Command('deploy')
11
- .description('Deploy your application to different environments')
12
- .option('-e, --env <environment>', 'Environment to deploy (dev, staging, prod)', 'dev')
13
- .option('-b, --branch <branch>', 'Git branch to deploy', 'main')
14
- .option('-r, --region <region>', 'AWS region', 'us-east-1')
15
- .option('--skip-tests', 'Skip running tests before deployment', false)
16
- .option('--dry-run', 'Simulate deployment without actually deploying', false)
17
- .action(async (options) => {
18
- console.log(chalk_1.default.blue('\n🚀 CodeCrypto Deployment\n'));
19
- console.log(chalk_1.default.gray('Deployment Configuration:'));
20
- console.log(chalk_1.default.white(` Environment: ${chalk_1.default.green(options.env)}`));
21
- console.log(chalk_1.default.white(` Branch: ${chalk_1.default.green(options.branch)}`));
22
- console.log(chalk_1.default.white(` Region: ${chalk_1.default.green(options.region)}`));
23
- console.log(chalk_1.default.white(` Skip Tests: ${options.skipTests ? chalk_1.default.yellow('Yes') : chalk_1.default.green('No')}`));
24
- console.log(chalk_1.default.white(` Dry Run: ${options.dryRun ? chalk_1.default.yellow('Yes') : chalk_1.default.green('No')}`));
25
- if (options.dryRun) {
26
- console.log(chalk_1.default.yellow('\n⚠️ Running in dry-run mode. No actual deployment will occur.\n'));
47
+ .description('Build and deploy Docker image for Next.js standalone application')
48
+ .argument('<project-path>', 'Path to the Next.js project directory')
49
+ .argument('[dest-folder]', 'Destination folder for Docker build context', './docker-build')
50
+ .option('--skip-build', 'Skip npm run build (assume already built)', false)
51
+ .option('--no-push', 'Build image but do not push to registry', false)
52
+ .action(async (projectPath, destFolder, options) => {
53
+ console.log(chalk_1.default.blue('\n🐳 CodeCrypto Docker Deployment\n'));
54
+ try {
55
+ // Validar que el proyecto existe
56
+ const resolvedProjectPath = path.resolve(projectPath);
57
+ if (!fs.existsSync(resolvedProjectPath)) {
58
+ console.error(chalk_1.default.red(`❌ Error: El directorio del proyecto no existe: ${resolvedProjectPath}`));
59
+ process.exit(1);
60
+ }
61
+ // Verificar que es un proyecto Next.js
62
+ const packageJsonPath = path.join(resolvedProjectPath, 'package.json');
63
+ if (!fs.existsSync(packageJsonPath)) {
64
+ console.error(chalk_1.default.red(`❌ Error: No se encontró package.json en el proyecto`));
65
+ process.exit(1);
66
+ }
67
+ // Leer versión del package.json
68
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
69
+ const version = packageJson.version || 'latest';
70
+ const projectName = path.basename(resolvedProjectPath);
71
+ const imageBase = `jviejo/${projectName}`;
72
+ const imageName = `${imageBase}:${version}`;
73
+ const imageLatest = `${imageBase}:latest`;
74
+ console.log(chalk_1.default.gray('Deployment Configuration:'));
75
+ console.log(chalk_1.default.white(` Project: ${chalk_1.default.green(projectName)}`));
76
+ console.log(chalk_1.default.white(` Version: ${chalk_1.default.green(version)}`));
77
+ console.log(chalk_1.default.white(` Image: ${chalk_1.default.green(imageName)}`));
78
+ console.log(chalk_1.default.white(` Latest: ${chalk_1.default.green(imageLatest)}`));
79
+ console.log(chalk_1.default.white(` Push to Registry: ${options.push ? chalk_1.default.green('Yes') : chalk_1.default.yellow('No')}\n`));
80
+ // Paso 1: Build del proyecto si es necesario
81
+ if (!options.skipBuild) {
82
+ const buildSpinner = (0, ora_1.default)('Building Next.js application...').start();
83
+ try {
84
+ (0, child_process_1.execSync)('npm run build', {
85
+ cwd: resolvedProjectPath,
86
+ stdio: 'pipe'
87
+ });
88
+ buildSpinner.succeed('Build completed successfully');
89
+ }
90
+ catch (error) {
91
+ buildSpinner.fail('Build failed');
92
+ console.error(chalk_1.default.red('Error during build. Make sure you have "output: standalone" in next.config.ts'));
93
+ process.exit(1);
94
+ }
95
+ }
96
+ // Verificar que existe .next/standalone
97
+ const standalonePath = path.join(resolvedProjectPath, '.next', 'standalone');
98
+ if (!fs.existsSync(standalonePath)) {
99
+ console.error(chalk_1.default.red(`❌ Error: No se encontró .next/standalone`));
100
+ console.error(chalk_1.default.yellow('Asegúrate de tener "output: standalone" en next.config.ts y ejecutar "npm run build"'));
101
+ process.exit(1);
102
+ }
103
+ // Paso 2: Preparar directorio destino
104
+ const resolvedDestFolder = path.resolve(destFolder);
105
+ const standaloneDest = path.join(resolvedDestFolder, 'standalone');
106
+ const copySpinner = (0, ora_1.default)('Copying standalone files...').start();
107
+ if (fs.existsSync(resolvedDestFolder)) {
108
+ fs.rmSync(resolvedDestFolder, { recursive: true, force: true });
109
+ }
110
+ fs.mkdirSync(standaloneDest, { recursive: true });
111
+ // Copiar contenido de standalone
112
+ const nextDir = findDirectory(standalonePath, '.next');
113
+ if (nextDir) {
114
+ const parentDir = path.dirname(nextDir);
115
+ copyDirectory(parentDir, standaloneDest);
116
+ }
117
+ else {
118
+ copyDirectory(standalonePath, standaloneDest);
119
+ }
120
+ // Copiar .next/static
121
+ const staticPath = path.join(resolvedProjectPath, '.next', 'static');
122
+ if (fs.existsSync(staticPath)) {
123
+ const staticDest = path.join(standaloneDest, '.next', 'static');
124
+ fs.mkdirSync(staticDest, { recursive: true });
125
+ copyDirectory(staticPath, staticDest);
126
+ }
127
+ // Copiar public
128
+ const publicPath = path.join(resolvedProjectPath, 'public');
129
+ if (fs.existsSync(publicPath)) {
130
+ const publicDest = path.join(standaloneDest, 'public');
131
+ fs.mkdirSync(publicDest, { recursive: true });
132
+ copyDirectory(publicPath, publicDest);
133
+ }
134
+ // Verificar server.js
135
+ const serverJsPath = path.join(standaloneDest, 'server.js');
136
+ if (!fs.existsSync(serverJsPath)) {
137
+ copySpinner.fail('server.js not found in standalone');
138
+ process.exit(1);
139
+ }
140
+ copySpinner.succeed('Files copied successfully');
141
+ // Paso 3: Crear Dockerfile
142
+ const dockerfilePath = path.join(resolvedDestFolder, 'Dockerfile');
143
+ const dockerfileContent = `FROM node:20-alpine
144
+ WORKDIR /app
145
+
146
+ ENV NODE_ENV=production
147
+ ENV PORT=3000
148
+
149
+ # Copiamos el contenido de standalone
150
+ COPY standalone/ .
151
+
152
+ # Exponemos el puerto para Traefik
153
+ EXPOSE 3000
154
+
155
+ # Arrancamos directamente con Node
156
+ CMD ["node", "server.js"]
157
+ `;
158
+ fs.writeFileSync(dockerfilePath, dockerfileContent);
159
+ // Paso 4: Verificar/crear builder multi-plataforma
160
+ const builderSpinner = (0, ora_1.default)('Setting up multi-platform builder...').start();
161
+ try {
162
+ const builders = (0, child_process_1.execSync)('docker buildx ls', { encoding: 'utf-8' });
163
+ const builderName = 'multiarch-builder';
164
+ if (!builders.includes(builderName)) {
165
+ (0, child_process_1.execSync)(`docker buildx create --name ${builderName} --use --bootstrap`, { stdio: 'pipe' });
166
+ }
167
+ else {
168
+ (0, child_process_1.execSync)(`docker buildx use ${builderName}`, { stdio: 'pipe' });
169
+ }
170
+ builderSpinner.succeed('Builder ready');
171
+ }
172
+ catch (error) {
173
+ builderSpinner.fail('Failed to setup builder');
174
+ console.error(chalk_1.default.red('Error setting up Docker buildx builder'));
175
+ process.exit(1);
176
+ }
177
+ // Paso 5: Construir y hacer push
178
+ const buildDockerSpinner = (0, ora_1.default)('Building Docker image for multiple platforms...').start();
179
+ try {
180
+ const tags = options.push
181
+ ? [`--tag ${imageName}`, `--tag ${imageLatest}`, '--push']
182
+ : [`--tag ${imageName}`, `--tag ${imageLatest}`, '--load'];
183
+ const buildCommand = `docker buildx build \
184
+ --platform linux/amd64,linux/arm64 \
185
+ ${tags.join(' \\\n ')} \
186
+ --progress=plain \
187
+ .`;
188
+ (0, child_process_1.execSync)(buildCommand, {
189
+ cwd: resolvedDestFolder,
190
+ stdio: 'inherit'
191
+ });
192
+ buildDockerSpinner.succeed('Docker image built successfully');
193
+ console.log(chalk_1.default.green('\n✅ Deployment completed successfully!'));
194
+ console.log(chalk_1.default.gray('Image details:'));
195
+ console.log(chalk_1.default.white(` Platforms: ${chalk_1.default.cyan('linux/amd64, linux/arm64')}`));
196
+ console.log(chalk_1.default.white(` Version: ${chalk_1.default.cyan(version)}`));
197
+ console.log(chalk_1.default.white(` Tags:`));
198
+ console.log(chalk_1.default.white(` - ${chalk_1.default.cyan(imageName)}`));
199
+ console.log(chalk_1.default.white(` - ${chalk_1.default.cyan(imageLatest)}`));
200
+ if (options.push) {
201
+ console.log(chalk_1.default.white(` Registry: ${chalk_1.default.cyan('Docker Hub')}`));
202
+ console.log(chalk_1.default.white(` URL: ${chalk_1.default.cyan(`https://hub.docker.com/r/${imageBase}`)}`));
203
+ }
204
+ }
205
+ catch (error) {
206
+ buildDockerSpinner.fail('Docker build failed');
207
+ console.error(chalk_1.default.red('\n❌ Error building Docker image'));
208
+ if (options.push) {
209
+ console.error(chalk_1.default.yellow('Make sure you are authenticated: docker login'));
210
+ }
211
+ process.exit(1);
212
+ }
27
213
  }
28
- // Simular proceso de deployment
29
- const spinner = (0, ora_1.default)('Preparing deployment...').start();
30
- await sleep(1000);
31
- spinner.text = 'Building application...';
32
- await sleep(1500);
33
- if (!options.skipTests) {
34
- spinner.text = 'Running tests...';
35
- await sleep(1000);
214
+ catch (error) {
215
+ console.error(chalk_1.default.red(`\n❌ Error: ${error.message}`));
216
+ process.exit(1);
36
217
  }
37
- await sleep(1000);
38
- spinner.text = `Deploying to ${options.env}...`;
39
- await sleep(2000);
40
- spinner.succeed(chalk_1.default.green(`✅ Successfully deployed to ${options.env}!`));
41
- console.log(chalk_1.default.gray('\n📦 Deployment URL:'), chalk_1.default.cyan(`https://${options.env}.codecrypto.com`));
42
218
  });
43
- function sleep(ms) {
44
- return new Promise(resolve => setTimeout(resolve, ms));
219
+ // Helper functions
220
+ function findDirectory(root, name) {
221
+ try {
222
+ const entries = fs.readdirSync(root, { withFileTypes: true });
223
+ for (const entry of entries) {
224
+ const fullPath = path.join(root, entry.name);
225
+ if (entry.isDirectory()) {
226
+ if (entry.name === name) {
227
+ return fullPath;
228
+ }
229
+ const found = findDirectory(fullPath, name);
230
+ if (found)
231
+ return found;
232
+ }
233
+ }
234
+ }
235
+ catch (error) {
236
+ // Ignore errors
237
+ }
238
+ return null;
239
+ }
240
+ function copyDirectory(src, dest) {
241
+ if (!fs.existsSync(dest)) {
242
+ fs.mkdirSync(dest, { recursive: true });
243
+ }
244
+ const entries = fs.readdirSync(src, { withFileTypes: true });
245
+ for (const entry of entries) {
246
+ const srcPath = path.join(src, entry.name);
247
+ const destPath = path.join(dest, entry.name);
248
+ if (entry.isDirectory()) {
249
+ copyDirectory(srcPath, destPath);
250
+ }
251
+ else {
252
+ fs.copyFileSync(srcPath, destPath);
253
+ }
254
+ }
45
255
  }
46
256
  //# sourceMappingURL=deploy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codecrypto-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "CLI tool for CodeCrypto operations",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -1,49 +1,233 @@
1
1
  import { Command } from 'commander';
2
2
  import chalk from 'chalk';
3
3
  import ora from 'ora';
4
+ import { execSync } from 'child_process';
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
4
7
 
5
8
  export const deployCommand = new Command('deploy')
6
- .description('Deploy your application to different environments')
7
- .option('-e, --env <environment>', 'Environment to deploy (dev, staging, prod)', 'dev')
8
- .option('-b, --branch <branch>', 'Git branch to deploy', 'main')
9
- .option('-r, --region <region>', 'AWS region', 'us-east-1')
10
- .option('--skip-tests', 'Skip running tests before deployment', false)
11
- .option('--dry-run', 'Simulate deployment without actually deploying', false)
12
- .action(async (options) => {
13
- console.log(chalk.blue('\n🚀 CodeCrypto Deployment\n'));
14
-
15
- console.log(chalk.gray('Deployment Configuration:'));
16
- console.log(chalk.white(` Environment: ${chalk.green(options.env)}`));
17
- console.log(chalk.white(` Branch: ${chalk.green(options.branch)}`));
18
- console.log(chalk.white(` Region: ${chalk.green(options.region)}`));
19
- console.log(chalk.white(` Skip Tests: ${options.skipTests ? chalk.yellow('Yes') : chalk.green('No')}`));
20
- console.log(chalk.white(` Dry Run: ${options.dryRun ? chalk.yellow('Yes') : chalk.green('No')}`));
21
-
22
- if (options.dryRun) {
23
- console.log(chalk.yellow('\n⚠️ Running in dry-run mode. No actual deployment will occur.\n'));
24
- }
9
+ .description('Build and deploy Docker image for Next.js standalone application')
10
+ .argument('<project-path>', 'Path to the Next.js project directory')
11
+ .argument('[dest-folder]', 'Destination folder for Docker build context', './docker-build')
12
+ .option('--skip-build', 'Skip npm run build (assume already built)', false)
13
+ .option('--no-push', 'Build image but do not push to registry', false)
14
+ .action(async (projectPath: string, destFolder: string, options) => {
15
+ console.log(chalk.blue('\n🐳 CodeCrypto Docker Deployment\n'));
25
16
 
26
- // Simular proceso de deployment
27
- const spinner = ora('Preparing deployment...').start();
17
+ try {
18
+ // Validar que el proyecto existe
19
+ const resolvedProjectPath = path.resolve(projectPath);
20
+ if (!fs.existsSync(resolvedProjectPath)) {
21
+ console.error(chalk.red(`❌ Error: El directorio del proyecto no existe: ${resolvedProjectPath}`));
22
+ process.exit(1);
23
+ }
28
24
 
29
- await sleep(1000);
30
- spinner.text = 'Building application...';
25
+ // Verificar que es un proyecto Next.js
26
+ const packageJsonPath = path.join(resolvedProjectPath, 'package.json');
27
+ if (!fs.existsSync(packageJsonPath)) {
28
+ console.error(chalk.red(`❌ Error: No se encontró package.json en el proyecto`));
29
+ process.exit(1);
30
+ }
31
31
 
32
- await sleep(1500);
33
- if (!options.skipTests) {
34
- spinner.text = 'Running tests...';
35
- await sleep(1000);
36
- }
32
+ // Leer versión del package.json
33
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
34
+ const version = packageJson.version || 'latest';
35
+ const projectName = path.basename(resolvedProjectPath);
36
+ const imageBase = `jviejo/${projectName}`;
37
+ const imageName = `${imageBase}:${version}`;
38
+ const imageLatest = `${imageBase}:latest`;
39
+
40
+ console.log(chalk.gray('Deployment Configuration:'));
41
+ console.log(chalk.white(` Project: ${chalk.green(projectName)}`));
42
+ console.log(chalk.white(` Version: ${chalk.green(version)}`));
43
+ console.log(chalk.white(` Image: ${chalk.green(imageName)}`));
44
+ console.log(chalk.white(` Latest: ${chalk.green(imageLatest)}`));
45
+ console.log(chalk.white(` Push to Registry: ${options.push ? chalk.green('Yes') : chalk.yellow('No')}\n`));
46
+
47
+ // Paso 1: Build del proyecto si es necesario
48
+ if (!options.skipBuild) {
49
+ const buildSpinner = ora('Building Next.js application...').start();
50
+ try {
51
+ execSync('npm run build', {
52
+ cwd: resolvedProjectPath,
53
+ stdio: 'pipe'
54
+ });
55
+ buildSpinner.succeed('Build completed successfully');
56
+ } catch (error) {
57
+ buildSpinner.fail('Build failed');
58
+ console.error(chalk.red('Error during build. Make sure you have "output: standalone" in next.config.ts'));
59
+ process.exit(1);
60
+ }
61
+ }
62
+
63
+ // Verificar que existe .next/standalone
64
+ const standalonePath = path.join(resolvedProjectPath, '.next', 'standalone');
65
+ if (!fs.existsSync(standalonePath)) {
66
+ console.error(chalk.red(`❌ Error: No se encontró .next/standalone`));
67
+ console.error(chalk.yellow('Asegúrate de tener "output: standalone" en next.config.ts y ejecutar "npm run build"'));
68
+ process.exit(1);
69
+ }
70
+
71
+ // Paso 2: Preparar directorio destino
72
+ const resolvedDestFolder = path.resolve(destFolder);
73
+ const standaloneDest = path.join(resolvedDestFolder, 'standalone');
74
+
75
+ const copySpinner = ora('Copying standalone files...').start();
76
+ if (fs.existsSync(resolvedDestFolder)) {
77
+ fs.rmSync(resolvedDestFolder, { recursive: true, force: true });
78
+ }
79
+ fs.mkdirSync(standaloneDest, { recursive: true });
80
+
81
+ // Copiar contenido de standalone
82
+ const nextDir = findDirectory(standalonePath, '.next');
83
+ if (nextDir) {
84
+ const parentDir = path.dirname(nextDir);
85
+ copyDirectory(parentDir, standaloneDest);
86
+ } else {
87
+ copyDirectory(standalonePath, standaloneDest);
88
+ }
89
+
90
+ // Copiar .next/static
91
+ const staticPath = path.join(resolvedProjectPath, '.next', 'static');
92
+ if (fs.existsSync(staticPath)) {
93
+ const staticDest = path.join(standaloneDest, '.next', 'static');
94
+ fs.mkdirSync(staticDest, { recursive: true });
95
+ copyDirectory(staticPath, staticDest);
96
+ }
97
+
98
+ // Copiar public
99
+ const publicPath = path.join(resolvedProjectPath, 'public');
100
+ if (fs.existsSync(publicPath)) {
101
+ const publicDest = path.join(standaloneDest, 'public');
102
+ fs.mkdirSync(publicDest, { recursive: true });
103
+ copyDirectory(publicPath, publicDest);
104
+ }
105
+
106
+ // Verificar server.js
107
+ const serverJsPath = path.join(standaloneDest, 'server.js');
108
+ if (!fs.existsSync(serverJsPath)) {
109
+ copySpinner.fail('server.js not found in standalone');
110
+ process.exit(1);
111
+ }
112
+
113
+ copySpinner.succeed('Files copied successfully');
114
+
115
+ // Paso 3: Crear Dockerfile
116
+ const dockerfilePath = path.join(resolvedDestFolder, 'Dockerfile');
117
+ const dockerfileContent = `FROM node:20-alpine
118
+ WORKDIR /app
37
119
 
38
- await sleep(1000);
39
- spinner.text = `Deploying to ${options.env}...`;
120
+ ENV NODE_ENV=production
121
+ ENV PORT=3000
40
122
 
41
- await sleep(2000);
42
- spinner.succeed(chalk.green(`✅ Successfully deployed to ${options.env}!`));
123
+ # Copiamos el contenido de standalone
124
+ COPY standalone/ .
43
125
 
44
- console.log(chalk.gray('\n📦 Deployment URL:'), chalk.cyan(`https://${options.env}.codecrypto.com`));
126
+ # Exponemos el puerto para Traefik
127
+ EXPOSE 3000
128
+
129
+ # Arrancamos directamente con Node
130
+ CMD ["node", "server.js"]
131
+ `;
132
+ fs.writeFileSync(dockerfilePath, dockerfileContent);
133
+
134
+ // Paso 4: Verificar/crear builder multi-plataforma
135
+ const builderSpinner = ora('Setting up multi-platform builder...').start();
136
+ try {
137
+ const builders = execSync('docker buildx ls', { encoding: 'utf-8' });
138
+ const builderName = 'multiarch-builder';
139
+ if (!builders.includes(builderName)) {
140
+ execSync(`docker buildx create --name ${builderName} --use --bootstrap`, { stdio: 'pipe' });
141
+ } else {
142
+ execSync(`docker buildx use ${builderName}`, { stdio: 'pipe' });
143
+ }
144
+ builderSpinner.succeed('Builder ready');
145
+ } catch (error) {
146
+ builderSpinner.fail('Failed to setup builder');
147
+ console.error(chalk.red('Error setting up Docker buildx builder'));
148
+ process.exit(1);
149
+ }
150
+
151
+ // Paso 5: Construir y hacer push
152
+ const buildDockerSpinner = ora('Building Docker image for multiple platforms...').start();
153
+ try {
154
+ const tags = options.push
155
+ ? [`--tag ${imageName}`, `--tag ${imageLatest}`, '--push']
156
+ : [`--tag ${imageName}`, `--tag ${imageLatest}`, '--load'];
157
+
158
+ const buildCommand = `docker buildx build \
159
+ --platform linux/amd64,linux/arm64 \
160
+ ${tags.join(' \\\n ')} \
161
+ --progress=plain \
162
+ .`;
163
+
164
+ execSync(buildCommand, {
165
+ cwd: resolvedDestFolder,
166
+ stdio: 'inherit'
167
+ });
168
+
169
+ buildDockerSpinner.succeed('Docker image built successfully');
170
+
171
+ console.log(chalk.green('\n✅ Deployment completed successfully!'));
172
+ console.log(chalk.gray('Image details:'));
173
+ console.log(chalk.white(` Platforms: ${chalk.cyan('linux/amd64, linux/arm64')}`));
174
+ console.log(chalk.white(` Version: ${chalk.cyan(version)}`));
175
+ console.log(chalk.white(` Tags:`));
176
+ console.log(chalk.white(` - ${chalk.cyan(imageName)}`));
177
+ console.log(chalk.white(` - ${chalk.cyan(imageLatest)}`));
178
+ if (options.push) {
179
+ console.log(chalk.white(` Registry: ${chalk.cyan('Docker Hub')}`));
180
+ console.log(chalk.white(` URL: ${chalk.cyan(`https://hub.docker.com/r/${imageBase}`)}`));
181
+ }
182
+ } catch (error) {
183
+ buildDockerSpinner.fail('Docker build failed');
184
+ console.error(chalk.red('\n❌ Error building Docker image'));
185
+ if (options.push) {
186
+ console.error(chalk.yellow('Make sure you are authenticated: docker login'));
187
+ }
188
+ process.exit(1);
189
+ }
190
+
191
+ } catch (error: any) {
192
+ console.error(chalk.red(`\n❌ Error: ${error.message}`));
193
+ process.exit(1);
194
+ }
45
195
  });
46
196
 
47
- function sleep(ms: number): Promise<void> {
48
- return new Promise(resolve => setTimeout(resolve, ms));
197
+ // Helper functions
198
+ function findDirectory(root: string, name: string): string | null {
199
+ try {
200
+ const entries = fs.readdirSync(root, { withFileTypes: true });
201
+ for (const entry of entries) {
202
+ const fullPath = path.join(root, entry.name);
203
+ if (entry.isDirectory()) {
204
+ if (entry.name === name) {
205
+ return fullPath;
206
+ }
207
+ const found = findDirectory(fullPath, name);
208
+ if (found) return found;
209
+ }
210
+ }
211
+ } catch (error) {
212
+ // Ignore errors
213
+ }
214
+ return null;
215
+ }
216
+
217
+ function copyDirectory(src: string, dest: string): void {
218
+ if (!fs.existsSync(dest)) {
219
+ fs.mkdirSync(dest, { recursive: true });
220
+ }
221
+
222
+ const entries = fs.readdirSync(src, { withFileTypes: true });
223
+ for (const entry of entries) {
224
+ const srcPath = path.join(src, entry.name);
225
+ const destPath = path.join(dest, entry.name);
226
+
227
+ if (entry.isDirectory()) {
228
+ copyDirectory(srcPath, destPath);
229
+ } else {
230
+ fs.copyFileSync(srcPath, destPath);
231
+ }
232
+ }
49
233
  }
Binary file