@yawlabs/lemonsqueezy-webhook-sink 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/README.md CHANGED
@@ -35,11 +35,26 @@ Optional:
35
35
  | Method | Path | Auth | Purpose |
36
36
  | --- | --- | --- | --- |
37
37
  | `POST` | `/webhook` | HMAC | Receive a LemonSqueezy webhook. Returns 200 for both new and duplicate events. |
38
- | `GET` | `/healthz` | none | Liveness check. |
38
+ | `GET` | `/healthz` | none | Liveness check. 200 when the DB is reachable, 503 otherwise. |
39
39
  | `GET` | `/events?since=<ts>&type=<name>&limit=<n>` | `WEBHOOK_SINK_ADMIN_TOKEN` | Page events in order of `received_at`. Use `since=<last-seen-ts>` to checkpoint. |
40
40
  | `POST` | `/events/:id/processed` | `WEBHOOK_SINK_ADMIN_TOKEN` | Mark an event consumed. |
41
41
  | `GET` | `/stats` | `WEBHOOK_SINK_ADMIN_TOKEN` | Total events, unprocessed count, last-received timestamp. |
42
42
 
43
+ ### Response codes for `POST /webhook`
44
+
45
+ | Status | When |
46
+ | --- | --- |
47
+ | `200` | Valid signature and parseable payload (new or duplicate event). |
48
+ | `400` | Signature valid, but body is not JSON or `meta.event_name` is missing. |
49
+ | `401` | Missing or invalid `X-Signature`. |
50
+ | `413` | Body exceeds 1 MB. |
51
+
52
+ When `WEBHOOK_SINK_ADMIN_TOKEN` is unset, the admin endpoints (`/events`, `/events/:id/processed`, `/stats`) respond `404` indistinguishably from any unknown route -- they do not reveal that an admin surface exists.
53
+
54
+ ### Using with `@yawlabs/lemonsqueezy-mcp`
55
+
56
+ The [LemonSqueezy MCP server](https://github.com/YawLabs/lemonsqueezy-mcp) exposes `ls_sink_events_list`, `ls_sink_event_mark_processed`, and `ls_sink_stats` tools that bridge to this sink over HTTP. Point the MCP server at this sink by setting `LEMONSQUEEZY_SINK_URL` and `LEMONSQUEEZY_SINK_ADMIN_TOKEN` in its environment; agents can then query "what events have actually fired" through the same MCP surface they use for LS API calls.
57
+
43
58
  ## Deduplication
44
59
 
45
60
  Every event is stored under a stable `event_key`:
package/dist/app.js CHANGED
@@ -1,20 +1,41 @@
1
+ import { timingSafeEqual } from "node:crypto";
1
2
  import { Hono } from "hono";
3
+ import { bodyLimit } from "hono/body-limit";
2
4
  import { handleWebhook } from "./handler.js";
5
+ const MAX_WEBHOOK_BYTES = 1024 * 1024;
3
6
  export function createApp(config) {
4
7
  const { store, signingSecret, adminToken } = config;
5
8
  const app = new Hono();
6
- app.get("/healthz", (c) => c.json({ ok: true }));
7
- app.post("/webhook", async (c) => {
9
+ app.get("/healthz", (c) => {
10
+ try {
11
+ store.ping();
12
+ return c.json({ ok: true });
13
+ }
14
+ catch {
15
+ return c.json({ ok: false }, 503);
16
+ }
17
+ });
18
+ app.post("/webhook", bodyLimit({
19
+ maxSize: MAX_WEBHOOK_BYTES,
20
+ onError: (c) => c.json({ ok: false, error: "payload too large" }, 413),
21
+ }), async (c) => {
8
22
  const rawBody = await c.req.text();
9
23
  const signature = c.req.header("x-signature") ?? null;
10
24
  const result = handleWebhook({ store, signingSecret }, { rawBody, signature });
11
25
  return c.json(result.body, result.status);
12
26
  });
13
27
  function requireAdmin(c) {
28
+ // Admin endpoints look identical to unknown routes when no token is configured -- avoids
29
+ // confirming the endpoint exists to unauthenticated callers.
14
30
  if (!adminToken)
15
- return c.json({ error: "admin endpoints disabled" }, 404);
31
+ return c.text("404 Not Found", 404);
16
32
  const auth = c.req.header("authorization") ?? "";
17
- if (auth !== `Bearer ${adminToken}`)
33
+ const expected = `Bearer ${adminToken}`;
34
+ const authBuf = Buffer.from(auth, "utf8");
35
+ const expectedBuf = Buffer.from(expected, "utf8");
36
+ if (authBuf.length !== expectedBuf.length)
37
+ return c.json({ error: "unauthorized" }, 401);
38
+ if (!timingSafeEqual(authBuf, expectedBuf))
18
39
  return c.json({ error: "unauthorized" }, 401);
19
40
  return null;
20
41
  }
@@ -22,9 +43,15 @@ export function createApp(config) {
22
43
  const unauthorized = requireAdmin(c);
23
44
  if (unauthorized)
24
45
  return unauthorized;
25
- const since = Number(c.req.query("since") ?? 0);
26
- const type = c.req.query("type") ?? undefined;
27
- const limit = Number(c.req.query("limit") ?? 100);
46
+ const sinceRaw = c.req.query("since");
47
+ const since = sinceRaw === undefined ? 0 : Number(sinceRaw);
48
+ if (!Number.isFinite(since) || since < 0)
49
+ return c.json({ error: "invalid since" }, 400);
50
+ const type = c.req.query("type") || undefined;
51
+ const limitRaw = c.req.query("limit");
52
+ const limit = limitRaw === undefined ? 100 : Number(limitRaw);
53
+ if (!Number.isFinite(limit) || limit < 1)
54
+ return c.json({ error: "invalid limit" }, 400);
28
55
  const rows = store.list({ since, type, limit });
29
56
  return c.json({ events: rows });
30
57
  });
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
package/dist/app.test.js CHANGED
@@ -135,6 +135,46 @@ describe("HTTP app", () => {
135
135
  });
136
136
  assert.equal(r.status, 400);
137
137
  });
138
+ it("GET /events rejects non-numeric since with 400", async () => {
139
+ const r = await req("/events?since=abc", { headers: { authorization: `Bearer ${ADMIN}` } });
140
+ assert.equal(r.status, 400);
141
+ const j = (await r.json());
142
+ assert.match(j.error, /since/);
143
+ });
144
+ it("GET /events rejects negative since with 400", async () => {
145
+ const r = await req("/events?since=-1", { headers: { authorization: `Bearer ${ADMIN}` } });
146
+ assert.equal(r.status, 400);
147
+ });
148
+ it("GET /events rejects non-numeric limit with 400", async () => {
149
+ const r = await req("/events?limit=abc", { headers: { authorization: `Bearer ${ADMIN}` } });
150
+ assert.equal(r.status, 400);
151
+ const j = (await r.json());
152
+ assert.match(j.error, /limit/);
153
+ });
154
+ it("GET /events rejects zero limit with 400", async () => {
155
+ const r = await req("/events?limit=0", { headers: { authorization: `Bearer ${ADMIN}` } });
156
+ assert.equal(r.status, 400);
157
+ });
158
+ it("POST /webhook rejects oversized body with 413", async () => {
159
+ const huge = "x".repeat(1024 * 1024 + 10);
160
+ const r = await req("/webhook", {
161
+ method: "POST",
162
+ headers: { "x-signature": sign(huge), "content-length": String(huge.length) },
163
+ body: huge,
164
+ });
165
+ assert.equal(r.status, 413);
166
+ assert.equal(store.stats().total, 0);
167
+ });
168
+ it("GET /healthz returns 503 when DB is closed", async () => {
169
+ store.close();
170
+ const r = await req("/healthz");
171
+ assert.equal(r.status, 503);
172
+ const j = (await r.json());
173
+ assert.equal(j.ok, false);
174
+ // Re-open so afterEach close() doesn't double-close
175
+ store = new EventStore(dbPath);
176
+ app = createApp({ store, signingSecret: SECRET, adminToken: ADMIN });
177
+ });
138
178
  it("GET /stats returns totals", async () => {
139
179
  const body = payload();
140
180
  await req("/webhook", {
@@ -148,14 +188,23 @@ describe("HTTP app", () => {
148
188
  assert.equal(s.total, 1);
149
189
  assert.equal(s.unprocessed, 1);
150
190
  });
151
- it("admin endpoints return 404 when token is unset", async () => {
191
+ it("admin endpoints return 404 when token is unset, with no leaking body", async () => {
152
192
  const noAuthApp = createApp({ store, signingSecret: SECRET, adminToken: undefined });
153
193
  const r = await noAuthApp.fetch(new Request("http://test/events", { headers: { authorization: "Bearer anything" } }));
154
194
  assert.equal(r.status, 404);
195
+ const text = await r.text();
196
+ assert.doesNotMatch(text, /admin/i, "404 body must not reveal admin endpoint existence");
197
+ assert.doesNotMatch(text, /disabled/i);
155
198
  });
156
199
  it("admin endpoints reject wrong bearer token with 401", async () => {
157
200
  const r = await req("/stats", { headers: { authorization: "Bearer wrong" } });
158
201
  assert.equal(r.status, 401);
159
202
  });
203
+ it("admin endpoints reject token with same length but wrong bytes via timing-safe compare", async () => {
204
+ // Same length as `Bearer ${ADMIN}` -> ensures we hit the timingSafeEqual branch, not the length branch
205
+ const sameLength = `Bearer ${"x".repeat(ADMIN.length)}`;
206
+ const r = await req("/stats", { headers: { authorization: sameLength } });
207
+ assert.equal(r.status, 401);
208
+ });
160
209
  });
161
210
  //# sourceMappingURL=app.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app.test.js","sourceRoot":"","sources":["../src/app.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.test.js","sourceRoot":"","sources":["../src/app.test.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -8,17 +8,35 @@ function requireEnv(name) {
8
8
  throw new Error(`${name} environment variable is required`);
9
9
  return v;
10
10
  }
11
+ function parsePort(raw) {
12
+ const n = Number(raw);
13
+ if (!Number.isInteger(n) || n < 1 || n > 65535) {
14
+ throw new Error(`PORT must be an integer in [1, 65535], got: ${JSON.stringify(raw)}`);
15
+ }
16
+ return n;
17
+ }
18
+ const SHUTDOWN_TIMEOUT_MS = 10_000;
11
19
  const SIGNING_SECRET = requireEnv("LEMONSQUEEZY_SIGNING_SECRET");
12
20
  const DB_PATH = process.env.WEBHOOK_SINK_DB ?? "./events.db";
13
- const PORT = Number(process.env.PORT ?? 8787);
21
+ const PORT = parsePort(process.env.PORT ?? "8787");
14
22
  const ADMIN_TOKEN = process.env.WEBHOOK_SINK_ADMIN_TOKEN;
15
23
  const store = new EventStore(DB_PATH);
16
24
  const app = createApp({ store, signingSecret: SIGNING_SECRET, adminToken: ADMIN_TOKEN });
17
25
  const server = serve({ fetch: app.fetch, port: PORT }, (info) => {
18
26
  console.log(`lemonsqueezy-webhook-sink listening on :${info.port}`);
19
27
  });
28
+ let shuttingDown = false;
20
29
  const shutdown = () => {
30
+ if (shuttingDown)
31
+ return;
32
+ shuttingDown = true;
33
+ const forceExit = setTimeout(() => {
34
+ console.error(`shutdown timed out after ${SHUTDOWN_TIMEOUT_MS}ms, forcing exit`);
35
+ process.exit(1);
36
+ }, SHUTDOWN_TIMEOUT_MS);
37
+ forceExit.unref();
21
38
  server.close(() => {
39
+ clearTimeout(forceExit);
22
40
  store.close();
23
41
  process.exit(0);
24
42
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,mCAAmC,CAAC,CAAC;IACvF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,cAAc,GAAG,UAAU,CAAC,6BAA6B,CAAC,CAAC;AACjE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,aAAa,CAAC;AAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;AAC9C,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;AAEzD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;AACtC,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;AAEzF,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE;IAC9D,OAAO,CAAC,GAAG,CAAC,2CAA2C,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,GAAG,EAAE;IACpB,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;QAChB,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AACF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAChC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,mCAAmC,CAAC,CAAC;IACvF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,+CAA+C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAEnC,MAAM,cAAc,GAAG,UAAU,CAAC,6BAA6B,CAAC,CAAC;AACjE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,aAAa,CAAC;AAC7D,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC;AACnD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;AAEzD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;AACtC,MAAM,GAAG,GAAG,SAAS,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;AAEzF,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE;IAC9D,OAAO,CAAC,GAAG,CAAC,2CAA2C,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AACtE,CAAC,CAAC,CAAC;AAEH,IAAI,YAAY,GAAG,KAAK,CAAC;AACzB,MAAM,QAAQ,GAAG,GAAG,EAAE;IACpB,IAAI,YAAY;QAAE,OAAO;IACzB,YAAY,GAAG,IAAI,CAAC;IACpB,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;QAChC,OAAO,CAAC,KAAK,CAAC,4BAA4B,mBAAmB,kBAAkB,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,EAAE,mBAAmB,CAAC,CAAC;IACxB,SAAS,CAAC,KAAK,EAAE,CAAC;IAClB,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;QAChB,YAAY,CAAC,SAAS,CAAC,CAAC;QACxB,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AACF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAChC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC"}
package/dist/store.js CHANGED
@@ -5,25 +5,39 @@ import Database from "better-sqlite3";
5
5
  const SCHEMA_PATH = resolve(dirname(fileURLToPath(import.meta.url)), "../schema.sql");
6
6
  export class EventStore {
7
7
  db;
8
+ stmtFindByKey;
9
+ stmtInsert;
10
+ stmtListAll;
11
+ stmtListByType;
12
+ stmtMarkProcessed;
13
+ stmtCountTotal;
14
+ stmtCountUnprocessed;
15
+ stmtMaxReceivedAt;
16
+ stmtPing;
8
17
  constructor(dbPath) {
9
18
  this.db = new Database(dbPath);
10
19
  this.db.pragma("journal_mode = WAL");
11
20
  this.db.pragma("synchronous = NORMAL");
12
21
  this.db.exec(readFileSync(SCHEMA_PATH, "utf8"));
22
+ this.stmtFindByKey = this.db.prepare("SELECT id FROM events WHERE event_key = ?");
23
+ this.stmtInsert = this.db.prepare("INSERT INTO events (event_key, event_name, resource_id, received_at, payload) VALUES (?, ?, ?, ?, ?)");
24
+ this.stmtListAll = this.db.prepare("SELECT * FROM events WHERE received_at > ? ORDER BY received_at ASC LIMIT ?");
25
+ this.stmtListByType = this.db.prepare("SELECT * FROM events WHERE received_at > ? AND event_name = ? ORDER BY received_at ASC LIMIT ?");
26
+ this.stmtMarkProcessed = this.db.prepare("UPDATE events SET processed = 1 WHERE id = ?");
27
+ this.stmtCountTotal = this.db.prepare("SELECT COUNT(*) as c FROM events");
28
+ this.stmtCountUnprocessed = this.db.prepare("SELECT COUNT(*) as c FROM events WHERE processed = 0");
29
+ this.stmtMaxReceivedAt = this.db.prepare("SELECT MAX(received_at) as m FROM events");
30
+ this.stmtPing = this.db.prepare("SELECT 1 as ok");
13
31
  }
14
32
  /**
15
- * Insert an event. Dedupes on event_key — if the key exists, returns the
33
+ * Insert an event. Dedupes on event_key -- if the key exists, returns the
16
34
  * existing row's id and `duplicate: true` without touching the row.
17
35
  */
18
36
  insert(input) {
19
- const existing = this.db
20
- .prepare("SELECT id FROM events WHERE event_key = ?")
21
- .get(input.event_key);
37
+ const existing = this.stmtFindByKey.get(input.event_key);
22
38
  if (existing)
23
39
  return { id: existing.id, duplicate: true };
24
- const info = this.db
25
- .prepare("INSERT INTO events (event_key, event_name, resource_id, received_at, payload) VALUES (?, ?, ?, ?, ?)")
26
- .run(input.event_key, input.event_name, input.resource_id, input.received_at, input.payload);
40
+ const info = this.stmtInsert.run(input.event_key, input.event_name, input.resource_id, input.received_at, input.payload);
27
41
  return { id: info.lastInsertRowid, duplicate: false };
28
42
  }
29
43
  /**
@@ -34,28 +48,27 @@ export class EventStore {
34
48
  list(opts) {
35
49
  const limit = Math.min(Math.max(opts.limit ?? 100, 1), 1000);
36
50
  const since = opts.since ?? 0;
37
- if (opts.type) {
38
- return this.db
39
- .prepare("SELECT * FROM events WHERE received_at > ? AND event_name = ? ORDER BY received_at ASC LIMIT ?")
40
- .all(since, opts.type, limit);
41
- }
42
- return this.db
43
- .prepare("SELECT * FROM events WHERE received_at > ? ORDER BY received_at ASC LIMIT ?")
44
- .all(since, limit);
51
+ if (opts.type)
52
+ return this.stmtListByType.all(since, opts.type, limit);
53
+ return this.stmtListAll.all(since, limit);
45
54
  }
46
55
  markProcessed(id) {
47
- this.db.prepare("UPDATE events SET processed = 1 WHERE id = ?").run(id);
56
+ this.stmtMarkProcessed.run(id);
48
57
  }
49
58
  stats() {
50
- const totalRow = this.db.prepare("SELECT COUNT(*) as c FROM events").get();
51
- const unprocRow = this.db.prepare("SELECT COUNT(*) as c FROM events WHERE processed = 0").get();
52
- const lastRow = this.db.prepare("SELECT MAX(received_at) as m FROM events").get();
59
+ const totalRow = this.stmtCountTotal.get();
60
+ const unprocRow = this.stmtCountUnprocessed.get();
61
+ const lastRow = this.stmtMaxReceivedAt.get();
53
62
  return {
54
63
  total: totalRow?.c ?? 0,
55
64
  unprocessed: unprocRow?.c ?? 0,
56
65
  lastReceivedAt: lastRow?.m ?? null,
57
66
  };
58
67
  }
68
+ /** Cheap liveness probe -- throws if the underlying DB handle is unhealthy. */
69
+ ping() {
70
+ this.stmtPing.get();
71
+ }
59
72
  close() {
60
73
  this.db.close();
61
74
  }
package/dist/store.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -73,5 +73,14 @@ describe("EventStore", () => {
73
73
  store.insert(base({ event_key: "b", received_at: 700 }));
74
74
  assert.equal(store.stats().lastReceivedAt, 700);
75
75
  });
76
+ it("ping succeeds on a healthy DB", () => {
77
+ assert.doesNotThrow(() => store.ping());
78
+ });
79
+ it("ping throws on a closed DB", () => {
80
+ store.close();
81
+ assert.throws(() => store.ping());
82
+ // Reopen so afterEach close() doesn't double-close
83
+ store = new EventStore(dbPath);
84
+ });
76
85
  });
77
86
  //# sourceMappingURL=store.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.test.js","sourceRoot":"","sources":["../src/store.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.test.js","sourceRoot":"","sources":["../src/store.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yawlabs/lemonsqueezy-webhook-sink",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Durable webhook receiver for LemonSqueezy — verifies signatures, deduplicates events, and persists them for replay and reconciliation",
5
5
  "license": "MIT",
6
6
  "author": "YawLabs <contact@yaw.sh>",
package/schema.sql CHANGED
@@ -1,6 +1,8 @@
1
- -- Webhook event store. One row per received webhook, deduplicated by LemonSqueezy's event_name + custom_data.event_id when present.
2
- -- The payload is stored as raw JSON so the HMAC signature can be re-verified
3
- -- against the original bytes if needed.
1
+ -- Webhook event store. One row per received webhook, deduplicated by `event_key`:
2
+ -- either `meta.custom_data.event_id` when the sender supplies one, or a SHA-256
3
+ -- hash of `event_name + data.type + data.id + data.attributes.created_at` as a
4
+ -- stable fallback. The payload is stored as raw JSON so the HMAC signature can
5
+ -- be re-verified against the original bytes if needed.
4
6
 
5
7
  CREATE TABLE IF NOT EXISTS events (
6
8
  -- Surrogate primary key; external consumers should prefer `event_key`.