ninedeploy 0.16.6 → 0.16.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -154,6 +154,16 @@ ninedeploy system update-check # Check for newer releases
154
154
  ninedeploy system prune # Housekeeping prune (dangling containers & cache)
155
155
  ```
156
156
 
157
+ ### 📡 Uptime Monitors & Status Pages (0.16.8)
158
+ ```bash
159
+ ninedeploy monitors list [--service <id|slug>] [--json] # Status, 24h / 30d uptime, last response
160
+ ninedeploy monitors add site https://app.example.com/health # HTTP(S); host:port (or --tcp) is a TCP check
161
+ ninedeploy monitors show|check|pause|resume|rm <id> # Details + last 10 checks, check now, pause, delete
162
+ ninedeploy status-pages add acme "Acme status" --monitor 1 2 --publish
163
+ ninedeploy status-pages publish|unpublish|rm <id>
164
+ ninedeploy status-pages notice <id> "Maintenance at 22:00" # --clear removes it
165
+ ```
166
+
157
167
  ---
158
168
 
159
169
  ## 📄 License
@@ -0,0 +1,68 @@
1
+ import { type StatusPageView } from '@ninedeploy/schemas';
2
+ import { type NineDeployClient } from '../client.js';
3
+ /** A service id, or the id of the service with that slug (or name); null after printing why not. */
4
+ export declare function resolveServiceRef(client: NineDeployClient, ref: string): Promise<number | null>;
5
+ /** A zod failure as one line, each issue led by the flag or argument it is about. */
6
+ export declare function validationMessage(err: {
7
+ issues: Array<{
8
+ path: PropertyKey[];
9
+ message: string;
10
+ }>;
11
+ }): string;
12
+ /** `ninedeploy monitors list [--service <id|slug>] [--json]` */
13
+ export declare function monitorsList(client: NineDeployClient, opts?: {
14
+ service?: string;
15
+ json?: boolean;
16
+ }): Promise<void>;
17
+ export interface MonitorAddOptions {
18
+ tcp?: boolean;
19
+ service?: string;
20
+ interval?: string;
21
+ timeout?: string;
22
+ failures?: string;
23
+ expect?: string;
24
+ keyword?: string;
25
+ head?: boolean;
26
+ /** Commander's `--no-follow-redirects` sets this to false. */
27
+ followRedirects?: boolean;
28
+ insecure?: boolean;
29
+ disabled?: boolean;
30
+ }
31
+ /** `--tcp`, or a target without a scheme that reads as host:port, is a TCP check; anything else HTTP. */
32
+ export declare function monitorKindFor(target: string, tcp?: boolean): 'http' | 'tcp';
33
+ /** `ninedeploy monitors add <name> <target> [...]` */
34
+ export declare function monitorsAdd(client: NineDeployClient, name: string, target: string, opts?: MonitorAddOptions): Promise<void>;
35
+ /** `ninedeploy monitors show <id> [--json]` — details and the last 10 checks. */
36
+ export declare function monitorsShow(client: NineDeployClient, idRaw: string, opts?: {
37
+ json?: boolean;
38
+ }): Promise<void>;
39
+ /** `ninedeploy monitors check <id>` — run a check now. */
40
+ export declare function monitorsCheck(client: NineDeployClient, idRaw: string): Promise<void>;
41
+ /** `ninedeploy monitors pause|resume <id>` */
42
+ export declare function monitorsSetEnabled(client: NineDeployClient, idRaw: string, enabled: boolean): Promise<void>;
43
+ /** `ninedeploy monitors rm <id> [--yes]` */
44
+ export declare function monitorsRemove(client: NineDeployClient, idRaw: string, opts?: {
45
+ yes?: boolean;
46
+ }): Promise<void>;
47
+ /** The public address of a status page: the panel URL plus its path. */
48
+ export declare const statusPageUrl: (p: Pick<StatusPageView, 'path'>) => string;
49
+ /** `ninedeploy status-pages list [--json]` */
50
+ export declare function statusPagesList(client: NineDeployClient, opts?: {
51
+ json?: boolean;
52
+ }): Promise<void>;
53
+ /** `ninedeploy status-pages add <slug> <title> [--monitor <id>...] [--publish]` */
54
+ export declare function statusPagesAdd(client: NineDeployClient, slug: string, title: string, opts?: {
55
+ monitor?: string[];
56
+ publish?: boolean;
57
+ }): Promise<void>;
58
+ /** `ninedeploy status-pages publish|unpublish <id>` */
59
+ export declare function statusPagesSetPublished(client: NineDeployClient, idRaw: string, published: boolean): Promise<void>;
60
+ /** `ninedeploy status-pages notice <id> [text] [--clear]` */
61
+ export declare function statusPagesNotice(client: NineDeployClient, idRaw: string, text: string | undefined, opts?: {
62
+ clear?: boolean;
63
+ }): Promise<void>;
64
+ /** `ninedeploy status-pages rm <id> [--yes]` */
65
+ export declare function statusPagesRemove(client: NineDeployClient, idRaw: string, opts?: {
66
+ yes?: boolean;
67
+ }): Promise<void>;
68
+ //# sourceMappingURL=uptime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uptime.d.ts","sourceRoot":"","sources":["../../src/commands/uptime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,386 @@
1
+ import { monitorCreate, parseTcpTarget, statusPageCreate, statusPagePatch, } from '@ninedeploy/schemas';
2
+ import { apiUrl } from '../client.js';
3
+ import { prompt } from '../prompts.js';
4
+ import { c, error, fmtTime, header, info, kv, spinner, success, table } from '../lib/format.js';
5
+ import { plain } from './sources.js';
6
+ /**
7
+ * 0.16.8 uptime monitors and public status pages:
8
+ *
9
+ * ninedeploy monitors list [--service <id|slug>] [--json]
10
+ * ninedeploy monitors add <name> <target> [--tcp] [--service] [--interval] [--timeout] [--failures]
11
+ * [--expect] [--keyword] [--head] [--no-follow-redirects] [--insecure] [--disabled]
12
+ * ninedeploy monitors show|check|pause|resume|rm <id>
13
+ * ninedeploy status-pages list | add <slug> <title> [--monitor <id>...] [--publish]
14
+ * | publish|unpublish <id> | notice <id> [text] [--clear] | rm <id>
15
+ *
16
+ * Managing monitors and every status-page call is operator only on the
17
+ * server. Names, targets, errors and notices are user text and go through
18
+ * the F1011 sanitiser before they reach the terminal.
19
+ */
20
+ const message = (err) => plain(err instanceof Error ? err.message : String(err));
21
+ function positiveInt(raw, what) {
22
+ const n = Number(raw);
23
+ if (!raw || !Number.isInteger(n) || n <= 0) {
24
+ error(`${what} must be a positive integer`);
25
+ return null;
26
+ }
27
+ return n;
28
+ }
29
+ /** Skip the spinner for `--json` so stdout stays parseable. */
30
+ const load = (json, msg, fn) => (json ? fn() : spinner(msg, fn));
31
+ /** A service id, or the id of the service with that slug (or name); null after printing why not. */
32
+ export async function resolveServiceRef(client, ref) {
33
+ if (/^\d+$/.test(ref))
34
+ return positiveInt(ref, '--service');
35
+ const found = (await client.services.list()).find((s) => s.slug === ref || s.name === ref);
36
+ if (!found) {
37
+ error(`No service named "${plain(ref)}".`);
38
+ return null;
39
+ }
40
+ return found.id;
41
+ }
42
+ const pct = (v) => (v === null ? c.gray('—') : `${v.toFixed(2)}%`);
43
+ function monitorStatus(s) {
44
+ switch (s) {
45
+ case 'up':
46
+ return c.green(s);
47
+ case 'down':
48
+ return c.red(s);
49
+ case 'pending':
50
+ return c.yellow(s);
51
+ default:
52
+ return c.gray(s);
53
+ }
54
+ }
55
+ /** Flag names for the schema fields, so a validation failure names what the user typed. */
56
+ const FLAG = {
57
+ name: '<name>',
58
+ target: '<target>',
59
+ serviceId: '--service',
60
+ intervalSeconds: '--interval',
61
+ timeoutSeconds: '--timeout',
62
+ failuresBeforeDown: '--failures',
63
+ expectedStatus: '--expect',
64
+ keyword: '--keyword',
65
+ slug: '<slug>',
66
+ title: '<title>',
67
+ notice: '<text>',
68
+ monitorIds: '--monitor',
69
+ };
70
+ /** A zod failure as one line, each issue led by the flag or argument it is about. */
71
+ export function validationMessage(err) {
72
+ return err.issues
73
+ .map((i) => {
74
+ const field = String(i.path[0] ?? '');
75
+ return `${FLAG[field] ?? (field || 'input')}: ${i.message}`;
76
+ })
77
+ .join('; ');
78
+ }
79
+ // ── monitors ──────────────────────────────────────────────────────────────
80
+ /** `ninedeploy monitors list [--service <id|slug>] [--json]` */
81
+ export async function monitorsList(client, opts = {}) {
82
+ try {
83
+ const serviceId = opts.service === undefined ? undefined : await resolveServiceRef(client, opts.service);
84
+ if (serviceId === null)
85
+ return;
86
+ const rows = await load(opts.json, 'Loading monitors', () => client.monitors.list(serviceId === undefined ? undefined : { serviceId }));
87
+ if (opts.json) {
88
+ console.log(JSON.stringify(rows, null, 2));
89
+ return;
90
+ }
91
+ header('Uptime monitors');
92
+ if (rows.length === 0) {
93
+ info('No monitors yet. Add one with `ninedeploy monitors add <name> <url>`.');
94
+ return;
95
+ }
96
+ table(rows.map((m) => ({
97
+ id: m.id,
98
+ status: monitorStatus(m.status),
99
+ name: plain(m.name),
100
+ target: `${m.kind === 'tcp' ? 'tcp ' : ''}${plain(m.target)}`,
101
+ '24h': pct(m.uptime.h24),
102
+ '30d': pct(m.uptime.d30),
103
+ 'last ms': m.lastResponseMs ?? c.gray('—'),
104
+ 'last checked': fmtTime(m.lastCheckedAt),
105
+ })), ['id', 'status', 'name', 'target', '24h', '30d', 'last ms', 'last checked']);
106
+ }
107
+ catch (err) {
108
+ error(message(err));
109
+ }
110
+ }
111
+ /** `--tcp`, or a target without a scheme that reads as host:port, is a TCP check; anything else HTTP. */
112
+ export function monitorKindFor(target, tcp) {
113
+ if (tcp)
114
+ return 'tcp';
115
+ return !target.includes('://') && parseTcpTarget(target.trim()) ? 'tcp' : 'http';
116
+ }
117
+ function intFlag(raw, flag) {
118
+ if (raw === undefined)
119
+ return undefined;
120
+ const n = Number(raw);
121
+ if (raw.trim() === '' || !Number.isInteger(n)) {
122
+ error(`${flag} must be a whole number`);
123
+ return null;
124
+ }
125
+ return n;
126
+ }
127
+ /** `ninedeploy monitors add <name> <target> [...]` */
128
+ export async function monitorsAdd(client, name, target, opts = {}) {
129
+ const kind = monitorKindFor(target, opts.tcp);
130
+ const intervalSeconds = intFlag(opts.interval, '--interval');
131
+ const timeoutSeconds = intFlag(opts.timeout, '--timeout');
132
+ const failuresBeforeDown = intFlag(opts.failures, '--failures');
133
+ if (intervalSeconds === null || timeoutSeconds === null || failuresBeforeDown === null)
134
+ return;
135
+ try {
136
+ const serviceId = opts.service === undefined ? undefined : await resolveServiceRef(client, opts.service);
137
+ if (serviceId === null)
138
+ return;
139
+ const input = {
140
+ name,
141
+ kind,
142
+ target,
143
+ ...(serviceId !== undefined ? { serviceId } : {}),
144
+ ...(intervalSeconds !== undefined ? { intervalSeconds } : {}),
145
+ ...(timeoutSeconds !== undefined ? { timeoutSeconds } : {}),
146
+ ...(failuresBeforeDown !== undefined ? { failuresBeforeDown } : {}),
147
+ ...(opts.expect !== undefined ? { expectedStatus: opts.expect } : {}),
148
+ ...(opts.keyword !== undefined ? { keyword: opts.keyword } : {}),
149
+ ...(opts.head ? { method: 'HEAD' } : {}),
150
+ ...(opts.followRedirects === false ? { followRedirects: false } : {}),
151
+ ...(opts.insecure ? { verifyTls: false } : {}),
152
+ ...(opts.disabled ? { enabled: false } : {}),
153
+ };
154
+ const parsed = monitorCreate.safeParse(input);
155
+ if (!parsed.success)
156
+ return error(validationMessage(parsed.error));
157
+ const m = await spinner('Creating the monitor', () => client.monitors.create(input));
158
+ success(`Monitor #${m.id} "${plain(m.name)}" created (${m.kind} ${plain(m.target)}, every ${m.intervalSeconds}s).`);
159
+ if (m.enabled)
160
+ info(`Run a check now: ninedeploy monitors check ${m.id}`);
161
+ else
162
+ info(`Paused. Start it with: ninedeploy monitors resume ${m.id}`);
163
+ }
164
+ catch (err) {
165
+ error(message(err));
166
+ }
167
+ }
168
+ function printChecks(checks) {
169
+ if (checks.length === 0) {
170
+ info('No checks recorded yet.');
171
+ return;
172
+ }
173
+ table(checks.map((k) => ({
174
+ time: fmtTime(k.ts),
175
+ result: k.ok ? c.green('ok') : c.red('fail'),
176
+ ms: k.responseMs ?? c.gray('—'),
177
+ code: k.statusCode ?? c.gray('—'),
178
+ error: k.error ? plain(k.error) : '',
179
+ })), ['time', 'result', 'ms', 'code', 'error']);
180
+ }
181
+ /** Hours of history that hold the last ten checks of a monitor with this interval (1–168, at least a day). */
182
+ const historyHours = (intervalSeconds) => Math.min(168, Math.max(24, Math.ceil((10 * intervalSeconds) / 3600) + 1));
183
+ /** `ninedeploy monitors show <id> [--json]` — details and the last 10 checks. */
184
+ export async function monitorsShow(client, idRaw, opts = {}) {
185
+ const id = positiveInt(idRaw, 'Monitor id');
186
+ if (id === null)
187
+ return;
188
+ try {
189
+ const m = await load(opts.json, 'Loading the monitor', () => client.monitors.get(id));
190
+ const checks = (await client.monitors.checks(id, { hours: historyHours(m.intervalSeconds) })).slice(0, 10);
191
+ if (opts.json) {
192
+ console.log(JSON.stringify({ monitor: m, checks }, null, 2));
193
+ return;
194
+ }
195
+ header(`Monitor #${m.id}: ${plain(m.name)}`);
196
+ kv('Status', `${monitorStatus(m.status)}${m.statusSince ? c.gray(` since ${m.statusSince}`) : ''}`);
197
+ kv('Kind', m.kind);
198
+ kv('Target', plain(m.target));
199
+ kv('Service', m.serviceId === null ? c.gray('— (operator only)') : `#${m.serviceId}`);
200
+ if (m.kind === 'http') {
201
+ kv('Method', m.method);
202
+ kv('Expect', m.expectedStatus);
203
+ kv('Keyword', m.keyword === null ? null : plain(m.keyword));
204
+ kv('Redirects', m.followRedirects ? 'followed' : 'not followed');
205
+ kv('TLS', m.verifyTls ? 'verified' : c.yellow('not verified'));
206
+ }
207
+ kv('Interval', `${m.intervalSeconds}s (timeout ${m.timeoutSeconds}s, down after ${m.failuresBeforeDown} failures)`);
208
+ kv('Uptime', `24h ${pct(m.uptime.h24)} 7d ${pct(m.uptime.d7)} 30d ${pct(m.uptime.d30)}`);
209
+ kv('Last check', m.lastCheckedAt);
210
+ kv('Last response', m.lastResponseMs === null ? null : `${m.lastResponseMs} ms${m.lastStatusCode !== null ? ` (HTTP ${m.lastStatusCode})` : ''}`);
211
+ kv('Last error', m.lastError === null ? null : plain(m.lastError));
212
+ if (m.certExpiresAt)
213
+ kv('Cert expires', m.certExpiresAt);
214
+ kv('Created', m.createdAt);
215
+ console.log();
216
+ console.log(` ${c.bold('Last checks')}`);
217
+ printChecks(checks);
218
+ }
219
+ catch (err) {
220
+ error(message(err));
221
+ }
222
+ }
223
+ /** `ninedeploy monitors check <id>` — run a check now. */
224
+ export async function monitorsCheck(client, idRaw) {
225
+ const id = positiveInt(idRaw, 'Monitor id');
226
+ if (id === null)
227
+ return;
228
+ try {
229
+ const { check, monitor } = await spinner('Checking', () => client.monitors.checkNow(id));
230
+ const detail = [check.responseMs !== null ? `${check.responseMs} ms` : null, check.statusCode !== null ? `HTTP ${check.statusCode}` : null]
231
+ .filter(Boolean)
232
+ .join(', ');
233
+ if (check.ok)
234
+ success(`Check passed${detail ? ` (${detail})` : ''}.`);
235
+ else
236
+ error(`Check failed${detail ? ` (${detail})` : ''}: ${check.error ? plain(check.error) : 'no detail'}`);
237
+ info(`Monitor #${monitor.id} is ${monitor.status}.`);
238
+ }
239
+ catch (err) {
240
+ error(message(err));
241
+ }
242
+ }
243
+ /** `ninedeploy monitors pause|resume <id>` */
244
+ export async function monitorsSetEnabled(client, idRaw, enabled) {
245
+ const id = positiveInt(idRaw, 'Monitor id');
246
+ if (id === null)
247
+ return;
248
+ try {
249
+ const m = await spinner(enabled ? 'Resuming' : 'Pausing', () => client.monitors.update(id, { enabled }));
250
+ success(`Monitor #${m.id} ${enabled ? 'resumed' : 'paused'} (${m.status}).`);
251
+ }
252
+ catch (err) {
253
+ error(message(err));
254
+ }
255
+ }
256
+ /** `ninedeploy monitors rm <id> [--yes]` */
257
+ export async function monitorsRemove(client, idRaw, opts = {}) {
258
+ const id = positiveInt(idRaw, 'Monitor id');
259
+ if (id === null)
260
+ return;
261
+ if (!opts.yes) {
262
+ const answer = await prompt(`Delete monitor #${id} and its check history? Type "yes" to confirm`);
263
+ if (answer.trim().toLowerCase() !== 'yes')
264
+ return info('Cancelled');
265
+ }
266
+ try {
267
+ await spinner('Deleting', () => client.monitors.delete(id));
268
+ success(`Monitor #${id} deleted.`);
269
+ }
270
+ catch (err) {
271
+ error(message(err));
272
+ }
273
+ }
274
+ // ── status pages ──────────────────────────────────────────────────────────
275
+ /** The public address of a status page: the panel URL plus its path. */
276
+ export const statusPageUrl = (p) => apiUrl(p.path);
277
+ /** `ninedeploy status-pages list [--json]` */
278
+ export async function statusPagesList(client, opts = {}) {
279
+ try {
280
+ const rows = await load(opts.json, 'Loading status pages', () => client.statusPages.list());
281
+ if (opts.json) {
282
+ console.log(JSON.stringify(rows, null, 2));
283
+ return;
284
+ }
285
+ header('Status pages');
286
+ if (rows.length === 0) {
287
+ info('No status pages yet. Add one with `ninedeploy status-pages add <slug> <title>`.');
288
+ return;
289
+ }
290
+ table(rows.map((p) => ({
291
+ id: p.id,
292
+ slug: plain(p.slug),
293
+ title: plain(p.title),
294
+ published: p.published ? c.green('yes') : c.gray('no'),
295
+ monitors: p.monitorIds.length,
296
+ notice: p.notice ? 'yes' : '',
297
+ url: statusPageUrl(p),
298
+ })), ['id', 'slug', 'title', 'published', 'monitors', 'notice', 'url']);
299
+ }
300
+ catch (err) {
301
+ error(message(err));
302
+ }
303
+ }
304
+ function printPageUrl(p) {
305
+ if (p.published)
306
+ info(`Public URL: ${statusPageUrl(p)}`);
307
+ else
308
+ info(`Not published (answers 404). Publish it with: ninedeploy status-pages publish ${p.id}`);
309
+ }
310
+ /** `ninedeploy status-pages add <slug> <title> [--monitor <id>...] [--publish]` */
311
+ export async function statusPagesAdd(client, slug, title, opts = {}) {
312
+ const monitorIds = [];
313
+ for (const raw of opts.monitor ?? []) {
314
+ const id = positiveInt(raw, '--monitor');
315
+ if (id === null)
316
+ return;
317
+ monitorIds.push(id);
318
+ }
319
+ const input = { slug, title, monitorIds, published: opts.publish === true };
320
+ const parsed = statusPageCreate.safeParse(input);
321
+ if (!parsed.success)
322
+ return error(validationMessage(parsed.error));
323
+ try {
324
+ const p = await spinner('Creating the status page', () => client.statusPages.create(input));
325
+ success(`Status page #${p.id} "${plain(p.title)}" created with ${p.monitorIds.length} monitor(s).`);
326
+ printPageUrl(p);
327
+ }
328
+ catch (err) {
329
+ error(message(err));
330
+ }
331
+ }
332
+ /** `ninedeploy status-pages publish|unpublish <id>` */
333
+ export async function statusPagesSetPublished(client, idRaw, published) {
334
+ const id = positiveInt(idRaw, 'Status page id');
335
+ if (id === null)
336
+ return;
337
+ try {
338
+ const p = await spinner(published ? 'Publishing' : 'Unpublishing', () => client.statusPages.update(id, { published }));
339
+ success(`Status page #${p.id} ${published ? 'published' : 'unpublished'}.`);
340
+ printPageUrl(p);
341
+ }
342
+ catch (err) {
343
+ error(message(err));
344
+ }
345
+ }
346
+ /** `ninedeploy status-pages notice <id> [text] [--clear]` */
347
+ export async function statusPagesNotice(client, idRaw, text, opts = {}) {
348
+ const id = positiveInt(idRaw, 'Status page id');
349
+ if (id === null)
350
+ return;
351
+ if (opts.clear && text !== undefined)
352
+ return error('Pass the notice text or --clear, not both.');
353
+ if (!opts.clear && !text?.trim())
354
+ return error('Usage: ninedeploy status-pages notice <id> <text> | --clear');
355
+ const notice = opts.clear ? null : text;
356
+ const parsed = statusPagePatch.safeParse({ notice });
357
+ if (!parsed.success)
358
+ return error(validationMessage(parsed.error));
359
+ try {
360
+ const p = await spinner(notice === null ? 'Clearing the notice' : 'Setting the notice', () => client.statusPages.update(id, { notice }));
361
+ success(notice === null ? `Notice cleared on status page #${p.id}.` : `Notice set on status page #${p.id}.`);
362
+ printPageUrl(p);
363
+ }
364
+ catch (err) {
365
+ error(message(err));
366
+ }
367
+ }
368
+ /** `ninedeploy status-pages rm <id> [--yes]` */
369
+ export async function statusPagesRemove(client, idRaw, opts = {}) {
370
+ const id = positiveInt(idRaw, 'Status page id');
371
+ if (id === null)
372
+ return;
373
+ if (!opts.yes) {
374
+ const answer = await prompt(`Delete status page #${id}? Its public URL stops working. Type "yes" to confirm`);
375
+ if (answer.trim().toLowerCase() !== 'yes')
376
+ return info('Cancelled');
377
+ }
378
+ try {
379
+ await spinner('Deleting', () => client.statusPages.delete(id));
380
+ success(`Status page #${id} deleted.`);
381
+ }
382
+ catch (err) {
383
+ error(message(err));
384
+ }
385
+ }
386
+ //# sourceMappingURL=uptime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uptime.js","sourceRoot":"","sources":["../../src/commands/uptime.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -47,6 +47,7 @@ import { panelBackupDecryptAction, panelBackupListAction, panelBackupNowAction,
47
47
  // ── 0.16 T8 surfaces ──
48
48
  import { serversList, serversRoles, servicesPlacement, servicesSwarm, servicesTransfers, sourcesAllowOnNodes, sourcesHostKeys, sourcesPinHostKeys, sourcesResetHostKeys, swarmInit, swarmJoin, swarmLeave, swarmSetEnabled, swarmStatus, volumesCreate, } from './commands/multiNode.js';
49
49
  // ── end 0.16 T8 ──
50
+ import { monitorsAdd, monitorsCheck, monitorsList, monitorsRemove, monitorsSetEnabled, monitorsShow, statusPagesAdd, statusPagesList, statusPagesNotice, statusPagesRemove, statusPagesSetPublished, } from './commands/uptime.js';
50
51
  const program = new Command();
51
52
  program
52
53
  .name('ninedeploy')
@@ -929,6 +930,64 @@ swarmCmd.command('leave <serverId>')
929
930
  .option('-y, --yes', 'Skip the confirmation prompt')
930
931
  .action((serverId, opts) => swarmLeave(getClient(), serverId, opts));
931
932
  /* v8 ignore stop */
933
+ // ── 0.16.8: uptime monitors and public status pages ──────────────────────
934
+ const monitorsCmd = program.command('monitors').alias('monitor').description('Uptime monitors: HTTP(S) and TCP checks with up/down alerts');
935
+ /* v8 ignore start -- exercised by test/uptime.test.ts. */
936
+ monitorsCmd.command('list')
937
+ .description('List monitors with their status and uptime')
938
+ .option('--service <idOrSlug>', 'Only the monitors of this service')
939
+ .option('--json', 'Print raw JSON instead of the table')
940
+ .action((opts) => monitorsList(getClient(), opts));
941
+ monitorsCmd.command('add <name> <target>')
942
+ .description('Add a monitor (operator): an http(s):// URL, or host:port for a TCP check')
943
+ .option('--tcp', 'TCP connect check (the default for a host:port target)')
944
+ .option('--service <idOrSlug>', 'Attach it to a service (its members can see it)')
945
+ .option('--interval <seconds>', 'Seconds between checks (30-3600, default 60)')
946
+ .option('--timeout <seconds>', 'Seconds before a check fails (1-60, default 10)')
947
+ .option('--failures <n>', 'Failed checks in a row before it is down (1-10, default 2)')
948
+ .option('--expect <codes>', 'Accepted HTTP status codes, e.g. 200-299,301 (default 200-399)')
949
+ .option('--keyword <text>', 'Text the response body must contain')
950
+ .option('--head', 'Send HEAD instead of GET')
951
+ .option('--no-follow-redirects', 'Do not follow redirects')
952
+ .option('--insecure', 'Accept a self-signed or expired certificate')
953
+ .option('--disabled', 'Create it paused')
954
+ .action((name, target, opts) => monitorsAdd(getClient(), name, target, opts));
955
+ monitorsCmd.command('show <id>')
956
+ .description('Monitor details and the last 10 checks')
957
+ .option('--json', 'Print raw JSON')
958
+ .action((id, opts) => monitorsShow(getClient(), id, opts));
959
+ monitorsCmd.command('check <id>').description('Run a check now (operator)').action((id) => monitorsCheck(getClient(), id));
960
+ monitorsCmd.command('pause <id>').description('Stop checking (operator)').action((id) => monitorsSetEnabled(getClient(), id, false));
961
+ monitorsCmd.command('resume <id>').description('Start checking again (operator)').action((id) => monitorsSetEnabled(getClient(), id, true));
962
+ monitorsCmd.command('rm <id>')
963
+ .alias('remove')
964
+ .description('Delete a monitor and its history (operator)')
965
+ .option('-y, --yes', 'Skip the confirmation prompt')
966
+ .action((id, opts) => monitorsRemove(getClient(), id, opts));
967
+ /* v8 ignore stop */
968
+ const statusPagesCmd = program.command('status-pages').alias('status-page').description('Public status pages showing a set of monitors (operator)');
969
+ /* v8 ignore start -- exercised by test/uptime.test.ts. */
970
+ statusPagesCmd.command('list')
971
+ .description('List status pages with their public URL')
972
+ .option('--json', 'Print raw JSON instead of the table')
973
+ .action((opts) => statusPagesList(getClient(), opts));
974
+ statusPagesCmd.command('add <slug> <title>')
975
+ .description('Create a status page (unpublished unless --publish)')
976
+ .option('--monitor <id...>', 'Monitors to show, in order')
977
+ .option('--publish', 'Publish it right away')
978
+ .action((slug, title, opts) => statusPagesAdd(getClient(), slug, title, opts));
979
+ statusPagesCmd.command('publish <id>').description('Make the page public').action((id) => statusPagesSetPublished(getClient(), id, true));
980
+ statusPagesCmd.command('unpublish <id>').description('Take the page offline (404)').action((id) => statusPagesSetPublished(getClient(), id, false));
981
+ statusPagesCmd.command('notice <id> [text]')
982
+ .description('Set the notice shown at the top (maintenance, an incident)')
983
+ .option('--clear', 'Remove the notice')
984
+ .action((id, text, opts) => statusPagesNotice(getClient(), id, text, opts));
985
+ statusPagesCmd.command('rm <id>')
986
+ .alias('remove')
987
+ .description('Delete a status page')
988
+ .option('-y, --yes', 'Skip the confirmation prompt')
989
+ .action((id, opts) => statusPagesRemove(getClient(), id, opts));
990
+ /* v8 ignore stop */
932
991
  deploys.command('watch <serviceId> <deployId>').description('Stream a deployment\'s build logs live').action((svcId, depId) => deploysWatch(svcId, depId));
933
992
  // ── Diagnostics ───────────────────────────────────────────────────────────
934
993
  program