@devalade/shipnode 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.
Files changed (189) hide show
  1. package/dist/cli/commands/backup.d.ts +14 -0
  2. package/dist/cli/commands/backup.d.ts.map +1 -0
  3. package/dist/cli/commands/backup.js +144 -0
  4. package/dist/cli/commands/backup.js.map +1 -0
  5. package/dist/cli/commands/ci.d.ts +5 -0
  6. package/dist/cli/commands/ci.d.ts.map +1 -0
  7. package/dist/cli/commands/ci.js +222 -0
  8. package/dist/cli/commands/ci.js.map +1 -0
  9. package/dist/cli/commands/cloudflare.d.ts +10 -0
  10. package/dist/cli/commands/cloudflare.d.ts.map +1 -0
  11. package/dist/cli/commands/cloudflare.js +166 -0
  12. package/dist/cli/commands/cloudflare.js.map +1 -0
  13. package/dist/cli/commands/config.d.ts +10 -0
  14. package/dist/cli/commands/config.d.ts.map +1 -0
  15. package/dist/cli/commands/config.js +99 -0
  16. package/dist/cli/commands/config.js.map +1 -0
  17. package/dist/cli/commands/deploy.d.ts +6 -0
  18. package/dist/cli/commands/deploy.d.ts.map +1 -0
  19. package/dist/cli/commands/deploy.js +95 -0
  20. package/dist/cli/commands/deploy.js.map +1 -0
  21. package/dist/cli/commands/doctor.d.ts +5 -0
  22. package/dist/cli/commands/doctor.d.ts.map +1 -0
  23. package/dist/cli/commands/doctor.js +86 -0
  24. package/dist/cli/commands/doctor.js.map +1 -0
  25. package/dist/cli/commands/eject.d.ts +2 -0
  26. package/dist/cli/commands/eject.d.ts.map +1 -0
  27. package/dist/cli/commands/eject.js +74 -0
  28. package/dist/cli/commands/eject.js.map +1 -0
  29. package/dist/cli/commands/env.d.ts +4 -0
  30. package/dist/cli/commands/env.d.ts.map +1 -0
  31. package/dist/cli/commands/env.js +50 -0
  32. package/dist/cli/commands/env.js.map +1 -0
  33. package/dist/cli/commands/harden.d.ts +4 -0
  34. package/dist/cli/commands/harden.d.ts.map +1 -0
  35. package/dist/cli/commands/harden.js +110 -0
  36. package/dist/cli/commands/harden.js.map +1 -0
  37. package/dist/cli/commands/help.d.ts +2 -0
  38. package/dist/cli/commands/help.d.ts.map +1 -0
  39. package/dist/cli/commands/help.js +99 -0
  40. package/dist/cli/commands/help.js.map +1 -0
  41. package/dist/cli/commands/init.d.ts +5 -0
  42. package/dist/cli/commands/init.d.ts.map +1 -0
  43. package/dist/cli/commands/init.js +246 -0
  44. package/dist/cli/commands/init.js.map +1 -0
  45. package/dist/cli/commands/logs.d.ts +5 -0
  46. package/dist/cli/commands/logs.d.ts.map +1 -0
  47. package/dist/cli/commands/logs.js +17 -0
  48. package/dist/cli/commands/logs.js.map +1 -0
  49. package/dist/cli/commands/metrics.d.ts +4 -0
  50. package/dist/cli/commands/metrics.d.ts.map +1 -0
  51. package/dist/cli/commands/metrics.js +21 -0
  52. package/dist/cli/commands/metrics.js.map +1 -0
  53. package/dist/cli/commands/migrate.d.ts +4 -0
  54. package/dist/cli/commands/migrate.d.ts.map +1 -0
  55. package/dist/cli/commands/migrate.js +71 -0
  56. package/dist/cli/commands/migrate.js.map +1 -0
  57. package/dist/cli/commands/restart.d.ts +4 -0
  58. package/dist/cli/commands/restart.d.ts.map +1 -0
  59. package/dist/cli/commands/restart.js +14 -0
  60. package/dist/cli/commands/restart.js.map +1 -0
  61. package/dist/cli/commands/rollback.d.ts +5 -0
  62. package/dist/cli/commands/rollback.d.ts.map +1 -0
  63. package/dist/cli/commands/rollback.js +49 -0
  64. package/dist/cli/commands/rollback.js.map +1 -0
  65. package/dist/cli/commands/run.d.ts +5 -0
  66. package/dist/cli/commands/run.d.ts.map +1 -0
  67. package/dist/cli/commands/run.js +69 -0
  68. package/dist/cli/commands/run.js.map +1 -0
  69. package/dist/cli/commands/setup.d.ts +4 -0
  70. package/dist/cli/commands/setup.d.ts.map +1 -0
  71. package/dist/cli/commands/setup.js +46 -0
  72. package/dist/cli/commands/setup.js.map +1 -0
  73. package/dist/cli/commands/status.d.ts +4 -0
  74. package/dist/cli/commands/status.d.ts.map +1 -0
  75. package/dist/cli/commands/status.js +49 -0
  76. package/dist/cli/commands/status.js.map +1 -0
  77. package/dist/cli/commands/stop.d.ts +4 -0
  78. package/dist/cli/commands/stop.d.ts.map +1 -0
  79. package/dist/cli/commands/stop.js +14 -0
  80. package/dist/cli/commands/stop.js.map +1 -0
  81. package/dist/cli/commands/unlock.d.ts +4 -0
  82. package/dist/cli/commands/unlock.d.ts.map +1 -0
  83. package/dist/cli/commands/unlock.js +27 -0
  84. package/dist/cli/commands/unlock.js.map +1 -0
  85. package/dist/cli/commands/upgrade.d.ts +2 -0
  86. package/dist/cli/commands/upgrade.d.ts.map +1 -0
  87. package/dist/cli/commands/upgrade.js +63 -0
  88. package/dist/cli/commands/upgrade.js.map +1 -0
  89. package/dist/cli/commands/user.d.ts +17 -0
  90. package/dist/cli/commands/user.d.ts.map +1 -0
  91. package/dist/cli/commands/user.js +98 -0
  92. package/dist/cli/commands/user.js.map +1 -0
  93. package/dist/cli/index.d.ts +3 -0
  94. package/dist/cli/index.d.ts.map +1 -0
  95. package/dist/cli/index.js +218 -0
  96. package/dist/cli/index.js.map +1 -0
  97. package/dist/cli/prompt.d.ts +2 -0
  98. package/dist/cli/prompt.d.ts.map +1 -0
  99. package/dist/cli/prompt.js +11 -0
  100. package/dist/cli/prompt.js.map +1 -0
  101. package/dist/cli/runner.d.ts +34 -0
  102. package/dist/cli/runner.d.ts.map +1 -0
  103. package/dist/cli/runner.js +44 -0
  104. package/dist/cli/runner.js.map +1 -0
  105. package/dist/cli/ui.d.ts +9 -0
  106. package/dist/cli/ui.d.ts.map +1 -0
  107. package/dist/cli/ui.js +26 -0
  108. package/dist/cli/ui.js.map +1 -0
  109. package/dist/config/assembly.d.ts +14 -0
  110. package/dist/config/assembly.d.ts.map +1 -0
  111. package/dist/config/assembly.js +62 -0
  112. package/dist/config/assembly.js.map +1 -0
  113. package/dist/config/builder.d.ts +33 -0
  114. package/dist/config/builder.d.ts.map +1 -0
  115. package/dist/config/builder.js +119 -0
  116. package/dist/config/builder.js.map +1 -0
  117. package/dist/config/loader.d.ts +3 -0
  118. package/dist/config/loader.d.ts.map +1 -0
  119. package/dist/config/loader.js +20 -0
  120. package/dist/config/loader.js.map +1 -0
  121. package/dist/config/schema.d.ts +416 -0
  122. package/dist/config/schema.d.ts.map +1 -0
  123. package/dist/config/schema.js +75 -0
  124. package/dist/config/schema.js.map +1 -0
  125. package/dist/domain/deploy/backend-strategy.d.ts +15 -0
  126. package/dist/domain/deploy/backend-strategy.d.ts.map +1 -0
  127. package/dist/domain/deploy/backend-strategy.js +110 -0
  128. package/dist/domain/deploy/backend-strategy.js.map +1 -0
  129. package/dist/domain/deploy/frontend-strategy.d.ts +13 -0
  130. package/dist/domain/deploy/frontend-strategy.d.ts.map +1 -0
  131. package/dist/domain/deploy/frontend-strategy.js +64 -0
  132. package/dist/domain/deploy/frontend-strategy.js.map +1 -0
  133. package/dist/domain/deploy/orchestrator.d.ts +34 -0
  134. package/dist/domain/deploy/orchestrator.d.ts.map +1 -0
  135. package/dist/domain/deploy/orchestrator.js +149 -0
  136. package/dist/domain/deploy/orchestrator.js.map +1 -0
  137. package/dist/domain/deploy/strategy.d.ts +44 -0
  138. package/dist/domain/deploy/strategy.d.ts.map +1 -0
  139. package/dist/domain/deploy/strategy.js +2 -0
  140. package/dist/domain/deploy/strategy.js.map +1 -0
  141. package/dist/domain/framework/detector.d.ts +7 -0
  142. package/dist/domain/framework/detector.d.ts.map +1 -0
  143. package/dist/domain/framework/detector.js +109 -0
  144. package/dist/domain/framework/detector.js.map +1 -0
  145. package/dist/domain/release/manager.d.ts +22 -0
  146. package/dist/domain/release/manager.d.ts.map +1 -0
  147. package/dist/domain/release/manager.js +100 -0
  148. package/dist/domain/release/manager.js.map +1 -0
  149. package/dist/domain/remote/executor.d.ts +16 -0
  150. package/dist/domain/remote/executor.d.ts.map +1 -0
  151. package/dist/domain/remote/executor.js +2 -0
  152. package/dist/domain/remote/executor.js.map +1 -0
  153. package/dist/domain/validation/ip.d.ts +5 -0
  154. package/dist/domain/validation/ip.d.ts.map +1 -0
  155. package/dist/domain/validation/ip.js +38 -0
  156. package/dist/domain/validation/ip.js.map +1 -0
  157. package/dist/index.d.ts +6 -0
  158. package/dist/index.d.ts.map +1 -0
  159. package/dist/index.js +4 -0
  160. package/dist/index.js.map +1 -0
  161. package/dist/infrastructure/ssh/connection.d.ts +19 -0
  162. package/dist/infrastructure/ssh/connection.d.ts.map +1 -0
  163. package/dist/infrastructure/ssh/connection.js +89 -0
  164. package/dist/infrastructure/ssh/connection.js.map +1 -0
  165. package/dist/services/caddy.service.d.ts +12 -0
  166. package/dist/services/caddy.service.d.ts.map +1 -0
  167. package/dist/services/caddy.service.js +56 -0
  168. package/dist/services/caddy.service.js.map +1 -0
  169. package/dist/services/deploy.service.d.ts +19 -0
  170. package/dist/services/deploy.service.d.ts.map +1 -0
  171. package/dist/services/deploy.service.js +53 -0
  172. package/dist/services/deploy.service.js.map +1 -0
  173. package/dist/services/health.service.d.ts +13 -0
  174. package/dist/services/health.service.d.ts.map +1 -0
  175. package/dist/services/health.service.js +38 -0
  176. package/dist/services/health.service.js.map +1 -0
  177. package/dist/shared/constants.d.ts +127 -0
  178. package/dist/shared/constants.d.ts.map +1 -0
  179. package/dist/shared/constants.js +85 -0
  180. package/dist/shared/constants.js.map +1 -0
  181. package/dist/shared/errors.d.ts +27 -0
  182. package/dist/shared/errors.d.ts.map +1 -0
  183. package/dist/shared/errors.js +53 -0
  184. package/dist/shared/errors.js.map +1 -0
  185. package/dist/shared/types.d.ts +116 -0
  186. package/dist/shared/types.d.ts.map +1 -0
  187. package/dist/shared/types.js +2 -0
  188. package/dist/shared/types.js.map +1 -0
  189. package/package.json +53 -0
@@ -0,0 +1,99 @@
1
+ import chalk from 'chalk';
2
+ export function cmdHelp() {
3
+ console.log(`
4
+ ${chalk.bold.blue('ShipNode')} v2.0.0 - Deploy Node.js apps to a single VPS
5
+
6
+ ${chalk.bold('USAGE')}
7
+ shipnode <command> [options]
8
+
9
+ ${chalk.bold('CORE')}
10
+ ${chalk.green('init')} Initialize a new shipnode.config.ts
11
+ ${chalk.green('setup')} Setup a new server with required dependencies
12
+ ${chalk.green('deploy')} Deploy your application
13
+ ${chalk.green('doctor')} Check local and remote configuration
14
+ ${chalk.green('status')} Check application status
15
+
16
+ ${chalk.bold('RELEASE MANAGEMENT')}
17
+ ${chalk.green('rollback')} Roll back to a previous release
18
+ ${chalk.green('migrate')} Migrate existing deploy to zero-downtime structure
19
+
20
+ ${chalk.bold('ENVIRONMENT')}
21
+ ${chalk.green('env')} Upload local .env file to the server
22
+ ${chalk.green('run')} <cmd> Run a one-off command on the production server
23
+
24
+ ${chalk.bold('PROCESS MANAGEMENT')}
25
+ ${chalk.green('logs')} Show application logs
26
+ ${chalk.green('restart')} Restart the application
27
+ ${chalk.green('stop')} Stop the application
28
+ ${chalk.green('metrics')} Open PM2 monitoring dashboard
29
+
30
+ ${chalk.bold('SECURITY & MAINTENANCE')}
31
+ ${chalk.green('harden')} Apply server security hardening
32
+ ${chalk.green('unlock')} Clear a stuck deployment lock
33
+
34
+ ${chalk.bold('USERS')}
35
+ ${chalk.green('user sync')} Sync .shipnode/users.yml to server
36
+ ${chalk.green('user list')} List non-system users on server
37
+ ${chalk.green('user remove')} <u> Remove a user from the server
38
+
39
+ ${chalk.bold('BACKUP')}
40
+ ${chalk.green('backup setup')} Install backup script and systemd timer
41
+ ${chalk.green('backup run')} Run a backup immediately
42
+ ${chalk.green('backup status')} Show backup timer and last run
43
+ ${chalk.green('backup list')} List recent backups in S3
44
+
45
+ ${chalk.bold('CLOUDFLARE')}
46
+ ${chalk.green('cloudflare init')} Install cloudflared, configure tunnel/DNS
47
+ ${chalk.green('cloudflare audit')} Verify DNS and tunnel configuration
48
+ ${chalk.green('cloudflare status')} Show cloudflared service status
49
+
50
+ ${chalk.bold('CI/CD')}
51
+ ${chalk.green('ci github')} Generate GitHub Actions deploy workflow
52
+ ${chalk.green('ci env-sync')} Sync .env and config to GitHub secrets
53
+
54
+ ${chalk.bold('CONFIGURATION')}
55
+ ${chalk.green('config show')} Show resolved configuration
56
+ ${chalk.green('config validate')} Validate configuration file
57
+ ${chalk.green('config path')} Print path to config file
58
+
59
+ ${chalk.bold('CUSTOMIZATION')}
60
+ ${chalk.green('eject')} [target] Eject PM2/Caddy templates (pm2, caddy, all)
61
+ ${chalk.green('upgrade')} Upgrade shipnode to the latest version
62
+
63
+ ${chalk.bold('OPTIONS')}
64
+ --dry-run Show what would be deployed (deploy only)
65
+ --skip-build Skip the build step (deploy only)
66
+ --steps <n> Releases to go back (rollback only)
67
+ --lines <n> Log lines to show (logs only, default: 100)
68
+ --tty Force interactive TTY (run only)
69
+ --security Run security audit (doctor only)
70
+ --all Skip confirmation (ci env-sync only)
71
+ --config <path> Use a specific config file
72
+
73
+ ${chalk.bold('EXAMPLES')}
74
+ ${chalk.dim('# First deploy')}
75
+ shipnode init && shipnode setup && shipnode deploy
76
+
77
+ ${chalk.dim('# Roll back one release')}
78
+ shipnode rollback
79
+
80
+ ${chalk.dim('# Run a database migration')}
81
+ shipnode run "npx prisma migrate deploy"
82
+
83
+ ${chalk.dim('# Open interactive shell on server')}
84
+ shipnode run bash
85
+
86
+ ${chalk.dim('# Push .env then restart')}
87
+ shipnode env && shipnode restart
88
+
89
+ ${chalk.dim('# Set up GitHub Actions CI')}
90
+ shipnode ci github && shipnode ci env-sync
91
+
92
+ ${chalk.dim('# Harden server security')}
93
+ shipnode harden
94
+
95
+ ${chalk.bold('DOCUMENTATION')}
96
+ https://github.com/devalade/shipnode
97
+ `);
98
+ }
99
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../../src/cli/commands/help.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,OAAO;IACrB,OAAO,CAAC,GAAG,CAAC;EACZ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;;EAE3B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;;;EAGnB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;IAChB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;IACnB,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;IACpB,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;IACrB,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;IACrB,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;;EAEvB,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC;IAC9B,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC;IACvB,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC;;EAExB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC;IACvB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;IAClB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;;EAEpB,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC;IAC9B,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;IACnB,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;IACnB,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC;;EAExB,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC;IAClC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;IACrB,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;;EAEvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;IACjB,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC;IACxB,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC;IACxB,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC;;EAE5B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;IAClB,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC;IAC3B,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC;IACzB,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC;IAC5B,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC;;EAE5B,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC;IACtB,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC;IAC9B,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC;IAC/B,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC;;EAElC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;IACjB,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC;IACxB,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC;;EAE5B,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC;IACzB,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC;IAC1B,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC;IAC9B,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC;;EAE5B,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC;IACzB,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;IACpB,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC;;EAExB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;;;;;;;;;;EAUrB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;IACpB,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC;;;IAG3B,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC;;;IAGpC,KAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC;;;IAGvC,KAAK,CAAC,GAAG,CAAC,oCAAoC,CAAC;;;IAG/C,KAAK,CAAC,GAAG,CAAC,0BAA0B,CAAC;;;IAGrC,KAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC;;;IAGvC,KAAK,CAAC,GAAG,CAAC,0BAA0B,CAAC;;;EAGvC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC;;CAE5B,CAAC,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function cmdInit(cwd: string, options: {
2
+ nonInteractive?: boolean;
3
+ print?: boolean;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAmBA,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2GhH"}
@@ -0,0 +1,246 @@
1
+ import { writeFile, mkdir, pathExists } from 'fs-extra';
2
+ import { resolve } from 'path';
3
+ import { createInterface } from 'readline';
4
+ import { detectFramework, detectPkgManager } from '../../domain/framework/detector.js';
5
+ import { isValidIpOrHostname, isValidPort } from '../../domain/validation/ip.js';
6
+ import { ORM_PATTERNS } from '../../shared/constants.js';
7
+ import { ui } from '../ui.js';
8
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
9
+ function ask(question, defaultValue) {
10
+ return new Promise((resolve) => {
11
+ const prompt = defaultValue ? `${question} (${defaultValue}): ` : `${question}: `;
12
+ rl.question(prompt, (answer) => {
13
+ resolve(answer.trim() || defaultValue || '');
14
+ });
15
+ });
16
+ }
17
+ export async function cmdInit(cwd, options) {
18
+ ui.info('Initializing ShipNode configuration...');
19
+ const detection = await detectFramework(cwd);
20
+ const pkgManager = await detectPkgManager(cwd);
21
+ const isBackend = detection.appType === 'backend';
22
+ const appName = await getAppName(cwd);
23
+ const defaultPort = detection.port ?? 3000;
24
+ if (options.nonInteractive || options.print) {
25
+ const config = generateConfig({
26
+ app: isBackend ? 'backend' : 'frontend',
27
+ appName,
28
+ backendPort: defaultPort,
29
+ pkgManager: pkgManager ?? undefined,
30
+ });
31
+ if (options.print) {
32
+ console.log(config);
33
+ return;
34
+ }
35
+ const configPath = resolve(cwd, 'shipnode.config.ts');
36
+ const exists = await pathExists(configPath);
37
+ if (exists) {
38
+ ui.warn('shipnode.config.ts already exists. Use --force to overwrite.');
39
+ return;
40
+ }
41
+ await writeFile(configPath, config, 'utf-8');
42
+ ui.success('Created shipnode.config.ts');
43
+ await generateShipnodeDir(cwd, detection.orm);
44
+ return;
45
+ }
46
+ ui.info(`Detected: ${detection.name} (${detection.appType})`);
47
+ if (detection.orm) {
48
+ ui.info(`ORM: ${detection.orm}`);
49
+ }
50
+ const appType = await ask('App type', isBackend ? 'backend' : 'frontend');
51
+ const sshHost = await ask('SSH host');
52
+ if (!isValidIpOrHostname(sshHost)) {
53
+ ui.error('Invalid host. Must be an IP address or hostname.');
54
+ process.exit(1);
55
+ }
56
+ const sshUser = await ask('SSH user', 'deploy');
57
+ const sshPortStr = await ask('SSH port', '22');
58
+ const sshPort = parseInt(sshPortStr, 10);
59
+ if (!isValidPort(sshPort)) {
60
+ ui.error('Invalid port number.');
61
+ process.exit(1);
62
+ }
63
+ const remotePath = await ask('Remote deploy path', `/var/www/${appName}`);
64
+ let pm2Name = '';
65
+ let backendPort = defaultPort;
66
+ let domain = '';
67
+ let zeroDowntime = true;
68
+ let healthCheckPath = '/health';
69
+ if (appType === 'backend') {
70
+ pm2Name = await ask('PM2 app name', appName);
71
+ backendPort = parseInt(await ask('Backend port', String(defaultPort)), 10);
72
+ domain = await ask('Domain (optional)', '');
73
+ const zd = await ask('Enable zero-downtime deployments?', 'yes');
74
+ zeroDowntime = zd.toLowerCase().startsWith('y');
75
+ if (zeroDowntime) {
76
+ healthCheckPath = await ask('Health check path', '/health');
77
+ }
78
+ }
79
+ else {
80
+ domain = await ask('Domain (optional)', '');
81
+ }
82
+ rl.close();
83
+ const config = generateConfig({
84
+ app: appType,
85
+ appName,
86
+ sshHost,
87
+ sshUser,
88
+ sshPort,
89
+ remotePath,
90
+ pm2Name,
91
+ backendPort,
92
+ domain: domain || undefined,
93
+ zeroDowntime,
94
+ healthCheckPath,
95
+ pkgManager: pkgManager ?? undefined,
96
+ });
97
+ const configPath = resolve(cwd, 'shipnode.config.ts');
98
+ const exists = await pathExists(configPath);
99
+ if (exists) {
100
+ ui.warn('shipnode.config.ts already exists. Use --force to overwrite.');
101
+ return;
102
+ }
103
+ await writeFile(configPath, config, 'utf-8');
104
+ ui.success('Created shipnode.config.ts');
105
+ await generateShipnodeDir(cwd, detection.orm);
106
+ }
107
+ async function getAppName(cwd) {
108
+ try {
109
+ const { readFile } = await import('fs/promises');
110
+ const pkgPath = resolve(cwd, 'package.json');
111
+ const content = await readFile(pkgPath, 'utf-8');
112
+ const pkg = JSON.parse(content);
113
+ if (pkg.name) {
114
+ return pkg.name.replace(/^@[^/]+\//, '').replace(/[^a-zA-Z0-9._-]/g, '-');
115
+ }
116
+ }
117
+ catch {
118
+ // ignore
119
+ }
120
+ return cwd.split('/').pop() ?? 'myapp';
121
+ }
122
+ async function generateShipnodeDir(cwd, detectedOrm) {
123
+ const dir = resolve(cwd, '.shipnode');
124
+ await mkdir(dir, { recursive: true });
125
+ const preDeployPath = resolve(dir, 'pre-deploy.sh');
126
+ const postDeployPath = resolve(dir, 'post-deploy.sh');
127
+ const ignorePath = resolve(cwd, '.shipnodeignore');
128
+ if (!(await pathExists(preDeployPath))) {
129
+ await writeFile(preDeployPath, generatePreDeployHook(detectedOrm), 'utf-8');
130
+ await import('fs/promises').then((fs) => fs.chmod(preDeployPath, 0o755));
131
+ }
132
+ if (!(await pathExists(postDeployPath))) {
133
+ await writeFile(postDeployPath, generatePostDeployHook(), 'utf-8');
134
+ await import('fs/promises').then((fs) => fs.chmod(postDeployPath, 0o755));
135
+ }
136
+ if (!(await pathExists(ignorePath))) {
137
+ await writeFile(ignorePath, generateShipnodeIgnore(), 'utf-8');
138
+ }
139
+ const ormMsg = detectedOrm ? ` with ${detectedOrm} commands` : '';
140
+ ui.success(`Generated .shipnode/ hooks${ormMsg} and .shipnodeignore`);
141
+ }
142
+ function generatePreDeployHook(detectedOrm) {
143
+ const ormCommands = Object.entries(ORM_PATTERNS)
144
+ .filter(([, p]) => p.migrateCmd)
145
+ .map(([name, p]) => {
146
+ const active = name === detectedOrm;
147
+ const prefix = active ? '' : '# ';
148
+ const lines = [`${prefix}# ${name}${active ? ' (detected)' : ''}`];
149
+ if (p.generateCmd)
150
+ lines.push(`${prefix}${p.generateCmd}`);
151
+ lines.push(`${prefix}${p.migrateCmd}`);
152
+ return lines.join('\n');
153
+ })
154
+ .join('\n\n');
155
+ return `#!/bin/bash
156
+ # ShipNode Pre-Deploy Hook
157
+ # Runs BEFORE the new release is activated. Exit non-zero to abort.
158
+ #
159
+ # Env vars: RELEASE_PATH REMOTE_PATH PM2_APP_NAME BACKEND_PORT SHARED_ENV_PATH
160
+ set -e
161
+
162
+ if [ -f "$SHARED_ENV_PATH" ]; then
163
+ set -a; source "$SHARED_ENV_PATH"; set +a
164
+ fi
165
+
166
+ echo "Pre-deploy: \${RELEASE_PATH}"
167
+
168
+ # ── Database migrations ──────────────────────────────────────────
169
+ ${ormCommands}
170
+ # ────────────────────────────────────────────────────────────────
171
+
172
+ echo "Pre-deploy hook complete"
173
+ `;
174
+ }
175
+ function generatePostDeployHook() {
176
+ return `#!/bin/bash
177
+ # ShipNode Post-Deploy Hook
178
+ # Runs AFTER deployment. Failure is logged but does NOT trigger rollback.
179
+ #
180
+ # Env vars: RELEASE_PATH RELEASE_TIMESTAMP REMOTE_PATH PM2_APP_NAME BACKEND_PORT
181
+ set -e
182
+
183
+ echo "Post-deploy: \${RELEASE_PATH}"
184
+
185
+ # Examples:
186
+ # curl -s http://localhost:\${BACKEND_PORT}/api/warmup
187
+ # npm run cache:clear
188
+
189
+ echo "Post-deploy hook complete"
190
+ `;
191
+ }
192
+ function generateShipnodeIgnore() {
193
+ return `# .shipnodeignore — files excluded from rsync (same syntax as .gitignore)
194
+ node_modules/
195
+ .env
196
+ .env.*
197
+ .git/
198
+ *.log
199
+ dist/
200
+ build/
201
+ coverage/
202
+ .DS_Store
203
+ `;
204
+ }
205
+ function generateConfig(opts) {
206
+ const lines = [
207
+ "import { shipnode } from '@devalade/shipnode';",
208
+ '',
209
+ 'export default shipnode',
210
+ ` .${opts.app}()`,
211
+ ];
212
+ const sshOpts = [];
213
+ if (opts.sshHost)
214
+ sshOpts.push(`host: '${opts.sshHost}'`);
215
+ if (opts.sshUser)
216
+ sshOpts.push(`user: '${opts.sshUser}'`);
217
+ if (opts.sshPort && opts.sshPort !== 22)
218
+ sshOpts.push(`port: ${opts.sshPort}`);
219
+ if (sshOpts.length > 0) {
220
+ lines.push(` .ssh({ ${sshOpts.join(', ')} })`);
221
+ }
222
+ if (opts.remotePath) {
223
+ lines.push(` .deployTo('${opts.remotePath}')`);
224
+ }
225
+ if (opts.pm2Name) {
226
+ lines.push(` .pm2('${opts.pm2Name}')`);
227
+ }
228
+ if (opts.backendPort && opts.backendPort !== 3000) {
229
+ lines.push(` .port(${opts.backendPort})`);
230
+ }
231
+ if (opts.domain) {
232
+ lines.push(` .domain('${opts.domain}')`);
233
+ }
234
+ if (opts.zeroDowntime !== false) {
235
+ lines.push(' .zeroDowntime()');
236
+ }
237
+ if (opts.healthCheckPath && opts.healthCheckPath !== '/health') {
238
+ lines.push(` .healthCheck('${opts.healthCheckPath}')`);
239
+ }
240
+ else if (opts.healthCheckPath) {
241
+ lines.push(` .healthCheck('${opts.healthCheckPath}')`);
242
+ }
243
+ lines.push('');
244
+ return lines.join('\n');
245
+ }
246
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function cmdLogs(cwd: string, options: {
2
+ lines?: number;
3
+ config?: string;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=logs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/logs.ts"],"names":[],"mappings":"AAEA,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBtG"}
@@ -0,0 +1,17 @@
1
+ import { runRemoteCommand } from '../runner.js';
2
+ export async function cmdLogs(cwd, options) {
3
+ await runRemoteCommand(cwd, async ({ config, executor }) => {
4
+ if (config.app !== 'backend' || !config.pm2?.name) {
5
+ throw new Error('Logs only available for backend apps with PM2');
6
+ }
7
+ const lines = options.lines ?? 100;
8
+ const nodeVersion = config.nodeVersion === 'lts' ? '24' : config.nodeVersion;
9
+ const mise = `export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"`;
10
+ const result = await executor.exec(`${mise}; mise exec "node@${nodeVersion}" -- pm2 logs ${config.pm2.name} --lines ${lines} --nostream`);
11
+ if (result.stdout)
12
+ process.stdout.write(result.stdout + '\n');
13
+ if (result.stderr)
14
+ process.stderr.write(result.stderr + '\n');
15
+ }, { configPath: options.config });
16
+ }
17
+ //# sourceMappingURL=logs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.js","sourceRoot":"","sources":["../../../src/cli/commands/logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW,EAAE,OAA4C;IACrF,MAAM,gBAAgB,CACpB,GAAG,EACH,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC7B,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,GAAG,CAAC;QACnC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;QAC7E,MAAM,IAAI,GAAG,oEAAoE,CAAC;QAClF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAChC,GAAG,IAAI,qBAAqB,WAAW,iBAAiB,MAAM,CAAC,GAAG,CAAC,IAAI,YAAY,KAAK,aAAa,CACtG,CAAC;QACF,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;QAC9D,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAChE,CAAC,EACD,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,CAC/B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function cmdMetrics(cwd: string, options: {
2
+ config?: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/metrics.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBzF"}
@@ -0,0 +1,21 @@
1
+ import { execa } from 'execa';
2
+ import { loadConfig } from '../../config/loader.js';
3
+ export async function cmdMetrics(cwd, options) {
4
+ const config = await loadConfig(cwd, options.config);
5
+ if (config.app !== 'backend' || !config.pm2?.name) {
6
+ throw new Error('Metrics only available for backend apps with PM2');
7
+ }
8
+ const nodeVersion = config.nodeVersion === 'lts' ? '24' : config.nodeVersion;
9
+ const mise = `export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"`;
10
+ const remoteCmd = `${mise}; mise exec "node@${nodeVersion}" -- pm2 monit`;
11
+ const sshArgs = [
12
+ '-t',
13
+ '-p', String(config.ssh.port),
14
+ ...(config.ssh.identityFile ? ['-i', config.ssh.identityFile] : []),
15
+ `${config.ssh.user}@${config.ssh.host}`,
16
+ remoteCmd,
17
+ ];
18
+ const result = await execa('ssh', sshArgs, { stdio: 'inherit', reject: false });
19
+ process.exit(result.exitCode ?? 0);
20
+ }
21
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/cli/commands/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,OAA4B;IACxE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;IAC7E,MAAM,IAAI,GAAG,oEAAoE,CAAC;IAClF,MAAM,SAAS,GAAG,GAAG,IAAI,qBAAqB,WAAW,gBAAgB,CAAC;IAE1E,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;QAC7B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE;QACvC,SAAS;KACV,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAChF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;AACrC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function cmdMigrate(cwd: string, options: {
2
+ config?: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/migrate.ts"],"names":[],"mappings":"AAKA,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkGzF"}
@@ -0,0 +1,71 @@
1
+ import { confirm } from '../prompt.js';
2
+ import { runRemoteCommand } from '../runner.js';
3
+ import { ReleaseManager } from '../../domain/release/manager.js';
4
+ import { ui } from '../ui.js';
5
+ export async function cmdMigrate(cwd, options) {
6
+ await runRemoteCommand(cwd, async ({ config, executor }) => {
7
+ if (!config.zeroDowntime) {
8
+ throw new Error('Migration requires zeroDowntime: true in your shipnode.config.ts. ' +
9
+ 'Enable it and re-run to migrate to the zero-downtime release structure.');
10
+ }
11
+ const remotePath = config.remotePath;
12
+ ui.heading('Zero-Downtime Migration');
13
+ ui.info(`Remote path: ${remotePath}`);
14
+ ui.warn('This will reorganise your remote deployment directory into releases/shared/current structure.');
15
+ const ok = await confirm('Proceed with migration?');
16
+ if (!ok) {
17
+ ui.info('Migration cancelled.');
18
+ return;
19
+ }
20
+ const timestamp = new Date()
21
+ .toISOString()
22
+ .replace(/[:.]/g, '-')
23
+ .replace('Z', '');
24
+ ui.info('Creating release structure directories...');
25
+ await executor.exec(`mkdir -p "${remotePath}/releases" "${remotePath}/shared" "${remotePath}/.shipnode"`);
26
+ await executor.exec(`echo '[]' > "${remotePath}/.shipnode/releases.json"`);
27
+ ui.success('Directory structure created');
28
+ ui.info(`Creating release snapshot: ${timestamp}...`);
29
+ await executor.exec(`mkdir -p "${remotePath}/releases/${timestamp}"`);
30
+ await executor.exec(`find "${remotePath}" -maxdepth 1 -mindepth 1 ` +
31
+ `! -name releases ! -name shared ! -name .shipnode ! -name current ` +
32
+ `-exec mv {} "${remotePath}/releases/${timestamp}/" \\;`);
33
+ ui.success('Existing files moved to release directory');
34
+ // Move .env to shared and symlink it back
35
+ const envCheckResult = await executor.exec(`[ -f "${remotePath}/releases/${timestamp}/.env" ] && echo "exists" || echo "missing"`);
36
+ if (envCheckResult.stdout.trim() === 'exists') {
37
+ ui.info('Moving .env to shared directory...');
38
+ await executor.exec(`mv "${remotePath}/releases/${timestamp}/.env" "${remotePath}/shared/.env"`);
39
+ await executor.exec(`ln -sf "${remotePath}/shared/.env" "${remotePath}/releases/${timestamp}/.env"`);
40
+ ui.success('Shared .env linked');
41
+ }
42
+ else {
43
+ ui.warn('No .env found in release — skipping shared env setup.');
44
+ }
45
+ ui.info('Creating current symlink...');
46
+ await executor.exec(`ln -sfn "${remotePath}/releases/${timestamp}" "${remotePath}/current"`);
47
+ ui.success('Symlink created: current → releases/' + timestamp);
48
+ // Reload PM2 if applicable
49
+ if (config.app === 'backend' && config.pm2?.name) {
50
+ const nodeVersion = config.nodeVersion === 'lts' ? '24' : config.nodeVersion;
51
+ const mise = `export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"`;
52
+ ui.info('Reloading PM2 from new path...');
53
+ await executor.exec(`${mise}; mise exec node@${nodeVersion} -- pm2 reload ${config.pm2.name} --update-env`);
54
+ ui.success('PM2 reloaded');
55
+ }
56
+ // Record the initial migrated release
57
+ const releases = new ReleaseManager(executor, remotePath, config.keepReleases);
58
+ await releases.recordRelease({
59
+ timestamp,
60
+ status: 'success',
61
+ duration: 0,
62
+ gitCommit: undefined,
63
+ });
64
+ ui.success('Release recorded in .shipnode/releases.json');
65
+ ui.heading('Migration Complete');
66
+ ui.success(`Active release: ${timestamp}`);
67
+ ui.info('Your app is now running under the zero-downtime release structure.');
68
+ ui.info('Future deployments will use releases/ and atomic symlink switches.');
69
+ }, { configPath: options.config });
70
+ }
71
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../../src/cli/commands/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function cmdRestart(cwd: string, options: {
2
+ config?: string;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=restart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restart.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/restart.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBzF"}
@@ -0,0 +1,14 @@
1
+ import { runRemoteCommand } from '../runner.js';
2
+ import { ui } from '../ui.js';
3
+ export async function cmdRestart(cwd, options) {
4
+ await runRemoteCommand(cwd, async ({ config, executor }) => {
5
+ if (config.app !== 'backend' || !config.pm2?.name) {
6
+ throw new Error('Restart only available for backend apps with PM2');
7
+ }
8
+ const nodeVersion = config.nodeVersion === 'lts' ? '24' : config.nodeVersion;
9
+ const mise = `export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"`;
10
+ await executor.exec(`${mise}; mise exec "node@${nodeVersion}" -- pm2 reload ${config.pm2.name} --update-env`);
11
+ ui.success(`App '${config.pm2.name}' restarted successfully`);
12
+ }, { configPath: options.config });
13
+ }
14
+ //# sourceMappingURL=restart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restart.js","sourceRoot":"","sources":["../../../src/cli/commands/restart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAE9B,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,OAA4B;IACxE,MAAM,gBAAgB,CACpB,GAAG,EACH,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC7B,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;QAC7E,MAAM,IAAI,GAAG,oEAAoE,CAAC;QAClF,MAAM,QAAQ,CAAC,IAAI,CACjB,GAAG,IAAI,qBAAqB,WAAW,mBAAmB,MAAM,CAAC,GAAG,CAAC,IAAI,eAAe,CACzF,CAAC;QACF,EAAE,CAAC,OAAO,CAAC,QAAQ,MAAM,CAAC,GAAG,CAAC,IAAI,0BAA0B,CAAC,CAAC;IAChE,CAAC,EACD,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,CAC/B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function cmdRollback(cwd: string, options: {
2
+ steps?: number;
3
+ config?: string;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=rollback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollback.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/rollback.ts"],"names":[],"mappings":"AAMA,wBAAsB,WAAW,CAC/B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,OAAO,CAAC,IAAI,CAAC,CA6Df"}
@@ -0,0 +1,49 @@
1
+ import { runRemoteCommand } from '../runner.js';
2
+ import { ReleaseManager } from '../../domain/release/manager.js';
3
+ import { HealthCheckService } from '../../services/health.service.js';
4
+ import { ui } from '../ui.js';
5
+ import { confirm } from '../prompt.js';
6
+ export async function cmdRollback(cwd, options) {
7
+ await runRemoteCommand(cwd, async ({ config, executor }) => {
8
+ if (!config.zeroDowntime) {
9
+ throw new Error('Rollback requires zero-downtime deployment. Enable zeroDowntime in config.');
10
+ }
11
+ const releases = new ReleaseManager(executor, config.remotePath, config.keepReleases);
12
+ const stepsBack = options.steps ?? 1;
13
+ ui.info('Fetching release history...');
14
+ const allReleases = await releases.listReleases();
15
+ if (allReleases.length < 2) {
16
+ throw new Error('No previous release to roll back to.');
17
+ }
18
+ const targetIdx = allReleases.length - 1 - stepsBack;
19
+ if (targetIdx < 0) {
20
+ throw new Error(`Cannot go back ${stepsBack} step(s) — only ${allReleases.length} release(s) recorded.`);
21
+ }
22
+ const current = allReleases[allReleases.length - 1];
23
+ const target = allReleases[targetIdx];
24
+ ui.warn(`Current release: ${current.timestamp}`);
25
+ ui.warn(`Target release: ${target.timestamp}`);
26
+ const ok = await confirm('Proceed with rollback?');
27
+ if (!ok) {
28
+ ui.info('Rollback cancelled.');
29
+ return;
30
+ }
31
+ const targetPath = `${config.remotePath}/releases/${target.timestamp}`;
32
+ await releases.switchSymlink(targetPath);
33
+ ui.success('Symlink switched');
34
+ if (config.app === 'backend' && config.pm2?.name) {
35
+ const nodeVersion = config.nodeVersion === 'lts' ? '24' : config.nodeVersion;
36
+ const mise = `export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"`;
37
+ await executor.exec(`${mise}; mise exec node@${nodeVersion} -- pm2 reload ${config.pm2.name} --update-env`);
38
+ ui.success('PM2 reloaded');
39
+ }
40
+ if (config.app === 'backend' && config.healthCheck.enabled) {
41
+ ui.info('Running health check...');
42
+ const health = new HealthCheckService(executor, config);
43
+ await health.perform();
44
+ ui.success('Health check passed');
45
+ }
46
+ ui.success(`Rolled back to ${target.timestamp}`);
47
+ }, { configPath: options.config });
48
+ }
49
+ //# sourceMappingURL=rollback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rollback.js","sourceRoot":"","sources":["../../../src/cli/commands/rollback.ts"],"names":[],"mappings":"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"}