vps-deployer 1.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 (134) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -0
  3. package/dist/app.d.ts +4 -0
  4. package/dist/app.d.ts.map +1 -0
  5. package/dist/app.js +39 -0
  6. package/dist/app.js.map +1 -0
  7. package/dist/db/db.d.ts +5 -0
  8. package/dist/db/db.d.ts.map +1 -0
  9. package/dist/db/db.js +100 -0
  10. package/dist/db/db.js.map +1 -0
  11. package/dist/helpers/arg.helper.d.ts +7 -0
  12. package/dist/helpers/arg.helper.d.ts.map +1 -0
  13. package/dist/helpers/arg.helper.js +28 -0
  14. package/dist/helpers/arg.helper.js.map +1 -0
  15. package/dist/helpers/cmd_executer.helper.d.ts +7 -0
  16. package/dist/helpers/cmd_executer.helper.d.ts.map +1 -0
  17. package/dist/helpers/cmd_executer.helper.js +88 -0
  18. package/dist/helpers/cmd_executer.helper.js.map +1 -0
  19. package/dist/helpers/common.helper.d.ts +2 -0
  20. package/dist/helpers/common.helper.d.ts.map +1 -0
  21. package/dist/helpers/common.helper.js +15 -0
  22. package/dist/helpers/common.helper.js.map +1 -0
  23. package/dist/helpers/config_files.helper.d.ts +2 -0
  24. package/dist/helpers/config_files.helper.d.ts.map +1 -0
  25. package/dist/helpers/config_files.helper.js +44 -0
  26. package/dist/helpers/config_files.helper.js.map +1 -0
  27. package/dist/helpers/create_systemd_service.helper.d.ts +9 -0
  28. package/dist/helpers/create_systemd_service.helper.d.ts.map +1 -0
  29. package/dist/helpers/create_systemd_service.helper.js +40 -0
  30. package/dist/helpers/create_systemd_service.helper.js.map +1 -0
  31. package/dist/helpers/date.helper.d.ts +2 -0
  32. package/dist/helpers/date.helper.d.ts.map +1 -0
  33. package/dist/helpers/date.helper.js +18 -0
  34. package/dist/helpers/date.helper.js.map +1 -0
  35. package/dist/helpers/email.helper.d.ts +11 -0
  36. package/dist/helpers/email.helper.d.ts.map +1 -0
  37. package/dist/helpers/email.helper.js +144 -0
  38. package/dist/helpers/email.helper.js.map +1 -0
  39. package/dist/helpers/logging.helper.d.ts +9 -0
  40. package/dist/helpers/logging.helper.d.ts.map +1 -0
  41. package/dist/helpers/logging.helper.js +32 -0
  42. package/dist/helpers/logging.helper.js.map +1 -0
  43. package/dist/helpers/remove_systemd_service.helper.d.ts +2 -0
  44. package/dist/helpers/remove_systemd_service.helper.d.ts.map +1 -0
  45. package/dist/helpers/remove_systemd_service.helper.js +21 -0
  46. package/dist/helpers/remove_systemd_service.helper.js.map +1 -0
  47. package/dist/helpers/start_systemd_service.helper.d.ts +2 -0
  48. package/dist/helpers/start_systemd_service.helper.d.ts.map +1 -0
  49. package/dist/helpers/start_systemd_service.helper.js +26 -0
  50. package/dist/helpers/start_systemd_service.helper.js.map +1 -0
  51. package/dist/index.d.ts +2 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +132 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/middleware/auth.middleware.d.ts +3 -0
  56. package/dist/middleware/auth.middleware.d.ts.map +1 -0
  57. package/dist/middleware/auth.middleware.js +7 -0
  58. package/dist/middleware/auth.middleware.js.map +1 -0
  59. package/dist/modules/auth/auth.route.d.ts +3 -0
  60. package/dist/modules/auth/auth.route.d.ts.map +1 -0
  61. package/dist/modules/auth/auth.route.js +16 -0
  62. package/dist/modules/auth/auth.route.js.map +1 -0
  63. package/dist/modules/auth/controllers/auth.controller.d.ts +6 -0
  64. package/dist/modules/auth/controllers/auth.controller.d.ts.map +1 -0
  65. package/dist/modules/auth/controllers/auth.controller.js +123 -0
  66. package/dist/modules/auth/controllers/auth.controller.js.map +1 -0
  67. package/dist/modules/auth/views/login.pug +254 -0
  68. package/dist/modules/auth/views/register.pug +298 -0
  69. package/dist/modules/common/views/404.pug +21 -0
  70. package/dist/modules/dashboard/dashboard.route.d.ts +3 -0
  71. package/dist/modules/dashboard/dashboard.route.d.ts.map +1 -0
  72. package/dist/modules/dashboard/dashboard.route.js +29 -0
  73. package/dist/modules/dashboard/dashboard.route.js.map +1 -0
  74. package/dist/modules/dashboard/views/dash.pug +149 -0
  75. package/dist/modules/dashboard/views/layout.pug +94 -0
  76. package/dist/modules/deployer/controllers/deployer.controller.d.ts +6 -0
  77. package/dist/modules/deployer/controllers/deployer.controller.d.ts.map +1 -0
  78. package/dist/modules/deployer/controllers/deployer.controller.js +119 -0
  79. package/dist/modules/deployer/controllers/deployer.controller.js.map +1 -0
  80. package/dist/modules/deployer/deployer.route.d.ts +3 -0
  81. package/dist/modules/deployer/deployer.route.d.ts.map +1 -0
  82. package/dist/modules/deployer/deployer.route.js +13 -0
  83. package/dist/modules/deployer/deployer.route.js.map +1 -0
  84. package/dist/modules/deployer/helper/deployer.d.ts +9 -0
  85. package/dist/modules/deployer/helper/deployer.d.ts.map +1 -0
  86. package/dist/modules/deployer/helper/deployer.js +89 -0
  87. package/dist/modules/deployer/helper/deployer.js.map +1 -0
  88. package/dist/modules/deployer/views/details.pug +157 -0
  89. package/dist/modules/deployer/views/index.pug +108 -0
  90. package/dist/modules/project/controllers/projects.controller.d.ts +12 -0
  91. package/dist/modules/project/controllers/projects.controller.d.ts.map +1 -0
  92. package/dist/modules/project/controllers/projects.controller.js +267 -0
  93. package/dist/modules/project/controllers/projects.controller.js.map +1 -0
  94. package/dist/modules/project/helper/project_file_sys.helper.d.ts +7 -0
  95. package/dist/modules/project/helper/project_file_sys.helper.d.ts.map +1 -0
  96. package/dist/modules/project/helper/project_file_sys.helper.js +93 -0
  97. package/dist/modules/project/helper/project_file_sys.helper.js.map +1 -0
  98. package/dist/modules/project/project.route.d.ts +3 -0
  99. package/dist/modules/project/project.route.d.ts.map +1 -0
  100. package/dist/modules/project/project.route.js +17 -0
  101. package/dist/modules/project/project.route.js.map +1 -0
  102. package/dist/modules/project/views/create.pug +189 -0
  103. package/dist/modules/project/views/details.pug +238 -0
  104. package/dist/modules/project/views/index.pug +114 -0
  105. package/dist/modules/settings/controllers/setting.controller.d.ts +5 -0
  106. package/dist/modules/settings/controllers/setting.controller.d.ts.map +1 -0
  107. package/dist/modules/settings/controllers/setting.controller.js +193 -0
  108. package/dist/modules/settings/controllers/setting.controller.js.map +1 -0
  109. package/dist/modules/settings/settings.route.d.ts +3 -0
  110. package/dist/modules/settings/settings.route.d.ts.map +1 -0
  111. package/dist/modules/settings/settings.route.js +10 -0
  112. package/dist/modules/settings/settings.route.js.map +1 -0
  113. package/dist/modules/settings/views/index.pug +173 -0
  114. package/dist/modules/webhook/controllers/webhook.controller.d.ts +3 -0
  115. package/dist/modules/webhook/controllers/webhook.controller.d.ts.map +1 -0
  116. package/dist/modules/webhook/controllers/webhook.controller.js +72 -0
  117. package/dist/modules/webhook/controllers/webhook.controller.js.map +1 -0
  118. package/dist/modules/webhook/webhook.route.d.ts +3 -0
  119. package/dist/modules/webhook/webhook.route.d.ts.map +1 -0
  120. package/dist/modules/webhook/webhook.route.js +6 -0
  121. package/dist/modules/webhook/webhook.route.js.map +1 -0
  122. package/dist/utils/app_config.d.ts +3 -0
  123. package/dist/utils/app_config.d.ts.map +1 -0
  124. package/dist/utils/app_config.js +5 -0
  125. package/dist/utils/app_config.js.map +1 -0
  126. package/dist/utils/cli.d.ts +2 -0
  127. package/dist/utils/cli.d.ts.map +1 -0
  128. package/dist/utils/cli.js +68 -0
  129. package/dist/utils/cli.js.map +1 -0
  130. package/package.json +80 -0
  131. package/public/favicon.svg +18 -0
  132. package/public/js/deploy.js +36 -0
  133. package/public/js/deployment-details.js +56 -0
  134. package/public/js/login.js +21 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 0xv1shal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,151 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/0xv1shal/vps-deployer/main/public/favicon.svg" alt="VPS Deployer Logo" width="120" />
3
+ <h1 align="center">VPS Deployer</h1>
4
+ <p align="center"><strong>Deployment made easy.</strong></p>
5
+ </p>
6
+
7
+ <p align="center">
8
+ A lightweight, self-hosted continuous deployment (CD) system with a built-in web UI — manages projects on your VPS, accepts GitHub webhooks for automatic deployments, and sends real-time email notifications on deployment events.
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/vps-deployer"><img src="https://img.shields.io/npm/v/vps-deployer.svg?style=flat-square&color=cb3837" alt="npm version" /></a>
13
+ <a href="https://nodejs.org/en/about/releases/"><img src="https://img.shields.io/node/v/vps-deployer.svg?style=flat-square&color=339933" alt="Node.js version" /></a>
14
+ <a href="https://github.com/0xv1shal/vps-deployer/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/vps-deployer.svg?style=flat-square&color=blue" alt="License" /></a>
15
+ <a href="https://github.com/0xv1shal/vps-deployer"><img src="https://img.shields.io/badge/platform-linux-lightgrey.svg?style=flat-square" alt="Platform" /></a>
16
+ </p>
17
+
18
+ ---
19
+
20
+ ## Features
21
+
22
+ | | |
23
+ |---|---|
24
+ | 🖥️ **Web UI Dashboard** | Monitor projects, deployments, and logs from your browser |
25
+ | 🔄 **GitHub Webhooks** | Push to a branch and let VPS Deployer handle the rest |
26
+ | 📧 **Email Notifications** | Get notified on deployment success or failure via SMTP |
27
+ | ⚙️ **Custom Build Commands** | Define per-project command sequences (build, migrate, restart) |
28
+ | 🔐 **Per-Project Env Vars** | Manage `.env` files through the UI |
29
+ | 🪶 **Lightweight** | Single SQLite database, no external services required |
30
+ | 🚀 **CLI-Driven** | Start with a single command, manage everything from the web |
31
+
32
+ ## Prerequisites
33
+
34
+ - **Linux** (requires `root`/`sudo` for systemd service creation)
35
+ - **Node.js** >= 18
36
+ - **npm** or **pnpm**
37
+
38
+ ## Quick Start
39
+
40
+ ### 1. Install
41
+
42
+ ```bash
43
+ npm install -g vps-deployer
44
+ ```
45
+
46
+ ### 2. Generate Configs
47
+
48
+ ```bash
49
+ sudo vps-deployer -w /opt/vps-deployer -p 3000 -s your-super-secret-session-key
50
+ ```
51
+
52
+ This creates the systemd service file, database, and reference configs, then exits.
53
+
54
+ | Flag | Description |
55
+ |------|-------------|
56
+ | `-w, --working-dir` | Directory where projects and data will be stored |
57
+ | `-p, --port` | Port for the web UI and API (1024–50000) |
58
+ | `-s, --session-key` | Secret key for session encryption (min 6 characters) |
59
+ | `--dev` | Run in development mode (foreground, no systemd) |
60
+
61
+ ### 3. Start the Service
62
+
63
+ ```bash
64
+ sudo vps-deployer start
65
+ ```
66
+
67
+ This enables and starts the systemd service. The terminal is freed immediately.
68
+
69
+ > **Dev mode:** To run in the foreground without systemd, use `sudo vps-deployer -w /opt/vps-deployer -p 3000 -s key --dev`
70
+
71
+ ### 4. Open the Web UI
72
+
73
+ Navigate to `http://<your-server-ip>:3000` and register your account.
74
+
75
+ ### 5. Create a Project
76
+
77
+ 1. Go to **Projects** → **Create**
78
+ 2. Enter your GitHub repo URL and branch name
79
+ 3. Add build/deploy commands (e.g., `npm install`, `npm run build`, `pm2 restart app`)
80
+ 4. Save — your unique webhook URL and secret will be displayed
81
+
82
+ ### 6. Configure the Webhook
83
+
84
+ Copy the webhook URL and secret from the project details page, then add them to your GitHub repo:
85
+
86
+ `Settings → Webhooks → Add webhook → Paste URL → Set Content type to application/json → Paste Secret`
87
+
88
+ ### 7. Deploy
89
+
90
+ Push to your configured branch. VPS Deployer will receive the webhook, run your commands, and notify you via email.
91
+
92
+ > **Important:** VPS Deployer does **not** automatically pull your repository on webhook receipt. You must explicitly add a `git pull` (or `git clone`) command as the first step in your project's command list. For example:
93
+ >
94
+ > ```
95
+ > 1. git pull origin main
96
+ > 2. npm install
97
+ > 3. npm run build
98
+ > ```
99
+
100
+ ## Screenshots
101
+
102
+ > ![Dashboard](https://raw.githubusercontent.com/0xv1shal/vps-deployer/main/docs/screenshots/dashboard.png)
103
+ >
104
+ > *Dashboard with project stats and recent deployments*
105
+
106
+ > ![Project Details](https://raw.githubusercontent.com/0xv1shal/vps-deployer/main/docs/screenshots/project-details.png)
107
+ >
108
+ > *Project configuration with commands and environment variables*
109
+
110
+ > ![Deployment Logs](https://raw.githubusercontent.com/0xv1shal/vps-deployer/main/docs/screenshots/deployment-logs.png)
111
+ >
112
+ > *Real-time deployment log output*
113
+
114
+ ## Project Structure
115
+
116
+ When you run VPS Deployer, it creates the following structure in your working directory:
117
+
118
+ ```
119
+ /opt/vps-deployer/
120
+ ├── data.db # SQLite database
121
+ ├── caddy.config # Generated reverse proxy config
122
+ ├── nginx.config # Generated reverse proxy config
123
+ ├── systemd.file.copy.txt # Systemd unit file reference
124
+ └── <project-id>/ # Per-project workspace
125
+ ├── .env # Environment variables
126
+ └── ... # Cloned repository files
127
+ ```
128
+
129
+ ## Documentation
130
+
131
+ | Document | Description |
132
+ |----------|-------------|
133
+ | [Quick Start](https://github.com/0xv1shal/vps-deployer/blob/main/docs/quick-start.md) | Step-by-step walkthrough from install to first deployment |
134
+ | [CLI Reference](https://github.com/0xv1shal/vps-deployer/blob/main/docs/cli-reference.md) | All flags, validation rules, and examples |
135
+ | [Webhook Setup](https://github.com/0xv1shal/vps-deployer/blob/main/docs/webhook-setup.md) | Configure GitHub webhooks for auto-deployment |
136
+ | [Email Setup](https://github.com/0xv1shal/vps-deployer/blob/main/docs/email-setup.md) | Configure SMTP for deployment notifications |
137
+ | [Architecture](https://github.com/0xv1shal/vps-deployer/blob/main/docs/architecture.md) | System design, database schema, and deployment flow |
138
+ | [Database Schema](https://github.com/0xv1shal/vps-deployer/blob/main/docs/schema.md) | Full table definitions |
139
+
140
+ ## Security
141
+
142
+ - This tool **must be run as root** to create systemd services and execute deployment commands
143
+ - The web UI is protected by session-based authentication (login/register)
144
+ - Rate limiting is applied on auth endpoints (40 req/min per IP)
145
+ - Every webhook is verified using HMAC-SHA256 with a per-project secret
146
+ - Use a strong, unique session key (`-s` flag)
147
+ - Keep the working directory restricted to the tool only
148
+
149
+ ## License
150
+
151
+ MIT — see [LICENSE](https://github.com/0xv1shal/vps-deployer/blob/main/LICENSE) for details.
package/dist/app.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ declare const app: import("express-serve-static-core").Express;
2
+ export default app;
3
+ export declare const initSessionAndRoutes: (app: any) => void;
4
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAYA,QAAA,MAAM,GAAG,6CAAY,CAAC;AAUtB,eAAe,GAAG,CAAC;AAEnB,eAAO,MAAM,oBAAoB,GAAI,KAAK,GAAG,SAsB5C,CAAC"}
package/dist/app.js ADDED
@@ -0,0 +1,39 @@
1
+ import express, {} from "express";
2
+ import helmet from "helmet";
3
+ import path from "path";
4
+ import session from "express-session";
5
+ import authRouter from "./modules/auth/auth.route.js";
6
+ import dashboardRouter from "./modules/dashboard/dashboard.route.js";
7
+ import projectRouter from "./modules/project/project.route.js";
8
+ import settingsRouter from "./modules/settings/settings.route.js";
9
+ import deployRouter from "./modules/deployer/deployer.route.js";
10
+ import webhookRouter from "./modules/webhook/webhook.route.js";
11
+ import { getSessKey } from "./helpers/arg.helper.js";
12
+ const app = express();
13
+ const basePath = import.meta.dirname;
14
+ app.set("view engine", "pug");
15
+ app.set("views", path.join(basePath, "modules"));
16
+ app.use(express.static(path.join(basePath, "..", "public")));
17
+ app.use(helmet());
18
+ app.use(express.json());
19
+ app.use(express.urlencoded({ extended: true }));
20
+ export default app;
21
+ export const initSessionAndRoutes = (app) => {
22
+ const sessionKey = getSessKey();
23
+ app.use(session({
24
+ secret: sessionKey,
25
+ resave: false,
26
+ saveUninitialized: false,
27
+ cookie: { secure: "auto" },
28
+ }));
29
+ app.use(dashboardRouter);
30
+ app.use(authRouter);
31
+ app.use(projectRouter);
32
+ app.use(settingsRouter);
33
+ app.use(deployRouter);
34
+ app.use(webhookRouter);
35
+ app.use((_req, res) => {
36
+ res.status(404).render("common/views/404");
37
+ });
38
+ };
39
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EAA+B,MAAM,SAAS,CAAC;AAC/D,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,OAAO,MAAM,iBAAiB,CAAC;AACtC,OAAO,UAAU,MAAM,8BAA8B,CAAC;AACtD,OAAO,eAAe,MAAM,wCAAwC,CAAC;AACrE,OAAO,aAAa,MAAM,oCAAoC,CAAC;AAC/D,OAAO,cAAc,MAAM,sCAAsC,CAAC;AAClE,OAAO,YAAY,MAAM,sCAAsC,CAAC;AAChE,OAAO,aAAa,MAAM,oCAAoC,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;AACtB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;AAErC,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;AAC9B,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;AACjD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC7D,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;AAClB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AACxB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAEhD,eAAe,GAAG,CAAC;AAEnB,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAQ,EAAE,EAAE;IAC/C,MAAM,UAAU,GAAG,UAAU,EAAE,CAAC;IAEhC,GAAG,CAAC,GAAG,CACL,OAAO,CAAC;QACN,MAAM,EAAE,UAAU;QAClB,MAAM,EAAE,KAAK;QACb,iBAAiB,EAAE,KAAK;QACxB,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;KAC3B,CAAC,CACH,CAAC;IAEF,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACzB,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACpB,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACvB,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACxB,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACtB,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAEvB,GAAG,CAAC,GAAG,CAAC,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QACvC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { type Database as dbType } from "better-sqlite3";
2
+ export declare const initalizeDB: () => void;
3
+ export declare const getDB: () => dbType;
4
+ export declare const closeDB: () => void;
5
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,QAAQ,IAAI,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAqFzD,eAAO,MAAM,WAAW,YAMvB,CAAC;AAEF,eAAO,MAAM,KAAK,QAAO,MAIxB,CAAC;AAEF,eAAO,MAAM,OAAO,YAEnB,CAAC"}
package/dist/db/db.js ADDED
@@ -0,0 +1,100 @@
1
+ import Database from "better-sqlite3";
2
+ import path from "path";
3
+ import {} from "better-sqlite3";
4
+ import { getWorkDirPath } from "../helpers/arg.helper.js";
5
+ let DB = null;
6
+ const createTables = () => {
7
+ if (!DB)
8
+ throw new Error("DB not initialized");
9
+ DB.exec(`
10
+ CREATE TABLE IF NOT EXISTS user (
11
+ id TEXT PRIMARY KEY,
12
+ username TEXT NOT NULL,
13
+ password TEXT NOT NULL,
14
+ email TEXT NOT NULL,
15
+ last_logged_in TEXT DEFAULT (datetime('now')),
16
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
17
+ );
18
+
19
+ CREATE TABLE IF NOT EXISTS email (
20
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
21
+ username TEXT,
22
+ password TEXT,
23
+ smtp TEXT,
24
+ smtp_port INTEGER,
25
+ "from" TEXT
26
+ );
27
+
28
+ CREATE TABLE IF NOT EXISTS project (
29
+ id TEXT PRIMARY KEY,
30
+ name TEXT NOT NULL,
31
+ github_url TEXT NOT NULL,
32
+ branch_name TEXT NOT NULL,
33
+ receive_email_notf INTEGER DEFAULT 0 CHECK (receive_email_notf IN (0,1)),
34
+ auto_deploy INTEGER DEFAULT 0 CHECK (auto_deploy IN (0,1)),
35
+ webhook_secret TEXT NOT NULL UNIQUE
36
+ );
37
+
38
+ CREATE TABLE IF NOT EXISTS project_commands (
39
+ id TEXT PRIMARY KEY,
40
+ proj_id TEXT NOT NULL,
41
+ seq_no INTEGER NOT NULL,
42
+ cmd TEXT NOT NULL,
43
+ FOREIGN KEY (proj_id) REFERENCES project(id) ON DELETE CASCADE
44
+ );
45
+
46
+ CREATE TABLE IF NOT EXISTS project_env (
47
+ id TEXT PRIMARY KEY,
48
+ proj_id TEXT NOT NULL,
49
+ key TEXT NOT NULL,
50
+ value TEXT NOT NULL,
51
+ FOREIGN KEY (proj_id) REFERENCES project(id) ON DELETE CASCADE,
52
+ UNIQUE (proj_id, key)
53
+ );
54
+
55
+ CREATE TABLE IF NOT EXISTS deployment (
56
+ id TEXT PRIMARY KEY,
57
+ proj_id TEXT NOT NULL,
58
+ started_at TEXT NOT NULL DEFAULT (datetime('now')),
59
+ finished_at TEXT,
60
+ status TEXT CHECK (status IN ('running','success','failed')) NOT NULL DEFAULT 'running',
61
+ FOREIGN KEY (proj_id) REFERENCES project(id) ON DELETE CASCADE
62
+ );
63
+
64
+ CREATE TABLE IF NOT EXISTS deployment_logs (
65
+ id TEXT PRIMARY KEY,
66
+ deploy_id TEXT NOT NULL,
67
+ cmd TEXT NOT NULL,
68
+ log TEXT,
69
+ started_at TEXT NOT NULL DEFAULT (datetime('now')),
70
+ finished_at TEXT,
71
+ status TEXT CHECK (status IN ('running','success','failed')) NOT NULL DEFAULT 'running',
72
+ FOREIGN KEY (deploy_id) REFERENCES deployment(id) ON DELETE CASCADE
73
+ );
74
+
75
+ CREATE INDEX IF NOT EXISTS idx_project_commands_proj_id
76
+ ON project_commands(proj_id);
77
+
78
+ CREATE INDEX IF NOT EXISTS idx_deployment_proj_id
79
+ ON deployment(proj_id);
80
+
81
+ CREATE INDEX IF NOT EXISTS idx_deployment_logs_deploy_id
82
+ ON deployment_logs(deploy_id);
83
+ `);
84
+ };
85
+ export const initalizeDB = () => {
86
+ const workingDir = getWorkDirPath();
87
+ const dbPath = path.join(workingDir, "vps-deployer.db");
88
+ DB = new Database(dbPath);
89
+ DB.pragma("journal_mode = WAL");
90
+ createTables();
91
+ };
92
+ export const getDB = () => {
93
+ if (DB === null)
94
+ throw new Error("DB not initalized");
95
+ return DB;
96
+ };
97
+ export const closeDB = () => {
98
+ DB?.close();
99
+ };
100
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAA2B,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,IAAI,EAAE,GAAkB,IAAI,CAAC;AAE7B,MAAM,YAAY,GAAG,GAAG,EAAE;IACxB,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IAE/C,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EP,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,EAAE;IAC9B,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;IACxD,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1B,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,YAAY,EAAE,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,GAAW,EAAE;IAChC,IAAI,EAAE,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAEtD,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,EAAE;IAC1B,EAAE,EAAE,KAAK,EAAE,CAAC;AACd,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare const setWorkDirPath: (path: string) => void;
2
+ export declare const getWorkDirPath: () => string;
3
+ export declare const setPort: (port: number) => void;
4
+ export declare const setSessKey: (sessKey: string) => void;
5
+ export declare const getSessKey: () => string;
6
+ export declare const getPort: () => number;
7
+ //# sourceMappingURL=arg.helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arg.helper.d.ts","sourceRoot":"","sources":["../../src/helpers/arg.helper.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc,GAAI,MAAK,MAAM,SAEzC,CAAA;AAED,eAAO,MAAM,cAAc,cAG1B,CAAA;AAED,eAAO,MAAM,OAAO,GAAI,MAAK,MAAM,SAElC,CAAA;AACD,eAAO,MAAM,UAAU,GAAI,SAAQ,MAAM,SAExC,CAAA;AAED,eAAO,MAAM,UAAU,cAGtB,CAAA;AAED,eAAO,MAAM,OAAO,cAGnB,CAAA"}
@@ -0,0 +1,28 @@
1
+ let DIR_PATH = '';
2
+ let PORT = 0;
3
+ let SESS_KEY = '';
4
+ export const setWorkDirPath = (path) => {
5
+ DIR_PATH = path;
6
+ };
7
+ export const getWorkDirPath = () => {
8
+ if (DIR_PATH.trim() === '')
9
+ throw new Error('DIR_PATH is not set');
10
+ return DIR_PATH;
11
+ };
12
+ export const setPort = (port) => {
13
+ PORT = port;
14
+ };
15
+ export const setSessKey = (sessKey) => {
16
+ SESS_KEY = sessKey;
17
+ };
18
+ export const getSessKey = () => {
19
+ if (SESS_KEY.trim() === '')
20
+ throw new Error('SESS_KEY is not set, please set it using -s | --session-key <sessKey> flag');
21
+ return SESS_KEY;
22
+ };
23
+ export const getPort = () => {
24
+ if (PORT === 0)
25
+ throw new Error('PORT is not set');
26
+ return PORT;
27
+ };
28
+ //# sourceMappingURL=arg.helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arg.helper.js","sourceRoot":"","sources":["../../src/helpers/arg.helper.ts"],"names":[],"mappings":"AAAA,IAAI,QAAQ,GAAG,EAAE,CAAA;AACjB,IAAI,IAAI,GAAG,CAAC,CAAA;AACZ,IAAI,QAAQ,GAAG,EAAE,CAAA;AAEjB,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAW,EAAC,EAAE;IACzC,QAAQ,GAAG,IAAI,CAAA;AACnB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,GAAE,EAAE;IAC9B,IAAG,QAAQ,CAAC,IAAI,EAAE,KAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;IAC/D,OAAO,QAAQ,CAAA;AACnB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAW,EAAC,EAAE;IAClC,IAAI,GAAG,IAAI,CAAA;AACf,CAAC,CAAA;AACD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAc,EAAC,EAAE;IACxC,QAAQ,GAAG,OAAO,CAAA;AACtB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,GAAE,EAAE;IAC1B,IAAG,QAAQ,CAAC,IAAI,EAAE,KAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAA;IACtH,OAAO,QAAQ,CAAA;AACnB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,GAAE,EAAE;IACvB,IAAG,IAAI,KAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;IAC/C,OAAO,IAAI,CAAA;AACf,CAAC,CAAA"}
@@ -0,0 +1,7 @@
1
+ export declare const dangerCmdDetector: (cmd: string) => boolean;
2
+ export declare const runCmd: (cmd: string, projDir: string, deployId: string) => Promise<{
3
+ stdout: string;
4
+ stderr: string;
5
+ }>;
6
+ export declare const runCmdSeq: (commands: string[], projDir: string, deployId: string) => Promise<void>;
7
+ //# sourceMappingURL=cmd_executer.helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd_executer.helper.d.ts","sourceRoot":"","sources":["../../src/helpers/cmd_executer.helper.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,YAU5C,CAAC;AAEF,eAAO,MAAM,MAAM,GACjB,KAAK,MAAM,EACX,SAAS,MAAM,EACf,UAAU,MAAM;YAYa,MAAM;YAAU,MAAM;EA2DpD,CAAC;AAEF,eAAO,MAAM,SAAS,GACpB,UAAU,MAAM,EAAE,EAClB,SAAS,MAAM,EACf,UAAU,MAAM,kBAKjB,CAAC"}
@@ -0,0 +1,88 @@
1
+ import { spawn } from "child_process";
2
+ import { getDB } from "../db/db.js";
3
+ const startCmdLog = (deployId, cmd) => {
4
+ const db = getDB();
5
+ const id = crypto.randomUUID();
6
+ db.prepare(`
7
+ INSERT INTO deployment_logs (id, deploy_id, cmd,status)
8
+ VALUES (?, ?, ?,?)
9
+ `).run(id, deployId, cmd, 'running');
10
+ return id;
11
+ };
12
+ const finishCmdLog = (logId, log, status) => {
13
+ const db = getDB();
14
+ db.prepare(`
15
+ UPDATE deployment_logs
16
+ SET log = ?, status = ?, finished_at = datetime('now')
17
+ WHERE id = ?
18
+ `).run(log, status, logId);
19
+ };
20
+ export const dangerCmdDetector = (cmd) => {
21
+ const dangerous = [
22
+ "rm -rf /",
23
+ "shutdown",
24
+ "reboot",
25
+ "mkfs",
26
+ ":(){:|:&};:", // fork bomb
27
+ ];
28
+ return dangerous.some((d) => cmd.includes(d));
29
+ };
30
+ export const runCmd = (cmd, projDir, deployId) => {
31
+ if (dangerCmdDetector(cmd)) {
32
+ throw new Error("Dangerous command blocked");
33
+ }
34
+ const logId = startCmdLog(deployId, cmd);
35
+ let stderr = "";
36
+ let stdout = "";
37
+ let isFinished = false;
38
+ return new Promise((resolve, reject) => {
39
+ const child = spawn(cmd, {
40
+ cwd: projDir,
41
+ shell: true,
42
+ });
43
+ // ⏱️ 5 min timeout
44
+ const timeout = setTimeout(() => {
45
+ if (!isFinished) {
46
+ child.kill("SIGKILL");
47
+ }
48
+ }, 5 * 60 * 1000);
49
+ child.stdout.on("data", (data) => {
50
+ stdout += data.toString();
51
+ });
52
+ child.stderr.on("data", (data) => {
53
+ stderr += data.toString();
54
+ });
55
+ child.on("error", async (err) => {
56
+ if (isFinished)
57
+ return;
58
+ isFinished = true;
59
+ clearTimeout(timeout);
60
+ finishCmdLog(logId, err.message, "failed");
61
+ reject(new Error(`Failed to exec ${cmd}: ${err.message}`));
62
+ });
63
+ child.on("close", async (code, signal) => {
64
+ if (isFinished)
65
+ return;
66
+ isFinished = true;
67
+ clearTimeout(timeout);
68
+ const combinedLog = stdout + "\n" + stderr;
69
+ // If killed by timeout
70
+ if (signal === "SIGKILL") {
71
+ finishCmdLog(logId, combinedLog + "\n[Timeout: Killed]", "failed");
72
+ return reject(new Error(`Command timed out: ${cmd}`));
73
+ }
74
+ if (code === 0) {
75
+ finishCmdLog(logId, combinedLog, "success");
76
+ return resolve({ stdout, stderr });
77
+ }
78
+ finishCmdLog(logId, combinedLog, "failed");
79
+ reject(new Error(stderr.trim() || `Command failed: ${cmd} (code ${code})`));
80
+ });
81
+ });
82
+ };
83
+ export const runCmdSeq = async (commands, projDir, deployId) => {
84
+ for (const cmd of commands) {
85
+ await runCmd(cmd, projDir, deployId);
86
+ }
87
+ };
88
+ //# sourceMappingURL=cmd_executer.helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmd_executer.helper.js","sourceRoot":"","sources":["../../src/helpers/cmd_executer.helper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const normalizeRepoUrl: (url: string) => string;
2
+ //# sourceMappingURL=common.helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.helper.d.ts","sourceRoot":"","sources":["../../src/helpers/common.helper.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,MAe9C,CAAC"}
@@ -0,0 +1,15 @@
1
+ export const normalizeRepoUrl = (url) => {
2
+ url = url.trim();
3
+ // already SSH
4
+ if (url.startsWith("git@"))
5
+ return url;
6
+ // HTTPS → SSH
7
+ if (url.startsWith("https://github.com/")) {
8
+ return url
9
+ .replace("https://github.com/", "git@github.com:")
10
+ .replace(/\.git$/, "") + ".git";
11
+ }
12
+ // fallback (leave as is)
13
+ return url;
14
+ };
15
+ //# sourceMappingURL=common.helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.helper.js","sourceRoot":"","sources":["../../src/helpers/common.helper.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAW,EAAU,EAAE;IACtD,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAEjB,cAAc;IACd,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,GAAG,CAAC;IAEvC,cAAc;IACd,IAAI,GAAG,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;QAC1C,OAAO,GAAG;aACP,OAAO,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;aACjD,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC;IACpC,CAAC;IAED,yBAAyB;IACzB,OAAO,GAAG,CAAC;AACb,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const createProxyAndLogConfigs: () => void;
2
+ //# sourceMappingURL=config_files.helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config_files.helper.d.ts","sourceRoot":"","sources":["../../src/helpers/config_files.helper.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,wBAAwB,YA+CpC,CAAC"}
@@ -0,0 +1,44 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { getPort, getWorkDirPath } from "./arg.helper.js";
4
+ export const createProxyAndLogConfigs = () => {
5
+ const dir = getWorkDirPath();
6
+ const port = getPort();
7
+ const nginxPath = path.join(dir, "nginx.conf");
8
+ const caddyPath = path.join(dir, "Caddyfile");
9
+ const logFile = path.join(dir, "vps-deployer.log");
10
+ // NGINX config
11
+ const nginxConfig = `
12
+ server {
13
+ listen 80;
14
+ server_name _;
15
+
16
+ location / {
17
+ proxy_pass http://127.0.0.1:${port};
18
+ proxy_http_version 1.1;
19
+
20
+ proxy_set_header Upgrade $http_upgrade;
21
+ proxy_set_header Connection "upgrade";
22
+ proxy_set_header Host $host;
23
+ proxy_cache_bypass $http_upgrade;
24
+ }
25
+ }
26
+ `.trim();
27
+ // Caddy config
28
+ const caddyConfig = `
29
+ :80 {
30
+ reverse_proxy 127.0.0.1:${port}
31
+ }
32
+ `.trim();
33
+ if (!fs.existsSync(nginxPath)) {
34
+ fs.writeFileSync(nginxPath, nginxConfig);
35
+ }
36
+ if (!fs.existsSync(caddyPath)) {
37
+ fs.writeFileSync(caddyPath, caddyConfig);
38
+ }
39
+ if (!fs.existsSync(logFile)) {
40
+ fs.writeFileSync(logFile, 'file created');
41
+ }
42
+ console.log('proxy config files created successfully');
43
+ };
44
+ //# sourceMappingURL=config_files.helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config_files.helper.js","sourceRoot":"","sources":["../../src/helpers/config_files.helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE1D,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,EAAE;IAE3C,MAAM,GAAG,GAAI,cAAc,EAAE,CAAA;IAC7B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IAEtB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;IAEnD,eAAe;IACf,MAAM,WAAW,GAAG;;;;;;sCAMgB,IAAI;;;;;;;;;CASzC,CAAC,IAAI,EAAE,CAAC;IAEP,eAAe;IACf,MAAM,WAAW,GAAG;;8BAEQ,IAAI;;CAEjC,CAAC,IAAI,EAAE,CAAC;IAEP,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAA;AACxD,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ type ServiceConfig = {
2
+ serviceName: string;
3
+ execPath: string;
4
+ args: string[];
5
+ workingDir: string;
6
+ };
7
+ export declare const createSystemdService: ({ serviceName, execPath, args, workingDir, }: ServiceConfig) => void;
8
+ export {};
9
+ //# sourceMappingURL=create_systemd_service.helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_systemd_service.helper.d.ts","sourceRoot":"","sources":["../../src/helpers/create_systemd_service.helper.ts"],"names":[],"mappings":"AAIA,KAAK,aAAa,GAAG;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,8CAKlC,aAAa,SAyCf,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { execSync } from "child_process";
2
+ import fs from "fs";
3
+ import { writeToLogFile } from "./logging.helper.js";
4
+ export const createSystemdService = ({ serviceName, execPath, args, workingDir, }) => {
5
+ const serviceFilePath = `/etc/systemd/system/${serviceName}.service`;
6
+ const execCmd = [execPath, ...args, "--daemon"].join(" ");
7
+ const serviceContent = `
8
+ [Unit]
9
+ Description=VPS Deployer Service (${serviceName})
10
+ After=network.target
11
+
12
+ [Service]
13
+ Type=simple
14
+ ExecStart=${execCmd}
15
+ WorkingDirectory=${workingDir}
16
+ Restart=always
17
+ RestartSec=5
18
+ User=root
19
+
20
+ # logs go to journald
21
+ StandardOutput=journal
22
+ StandardError=journal
23
+
24
+ [Install]
25
+ WantedBy=multi-user.target
26
+ `;
27
+ try {
28
+ // 1. write service file
29
+ fs.writeFileSync(serviceFilePath, serviceContent.trim());
30
+ // 2. reload systemd
31
+ execSync("systemctl daemon-reexec");
32
+ execSync("systemctl daemon-reload");
33
+ writeToLogFile(`Service file created at ${serviceFilePath}. Run "vps-deployer start" to enable and start it.`, { level: "INFO", source: "SYS" });
34
+ }
35
+ catch (err) {
36
+ writeToLogFile(`Systemd setup failed:${err.message}`, { level: "ERROR", source: "SYS" });
37
+ throw err;
38
+ }
39
+ };
40
+ //# sourceMappingURL=create_systemd_service.helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_systemd_service.helper.js","sourceRoot":"","sources":["../../src/helpers/create_systemd_service.helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AASrD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,EACnC,WAAW,EACX,QAAQ,EACR,IAAI,EACJ,UAAU,GACI,EAAE,EAAE;IAClB,MAAM,eAAe,GAAG,uBAAuB,WAAW,UAAU,CAAC;IAErE,MAAM,OAAO,GAAG,CAAC,QAAQ,EAAE,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE1D,MAAM,cAAc,GAAG;;oCAEW,WAAW;;;;;YAKnC,OAAO;mBACA,UAAU;;;;;;;;;;;CAW5B,CAAC;IAEA,IAAI,CAAC;QACH,wBAAwB;QACxB,EAAE,CAAC,aAAa,CAAC,eAAe,EAAE,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;QAEzD,oBAAoB;QACpB,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QACpC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAIpC,cAAc,CAAC,2BAA2B,eAAe,oDAAoD,EAAE,EAAC,KAAK,EAAC,MAAM,EAAE,MAAM,EAAC,KAAK,EAAC,CAAC,CAAC;IAC/I,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,cAAc,CAAC,wBAAwB,GAAG,CAAC,OAAO,EAAE,EAAC,EAAC,KAAK,EAAC,OAAO,EAAC,MAAM,EAAC,KAAK,EAAC,CAAC,CAAA;QAClF,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const convertDateToIST: (input: number) => string;
2
+ //# sourceMappingURL=date.helper.d.ts.map