entexto-cli 1.4.8 → 2.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/bin/entexto.js CHANGED
@@ -85,6 +85,45 @@ program
85
85
  require('../lib/commands/tunnel')({ target: target || '3000' });
86
86
  });
87
87
 
88
+ // ─── entexto create ──────────────────────────────────────────
89
+ program
90
+ .command('create')
91
+ .description('Crear un nuevo proyecto (interactivo o con opciones)')
92
+ .option('-n, --name <name>', 'Nombre del proyecto')
93
+ .option('-t, --template <type>', 'Plantilla: blank | basic | react | fullstack | local')
94
+ .option('-d, --dir <path>', 'Carpeta a subir (con template=local)', '.')
95
+ .action(require('../lib/commands/create'));
96
+
97
+ // ─── entexto domain ──────────────────────────────────────────
98
+ program
99
+ .command('domain [action] [value]')
100
+ .description('Gestionar dominios: list | add | subdomain | verify')
101
+ .option('-p, --project <id>', 'ID del proyecto a vincular')
102
+ .action(require('../lib/commands/domain'));
103
+
104
+ // ─── entexto publish ─────────────────────────────────────────
105
+ program
106
+ .command('publish')
107
+ .description('Publicar un proyecto rápidamente')
108
+ .option('-i, --id <uuid>', 'UUID del proyecto a publicar')
109
+ .action((options) => {
110
+ require('../lib/commands/publish')({ uuid: options.id });
111
+ });
112
+
113
+ // ─── entexto api ──────────────────────────────────────────────
114
+ program
115
+ .command('api [action] [slug]')
116
+ .description('API Platform: list | create | info | collection | insert | query')
117
+ .option('-n, --name <name>', 'Nombre')
118
+ .option('-D, --description <desc>', 'Descripción')
119
+ .action(require('../lib/commands/api-platform'));
120
+
121
+ // ─── entexto live ─────────────────────────────────────────────
122
+ program
123
+ .command('live')
124
+ .description('Guía del Live SDK (WebRTC, videollamadas, tiempo real)')
125
+ .action(require('../lib/commands/live'));
126
+
88
127
  program.parse(process.argv);
89
128
 
90
129
  if (!process.argv.slice(2).length) {
@@ -0,0 +1,657 @@
1
+ # fullappdeploy.md — Guía Completa para Desplegar Apps con EntExto CLI
2
+
3
+ > **Versión**: 2.0.0
4
+ > **Para**: IAs y desarrolladores que necesiten crear, configurar y desplegar una aplicación completa desde la terminal.
5
+
6
+ ---
7
+
8
+ ## 1. Instalación
9
+
10
+ ```bash
11
+ npm install -g entexto-cli
12
+ ```
13
+
14
+ Verifica la instalación:
15
+ ```bash
16
+ entexto --version
17
+ ```
18
+
19
+ ---
20
+
21
+ ## 2. Autenticación
22
+
23
+ ```bash
24
+ entexto login
25
+ ```
26
+
27
+ Ingresa tu email y contraseña de entexto.com. El token se guarda en `~/.entexto/config.json`.
28
+
29
+ **Verificar sesión:**
30
+ ```bash
31
+ entexto whoami
32
+ ```
33
+
34
+ **Cerrar sesión:**
35
+ ```bash
36
+ entexto logout
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 3. Crear un Proyecto
42
+
43
+ ### Modo interactivo
44
+ ```bash
45
+ entexto create
46
+ ```
47
+
48
+ El CLI te guía paso a paso:
49
+ 1. Nombre del proyecto
50
+ 2. Descripción
51
+ 3. Plantilla (blank, basic, react, fullstack, local)
52
+ 4. ¿Publicar ahora?
53
+ 5. ¿Vincular dominio/subdominio?
54
+
55
+ ### Con opciones directas
56
+ ```bash
57
+ entexto create --name "Mi App" --template react
58
+ entexto create --name "Backend" --template fullstack
59
+ entexto create --name "Desde carpeta" --template local --dir ./mi-proyecto
60
+ ```
61
+
62
+ ### Plantillas disponibles
63
+
64
+ | Plantilla | Descripción |
65
+ |-------------|-------------|
66
+ | `blank` | Proyecto vacío con index.html mínimo |
67
+ | `basic` | HTML + CSS + JS con estructura base |
68
+ | `react` | React con CDN (Babel + ReactDOM) listo para JSX |
69
+ | `fullstack` | React + VFS (sistema de archivos virtual) + Live SDK preconfigurado |
70
+ | `local` | Sube una carpeta existente de tu disco como proyecto |
71
+
72
+ ---
73
+
74
+ ## 4. Desplegar Archivos
75
+
76
+ ### Deploy básico
77
+ ```bash
78
+ entexto deploy --id <uuid> --dir ./mi-proyecto
79
+ ```
80
+
81
+ ### Deploy con publicación automática
82
+ ```bash
83
+ entexto deploy --id <uuid> --dir ./mi-proyecto --publish
84
+ ```
85
+
86
+ ### Deploy con watch (live reload)
87
+ ```bash
88
+ entexto deploy --id <uuid> --dir ./mi-proyecto --watch
89
+ ```
90
+
91
+ ### Deploy completo (sin delta)
92
+ ```bash
93
+ entexto deploy --id <uuid> --dir ./mi-proyecto --full
94
+ ```
95
+
96
+ > **Nota**: El deploy usa delta por defecto — solo sube archivos que cambiaron (basado en SHA256).
97
+
98
+ ---
99
+
100
+ ## 5. Publicar un Proyecto
101
+
102
+ ```bash
103
+ entexto publish --id <uuid>
104
+ ```
105
+
106
+ O selecciona de la lista interactiva:
107
+ ```bash
108
+ entexto publish
109
+ ```
110
+
111
+ Una vez publicado, el proyecto es accesible en: `https://entexto.com/p/<uuid>`
112
+
113
+ ---
114
+
115
+ ## 6. Gestión de Dominios
116
+
117
+ ### Listar dominios configurados
118
+ ```bash
119
+ entexto domain list
120
+ ```
121
+
122
+ ### Agregar un dominio propio
123
+ ```bash
124
+ entexto domain add midominio.com --project <id>
125
+ ```
126
+
127
+ El CLI mostrará las instrucciones DNS:
128
+ - **Opción A**: Registro A apuntando al IP del servidor
129
+ - **Opción B**: CNAME apuntando a `entexto.com`
130
+ - **Opción C**: CNAME apuntando al tunnel de Cloudflare
131
+
132
+ ### Crear un subdominio de un dominio verificado
133
+ ```bash
134
+ entexto domain subdomain --project <id>
135
+ ```
136
+
137
+ Selecciona el dominio padre y escribe el subdominio deseado (ej: `app` → `app.midominio.com`).
138
+
139
+ ### Verificar un dominio
140
+ ```bash
141
+ entexto domain verify midominio.com
142
+ ```
143
+
144
+ Métodos de verificación soportados:
145
+ 1. Registro A directo
146
+ 2. CNAME a cfargotunnel.com
147
+ 3. CNAME a entexto.com
148
+ 4. NS delegation (ns1/ns2.entexto.com)
149
+ 5. HTTP ping fallback
150
+
151
+ ---
152
+
153
+ ## 7. API Platform (BaaS)
154
+
155
+ EntExto incluye un Backend-as-a-Service completo. Gestiona APIs REST desde la terminal.
156
+
157
+ ### Crear una API
158
+ ```bash
159
+ entexto api create
160
+ ```
161
+
162
+ Responde: nombre y descripción. Recibirás:
163
+ - **Slug** para las URLs
164
+ - **API Key** para autenticarte
165
+ - **Base URL**: `https://api.entexto.com/v1/api/<slug>`
166
+
167
+ ### Listar tus APIs
168
+ ```bash
169
+ entexto api list
170
+ ```
171
+
172
+ ### Ver detalle de una API
173
+ ```bash
174
+ entexto api info <slug>
175
+ ```
176
+
177
+ ### Crear una colección
178
+ ```bash
179
+ entexto api collection <slug>
180
+ ```
181
+
182
+ ### Insertar un documento
183
+ ```bash
184
+ entexto api insert <slug>
185
+ ```
186
+
187
+ Se abre un editor para escribir el JSON del documento.
188
+
189
+ ### Consultar documentos
190
+ ```bash
191
+ entexto api query <slug>
192
+ ```
193
+
194
+ ### Usar la API desde código
195
+
196
+ ```javascript
197
+ // Autenticación con API Key
198
+ const resp = await fetch('https://api.entexto.com/v1/api/mi-api/collections/usuarios/documents', {
199
+ method: 'POST',
200
+ headers: {
201
+ 'Content-Type': 'application/json',
202
+ 'X-API-Key': 'tu-api-key'
203
+ },
204
+ body: JSON.stringify({
205
+ data: { nombre: 'Juan', email: 'juan@test.com' }
206
+ })
207
+ });
208
+
209
+ // O con JWT
210
+ const login = await fetch('https://api.entexto.com/v1/api/auth/login', {
211
+ method: 'POST',
212
+ headers: { 'Content-Type': 'application/json' },
213
+ body: JSON.stringify({ email: 'tu@email.com', password: 'tu-password' })
214
+ });
215
+ const { token } = await login.json();
216
+
217
+ const docs = await fetch('https://api.entexto.com/v1/api/mi-api/collections/usuarios/documents', {
218
+ headers: { 'Authorization': `Bearer ${token}` }
219
+ });
220
+ ```
221
+
222
+ ---
223
+
224
+ ## 8. Live SDK (Tiempo Real + WebRTC)
225
+
226
+ ### ¿Qué es?
227
+ El Live SDK permite agregar comunicación en tiempo real a cualquier proyecto: chat, videollamadas, audio, pantalla compartida, y eventos.
228
+
229
+ ### Ver la guía completa
230
+ ```bash
231
+ entexto live
232
+ ```
233
+
234
+ ### Uso rápido en un proyecto publicado
235
+
236
+ ```html
237
+ <!-- El SDK se inyecta automáticamente en proyectos publicados -->
238
+ <script>
239
+ // Crear/unirse a una sala
240
+ const sala = window.__entexto.live.sala('mi-sala', {
241
+ usuario: 'Pedro'
242
+ });
243
+
244
+ // Escuchar eventos
245
+ sala.escuchar('mensaje', (data, remitente) => {
246
+ console.log(remitente, 'dice:', data);
247
+ });
248
+
249
+ // Enviar a todos
250
+ sala.emitir('mensaje', { texto: 'Hola a todos' });
251
+
252
+ // Presencia
253
+ sala.onEntra((usuario, socketId) => {
254
+ console.log(usuario, 'entró');
255
+ });
256
+
257
+ sala.onSale((usuario, socketId) => {
258
+ console.log(usuario, 'salió');
259
+ });
260
+ </script>
261
+ ```
262
+
263
+ ### Métodos disponibles
264
+
265
+ | Método | Descripción |
266
+ |--------|-------------|
267
+ | `sala.escuchar(evento, callback)` | Escuchar un evento de la sala |
268
+ | `sala.emitir(evento, data)` | Enviar a todos en la sala |
269
+ | `sala.emitirA(socketId, evento, data)` | Enviar a un usuario específico |
270
+ | `sala.onRelay(callback)` | Recibir señalización WebRTC |
271
+ | `sala.onEntra(callback)` | Evento: usuario entró |
272
+ | `sala.onSale(callback)` | Evento: usuario salió |
273
+ | `sala.salir()` | Salir de la sala |
274
+
275
+ ### Videollamadas WebRTC
276
+
277
+ ```javascript
278
+ // 1. Obtener media local
279
+ const stream = await navigator.mediaDevices.getUserMedia({
280
+ video: true,
281
+ audio: true
282
+ });
283
+
284
+ // 2. Obtener config TURN (automático en EntExto)
285
+ const resp = await fetch('/api/turn-config');
286
+ const { iceServers } = await resp.json();
287
+
288
+ // 3. Crear conexión WebRTC
289
+ const pc = new RTCPeerConnection({ iceServers });
290
+
291
+ // 4. Agregar tracks
292
+ stream.getTracks().forEach(track => pc.addTrack(track, stream));
293
+
294
+ // 5. Negociar via Live SDK
295
+ pc.onicecandidate = (e) => {
296
+ if (e.candidate) sala.emitir('relay', { target: peerId, candidate: e.candidate });
297
+ };
298
+
299
+ pc.createOffer().then(offer => {
300
+ pc.setLocalDescription(offer);
301
+ sala.emitir('relay', { target: peerId, sdp: offer });
302
+ });
303
+
304
+ sala.onRelay((data, fromId) => {
305
+ if (data.sdp) {
306
+ pc.setRemoteDescription(data.sdp);
307
+ if (data.sdp.type === 'offer') {
308
+ pc.createAnswer().then(answer => {
309
+ pc.setLocalDescription(answer);
310
+ sala.emitir('relay', { target: fromId, sdp: answer });
311
+ });
312
+ }
313
+ }
314
+ if (data.candidate) pc.addIceCandidate(data.candidate);
315
+ });
316
+ ```
317
+
318
+ ### ICE Servers
319
+ - **STUN**: `stun:entexto.com:3478`
320
+ - **TURN**: Credenciales automáticas desde `/api/turn-config` (HMAC-SHA1, TTL 24h)
321
+
322
+ ---
323
+
324
+ ## 9. Flujo Completo Automatizado (para IAs)
325
+
326
+ Este es el flujo exacto que una IA debe seguir para crear una app completa:
327
+
328
+ ```bash
329
+ # Paso 1: Login
330
+ entexto login
331
+ # → Ingresar email y password
332
+
333
+ # Paso 2: Crear proyecto
334
+ entexto create --name "Mi App Completa" --template fullstack
335
+ # → Anota el UUID del proyecto creado
336
+
337
+ # Paso 3: Desarrollar localmente
338
+ # Crear archivos en una carpeta local:
339
+ mkdir mi-app && cd mi-app
340
+
341
+ # index.html - página principal
342
+ # app.js - lógica de la aplicación
343
+ # styles.css - estilos
344
+
345
+ # Paso 4: Deploy
346
+ entexto deploy --id <uuid> --dir . --publish
347
+
348
+ # Paso 5: Configurar dominio (opcional)
349
+ entexto domain add miapp.com --project <project_id>
350
+ # O crear subdominio:
351
+ entexto domain subdomain
352
+
353
+ # Paso 6: Crear API backend (opcional)
354
+ entexto api create
355
+ # → Nombre: "mi-app-api"
356
+ # → Anota el slug y API Key
357
+
358
+ # Paso 7: Crear colecciones de datos
359
+ entexto api collection mi-app-api
360
+ # → Nombre: "usuarios"
361
+
362
+ entexto api collection mi-app-api
363
+ # → Nombre: "datos"
364
+
365
+ # Paso 8: Insertar datos iniciales
366
+ entexto api insert mi-app-api
367
+ # → Seleccionar colección → Escribir JSON
368
+
369
+ # Paso 9: Agregar Live SDK al proyecto (si necesita tiempo real)
370
+ # En index.html agregar:
371
+ # <script src="/_entexto/live.js"></script>
372
+ # Usar sala.escuchar/emitir para comunicación
373
+
374
+ # Paso 10: Re-deploy con cambios finales
375
+ entexto deploy --id <uuid> --dir . --publish
376
+ ```
377
+
378
+ ### Ejemplo: App de Chat en Tiempo Real
379
+
380
+ ```bash
381
+ # Login
382
+ entexto login
383
+
384
+ # Crear proyecto
385
+ entexto create --name "Chat App" --template basic
386
+
387
+ # Crear carpeta local
388
+ mkdir chat-app && cd chat-app
389
+ ```
390
+
391
+ Crear `index.html`:
392
+ ```html
393
+ <!DOCTYPE html>
394
+ <html lang="es">
395
+ <head>
396
+ <meta charset="UTF-8">
397
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
398
+ <title>Chat App</title>
399
+ <style>
400
+ * { margin: 0; padding: 0; box-sizing: border-box; }
401
+ body { font-family: system-ui; background: #1a1a2e; color: #eee; display: flex; flex-direction: column; height: 100vh; }
402
+ #chat { flex: 1; overflow-y: auto; padding: 20px; }
403
+ .msg { margin: 8px 0; padding: 10px 15px; background: #16213e; border-radius: 10px; max-width: 80%; }
404
+ .msg .user { color: #e94560; font-weight: bold; font-size: 0.85em; }
405
+ #form { display: flex; padding: 15px; background: #0f3460; }
406
+ #form input { flex: 1; padding: 12px; border: none; border-radius: 8px; background: #1a1a2e; color: #eee; font-size: 1em; }
407
+ #form button { padding: 12px 24px; margin-left: 10px; border: none; border-radius: 8px; background: #e94560; color: #fff; cursor: pointer; font-weight: bold; }
408
+ </style>
409
+ </head>
410
+ <body>
411
+ <div id="chat"></div>
412
+ <form id="form">
413
+ <input id="msg" placeholder="Escribe un mensaje..." autocomplete="off">
414
+ <button type="submit">Enviar</button>
415
+ </form>
416
+ <script>
417
+ const usuario = prompt('Tu nombre:') || 'Anónimo';
418
+ const sala = window.__entexto.live.sala('chat-general', { usuario });
419
+ const chat = document.getElementById('chat');
420
+
421
+ function addMsg(user, text) {
422
+ const div = document.createElement('div');
423
+ div.className = 'msg';
424
+ div.innerHTML = '<span class="user">' + user + '</span><br>' + text;
425
+ chat.appendChild(div);
426
+ chat.scrollTop = chat.scrollHeight;
427
+ }
428
+
429
+ sala.escuchar('mensaje', (data, remitente) => {
430
+ addMsg(remitente.usuario || '?', data.texto);
431
+ });
432
+
433
+ sala.onEntra((u) => addMsg('Sistema', u + ' se unió al chat'));
434
+ sala.onSale((u) => addMsg('Sistema', u + ' salió del chat'));
435
+
436
+ document.getElementById('form').addEventListener('submit', (e) => {
437
+ e.preventDefault();
438
+ const input = document.getElementById('msg');
439
+ const texto = input.value.trim();
440
+ if (!texto) return;
441
+ sala.emitir('mensaje', { texto });
442
+ addMsg(usuario, texto);
443
+ input.value = '';
444
+ });
445
+ </script>
446
+ </body>
447
+ </html>
448
+ ```
449
+
450
+ ```bash
451
+ # Deploy y publicar
452
+ entexto deploy --id <uuid> --dir . --publish
453
+
454
+ # Listo! Chat funcionando en https://entexto.com/p/<uuid>
455
+ ```
456
+
457
+ ### Ejemplo: App con API + Base de Datos
458
+
459
+ ```bash
460
+ # Crear API
461
+ entexto api create
462
+ # Nombre: "tienda-api"
463
+
464
+ # Crear colecciones
465
+ entexto api collection tienda-api
466
+ # → "productos"
467
+
468
+ entexto api collection tienda-api
469
+ # → "pedidos"
470
+
471
+ # Insertar productos
472
+ entexto api insert tienda-api
473
+ # Colección: productos
474
+ # { "nombre": "Laptop", "precio": 999, "stock": 10 }
475
+ ```
476
+
477
+ Usar desde el frontend:
478
+ ```javascript
479
+ const API_BASE = 'https://api.entexto.com/v1/api/tienda-api';
480
+ const API_KEY = 'tu-api-key';
481
+
482
+ // Listar productos
483
+ const res = await fetch(`${API_BASE}/collections/productos/documents`, {
484
+ headers: { 'X-API-Key': API_KEY }
485
+ });
486
+ const { documents } = await res.json();
487
+
488
+ // Crear pedido
489
+ await fetch(`${API_BASE}/collections/pedidos/documents`, {
490
+ method: 'POST',
491
+ headers: {
492
+ 'Content-Type': 'application/json',
493
+ 'X-API-Key': API_KEY
494
+ },
495
+ body: JSON.stringify({
496
+ data: { producto_id: '...', cantidad: 1, total: 999 }
497
+ })
498
+ });
499
+ ```
500
+
501
+ ---
502
+
503
+ ## 10. Otros Comandos Útiles
504
+
505
+ ### Listar proyectos
506
+ ```bash
507
+ entexto projects
508
+ ```
509
+
510
+ ### Descargar un proyecto
511
+ ```bash
512
+ entexto pull --id <uuid> --dir ./descarga
513
+ entexto clone --id <uuid>
514
+ ```
515
+
516
+ ### Sincronización bidireccional (live)
517
+ ```bash
518
+ entexto sync --id <uuid> --dir .
519
+ ```
520
+
521
+ ### Exponer servidor local
522
+ ```bash
523
+ entexto tunnel 3000
524
+ ```
525
+ Tu servidor local en `localhost:3000` será accesible públicamente.
526
+
527
+ ---
528
+
529
+ ## 11. Estructura de Archivos de un Proyecto Típico
530
+
531
+ ```
532
+ mi-proyecto/
533
+ ├── index.html # Página principal (requerido)
534
+ ├── app.js # Lógica principal
535
+ ├── styles.css # Estilos
536
+ ├── assets/ # Imágenes, fuentes, etc.
537
+ │ ├── logo.png
538
+ │ └── favicon.ico
539
+ └── server/ # Carpeta privada (no se sirve públicamente)
540
+ ├── game-logic.js # Lógica del servidor
541
+ └── hooks.js # Hooks de eventos
542
+ ```
543
+
544
+ > **Nota**: La carpeta `server/` es privada — los archivos dentro no son accesibles desde el navegador pero sí desde la lógica del servidor (VFS).
545
+
546
+ ---
547
+
548
+ ## 12. Sistema de Archivos Virtual (VFS)
549
+
550
+ Los proyectos publicados tienen acceso al VFS para leer/escribir archivos desde JavaScript:
551
+
552
+ ```javascript
553
+ // Leer archivo
554
+ const resp = await fetch('/_entexto/api/fs/leer', {
555
+ method: 'POST',
556
+ headers: { 'Content-Type': 'application/json' },
557
+ body: JSON.stringify({ ruta: 'datos/config.json' })
558
+ });
559
+ const { contenido } = await resp.json();
560
+
561
+ // Escribir archivo
562
+ await fetch('/_entexto/api/fs/escribir', {
563
+ method: 'POST',
564
+ headers: { 'Content-Type': 'application/json' },
565
+ body: JSON.stringify({ ruta: 'datos/config.json', contenido: '{"key":"value"}' })
566
+ });
567
+
568
+ // Listar archivos
569
+ const list = await fetch('/_entexto/api/fs/listar', {
570
+ method: 'POST',
571
+ headers: { 'Content-Type': 'application/json' },
572
+ body: JSON.stringify({ ruta: '.' })
573
+ });
574
+
575
+ // Eliminar archivo
576
+ await fetch('/_entexto/api/fs/eliminar', {
577
+ method: 'POST',
578
+ headers: { 'Content-Type': 'application/json' },
579
+ body: JSON.stringify({ ruta: 'datos/temp.txt' })
580
+ });
581
+
582
+ // Verificar si existe
583
+ const exists = await fetch('/_entexto/api/fs/existe', {
584
+ method: 'POST',
585
+ headers: { 'Content-Type': 'application/json' },
586
+ body: JSON.stringify({ ruta: 'datos/config.json' })
587
+ });
588
+ ```
589
+
590
+ ---
591
+
592
+ ## 13. Seguridad
593
+
594
+ ### Autenticación
595
+ - **CLI**: JWT almacenado localmente en `~/.entexto/config.json`
596
+ - **API Platform**: API Key (header `X-API-Key`) o JWT
597
+ - **Dominios**: Verificación DNS obligatoria antes de servir contenido
598
+
599
+ ### Buenas prácticas
600
+ - Nunca expongas tu API Key en código del frontend público
601
+ - Usa JWT para operaciones sensibles
602
+ - La carpeta `server/` es privada y no se sirve al público
603
+ - Los tokens de TURN tienen TTL de 24 horas
604
+ - Las credenciales TURN usan HMAC-SHA1
605
+
606
+ ### Endpoints protegidos
607
+ Todos los endpoints de CLI, proyectos, y dominios requieren autenticación JWT. El middleware verifica:
608
+ 1. Header `Authorization: Bearer <token>`
609
+ 2. Token válido y no expirado
610
+ 3. Usuario activo en la base de datos
611
+
612
+ ---
613
+
614
+ ## 14. Referencia Rápida de Comandos
615
+
616
+ | Comando | Descripción |
617
+ |---------|-------------|
618
+ | `entexto login` | Iniciar sesión |
619
+ | `entexto logout` | Cerrar sesión |
620
+ | `entexto whoami` | Ver usuario actual |
621
+ | `entexto create` | Crear nuevo proyecto |
622
+ | `entexto projects` | Listar proyectos |
623
+ | `entexto deploy` | Subir archivos |
624
+ | `entexto publish` | Publicar proyecto |
625
+ | `entexto pull` | Descargar proyecto |
626
+ | `entexto clone` | Clonar proyecto |
627
+ | `entexto sync` | Sincronización bidireccional |
628
+ | `entexto tunnel` | Exponer servidor local |
629
+ | `entexto domain list` | Ver dominios |
630
+ | `entexto domain add` | Agregar dominio |
631
+ | `entexto domain subdomain` | Crear subdominio |
632
+ | `entexto domain verify` | Verificar DNS |
633
+ | `entexto api list` | Listar APIs |
634
+ | `entexto api create` | Crear nueva API |
635
+ | `entexto api info` | Ver detalle de API |
636
+ | `entexto api collection` | Crear colección |
637
+ | `entexto api insert` | Insertar documento |
638
+ | `entexto api query` | Consultar documentos |
639
+ | `entexto live` | Guía del Live SDK |
640
+
641
+ ---
642
+
643
+ ## 15. Resolución de Problemas
644
+
645
+ | Problema | Solución |
646
+ |----------|----------|
647
+ | "No has iniciado sesión" | Ejecuta `entexto login` |
648
+ | Deploy falla con timeout | Usa `--full` para forzar subida completa |
649
+ | Dominio no se verifica | Espera propagación DNS (puede tardar hasta 48h) |
650
+ | API Key inválida | Revisa con `entexto api info <slug>` |
651
+ | Live SDK no funciona | Asegúrate de que el proyecto esté publicado |
652
+ | TURN no conecta | Verifica que el servidor TURN esté activo (PM2 id=2) |
653
+ | Archivos no aparecen | Verifica que no estén en carpeta `server/` (privada) |
654
+
655
+ ---
656
+
657
+ *Generado por entexto-cli v2.0.0 — https://entexto.com*