@commentbox/server-worker 0.1.2 → 0.2.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.
@@ -0,0 +1,15 @@
1
+ -- 0002: session links (CommentBox mode "session"). Only the SHA-256 of a token is stored.
2
+ CREATE TABLE IF NOT EXISTS review_sessions (
3
+ id TEXT PRIMARY KEY,
4
+ name TEXT NOT NULL,
5
+ token_hash TEXT NOT NULL UNIQUE,
6
+ created_at TEXT NOT NULL,
7
+ expires_at INTEGER NOT NULL,
8
+ closed_at INTEGER
9
+ );
10
+
11
+ CREATE TABLE IF NOT EXISTS session_comments (
12
+ comment_id TEXT PRIMARY KEY,
13
+ session_id TEXT NOT NULL
14
+ );
15
+ CREATE INDEX IF NOT EXISTS session_comments_session ON session_comments (session_id);
@@ -0,0 +1,28 @@
1
+ -- CommentBox 0.2: comment rounds (opt-in). Adds the rounds table and two columns on comments.
2
+ -- Servers apply this by themselves on start (the ALTERs only when the columns are missing).
3
+ ALTER TABLE comments ADD COLUMN round_id TEXT;
4
+ ALTER TABLE comments ADD COLUMN screenshot_highlighted INTEGER NOT NULL DEFAULT 0;
5
+ CREATE INDEX IF NOT EXISTS comments_round ON comments (round_id);
6
+ CREATE TABLE IF NOT EXISTS rounds (
7
+ id TEXT PRIMARY KEY,
8
+ project TEXT NOT NULL,
9
+ page_url TEXT NOT NULL,
10
+ session TEXT NOT NULL,
11
+ status TEXT NOT NULL DEFAULT 'open',
12
+ comment_count INTEGER NOT NULL DEFAULT 0,
13
+ created_at TEXT NOT NULL,
14
+ updated_at TEXT NOT NULL,
15
+ last_comment_at INTEGER NOT NULL,
16
+ closed_at TEXT,
17
+ close_reason TEXT
18
+ );
19
+ CREATE INDEX IF NOT EXISTS rounds_open ON rounds (status, project, page_url, session);
20
+ CREATE INDEX IF NOT EXISTS rounds_idle ON rounds (status, last_comment_at);
21
+ CREATE TABLE IF NOT EXISTS screenshot_variants (
22
+ screenshot_id TEXT NOT NULL,
23
+ variant TEXT NOT NULL,
24
+ mime TEXT NOT NULL,
25
+ data TEXT NOT NULL,
26
+ created_at TEXT NOT NULL,
27
+ PRIMARY KEY (screenshot_id, variant)
28
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commentbox/server-worker",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "CommentBox server for Cloudflare Workers + D1.",
5
5
  "keywords": [
6
6
  "commentbox",
@@ -43,8 +43,8 @@
43
43
  "access": "public"
44
44
  },
45
45
  "dependencies": {
46
- "@commentbox/widget": "0.1.2",
47
- "@commentbox/core": "0.1.2"
46
+ "@commentbox/core": "0.2.1",
47
+ "@commentbox/widget": "0.2.1"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@cloudflare/workers-types": "^4.20241011.0",
package/src/worker.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { configFromEnv, createHandler, createSqlStore, processDeliveries } from '@commentbox/core'
1
+ import { applyRetention, configFromEnv, configWarnings, createHandler, createSqlStore, processDeliveries, processRounds, resolveConfig } from '@commentbox/core'
2
2
 
3
3
  import { d1Driver } from './d1.js'
4
4
 
@@ -12,14 +12,26 @@ export type Env = {
12
12
  WEBHOOK_URL?: string
13
13
  WEBHOOK_MAX_ATTEMPTS?: string
14
14
  WEBHOOK_INTEGRATION?: string
15
+ WEBHOOK_ALLOW_INSECURE?: string
15
16
  // Opt-in install count (off by default; DO_NOT_TRACK=1 always disables). See docs/telemetry.md.
16
17
  COMMENTBOX_TELEMETRY?: string
17
18
  COMMENTBOX_TELEMETRY_URL?: string
18
19
  DO_NOT_TRACK?: string
20
+ // Comment rounds and the Donna integration (opt-in). See integrations/donna/README.md.
21
+ COMMENTBOX_ROUNDS?: string
22
+ COMMENTBOX_DONNA?: string
23
+ COMMENTBOX_ROUND_IDLE_MINUTES?: string
24
+ COMMENTBOX_ROUND_MAX_COMMENTS?: string
25
+ // Limits for public demos.
26
+ MAX_COMMENT_LENGTH?: string
27
+ MAX_SCREENSHOT_BYTES?: string
28
+ RETENTION_HOURS?: string
19
29
  // Secrets (wrangler secret put …):
20
30
  ADMIN_TOKEN?: string
21
31
  WEBHOOK_SECRET?: string
22
32
  WEBHOOK_BEARER_TOKEN?: string
33
+ // Extra header on every delivery, `Header-Name: value` (e.g. `X-Api-Key: abc`). A secret: wrangler secret put.
34
+ WEBHOOK_AUTH_HEADER?: string
23
35
  }
24
36
 
25
37
  /** Worker entry, without the widget import so tests can run it against a fake D1. */
@@ -30,6 +42,8 @@ export function createWorker(widgetJs?: string) {
30
42
  let hit = cache.get(env)
31
43
  if (!hit) {
32
44
  const store = createSqlStore(d1Driver(env.DB))
45
+ // Once per isolate, never with secret values.
46
+ for (const w of configWarnings(env)) console.warn(w)
33
47
  hit = { store, handle: createHandler({ store, config: configFromEnv(env), widgetJs }), ready: null }
34
48
  cache.set(env, hit)
35
49
  }
@@ -40,12 +54,19 @@ export function createWorker(widgetJs?: string) {
40
54
  async fetch(req: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
41
55
  return get(env).handle(req, { waitUntil: (p) => ctx.waitUntil(p) })
42
56
  },
43
- /** Cron trigger (every minute): sends webhook retries that are due. */
57
+ /** Cron trigger (every minute): closes idle comment rounds and sends webhook retries that are due. */
44
58
  async scheduled(_event: ScheduledController, env: Env, ctx: ExecutionContext): Promise<void> {
45
59
  const hit = get(env)
46
60
  hit.ready ??= hit.store.init()
47
61
  await hit.ready
48
- ctx.waitUntil(processDeliveries(hit.store, configFromEnv(env)))
62
+ const config = configFromEnv(env)
63
+ // Idle rounds first (they queue round.closed), then every due delivery, retries included.
64
+ ctx.waitUntil(
65
+ processRounds(hit.store, config)
66
+ .then(() => resolveConfig(hit.store, config))
67
+ .then((cfg) => processDeliveries(hit.store, cfg))
68
+ .then(() => applyRetention(hit.store, config)),
69
+ )
49
70
  },
50
71
  } satisfies ExportedHandler<Env>
51
72
  }
package/wrangler.toml CHANGED
@@ -2,11 +2,15 @@
2
2
  # 1. npx wrangler d1 create commentbox -> paste the database_id below
3
3
  # 2. npx wrangler d1 migrations apply commentbox --remote
4
4
  # 3. npx wrangler secret put ADMIN_TOKEN / WEBHOOK_SECRET (never commit secrets)
5
+ # Optional secrets: WEBHOOK_BEARER_TOKEN, and WEBHOOK_AUTH_HEADER for an extra header on every delivery,
6
+ # format "Header-Name: value", e.g. "X-Api-Key: abc" or "Authorization: Bearer abc123" (wins over the bearer token).
5
7
  # 4. npx wrangler deploy
6
8
  # `npx @commentbox/cli init --origin https://your-site.com --provision` runs these steps for you.
7
9
  name = "commentbox"
8
10
  main = "src/index.ts"
9
11
  compatibility_date = "2024-10-01"
12
+ # nodejs_compat: Buffer for the server-side screenshot highlighter (jpeg-js) used by comment rounds.
13
+ compatibility_flags = ["nodejs_compat"]
10
14
 
11
15
  [vars]
12
16
  # Comma-separated origins allowed to post comments (no trailing slash).
@@ -23,6 +27,10 @@ WEBHOOK_INTEGRATION = "webhook"
23
27
  # Opt-in anonymous install count, OFF by default. "1" sends one ping per verified webhook registration
24
28
  # (random install id, version, integration, event kind; nothing else). DO_NOT_TRACK = "1" always wins. See docs/telemetry.md.
25
29
  COMMENTBOX_TELEMETRY = "0"
30
+ # Comment rounds + Donna review cards (opt-in, off by default). DONNA=1 implies ROUNDS=1 and shows "Send round".
31
+ COMMENTBOX_ROUNDS = "0"
32
+ COMMENTBOX_DONNA = "0"
33
+ COMMENTBOX_ROUND_IDLE_MINUTES = "15"
26
34
  # Set when the Worker runs behind a custom domain, e.g. "https://comments.example.com".
27
35
  PUBLIC_URL = ""
28
36