You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .claude/skills/npgsqlrest/SKILL.md
+50-6Lines changed: 50 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
---
2
2
name: npgsqlrest
3
-
description: Build and modify REST APIs with NpgsqlRest — exposing PostgreSQL as HTTP endpoints from two sources (database functions/procedures/tables/views, and plain .sql files), driven by SQL comment annotations (no C# needed). Use when working in an NpgsqlRest project: writing or changing endpoint SQL (functions or .sql files), comment annotations (HTTP routing, authorize, cached, proxy, HTTP Custom Types, SSE, MCP, upload), appsettings.json config, or running/troubleshooting the `npgsqlrest` client.
3
+
description: Build and modify REST APIs with NpgsqlRest — exposing PostgreSQL as HTTP endpoints from two sources (database functions/procedures/tables/views, and plain .sql files), driven by SQL comment annotations (no C# needed). Use when working in an NpgsqlRest project: writing or changing endpoint SQL (functions or .sql files), comment annotations (HTTP routing, authorize, cached, proxy, HTTP Custom Types, SSE, MCP, upload), appsettings.json config, testing endpoints with SQL test files (`--test`), running in watch mode (`--watch`), or running/troubleshooting the `npgsqlrest` client.
4
4
---
5
5
6
6
# Working with NpgsqlRest
@@ -67,20 +67,20 @@ Annotations live in **leading line comments** (`-- ...` or `/* ... */`) in a `.s
Files matching `SkipPattern` (default `"*.test.sql"`) are excluded from endpoint discovery — they are test files for the [test runner](#testing-sql-test-files---test), which makes the co-located layout (`app.sql` next to `app.test.sql`) safe.
-**Startup Describe = static type checking.** Each statement is parsed/described against the live DB (no execution); SQL errors fail startup (`ErrorMode: Exit`; set `Skip` to log-and-continue). This catches `column does not exist` etc. before serving.
83
-
-**Parameters are positional** (`$1, $2`). `@param$N name [type] [default ...]` names/retypes/defaults them (positional params have no native DEFAULT). `@define_param name [type]` creates a *virtual* param (for placeholders/claims; not bound to SQL).
83
+
-**Parameters: named (`:name`) or positional (`$1, $2`)** — one style per file (mixing is a startup error). **Prefer named**: the placeholder IS the parameter name (camelCased for the API: `:from_date` → `fromDate`), a repeated name is ONE parameter (also across statements), and claim mappings (`@user_parameters` + `:_user_id`) hook up with zero annotations. `@param` then only handles type/default: `@param from_date default null`, `@param :from_date date` (Describe type hint), `@param from_date type is date` (retype without rename). Positional: `@param $N name [type] [default ...]` names/retypes/defaults. `@define_param name [type]` creates a *virtual* param (placeholders/claims; not bound to SQL). Tokenizer caveats for `:name`: `::casts`, `:=`, and `a[1:3]` never match; a variable slice bound needs a space (`a[1 : n]`).
84
84
-**Verb inference** when no `HTTP` tag: `SELECT`→GET, `INSERT`→PUT, `UPDATE`→POST, `DELETE`→DELETE, `DO`→POST (most destructive wins). Explicit `-- HTTP POST` overrides.
85
85
-**Multi-command files** (statements split on `;`) run in **one batch / round-trip** and return a JSON object keyed per statement. Positional annotations apply to the *next* statement (or inline after `;`):
86
86
-`@result name` — name the result key (default `result1`, `result2`, …)
@@ -120,6 +120,9 @@ Same annotations apply to functions and `.sql` files. Confirm exact syntax/alias
A **composite type** whose comment defines an outbound HTTP request. When a routine (or `.sql` param) is of that type, NpgsqlRest performs the call **before** running the endpoint and fills the composite fields.
@@ -215,10 +218,48 @@ npgsqlrest # appsettings.json in cwd
npgsqlrest --log:minimallevels:npgsqlrest=debug # see every annotation parsed
221
+
npgsqlrest ./config.json --test # run SQL test files, then exit (0 pass / 1 fail / 2 error / 3 config / 4 none)
222
+
npgsqlrest ./config.json --watch # dev server: restart on SQL file / config / database routine changes
223
+
npgsqlrest ./config.json --test --watch # dev test loop: re-run tests on changes
218
224
```
219
225
220
226
Install via the GitHub release binary, `npm install -g npgsqlrest`, or the `vbilopav/npgsqlrest` Docker image.
221
227
228
+
## Testing: SQL test files (`--test`)
229
+
230
+
Tests are plain `.sql` files (glob: `TestRunner.FilePattern`, e.g. `./tests/**/*.test.sql` or co-located next to endpoints). Each file runs on its **own non-pooled connection**, in parallel; endpoints are invoked **in-process** (full pipeline: routing, auth, params, serialization) **on the test's own connection/transaction** — so a test can `begin`, insert fixtures, call the endpoint (it sees the uncommitted rows), assert, and `rollback`.
231
+
232
+
```sql
233
+
begin;
234
+
insert into users (email) values ('x@example.com');
235
+
236
+
/*
237
+
GET /api/get-users
238
+
# @claim user_id=1
239
+
*/
240
+
select (select status from _response) =200, 'authenticated caller gets 200';
-**Assertions**: a SELECT whose first column is `boolean` (2nd column = assertion name), or a `do $$ ... assert ... $$` block. Everything else is arrange/act.
248
+
-**HTTP blocks**: block comment, first line `METHOD /full/path` (incl. `/api` prefix). Directives: `# @claim name=value` (repeatable; any claim = authenticated principal, none = anonymous), `# @response name` (custom capture table). Body after a blank line. Response lands in temp table `_response` (`_response_{n}` for 2+ blocks): `status int, body text, content_type text, headers jsonb, is_success boolean`.
249
+
-**Per-file header annotations** (leading `--` comments, TEST files only): `-- @setup StepName ...`, `-- @teardown StepName ...`, `-- @connection Name` (perfect isolation: run the file on its own database), `-- @tag smoke, slow`. Reuse scripts with psql-style `\i file` / `\ir file` includes (paste semantics).
250
+
-**Setup/Teardown/Steps** (`TestRunner` config): run-once steps in written order — `{ "Sql": ... }` / `{ "SqlFile": ... }` / `{ "Command": ... }`, each with optional `ConnectionName` and `Enabled` (false = ignored wherever referenced; the default config ships disabled examples to flip on). `Setup` runs BEFORE endpoint discovery → it can `create database app_test_{rnd5}` on an admin connection; `TestRunner.ConnectionName` points the whole run at it; teardown drops it (guaranteed — runs even on Ctrl+C/SIGTERM). `{rnd1}`..`{rnd10}` are per-run-stable random tokens (`{rndN_1}`.. for independent instances).
-**Endpoint coverage** reports after full runs (on by default; `CoverageThreshold: 100` fails the build naming untested endpoints). `JUnitOutput` for CI.
253
+
-**Debugging**: `DetailedReport: true` (richer report); `ResponseTempTable.DebugTable: "_responses_debug"` mirrors every response into a permanent table (survives rollback; query it after the run; not for CI); the `NpgsqlRestTest` log channel at `Verbose` shows every statement and HTTP call.
254
+
255
+
## Watch mode (`--watch`)
256
+
257
+
One flag (`--watch`, or config `Watch: { "Enabled": true }`), two flavors chosen by `--test`:
258
+
-**Server watch** (`--watch`): a supervisor restarts the server (~1s) on `.sql` source changes (SkipPattern-filtered), **configuration file** changes, and **database routine changes** — polling runs the routine discovery query hashed server-side (`Watch:DatabasePollingInterval`, default `2s`; detects create/replace/drop/comment on functions, grants, and type/table shape changes; never fires on unrelated objects). Code generation (TS client, HTTP files) re-runs every cycle. A broken SQL file logs its error and drops only its endpoint (`ErrorMode` forced to `Skip` while watching).
259
+
-**Test watch** (`--test --watch`): a changed test re-runs alone; a changed endpoint file or database routine rebuilds endpoints in-process (endpoint delta reported) and re-runs everything; teardown runs once, on exit.
260
+
261
+
For Docker Desktop bind mounts set `DOTNET_USE_POLLING_FILE_WATCHER=1` (file events only; database polling is unaffected).
262
+
222
263
## Project conventions worth copying (from real projects)
223
264
224
265
-**One schema for the API** (`IncludeSchemas: ["myapi"]`); internal helpers in another schema.
@@ -234,5 +275,8 @@ Install via the GitHub release binary, `npm install -g npgsqlrest`, or the `vbil
234
275
-**HTTP-type directives** are safest **before the request line**.
235
276
-**Passthrough proxy doesn't run the function** — declare proxy-response params (transform mode) if you need the body executed.
236
277
-**`HttpClientOptions.Enabled` / `ProxyOptions.Enabled` / `SqlFileSource.Enabled`** must be true for those features. `@cache` on a non-GET HTTP type is ignored with a warning.
237
-
-**SQL files:** annotations are in `--`/`/* */` comments; params are positional `$N` (name via `@param`); a startup Describe error fails boot unless `ErrorMode: Skip`; use `@returns` for statements over not-yet-existing objects (temp tables); `DO` blocks can't take `$N` or return values.
278
+
-**SQL files:** annotations are in `--`/`/* */` comments; params are named `:name` (preferred — auto-named) or positional `$N` (name via `@param`) — **never mixed in one file** (startup error); a startup Describe error fails boot unless `ErrorMode: Skip`; use `@returns` for statements over not-yet-existing objects (temp tables); `DO` blocks can't take params or return values.
279
+
-**A `.sql` file named `*.test.sql` never becomes an endpoint** — `SqlFileSource.SkipPattern` excludes test files by default.
280
+
-**Test HTTP block paths must be the FULL path** including `UrlPathPrefix` (`/api/...`) — a bare `/get-users` is a 404 with a warning.
281
+
-**`ResponseTempTable.DebugTable` is a dev-only debugging aid** — never enable in CI; combine with `Keep: true` when the run drops its test database.
238
282
- After changing an annotation, re-run with `--log:minimallevels:npgsqlrest=debug` (or `--validate`) to confirm it parsed as intended.
Copy file name to clipboardExpand all lines: .claude/skills/npgsqlrest/annotations-reference.md
+3-4Lines changed: 3 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# NpgsqlRest — Full Annotation Reference
2
2
3
-
Every comment annotation, generated from `npgsqlrest --annotations` (NpgsqlRest v3.18.1).
3
+
Every comment annotation, generated from `npgsqlrest --annotations` (NpgsqlRest v3.19.0).
4
4
Annotations apply to both endpoint sources (database routines via `comment on`, and `.sql` files via leading `--` comments). The `@` prefix is optional. Regenerate with `npgsqlrest --annotations`.
5
5
6
6
## `http`
@@ -188,9 +188,9 @@ Enable file upload for this endpoint, optionally specifying upload handlers.
188
188
## `param`
189
189
190
190
-**Aliases:** parameter, param
191
-
-**Syntax:**`param <name> is hash of <other_name> | param <name> is upload metadata | param <original> <new_name> [type] | param <original> is <new_name> [type]`
191
+
-**Syntax:**`param <name> is hash of <other_name> | param <name> is upload metadata | param <original> <new_name> [type] | param <original> is <new_name> [type] | param <name> type is <type> | param <name> default <value>`
192
192
193
-
Configure parameter behavior: hash computation, upload metadata binding, or rename/retype. Rename forms: 'param $1 user_id', 'param $1 user_id integer', 'param $1 is user_id', 'param _old_name better_name'. Works on all endpoint types.
193
+
Configure parameter behavior: hash computation, upload metadata binding, rename/retype, retype WITHOUT rename ('param user_id type is integer'), or default value ('param user_id default null'). Rename forms: 'param $1 user_id', 'param $1 user_id integer', 'param $1 is user_id', 'param _old_name better_name'. In SQL files with named (:name) placeholders the parameter is addressed by the placeholder's own name (a leading ':' is tolerated). Works on all endpoint types.
194
194
195
195
## `sse_path`
196
196
@@ -352,4 +352,3 @@ Rename a result key in multi-command SQL file responses. N is the 1-based comman
352
352
-**Syntax:**`define_param <name> [type]`
353
353
354
354
Define a virtual parameter that exists for HTTP matching and claim mapping but is NOT bound to the PostgreSQL command. Useful for SQL file endpoints where you need parameters for comment placeholders or claim mapping without referencing them in SQL. Default type is text. SQL file source only.
0 commit comments