@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.
- package/migrations/0002_sessions.sql +15 -0
- package/migrations/0003_rounds.sql +28 -0
- package/package.json +3 -3
- package/src/worker.ts +24 -3
- package/wrangler.toml +8 -0
|
@@ -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
|
|
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/
|
|
47
|
-
"@commentbox/
|
|
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
|
-
|
|
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
|
|