@hasna/uptime 0.1.0 → 0.1.1

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/dist/store.js CHANGED
@@ -31,6 +31,13 @@ var MAX_RETRY_COUNT = 10;
31
31
  var MAX_RESULT_LIMIT = 1000;
32
32
 
33
33
  // src/store.ts
34
+ class StaleCheckResultError extends Error {
35
+ constructor(message) {
36
+ super(message);
37
+ this.name = "StaleCheckResultError";
38
+ }
39
+ }
40
+
34
41
  class UptimeStore {
35
42
  dbPath;
36
43
  db;
@@ -64,10 +71,12 @@ class UptimeStore {
64
71
  enabled INTEGER NOT NULL DEFAULT 1,
65
72
  status TEXT NOT NULL DEFAULT 'unknown',
66
73
  last_checked_at TEXT,
74
+ revision INTEGER NOT NULL DEFAULT 1,
67
75
  created_at TEXT NOT NULL,
68
76
  updated_at TEXT NOT NULL
69
77
  )
70
78
  `);
79
+ this.ensureColumn("monitors", "revision", "INTEGER NOT NULL DEFAULT 1");
71
80
  this.db.run(`
72
81
  CREATE TABLE IF NOT EXISTS check_results (
73
82
  id TEXT PRIMARY KEY,
@@ -93,8 +102,17 @@ class UptimeStore {
93
102
  reason TEXT
94
103
  )
95
104
  `);
105
+ this.db.run(`
106
+ CREATE TABLE IF NOT EXISTS check_leases (
107
+ monitor_id TEXT PRIMARY KEY REFERENCES monitors(id) ON DELETE CASCADE,
108
+ owner TEXT NOT NULL,
109
+ leased_until TEXT NOT NULL,
110
+ acquired_at TEXT NOT NULL
111
+ )
112
+ `);
96
113
  this.db.run("CREATE INDEX IF NOT EXISTS idx_results_monitor_time ON check_results(monitor_id, checked_at DESC)");
97
114
  this.db.run("CREATE INDEX IF NOT EXISTS idx_incidents_monitor_status ON incidents(monitor_id, status)");
115
+ this.db.run("CREATE INDEX IF NOT EXISTS idx_check_leases_until ON check_leases(leased_until)");
98
116
  }
99
117
  createMonitor(input) {
100
118
  const normalized = normalizeCreateMonitor(input);
@@ -114,14 +132,15 @@ class UptimeStore {
114
132
  enabled: normalized.enabled ?? true,
115
133
  status: normalized.enabled === false ? "paused" : "unknown",
116
134
  lastCheckedAt: null,
135
+ revision: 1,
117
136
  createdAt: now,
118
137
  updatedAt: now
119
138
  };
120
139
  this.db.query(`INSERT INTO monitors (
121
140
  id, name, kind, url, host, port, method, expected_status,
122
141
  interval_seconds, timeout_ms, retry_count, enabled, status,
123
- last_checked_at, created_at, updated_at
124
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(monitor.id, monitor.name, monitor.kind, monitor.url, monitor.host, monitor.port, monitor.method, monitor.expectedStatus, monitor.intervalSeconds, monitor.timeoutMs, monitor.retryCount, monitor.enabled ? 1 : 0, monitor.status, monitor.lastCheckedAt, monitor.createdAt, monitor.updatedAt);
142
+ last_checked_at, revision, created_at, updated_at
143
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(monitor.id, monitor.name, monitor.kind, monitor.url, monitor.host, monitor.port, monitor.method, monitor.expectedStatus, monitor.intervalSeconds, monitor.timeoutMs, monitor.retryCount, monitor.enabled ? 1 : 0, monitor.status, monitor.lastCheckedAt, monitor.revision, monitor.createdAt, monitor.updatedAt);
125
144
  return monitor;
126
145
  }
127
146
  listMonitors(options = {}) {
@@ -141,8 +160,12 @@ class UptimeStore {
141
160
  this.db.query(`UPDATE monitors SET
142
161
  name = ?, kind = ?, url = ?, host = ?, port = ?, method = ?,
143
162
  expected_status = ?, interval_seconds = ?, timeout_ms = ?,
144
- retry_count = ?, enabled = ?, status = ?, last_checked_at = ?, updated_at = ?
163
+ retry_count = ?, enabled = ?, status = ?, last_checked_at = ?,
164
+ revision = revision + 1, updated_at = ?
145
165
  WHERE id = ?`).run(next.name, next.kind, next.url, next.host, next.port, next.method, next.expectedStatus, next.intervalSeconds, next.timeoutMs, next.retryCount, next.enabled ? 1 : 0, next.status, next.lastCheckedAt, updatedAt, current.id);
166
+ if (definitionChanged(current, next)) {
167
+ this.closeOpenIncident(current.id, updatedAt);
168
+ }
146
169
  return this.getMonitor(current.id);
147
170
  }
148
171
  deleteMonitor(idOrName) {
@@ -152,10 +175,31 @@ class UptimeStore {
152
175
  this.db.query("DELETE FROM monitors WHERE id = ?").run(current.id);
153
176
  return true;
154
177
  }
178
+ acquireCheckLease(monitorId, owner, ttlMs) {
179
+ const now = new Date;
180
+ const nowIso = now.toISOString();
181
+ const leasedUntil = new Date(now.getTime() + Math.max(1000, ttlMs)).toISOString();
182
+ const tx = this.db.transaction(() => {
183
+ this.db.query("DELETE FROM check_leases WHERE monitor_id = ? AND leased_until <= ?").run(monitorId, nowIso);
184
+ this.db.query("INSERT OR IGNORE INTO check_leases (monitor_id, owner, leased_until, acquired_at) VALUES (?, ?, ?, ?)").run(monitorId, owner, leasedUntil, nowIso);
185
+ const row = this.db.query("SELECT * FROM check_leases WHERE monitor_id = ?").get(monitorId);
186
+ return row?.owner === owner;
187
+ });
188
+ return tx();
189
+ }
190
+ releaseCheckLease(monitorId, owner) {
191
+ this.db.query("DELETE FROM check_leases WHERE monitor_id = ? AND owner = ?").run(monitorId, owner);
192
+ }
155
193
  recordCheckResult(input) {
156
194
  const monitor = this.getMonitor(input.monitorId);
157
195
  if (!monitor)
158
196
  throw new Error(`Monitor not found: ${input.monitorId}`);
197
+ if (input.expectedMonitorRevision !== undefined && monitor.revision !== input.expectedMonitorRevision) {
198
+ throw new StaleCheckResultError(`Monitor changed while check was in progress: ${monitor.name}`);
199
+ }
200
+ if (!monitor.enabled) {
201
+ throw new StaleCheckResultError(`Monitor was disabled while check was in progress: ${monitor.name}`);
202
+ }
159
203
  const checkedAt = input.checkedAt ?? new Date().toISOString();
160
204
  const result = {
161
205
  id: newId("chk"),
@@ -168,6 +212,15 @@ class UptimeStore {
168
212
  attemptCount: Math.max(1, input.attemptCount)
169
213
  };
170
214
  const tx = this.db.transaction(() => {
215
+ const current = this.db.query("SELECT * FROM monitors WHERE id = ?").get(result.monitorId);
216
+ if (!current)
217
+ throw new Error(`Monitor not found: ${result.monitorId}`);
218
+ if (input.expectedMonitorRevision !== undefined && current.revision !== input.expectedMonitorRevision) {
219
+ throw new StaleCheckResultError(`Monitor changed while check was in progress: ${current.name}`);
220
+ }
221
+ if (!current.enabled) {
222
+ throw new StaleCheckResultError(`Monitor was disabled while check was in progress: ${current.name}`);
223
+ }
171
224
  this.db.query(`INSERT INTO check_results (
172
225
  id, monitor_id, checked_at, status, latency_ms, status_code, error, attempt_count
173
226
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(result.id, result.monitorId, result.checkedAt, result.status, result.latencyMs, result.statusCode, result.error, result.attemptCount);
@@ -215,10 +268,14 @@ class UptimeStore {
215
268
  down: monitors.filter((m) => m.status === "down").length,
216
269
  paused: monitors.filter((m) => !m.enabled || m.status === "paused").length,
217
270
  unknown: monitors.filter((m) => m.status === "unknown").length,
218
- openIncidents: this.listIncidents({ status: "open", limit: 1000 }).length
271
+ openIncidents: this.countOpenIncidents()
219
272
  }
220
273
  };
221
274
  }
275
+ countOpenIncidents() {
276
+ const row = this.db.query("SELECT COUNT(*) AS count FROM incidents WHERE status = 'open'").get();
277
+ return Number(row?.count ?? 0);
278
+ }
222
279
  monitorSummary(monitor) {
223
280
  const row = this.db.query(`SELECT
224
281
  COUNT(*) as total,
@@ -256,13 +313,24 @@ class UptimeStore {
256
313
  this.db.query("UPDATE incidents SET status = 'closed', closed_at = ?, recovery_check_id = ? WHERE id = ?").run(result.checkedAt, result.id, open.id);
257
314
  }
258
315
  }
316
+ closeOpenIncident(monitorId, closedAt) {
317
+ this.db.query("UPDATE incidents SET status = 'closed', closed_at = ? WHERE monitor_id = ? AND status = 'open'").run(closedAt, monitorId);
318
+ }
319
+ ensureColumn(table, name, definition) {
320
+ const columns = this.db.query(`PRAGMA table_info(${table})`).all();
321
+ if (!columns.some((column) => column.name === name)) {
322
+ this.db.run(`ALTER TABLE ${table} ADD COLUMN ${name} ${definition}`);
323
+ }
324
+ }
259
325
  }
260
326
  function normalizeCreateMonitor(input) {
261
327
  const name = input.name?.trim();
262
328
  if (!name)
263
329
  throw new Error("Monitor name is required");
330
+ rejectControlCharacters(name, "Monitor name");
264
331
  const method = normalizeMethod(input.method ?? "GET");
265
332
  const expectedStatus = normalizeExpectedStatus(input.expectedStatus);
333
+ const enabled = normalizeEnabled(input.enabled);
266
334
  if (input.kind === "http") {
267
335
  const url = normalizeHttpUrl(input.url);
268
336
  return {
@@ -274,12 +342,13 @@ function normalizeCreateMonitor(input) {
274
342
  intervalSeconds: boundedInteger(input.intervalSeconds ?? 60, "intervalSeconds", MIN_INTERVAL_SECONDS, MAX_INTERVAL_SECONDS),
275
343
  timeoutMs: boundedInteger(input.timeoutMs ?? 5000, "timeoutMs", MIN_TIMEOUT_MS, MAX_TIMEOUT_MS),
276
344
  retryCount: boundedInteger(input.retryCount ?? 0, "retryCount", MIN_RETRY_COUNT, MAX_RETRY_COUNT),
277
- enabled: input.enabled ?? true
345
+ enabled
278
346
  };
279
347
  } else if (input.kind === "tcp") {
280
348
  const host = input.host?.trim();
281
349
  if (!host)
282
350
  throw new Error("TCP monitors require host");
351
+ rejectControlCharacters(host, "TCP host");
283
352
  if (!Number.isInteger(input.port) || input.port <= 0 || input.port > 65535) {
284
353
  throw new Error("TCP monitors require a port from 1 to 65535");
285
354
  }
@@ -293,12 +362,15 @@ function normalizeCreateMonitor(input) {
293
362
  intervalSeconds: boundedInteger(input.intervalSeconds ?? 60, "intervalSeconds", MIN_INTERVAL_SECONDS, MAX_INTERVAL_SECONDS),
294
363
  timeoutMs: boundedInteger(input.timeoutMs ?? 5000, "timeoutMs", MIN_TIMEOUT_MS, MAX_TIMEOUT_MS),
295
364
  retryCount: boundedInteger(input.retryCount ?? 0, "retryCount", MIN_RETRY_COUNT, MAX_RETRY_COUNT),
296
- enabled: input.enabled ?? true
365
+ enabled
297
366
  };
298
367
  } else {
299
368
  throw new Error("Monitor kind must be http or tcp");
300
369
  }
301
370
  }
371
+ function definitionChanged(current, next) {
372
+ return next.kind !== current.kind || next.url !== current.url || next.host !== current.host || next.port !== current.port || next.method !== current.method || next.expectedStatus !== current.expectedStatus;
373
+ }
302
374
  function normalizeUpdateMonitor(current, input, updatedAt) {
303
375
  const merged = {
304
376
  ...current,
@@ -363,6 +435,18 @@ function normalizeExpectedStatus(value) {
363
435
  }
364
436
  return value;
365
437
  }
438
+ function normalizeEnabled(value) {
439
+ if (value === undefined)
440
+ return true;
441
+ if (typeof value !== "boolean")
442
+ throw new Error("enabled must be a boolean");
443
+ return value;
444
+ }
445
+ function rejectControlCharacters(value, label) {
446
+ if (/[\x00-\x1f\x7f-\x9f]/.test(value)) {
447
+ throw new Error(`${label} must not contain control characters`);
448
+ }
449
+ }
366
450
  function monitorFromRow(row) {
367
451
  return {
368
452
  id: row.id,
@@ -379,6 +463,7 @@ function monitorFromRow(row) {
379
463
  enabled: Boolean(row.enabled),
380
464
  status: row.status,
381
465
  lastCheckedAt: row.last_checked_at,
466
+ revision: row.revision ?? 1,
382
467
  createdAt: row.created_at,
383
468
  updatedAt: row.updated_at
384
469
  };
@@ -427,5 +512,6 @@ function round(value, places) {
427
512
  return Math.round(value * factor) / factor;
428
513
  }
429
514
  export {
430
- UptimeStore
515
+ UptimeStore,
516
+ StaleCheckResultError
431
517
  };
package/dist/types.d.ts CHANGED
@@ -17,6 +17,7 @@ export interface Monitor {
17
17
  enabled: boolean;
18
18
  status: MonitorStatus;
19
19
  lastCheckedAt: string | null;
20
+ revision: number;
20
21
  createdAt: string;
21
22
  updatedAt: string;
22
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/uptime",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Local-first uptime and downtime monitoring service with CLI, MCP, SDK, SQLite persistence, and a dashboard.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -12,6 +12,7 @@
12
12
  "bugs": {
13
13
  "url": "https://github.com/hasna/uptime/issues"
14
14
  },
15
+ "readmeFilename": "README.md",
15
16
  "keywords": [
16
17
  "uptime",
17
18
  "monitoring",
@@ -53,7 +54,7 @@
53
54
  }
54
55
  },
55
56
  "scripts": {
56
- "build": "rm -rf dist && bun build src/cli/index.ts --outdir dist/cli --target bun --external @modelcontextprotocol/sdk && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk && bun build src/index.ts src/api.ts src/service.ts src/store.ts src/checks.ts src/types.ts src/paths.ts src/dashboard.ts src/version.ts --root src --outdir dist --target bun && tsc -p tsconfig.build.json --emitDeclarationOnly --outDir dist && chmod +x dist/cli/index.js dist/mcp/index.js",
57
+ "build": "rm -rf dist && bun build src/cli/index.ts --outdir dist/cli --target bun --external @modelcontextprotocol/sdk && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk && bun build src/index.ts src/api.ts src/service.ts src/store.ts src/checks.ts src/report.ts src/types.ts src/paths.ts src/dashboard.ts src/version.ts --root src --outdir dist --target bun && tsc -p tsconfig.build.json --emitDeclarationOnly --outDir dist && chmod +x dist/cli/index.js dist/mcp/index.js",
57
58
  "typecheck": "tsc --noEmit",
58
59
  "test": "bun test ./tests",
59
60
  "dev:cli": "bun run src/cli/index.ts",