From 2b3f1b07873ab41f2c2a7078fd77ebdf02a61953 Mon Sep 17 00:00:00 2001 From: Trezy Date: Thu, 18 Jun 2026 14:28:56 -0500 Subject: [PATCH] docs: fix discrepancies with new script system Signed-off-by: Trezy --- packages/docs/content/blog/happyview-2.9.md | 8 ++-- .../docs/api-reference/admin/admin-api.md | 6 +++ .../api-reference/admin/script-variables.md | 2 +- .../docs/api-reference/lua/database-api.md | 2 +- .../docs/api-reference/lua/record-api.md | 20 ++++++++-- .../docs/api-reference/lua/utility-globals.md | 2 +- .../docs/content/docs/guides/lua-scripting.md | 8 ++-- .../content/docs/guides/record-scripts.md | 37 ++++++++++++------- 8 files changed, 57 insertions(+), 28 deletions(-) diff --git a/packages/docs/content/blog/happyview-2.9.md b/packages/docs/content/blog/happyview-2.9.md index 92866de..0f26140 100644 --- a/packages/docs/content/blog/happyview-2.9.md +++ b/packages/docs/content/blog/happyview-2.9.md @@ -65,11 +65,9 @@ Filters support comparison operators (`=`, `!=`, `>`, `<`, `>=`, `<=`), `AND`/`O local result = db.query({ collection = "com.example.post", filter = { - op = "AND", - conditions = { - { field = "status", value = "published" }, - { field = "views", op = ">", value = 100 }, - }, + combine = "AND", + { field = "status", value = "published" }, + { field = "views", op = ">", value = 100 }, }, }) ``` diff --git a/packages/docs/content/docs/api-reference/admin/admin-api.md b/packages/docs/content/docs/api-reference/admin/admin-api.md index 409c601..f389005 100644 --- a/packages/docs/content/docs/api-reference/admin/admin-api.md +++ b/packages/docs/content/docs/api-reference/admin/admin-api.md @@ -53,6 +53,7 @@ AUTH="Authorization: Bearer $TOKEN" | [Records](records.md) | List and delete indexed records | | [Instance Settings](settings.md) | Configure app name, logo, policy URLs, and concurrency settings | | [Domains](domains.md) | Manage domains and their OAuth client identities | +| [Scripts](scripts.md) | Create, list, update, and delete Lua scripts | | [Script Variables](script-variables.md) | Encrypted key/value pairs for Lua scripts | | [API Clients](api-clients.md) | Register and manage third-party XRPC clients | | [Plugins](plugins.md) | Install, configure, and manage WASM plugins | @@ -94,6 +95,11 @@ Each admin API endpoint requires a specific permission. See the [Permissions gui | `GET /admin/script-variables` | `script-variables:read` | | `POST /admin/script-variables` | `script-variables:create` | | `DELETE /admin/script-variables/{key}` | `script-variables:delete` | +| `GET /admin/scripts` | `scripts:read` | +| `POST /admin/scripts` | `scripts:manage` | +| `GET /admin/scripts/{id}` | `scripts:read` | +| `PATCH /admin/scripts/{id}` | `scripts:manage` | +| `DELETE /admin/scripts/{id}` | `scripts:manage` | | `POST /admin/labelers` | `labelers:create` | | `GET /admin/labelers` | `labelers:read` | | `PATCH /admin/labelers/{did}` | `labelers:create` | diff --git a/packages/docs/content/docs/api-reference/admin/script-variables.md b/packages/docs/content/docs/api-reference/admin/script-variables.md index 5d7f723..720500c 100644 --- a/packages/docs/content/docs/api-reference/admin/script-variables.md +++ b/packages/docs/content/docs/api-reference/admin/script-variables.md @@ -2,7 +2,7 @@ title: "Script Variables" --- -Script variables are encrypted key/value pairs available to Lua scripts via the `vars` global. Use them for secrets like API tokens. +Script variables are encrypted key/value pairs available to Lua scripts via the `env` global. Use them for secrets like API tokens. ```ts tab="TypeScript" tab-group="language" const TOKEN = "hv_..."; // your API key diff --git a/packages/docs/content/docs/api-reference/lua/database-api.md b/packages/docs/content/docs/api-reference/lua/database-api.md index a8ebbcf..baf1b77 100644 --- a/packages/docs/content/docs/api-reference/lua/database-api.md +++ b/packages/docs/content/docs/api-reference/lua/database-api.md @@ -171,7 +171,7 @@ Parameters are passed as an array and bound to `$1`, `$2`, etc. Supported parame ### SQL dialect -Write SQL in **SQLite syntax** — HappyView translates it to Postgres at runtime if you're using Postgres. See [Database Setup](../../guides/database/database-setup.md) for details on what gets translated. If you need database-specific SQL that can't be translated, check `db.backend()` at runtime. +Unlike the structured API methods (`db.query`, `db.get`, etc.), `db.raw` does **not** translate SQL between backends. Write native SQL for the database you're running against — `$1`/`$2` placeholders for Postgres, `?` for SQLite. Use `db.backend()` to branch when you need to support both. ### Column type mapping diff --git a/packages/docs/content/docs/api-reference/lua/record-api.md b/packages/docs/content/docs/api-reference/lua/record-api.md index d15fec9..419b0bc 100644 --- a/packages/docs/content/docs/api-reference/lua/record-api.md +++ b/packages/docs/content/docs/api-reference/lua/record-api.md @@ -2,7 +2,7 @@ title: "Record API" --- -The `Record` API is only available in **procedure** scripts. It handles creating, updating, loading, and deleting atproto records. Writes are proxied to the caller's PDS and indexed locally. +The `Record` API is available in **procedure**, **query**, and **record/label** scripts. In procedure scripts the full API is available — writes are proxied to the caller's PDS and indexed locally. In query and record/label scripts it runs in **no-auth mode**: `Record.load`, `r:save_local()`, `r:delete_local()`, and `Record.delete_local()` work, but PDS-touching methods (`r:save()`, `r:delete()`) raise an error. ## Constructor @@ -25,6 +25,10 @@ local r = Record.load("at://did:plc:abc/xyz.statusphere.status/abc123") -- Load multiple records in parallel local records = Record.load_all({ uri1, uri2 }) -- Returns nil entries for URIs not found + +-- Delete a record from the local database only (no PDS call) +local ok = Record.delete_local("at://did:plc:abc/xyz.statusphere.status/abc123") +-- Returns true if deleted, false if not found ``` ## Instance methods @@ -36,6 +40,15 @@ r:save() -- Delete from PDS and local database r:delete() +-- Save directly to the local database (no PDS call) +r:save_local() + +-- Delete from the local database only (no PDS call) +r:delete_local() + +-- Set the repo DID (for no-auth contexts like record/label scripts) +r:set_repo("did:plc:abc") + -- Set the record key type (tid, any, nsid, or literal:*) r:set_key_type("tid") @@ -65,8 +78,9 @@ These fields are set automatically and are read-only (writes raise an error): | `_cid` | string? | Content hash — set after `save()`, cleared after `delete()` | | `_key_type` | string? | Record key type from the lexicon definition | | `_rkey` | string? | Record key — set via `set_rkey()` or `generate_rkey()` | -| `_collection` | string | Collection NSID (always set) | -| `_schema` | table? | Schema definition from the lexicon (used for validation) | +| `_collection` | string | Collection NSID (always set) | +| `_schema` | table? | Schema definition from the lexicon (used for validation) | +| `_repo_override` | string? | DID set by `set_repo()`, used in no-auth contexts to target a repo | ## Schema validation diff --git a/packages/docs/content/docs/api-reference/lua/utility-globals.md b/packages/docs/content/docs/api-reference/lua/utility-globals.md index 42e796b..f59ea33 100644 --- a/packages/docs/content/docs/api-reference/lua/utility-globals.md +++ b/packages/docs/content/docs/api-reference/lua/utility-globals.md @@ -20,7 +20,7 @@ log("processing record: " .. uri) log("count: " .. tostring(n)) ``` -Writes a message to the server logs at debug level. Useful for debugging scripts during development. Log output appears in HappyView's stdout — check your platform's log viewer (Railway logs, `docker logs`, terminal output) to see it. +Writes a message to the server logs at debug level and records a `script.log` event in the [event logs](../../api-reference/admin/events.md). Useful for debugging scripts during development. Log output appears in HappyView's stdout and is also accessible via `GET /admin/events`. ## TID diff --git a/packages/docs/content/docs/guides/lua-scripting.md b/packages/docs/content/docs/guides/lua-scripting.md index f9d5c53..eda6062 100644 --- a/packages/docs/content/docs/guides/lua-scripting.md +++ b/packages/docs/content/docs/guides/lua-scripting.md @@ -2,7 +2,7 @@ title: "Lua Scripting" --- -Without Lua scripts, HappyView's query endpoints return raw records and procedure endpoints proxy simple creates and updates. Lua scripts let you go much further: +Without Lua scripts, HappyView's query endpoints return raw records and procedure endpoints proxy simple creates and updates. To attach a script to an XRPC endpoint, create a script with trigger `xrpc.query:` or `xrpc.procedure:` — see [trigger grammar](label-scripts#trigger-grammar). Lua scripts let you go much further: - Add filtering logic - Transform responses @@ -90,7 +90,7 @@ You don't need `toarray()` on results from `db.query`, `db.search`, `db.backlink ## Record API -The `Record` API is only available in **procedure** scripts. It handles creating, updating, loading, and deleting atproto records. Writes are proxied to the caller's PDS and indexed locally. +The `Record` API is available in **procedure**, **query**, and **record/label** scripts. In procedure scripts the full API is available — writes are proxied to the caller's PDS and indexed locally. In query and record/label scripts it runs in **no-auth mode**: `Record.load`, `r:save_local()`, `r:delete_local()`, and `Record.delete_local()` work, but PDS-touching methods (`r:save()`, `r:delete()`) raise an error. See the full [Record API reference](../api-reference/lua/record-api.md) for constructor, static methods, instance methods, fields, schema validation, and save behavior. @@ -161,7 +161,7 @@ See the full [JSON API reference](../api-reference/lua/json-api.md) for `json.en ### Logging -Use `log()` to trace script execution. Output appears in the server logs at **debug** level with the field `lua_log`: +Use `log()` to trace script execution. Output appears in the server logs at **debug** level with the field `lua_log`, and is also recorded as a `script.log` event in the [event logs](../api-reference/admin/events.md) (accessible via `GET /admin/events`): ```lua function handle() @@ -172,7 +172,7 @@ function handle() end ``` -To see log output, make sure your `RUST_LOG` environment variable includes debug level for HappyView (the default `happyview=debug` works). See [Configuration](../getting-started/configuration.md). +To see log output in stdout, make sure your `RUST_LOG` environment variable includes debug level for HappyView (the default `happyview=debug` works). See [Configuration](../getting-started/configuration.md). ### Error messages diff --git a/packages/docs/content/docs/guides/record-scripts.md b/packages/docs/content/docs/guides/record-scripts.md index b4af710..20cb256 100644 --- a/packages/docs/content/docs/guides/record-scripts.md +++ b/packages/docs/content/docs/guides/record-scripts.md @@ -23,6 +23,15 @@ Every script is identified by a **trigger string** -- the script's `id` in the ` **Cascade rule:** When a record event occurs, the dispatcher tries the action-specific trigger first (e.g. `record.create:`), then falls back to `record.index:` if no action-specific script exists. This means you can use `record.index` as a catch-all and override individual actions when needed. +### XRPC triggers + +| Trigger | Fires when | +| -------------------------- | --------------------------------------------- | +| `xrpc.query:` | An XRPC query endpoint is called | +| `xrpc.procedure:` | An XRPC procedure endpoint is called | + +XRPC scripts handle the request and return the response. Without a script, HappyView uses [default query/procedure behavior](../api-reference/xrpc-api.md). See [Lua Scripting](./lua-scripting.md) for the full query/procedure scripting reference. + ### Label event triggers | Trigger | Fires when | @@ -30,7 +39,7 @@ Every script is identified by a **trigger string** -- the script's `id` in the ` | `labeler.apply:` | A label arrives whose subject is `at:////` | | `labeler.apply:_actor` | A label arrives whose subject is a bare DID (actor-level label) | -There is no cascade for label triggers -- each trigger string must match exactly. +There is no cascade for label or XRPC triggers -- each trigger string must match exactly. ## Creating scripts @@ -111,12 +120,13 @@ These globals are set before `handle()` is called for label events: | `exp` | string? | Expiration timestamp (nil if the label does not expire) | | `event` | table | The full label event as a table (same fields) | -Record and label scripts do **not** have access to `caller_did`, `input`, `params`, `method`, or the `Record` API. They run from the event stream, not from a user request. +Record and label scripts do **not** have access to `caller_did`, `input`, `params`, or `method`. They run from the event stream, not from a user request. ## Available APIs Record and label scripts have access to: +- **[Record API](../api-reference/lua/record-api.md)** (no-auth mode) -- `Record.load`, `r:save_local()`, `r:delete_local()`, `Record.delete_local()`. PDS-touching methods (`r:save()`, `r:delete()`) raise an error. - **[Database API](../api-reference/lua/database-api.md)** -- `db.query`, `db.get`, `db.search`, `db.backlinks`, `db.count`, `db.raw` - **[HTTP API](../api-reference/lua/http-api.md)** -- `http.get`, `http.post`, `http.put`, `http.patch`, `http.delete`, `http.head` - **[XRPC Lua API](../api-reference/lua/xrpc-lua-api.md)** -- `xrpc.query`, `xrpc.procedure` @@ -143,17 +153,18 @@ Because scripts run synchronously before indexing, they block the Jetstream cons The `dead_letter_scripts` table stores events that failed all retry attempts: -| Column | Type | Description | -| ------------ | ----------- | ----------------------------------------------------- | -| `id` | BIGSERIAL | Primary key | -| `script_ref` | text | The trigger id of the script that failed | -| `host_kind` | text | `'record'` or `'label'` | -| `host_id` | text | Identifies the specific event source | -| `payload` | jsonb | The full event payload | -| `error` | text | The error message from the last attempt | -| `attempts` | int | Total number of attempts made | -| `created_at` | timestamptz | When the failure was recorded | -| `resolved_at`| timestamptz | When the failure was resolved (null until resolved) | +| Column | Type | Description | +| ------------ | --------- | ----------------------------------------------------- | +| `id` | BIGSERIAL | Primary key | +| `script_ref` | text | The trigger id of the script that failed | +| `host_kind` | text | `'record'` or `'label'` | +| `host_id` | text | Identifies the specific event source | +| `collection` | text | The collection NSID of the failed event | +| `payload` | jsonb | The full event payload | +| `error` | text | The error message from the last attempt | +| `attempts` | int | Total number of attempts made | +| `created_at` | text | When the failure was recorded (ISO 8601) | +| `resolved_at`| text | When the failure was resolved (null until resolved) | ## Examples -- 2.51.2