apihealthz 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 (39) hide show
  1. package/README.md +189 -0
  2. package/dist/commands/add.js +122 -0
  3. package/dist/commands/add.js.map +1 -0
  4. package/dist/commands/addApiCheck.js +14 -0
  5. package/dist/commands/addApiCheck.js.map +1 -0
  6. package/dist/commands/apiCheck.js +12 -0
  7. package/dist/commands/apiCheck.js.map +1 -0
  8. package/dist/commands/auth.js +26 -0
  9. package/dist/commands/auth.js.map +1 -0
  10. package/dist/commands/delete.js +45 -0
  11. package/dist/commands/delete.js.map +1 -0
  12. package/dist/commands/list.js +35 -0
  13. package/dist/commands/list.js.map +1 -0
  14. package/dist/index.js +19 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/services/api.js +20 -0
  17. package/dist/services/api.js.map +1 -0
  18. package/dist/services/apiHealth.js +21 -0
  19. package/dist/services/apiHealth.js.map +1 -0
  20. package/dist/services/apiHealthz.js +48 -0
  21. package/dist/services/apiHealthz.js.map +1 -0
  22. package/dist/services/auth.js +102 -0
  23. package/dist/services/auth.js.map +1 -0
  24. package/dist/services/timezone.js +29 -0
  25. package/dist/services/timezone.js.map +1 -0
  26. package/dist/utils/config.js +27 -0
  27. package/dist/utils/config.js.map +1 -0
  28. package/package.json +28 -0
  29. package/src/commands/add.ts +136 -0
  30. package/src/commands/auth.ts +28 -0
  31. package/src/commands/delete.ts +47 -0
  32. package/src/commands/list.ts +37 -0
  33. package/src/index.ts +21 -0
  34. package/src/services/api.ts +15 -0
  35. package/src/services/apiHealth.ts +25 -0
  36. package/src/services/auth.ts +121 -0
  37. package/src/services/timezone.ts +24 -0
  38. package/src/utils/config.ts +20 -0
  39. package/tsconfig.json +33 -0
package/README.md ADDED
@@ -0,0 +1,189 @@
1
+ # APIHealthz CLI
2
+
3
+ A command-line tool to monitor your API and website uptime and health. Keep track of your services' availability, receive alerts when they go down, and manage all your health checks from the terminal.
4
+
5
+ ## Features
6
+
7
+ - 🔐 **OAuth Authentication** - Secure login with Google
8
+ - 📊 **Health Monitoring** - Monitor any API or website endpoint
9
+ - ⏱️ **Flexible Intervals** - Choose from 5 minutes, 15 minutes, 30 minutes, or 1 hour check intervals
10
+ - 🔔 **Multiple Alert Channels** - Get notified via Slack, Email, or WhatsApp when your services go down
11
+ - 📋 **Easy Management** - List, add, and delete health checks with simple commands
12
+ - 🎯 **Interactive Setup** - User-friendly prompts guide you through configuration
13
+
14
+ ## Installation
15
+
16
+ ### Prerequisites
17
+
18
+ - Node.js (v14 or higher)
19
+ - npm or yarn
20
+
21
+ ### Setup
22
+
23
+ 1. Clone the repository:
24
+
25
+ ```bash
26
+ git clone <repository-url>
27
+ cd apihealthz-cli
28
+ ```
29
+
30
+ 2. Install dependencies:
31
+
32
+ ```bash
33
+ npm install
34
+ ```
35
+
36
+ 3. Build the project:
37
+
38
+ ```bash
39
+ npm run build
40
+ ```
41
+
42
+ 4. Link the CLI globally:
43
+
44
+ ```bash
45
+ npm link
46
+ ```
47
+
48
+ After linking, you can use the `apihealthz` command from anywhere in your terminal.
49
+
50
+ ## Usage
51
+
52
+ ### Authentication
53
+
54
+ Before you can use the CLI, you need to authenticate:
55
+
56
+ ```bash
57
+ # Login with Google
58
+ apihealthz auth login --provider google
59
+
60
+ # Check your authentication status
61
+ apihealthz auth status
62
+
63
+ # Logout
64
+ apihealthz auth logout
65
+ ```
66
+
67
+ ### Adding a Health Check
68
+
69
+ Add a new API or website to monitor:
70
+
71
+ ```bash
72
+ apihealthz add
73
+ ```
74
+
75
+ The interactive prompt will guide you through:
76
+
77
+ - **URL**: The API or website endpoint to monitor (must start with `http://` or `https://`)
78
+ - **Check Interval**: Choose how often to check (5 min, 15 min, 30 min, or 1 hour)
79
+ - **Alert Configuration**: Set up notifications via Slack, Email, WhatsApp, or skip alerts
80
+
81
+ **Example:**
82
+
83
+ ```
84
+ API URL to monitor: https://api.example.com/health
85
+ Select check interval: Every 5 minutes
86
+ How do you want to receive alerts?: Slack
87
+ Slack webhook URL: https://hooks.slack.com/services/YOUR/WEBHOOK/URL
88
+ ```
89
+
90
+ ### Listing Health Checks
91
+
92
+ View all your configured health checks:
93
+
94
+ ```bash
95
+ apihealthz list
96
+ ```
97
+
98
+ This displays a table with:
99
+
100
+ - Health check ID
101
+ - Monitored URL
102
+ - Check interval
103
+ - Last status (UP ✅ or DOWN ❌)
104
+ - Last checked timestamp
105
+
106
+ ### Deleting a Health Check
107
+
108
+ Remove a health check:
109
+
110
+ ```bash
111
+ apihealthz delete
112
+ ```
113
+
114
+ You'll be prompted to enter the health check ID and confirm deletion.
115
+
116
+ ## Commands Reference
117
+
118
+ | Command | Description |
119
+ | ------------------------------------------- | ---------------------------------------- |
120
+ | `apihealthz auth login [--provider google]` | Authenticate with ApiHealthz |
121
+ | `apihealthz auth logout` | Logout from ApiHealthz |
122
+ | `apihealthz auth status` | Show current authentication status |
123
+ | `apihealthz add` | Add a new API health check (interactive) |
124
+ | `apihealthz list` | List all configured health checks |
125
+ | `apihealthz delete` | Delete a health check (interactive) |
126
+ | `apihealthz --version` | Show version number |
127
+ | `apihealthz --help` | Show help message |
128
+
129
+ ## Alert Configuration
130
+
131
+ ### Slack Alerts
132
+
133
+ To receive Slack notifications, you'll need a Slack webhook URL:
134
+
135
+ 1. Go to your Slack workspace settings
136
+ 2. Create a new incoming webhook
137
+ 3. Copy the webhook URL (format: `https://hooks.slack.com/services/...`)
138
+ 4. Provide it when adding a health check
139
+
140
+ ### Email Alerts
141
+
142
+ Simply provide your email address when configuring alerts. You'll receive email notifications when your monitored endpoints go down.
143
+
144
+ ### WhatsApp Alerts
145
+
146
+ WhatsApp alerts are configured during the health check setup process.
147
+
148
+ ## Development
149
+
150
+ ### Project Structure
151
+
152
+ ```
153
+ apihealthz-cli/
154
+ ├── src/
155
+ │ ├── commands/ # CLI command implementations
156
+ │ ├── services/ # API and business logic
157
+ │ └── utils/ # Utility functions (config, etc.)
158
+ ├── dist/ # Compiled JavaScript output
159
+ └── package.json
160
+ ```
161
+
162
+ ### Building
163
+
164
+ ```bash
165
+ npm run build
166
+ ```
167
+
168
+ This compiles TypeScript to JavaScript in the `dist/` directory.
169
+
170
+ ### Development Setup
171
+
172
+ ```bash
173
+ npm run setup
174
+ ```
175
+
176
+ This builds the project and links it globally in one command.
177
+
178
+ ## Requirements
179
+
180
+ - Node.js 14+
181
+ - An ApiHealthz account (created during first login)
182
+
183
+ ## License
184
+
185
+ ISC
186
+
187
+ ## Support
188
+
189
+ For issues, questions, or contributions, please open an issue on the repository.
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.add = add;
4
+ const prompts_1 = require("@inquirer/prompts");
5
+ const config_1 = require("../utils/config");
6
+ const apiHealth_1 = require("../services/apiHealth");
7
+ async function add() {
8
+ const token = (0, config_1.getToken)();
9
+ if (!token) {
10
+ console.error("✖ Authentication required. Run `apihealthz login`");
11
+ process.exit(1);
12
+ }
13
+ try {
14
+ const url = await (0, prompts_1.input)({
15
+ message: "API URL to monitor:",
16
+ validate: (v) => v.startsWith("http://") || v.startsWith("https://")
17
+ ? true
18
+ : "Invalid URL",
19
+ });
20
+ const interval = await (0, prompts_1.select)({
21
+ message: "Select check interval:",
22
+ choices: [
23
+ { name: "Every 5 minutes", value: 300 },
24
+ { name: "Every 15 minutes", value: 900 },
25
+ { name: "Every 30 minutes", value: 1800 },
26
+ { name: "Every 1 hour", value: 3600 },
27
+ ],
28
+ });
29
+ const intervalName = interval === 300
30
+ ? "Every 5 minutes"
31
+ : interval === 900
32
+ ? "Every 15 minutes"
33
+ : interval === 1800
34
+ ? "Every 30 minutes"
35
+ : interval === 3600
36
+ ? "Every 1 hour"
37
+ : `${interval} seconds`;
38
+ const alertType = await (0, prompts_1.select)({
39
+ message: "How do you want to receive alerts?",
40
+ choices: [
41
+ { name: "Slack", value: "slack" },
42
+ { name: "Email", value: "email" },
43
+ { name: "WhatsApp", value: "whatsapp" },
44
+ { name: "None", value: null },
45
+ ],
46
+ });
47
+ let slack_webhook;
48
+ let email;
49
+ if (alertType === "slack") {
50
+ slack_webhook = await (0, prompts_1.input)({
51
+ message: "Slack webhook URL:",
52
+ validate: (v) => v.startsWith("https://hooks.slack.com/")
53
+ ? true
54
+ : "Invalid Slack webhook URL",
55
+ });
56
+ }
57
+ if (alertType === "email") {
58
+ email = await (0, prompts_1.input)({
59
+ message: "Email address:",
60
+ validate: (v) => (v.includes("@") ? true : "Invalid email address"),
61
+ });
62
+ }
63
+ // Show a preview summary before confirmation
64
+ console.log("\n=== Health Check Preview ===");
65
+ console.log(`URL: ${url}`);
66
+ console.log(`Interval: ${intervalName}`);
67
+ console.log(`Alert: ${alertType === null
68
+ ? "None"
69
+ : alertType === "slack"
70
+ ? "Slack"
71
+ : alertType === "email"
72
+ ? "Email"
73
+ : "N/A"}`);
74
+ if (slack_webhook)
75
+ console.log(`Slack Webhook: ${slack_webhook}`);
76
+ if (email)
77
+ console.log(`Email: ${email}`);
78
+ console.log("===========================\n");
79
+ const proceed = await (0, prompts_1.confirm)({
80
+ message: "Create this health check?",
81
+ default: true,
82
+ });
83
+ if (!proceed) {
84
+ console.log("Cancelled");
85
+ process.exit(0);
86
+ }
87
+ const payload = {
88
+ url,
89
+ interval_sec: interval,
90
+ slack_webhook,
91
+ email,
92
+ };
93
+ if (slack_webhook)
94
+ payload.slack_webhook = slack_webhook;
95
+ if (email)
96
+ payload.email = email;
97
+ try {
98
+ process.stdout.write("⠋ Creating health check...\r");
99
+ const response = await (0, apiHealth_1.createHealthCheck)({
100
+ url,
101
+ interval_sec: interval,
102
+ slack_webhook,
103
+ email,
104
+ });
105
+ console.log(`✔ Health check created successfully: ${response.id}`);
106
+ }
107
+ catch (err) {
108
+ console.error(`✖ ${err instanceof Error ? err.message : "Unknown error"}`);
109
+ process.exit(1);
110
+ }
111
+ }
112
+ catch (err) {
113
+ // Handle user cancellation (Ctrl+C)
114
+ if (err?.name === "ExitPromptError" || err?.message?.includes("SIGINT")) {
115
+ console.log("\nCancelled");
116
+ process.exit(0);
117
+ }
118
+ // Re-throw other errors
119
+ throw err;
120
+ }
121
+ }
122
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addApiCheckCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ const apiHealthz_1 = require("../services/apiHealthz");
6
+ exports.addApiCheckCommand = new commander_1.Command("add").description("Add a new API health check");
7
+ exports.addApiCheckCommand
8
+ .command("url")
9
+ .description("Add a new API health check")
10
+ .option("-u, --url <url>", "The URL of the API to check")
11
+ .action(async (options) => {
12
+ await (0, apiHealthz_1.addApiHealthCheckUrl)(options.url);
13
+ });
14
+ //# sourceMappingURL=addApiCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addApiCheck.js","sourceRoot":"","sources":["../../src/commands/addApiCheck.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,uDAA8D;AAEjD,QAAA,kBAAkB,GAAG,IAAI,mBAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAC9D,4BAA4B,CAC7B,CAAC;AAEF,0BAAkB;KACf,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,4BAA4B,CAAC;KACzC,MAAM,CAAC,iBAAiB,EAAE,6BAA6B,CAAC;KACxD,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,IAAA,iCAAoB,EAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addApiCheckCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ const apiHealthz_1 = require("../services/apiHealthz");
6
+ exports.addApiCheckCommand = new commander_1.Command("add").description("Add a new API health check");
7
+ exports.addApiCheckCommand
8
+ .command("url")
9
+ .description("The url of the API to monitor")
10
+ .argument("<url>", "The URL of the API to monitor")
11
+ .action(apiHealthz_1.add);
12
+ //# sourceMappingURL=apiCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiCheck.js","sourceRoot":"","sources":["../../src/commands/apiCheck.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,uDAA6C;AAEhC,QAAA,kBAAkB,GAAG,IAAI,mBAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAC9D,4BAA4B,CAC7B,CAAC;AAEF,0BAAkB;KACf,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,+BAA+B,CAAC;KAC5C,QAAQ,CAAC,OAAO,EAAE,+BAA+B,CAAC;KAClD,MAAM,CAAC,gBAAG,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authCommand = void 0;
4
+ const commander_1 = require("commander");
5
+ const auth_1 = require("../services/auth");
6
+ exports.authCommand = new commander_1.Command("auth").description("Authentication commands");
7
+ exports.authCommand
8
+ .command("login")
9
+ .description("Login to ApiHealthz")
10
+ .option("-p, --provider <provider>", "github | google")
11
+ .action(async (options) => {
12
+ await (0, auth_1.loginWithProvider)(options.provider);
13
+ });
14
+ exports.authCommand
15
+ .command("logout")
16
+ .description("Logout from ApiHealthz")
17
+ .action(async () => {
18
+ await (0, auth_1.logout)();
19
+ });
20
+ exports.authCommand
21
+ .command("status")
22
+ .description("Show auth status")
23
+ .action(async () => {
24
+ await (0, auth_1.authStatus)();
25
+ });
26
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,2CAAyE;AAE5D,QAAA,WAAW,GAAG,IAAI,mBAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CACxD,yBAAyB,CAC1B,CAAC;AAEF,mBAAW;KACR,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,qBAAqB,CAAC;KAClC,MAAM,CAAC,2BAA2B,EAAE,iBAAiB,CAAC;KACtD,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,IAAA,wBAAiB,EAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEL,mBAAW;KACR,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,wBAAwB,CAAC;KACrC,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,IAAA,aAAM,GAAE,CAAC;AACjB,CAAC,CAAC,CAAC;AAEL,mBAAW;KACR,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,kBAAkB,CAAC;KAC/B,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,IAAA,iBAAU,GAAE,CAAC;AACrB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.del = del;
4
+ const prompts_1 = require("@inquirer/prompts");
5
+ const config_1 = require("../utils/config");
6
+ const api_1 = require("../services/api");
7
+ async function del() {
8
+ const token = (0, config_1.getToken)();
9
+ if (!token) {
10
+ console.error("✖ Authentication required. Run `apihealthz login`");
11
+ process.exit(1);
12
+ }
13
+ try {
14
+ const id = await (0, prompts_1.input)({
15
+ message: "Enter the ID of the health check to delete:",
16
+ });
17
+ const proceed = await (0, prompts_1.confirm)({
18
+ message: `Delete check ${id}?`,
19
+ default: true,
20
+ });
21
+ if (!proceed) {
22
+ console.log("Cancelled");
23
+ process.exit(0);
24
+ }
25
+ try {
26
+ await api_1.api.delete(`/checks/${id}`);
27
+ console.log("✔ Health check deleted successfully");
28
+ process.exit(0);
29
+ }
30
+ catch (err) {
31
+ console.error(`✖ ${err instanceof Error ? err.message : "Unknown error"}`);
32
+ process.exit(1);
33
+ }
34
+ }
35
+ catch (err) {
36
+ // Handle user cancellation (Ctrl+C)
37
+ if (err?.name === "ExitPromptError" || err?.message?.includes("SIGINT")) {
38
+ console.log("\nCancelled");
39
+ process.exit(0);
40
+ }
41
+ // Re-throw other errors
42
+ throw err;
43
+ }
44
+ }
45
+ //# sourceMappingURL=delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../src/commands/delete.ts"],"names":[],"mappings":";;AAIA,kBA0CC;AA9CD,+CAAmD;AACnD,4CAA2C;AAC3C,yCAAsC;AAE/B,KAAK,UAAU,GAAG;IACvB,MAAM,KAAK,GAAG,IAAA,iBAAQ,GAAE,CAAC;IAEzB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,IAAA,eAAK,EAAC;YACrB,OAAO,EAAE,6CAA6C;SACvD,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,IAAA,iBAAO,EAAC;YAC5B,OAAO,EAAE,gBAAgB,EAAE,GAAG;YAC9B,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,CAAC;YACH,MAAM,SAAG,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;YACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CACX,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAC5D,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,oCAAoC;QACpC,IAAI,GAAG,EAAE,IAAI,KAAK,iBAAiB,IAAI,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxE,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,wBAAwB;QACxB,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.list = list;
4
+ const api_1 = require("../services/api");
5
+ const timezone_1 = require("../services/timezone");
6
+ const config_1 = require("../utils/config");
7
+ async function list() {
8
+ const token = (0, config_1.getToken)();
9
+ if (!token) {
10
+ console.error("✖ Authentication required. Run `apihealthz login`");
11
+ process.exit(1);
12
+ }
13
+ try {
14
+ const response = await api_1.api.get("/checks");
15
+ const data = response.data;
16
+ if (!data || data.length === 0) {
17
+ console.log("✖ No health checks found, add one with: `apihealthz add`");
18
+ process.exit(0);
19
+ }
20
+ console.table(data.map((c) => ({
21
+ ID: c.id,
22
+ URL: c.url,
23
+ Interval: `${c.interval_sec} seconds`,
24
+ "Last Status": c.last_status ? "✅ UP" : "❌ DOWN",
25
+ "Last Checked": c.last_checked_at
26
+ ? (0, timezone_1.formatDate)(c.last_checked_at)
27
+ : "N/A",
28
+ })));
29
+ }
30
+ catch (err) {
31
+ console.error(`✖ ${err instanceof Error ? err.message : "Unknown error"}`);
32
+ process.exit(1);
33
+ }
34
+ }
35
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":";;AAIA,oBAgCC;AApCD,yCAAsC;AACtC,mDAAkD;AAClD,4CAA2C;AAEpC,KAAK,UAAU,IAAI;IACxB,MAAM,KAAK,GAAG,IAAA,iBAAQ,GAAE,CAAC;IAEzB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;QAE3B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,KAAK,CACX,IAAI,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;YACpB,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,QAAQ,EAAE,GAAG,CAAC,CAAC,YAAY,UAAU;YACrC,aAAa,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;YAChD,cAAc,EAAE,CAAC,CAAC,eAAe;gBAC/B,CAAC,CAAC,IAAA,qBAAU,EAAC,CAAC,CAAC,eAAe,CAAC;gBAC/B,CAAC,CAAC,KAAK;SACV,CAAC,CAAC,CACJ,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const auth_1 = require("./commands/auth");
6
+ const add_1 = require("./commands/add");
7
+ const list_1 = require("./commands/list");
8
+ const delete_1 = require("./commands/delete");
9
+ const program = new commander_1.Command();
10
+ program
11
+ .name("apihealthz")
12
+ .description("API uptime & health monitoring CLI")
13
+ .version("1.0.0");
14
+ program.addCommand(auth_1.authCommand);
15
+ program.command("add").description("Add a new API health check").action(add_1.add);
16
+ program.command("list").description("List all API health checks").action(list_1.list);
17
+ program.command("delete").description("Delete a health check").action(delete_1.del);
18
+ program.parse(process.argv);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,0CAA8C;AAC9C,wCAAqC;AACrC,0CAAuC;AACvC,8CAAwC;AAExC,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,oCAAoC,CAAC;KACjD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,kBAAW,CAAC,CAAC;AAChC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC,MAAM,CAAC,SAAG,CAAC,CAAC;AAC7E,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC,MAAM,CAAC,WAAI,CAAC,CAAC;AAC/E,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,uBAAuB,CAAC,CAAC,MAAM,CAAC,YAAG,CAAC,CAAC;AAE3E,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.api = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const config_1 = require("../utils/config");
9
+ exports.api = axios_1.default.create({
10
+ baseURL: "https://be.apihealthz.com",
11
+ timeout: 10000,
12
+ });
13
+ exports.api.interceptors.request.use((config) => {
14
+ const token = (0, config_1.getToken)();
15
+ if (token) {
16
+ config.headers.Authorization = `Bearer ${token}`;
17
+ }
18
+ return config;
19
+ });
20
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/services/api.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,4CAA2C;AAE9B,QAAA,GAAG,GAAG,eAAK,CAAC,MAAM,CAAC;IAC9B,OAAO,EAAE,2BAA2B;IACpC,OAAO,EAAE,KAAK;CACf,CAAC,CAAC;AAEH,WAAG,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;IACtC,MAAM,KAAK,GAAG,IAAA,iBAAQ,GAAE,CAAC;IACzB,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,OAAO,CAAC,aAAa,GAAG,UAAU,KAAK,EAAE,CAAC;IACnD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createHealthCheck = createHealthCheck;
4
+ const config_1 = require("../utils/config");
5
+ const api_1 = require("./api");
6
+ async function createHealthCheck(payload) {
7
+ const token = (0, config_1.getToken)();
8
+ if (!token) {
9
+ console.error("✖ Authentication required. Run `apihealthz login`");
10
+ process.exit(1);
11
+ }
12
+ const body = {
13
+ url: payload.url,
14
+ interval_sec: payload.interval_sec,
15
+ slack_webhook: payload.slack_webhook,
16
+ email: payload.email,
17
+ };
18
+ const response = await api_1.api.post("/checks", body);
19
+ return response.data;
20
+ }
21
+ //# sourceMappingURL=apiHealth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiHealth.js","sourceRoot":"","sources":["../../src/services/apiHealth.ts"],"names":[],"mappings":";;AAGA,8CAqBC;AAxBD,4CAAuD;AACvD,+BAA4B;AAErB,KAAK,UAAU,iBAAiB,CAAC,OAKvC;IACC,MAAM,KAAK,GAAG,IAAA,iBAAQ,GAAE,CAAC;IACzB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACnE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG;QACX,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,SAAG,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACjD,OAAO,QAAQ,CAAC,IAAI,CAAC;AACvB,CAAC"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.add = add;
4
+ const prompts_1 = require("@inquirer/prompts");
5
+ async function add() {
6
+ const url = await (0, prompts_1.input)({
7
+ message: "API URL to monitor:",
8
+ validate: (v) => v.startsWith("http") || "Invalid URL",
9
+ });
10
+ console.log(url);
11
+ const interval = await (0, prompts_1.select)({
12
+ message: "Select check interval:",
13
+ choices: [
14
+ { name: "Every 5 minutes", value: 300 },
15
+ { name: "Every 15 minutes", value: 900 },
16
+ { name: "Every 30 minutes", value: 1800 },
17
+ { name: "Every 1 hour", value: 3600 },
18
+ ],
19
+ });
20
+ const alertType = await (0, prompts_1.select)({
21
+ message: "How do you want to receive alerts?",
22
+ choices: [
23
+ { name: "Slack", value: "slack" },
24
+ { name: "Email", value: "email" },
25
+ { name: "WhatsApp", value: "whatsapp" },
26
+ { name: "None", value: null },
27
+ ],
28
+ });
29
+ let alertValue;
30
+ if (alertType === "slack") {
31
+ alertValue = await (0, prompts_1.input)({ message: "Slack webhook URL:" });
32
+ }
33
+ if (alertType === "email") {
34
+ alertValue = await (0, prompts_1.input)({ message: "Email address:" });
35
+ }
36
+ if (alertType === "whatsapp") {
37
+ alertValue = await (0, prompts_1.input)({ message: "WhatsApp phone number:" });
38
+ }
39
+ console.log(alertValue);
40
+ const proceed = await (0, prompts_1.confirm)({
41
+ message: "Create this health check?",
42
+ });
43
+ if (!proceed) {
44
+ console.log("Cancelled");
45
+ process.exit(0);
46
+ }
47
+ }
48
+ //# sourceMappingURL=apiHealthz.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiHealthz.js","sourceRoot":"","sources":["../../src/services/apiHealthz.ts"],"names":[],"mappings":";;AAEA,kBAiDC;AAnDD,+CAA2D;AAEpD,KAAK,UAAU,GAAG;IACvB,MAAM,GAAG,GAAG,MAAM,IAAA,eAAK,EAAC;QACtB,OAAO,EAAE,qBAAqB;QAC9B,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,aAAa;KACvD,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEjB,MAAM,QAAQ,GAAG,MAAM,IAAA,gBAAM,EAAC;QAC5B,OAAO,EAAE,wBAAwB;QACjC,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,GAAG,EAAE;YACvC,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,GAAG,EAAE;YACxC,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,IAAI,EAAE;YACzC,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE;SACtC;KACF,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,MAAM,IAAA,gBAAM,EAAC;QAC7B,OAAO,EAAE,oCAAoC;QAC7C,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;YACjC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;YACjC,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;YACvC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE;SAC9B;KACF,CAAC,CAAC;IAEH,IAAI,UAAU,CAAC;IAEf,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QAC1B,UAAU,GAAG,MAAM,IAAA,eAAK,EAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QAC1B,UAAU,GAAG,MAAM,IAAA,eAAK,EAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC7B,UAAU,GAAG,MAAM,IAAA,eAAK,EAAC,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxB,MAAM,OAAO,GAAG,MAAM,IAAA,iBAAO,EAAC;QAC5B,OAAO,EAAE,2BAA2B;KACrC,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}