prest-js-sdk 0.2.0

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,11 @@
1
+ {
2
+ "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
3
+ "changelog": "@changesets/cli/changelog",
4
+ "commit": false,
5
+ "fixed": [],
6
+ "linked": [],
7
+ "access": "public",
8
+ "baseBranch": "master",
9
+ "updateInternalDependencies": "patch",
10
+ "ignore": []
11
+ }
@@ -0,0 +1,42 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+
8
+ concurrency: ${{ github.workflow }}-${{ github.ref }}
9
+
10
+ jobs:
11
+ release:
12
+ name: Create Release Pull Request or Publish
13
+ runs-on: ubuntu-latest
14
+ permissions:
15
+ contents: write
16
+ pull-requests: write
17
+ id-token: write
18
+ steps:
19
+ - name: Checkout
20
+ uses: actions/checkout@v4
21
+ with:
22
+ fetch-depth: 0
23
+
24
+ - name: Setup Node.js
25
+ uses: actions/setup-node@v4
26
+ with:
27
+ node-version: 20
28
+
29
+ - name: Install dependencies
30
+ run: npm ci
31
+
32
+ - name: Create Release Pull Request or Publish to npm
33
+ uses: changesets/action@v1
34
+ with:
35
+ publish: npm run release
36
+ version: npm run version-packages
37
+ commit: "chore(release): version packages"
38
+ title: "chore(release): version packages"
39
+ setupGitUser: true
40
+ env:
41
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
package/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # prest-js-sdk
2
+
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 6012e3a: Initial release. PrestClient with catalog, CRUD, stored-query, health, and login methods;
8
+ typed Filter / SelectOpts DSL that serializes to pREST's `?field=op.value` URL syntax;
9
+ fromKratosSession() factory for forward-compat with the planned Kratos auth integration.
package/CLAUDE.md ADDED
@@ -0,0 +1,203 @@
1
+ # prest-js-sdk
2
+
3
+ TypeScript SDK for pREST (PostgreSQL REST API). Wraps pREST's HTTP routes with route-shaped methods and a typed filter DSL.
4
+
5
+ ## Repository
6
+
7
+ - GitHub: https://github.com/yudaprama/prest-js-sdk (publish target)
8
+ - npm: https://www.npmjs.com/package/prest-js-sdk (publish target)
9
+ - Base branch: `master`
10
+ - Node: 20
11
+
12
+ ## Sibling project
13
+
14
+ This SDK mirrors `alist-kratos-sdk/` (the AList SDK in the parent `ai-orchestration` workspace). Same shape:
15
+
16
+ - Single-file SDK at `src/index.ts` (~500 lines)
17
+ - tsc direct build, ESM-only
18
+ - Changesets + GitHub Actions release flow
19
+ - `fromKratosSession()` static factory (forward-compat — pREST submodule does not yet wire Kratos)
20
+
21
+ When adding capabilities here, check whether `alist-kratos-sdk` has an analogous pattern to follow.
22
+
23
+ ## Project layout
24
+
25
+ ```
26
+ src/ TypeScript source (entry: src/index.ts)
27
+ examples/ Standalone scripts (filter serializer test, smoke test)
28
+ dist/ Build output (gitignored)
29
+ .changeset/ Changeset markdown files (one per unreleased change)
30
+ .github/workflows/ GitHub Actions release.yml
31
+ .npmrc Auth for npm publish (uses NPM_TOKEN)
32
+ package.json Version, scripts, deps
33
+ ```
34
+
35
+ ## Build
36
+
37
+ ```bash
38
+ npm ci # install (CI uses lockfile)
39
+ npm run build # tsc -> dist/
40
+ node examples/filters.ts # sanity check the filter serializer
41
+ ```
42
+
43
+ ## pREST HTTP surface (the contract this SDK wraps)
44
+
45
+ The `prest/` submodule in the parent workspace is vanilla upstream pREST v2.0.0.
46
+ Routes (from `prest/router/router.go:17`):
47
+
48
+ | Method | Route | SDK method |
49
+ |---|---|---|
50
+ | GET | `/databases` | `databases()` |
51
+ | GET | `/schemas` | `schemas()` |
52
+ | GET | `/tables` | `tables()` |
53
+ | GET | `/{database}/{schema}` | `tablesIn(db, schema)` |
54
+ | GET | `/show/{database}/{schema}/{table}` | `showTable(db, schema, table)` |
55
+ | GET | `/{database}/{schema}/{table}` | `select(...)` |
56
+ | POST | `/{database}/{schema}/{table}` | `insert(...)` |
57
+ | POST | `/batch/{database}/{schema}/{table}` | `insertBatch(...)` |
58
+ | PUT, PATCH | `/{database}/{schema}/{table}` | `update(...)` |
59
+ | DELETE | `/{database}/{schema}/{table}` | `delete(...)` |
60
+ | ANY | `/_QUERIES/{location}/{script}` | `query(location, script, params)` |
61
+ | GET | `/_health` | `health()` |
62
+ | POST | `/auth` | `login(username, password)` |
63
+
64
+ **Filter URL syntax** (verified against `prest/adapters/postgres/postgres.go`):
65
+ - `?field=op.value` — operator-prefixed (op defaults to `eq` when bare)
66
+ - Multi-value ops: `?field=in.(1,2,3)` — parens, comma-separated
67
+ - Value-less ops: `?field=null`, `?field=true` — no trailing dot
68
+ - Reserved params (start with `_`): `_select`, `_order`, `_groupby`, `_join`, `_where`, `_count`, `_count_first`, `_limit`, `_offset`, `_page`, `_size`, `_distinct`, `_returning`, `_or`
69
+
70
+ Operators (`prest/adapters/postgres/postgres.go:1474` GetQueryOperator):
71
+ `eq, ne, gt, gte, lt, lte, in, nin, any, some, all, null, notnull, true, nottrue, false, notfalse, like, ilike, nlike, nilike` (+ ltree ops, not exposed in v0.1).
72
+
73
+ ## Release workflow
74
+
75
+ Publishing is fully automated via **changesets** + GitHub Actions. **Do not run `npm version` or push tags manually.**
76
+
77
+ ### How a release happens
78
+
79
+ 1. A PR or direct push to `master` contains one or more `.changeset/<name>.md` files.
80
+ 2. The `Release` workflow runs on push to `master`:
81
+ - **If a "Version Packages" PR is already open**, it updates that PR with the new changesets.
82
+ - **If no PR is open**, it creates one titled `chore(release): version packages`. This PR:
83
+ - bumps `version` in `package.json` (consuming the changesets)
84
+ - regenerates `CHANGELOG.md`
85
+ - deletes the consumed changeset files
86
+ 3. When a maintainer **merges the "Version Packages" PR**:
87
+ - The same workflow runs on the merge commit
88
+ - There are no more pending changesets, so it skips versioning and runs `npm run release` (`tsc` + `changeset publish`)
89
+ - npm publish uses the `NPM_TOKEN` secret (granular token with **Bypass 2FA** enabled)
90
+
91
+ ### Authoring a changeset
92
+
93
+ When a PR changes user-facing behavior, add a file under `.changeset/`:
94
+
95
+ ```bash
96
+ npm run changeset
97
+ ```
98
+
99
+ …or create the file manually:
100
+
101
+ ```markdown
102
+ ---
103
+ "prest-js-sdk": minor
104
+ ---
105
+
106
+ Describe what changed and why. This text goes into CHANGELOG.md and the GitHub release notes.
107
+ ```
108
+
109
+ Bump levels:
110
+ - `patch` — bug fix, internal refactor
111
+ - `minor` — new feature, backward-compatible
112
+ - `major` — breaking change
113
+
114
+ Skip a changeset for docs-only or CI-only changes.
115
+
116
+ ### One-time setup (do this once when first publishing)
117
+
118
+ - `NPM_TOKEN` secret in repo Settings → Secrets → Actions (granular token, Bypass 2FA, Publish scope)
119
+ - Repo Settings → Actions → General → Workflow permissions: **Read and write permissions**, **Allow GitHub Actions to create and approve pull requests** enabled
120
+ - `NPM_TOKEN` env var is passed to the workflow and consumed by the repo's `.npmrc`
121
+
122
+ ### Triggering the first publish
123
+
124
+ 1. Ensure at least one `.changeset/*.md` exists on `master` (the `initial.md` is already there).
125
+ 2. Push to `master` → workflow opens the "Version Packages" PR.
126
+ 3. Review the PR (version bump, CHANGELOG entries look right).
127
+ 4. Merge it → workflow publishes to npm.
128
+
129
+ ### Manual override (emergency only)
130
+
131
+ ```bash
132
+ npm login
133
+ npm run version-packages
134
+ npm run release
135
+ git push --follow-tags
136
+ ```
137
+
138
+ **Do not do this routinely** — it bypasses the CHANGELOG PR review.
139
+
140
+ ## Secrets & tokens
141
+
142
+ | Secret | Used by | Notes |
143
+ |---|---|---|
144
+ | `NPM_TOKEN` | Release workflow | Granular token, Bypass 2FA, Publish scope. Rotate if leaked. |
145
+ | `GITHUB_TOKEN` | Release workflow | Auto-provided by GitHub Actions; needs write perms + PR creation enabled. |
146
+
147
+ ## Common tasks
148
+
149
+ | Task | Command |
150
+ |---|---|
151
+ | Add a changeset interactively | `npm run changeset` |
152
+ | Preview the next version locally | `npm run version-packages -- --snapshot` |
153
+ | Build types only | `npm run build` |
154
+ | Watch TS | `npm run dev` |
155
+ | Run filter test | `node examples/filters.ts` |
156
+ | Smoke test against running prest | `node examples/smoke.ts` (requires `planoctl up`) |
157
+ | Inspect a workflow run | `gh run list --repo yudaprama/prest-js-sdk --workflow=release.yml` |
158
+ | View logs | `gh run view <id> --repo yudaprama/prest-js-sdk --log` |
159
+ | Re-run a failed workflow | `gh run rerun <id> --repo yudaprama/prest-js-sdk` |
160
+
161
+ ## Troubleshooting
162
+
163
+ - **`E404 Not Found` on publish** — `NPM_TOKEN` not reaching the publish step. Confirm `.npmrc` uses `//registry.npmjs.org/:_authToken=${NPM_TOKEN}` and the env var is set on the `changesets/action` step.
164
+ - **`E403 ... 2FA required`** — The token was generated without "Bypass 2FA". Regenerate a granular token with that option enabled.
165
+ - **`GitHub Actions is not permitted to create or approve pull requests`** — Repo Settings → Actions → General → Workflow permissions: enable "Allow GitHub Actions to create and approve pull requests".
166
+ - **No "Version Packages" PR appears** — No `.changeset/*.md` files exist on `master`. Add one and push.
167
+ - **`npm ci` fails: lockfile out of sync** — Run `npm install` locally, commit `package-lock.json`, push.
168
+
169
+ ## SDK API quick reference
170
+
171
+ ```ts
172
+ import { PrestClient } from "prest-js-sdk";
173
+
174
+ const client = new PrestClient("http://localhost:3000");
175
+
176
+ // Catalog
177
+ await client.databases();
178
+ await client.schemas();
179
+ await client.tables();
180
+ await client.tablesIn("yarsew", "public");
181
+ await client.showTable("yarsew", "public", "users");
182
+
183
+ // CRUD with typed filter
184
+ await client.select("yarsew", "public", "billing_balances", {
185
+ where: { actor_id: 42, status: { eq: "active" } },
186
+ select: ["id", "amount"],
187
+ order: ["amount:desc"],
188
+ page: 1, size: 20,
189
+ });
190
+ await client.insert("yarsew", "public", "billing_balances", { actor_id: 42, amount: 100 });
191
+ await client.insertBatch("yarsew", "public", "billing_balances", [/* ... */]);
192
+ await client.update("yarsew", "public", "billing_balances", { actor_id: 42 }, { status: "frozen" });
193
+ await client.delete("yarsew", "public", "billing_balances", { actor_id: 42 });
194
+
195
+ // Stored SQL
196
+ await client.query("reports", "top_balances", { min: 1000 });
197
+
198
+ // Health + auth
199
+ await client.health(); // → boolean
200
+ await client.login("alice", "hunter2"); // → JWT, also stores internally
201
+ ```
202
+
203
+ See `README.md` for full type definitions and the auth flow.
package/README.md ADDED
@@ -0,0 +1,219 @@
1
+ # prest-js-sdk
2
+
3
+ TypeScript SDK for [pREST](https://github.com/prest/prest) — PostgreSQL REST API. Route-shaped methods for catalog/CRUD/stored-queries, plus a typed filter DSL that serializes to pREST's `?field=op.value` URL syntax.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install prest-js-sdk
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```ts
14
+ import { PrestClient } from "prest-js-sdk";
15
+
16
+ // Option 1: explicit URL (no auth — open prest)
17
+ const client = new PrestClient("http://localhost:3000");
18
+
19
+ // Option 2: URL + auth token (JWT from POST /auth, or Kratos session)
20
+ const client = new PrestClient({
21
+ prestUrl: "http://localhost:3000",
22
+ authToken: "eyJhbGci...",
23
+ });
24
+
25
+ // Option 3: auto-detect Kratos session (forward-compat — see Auth section)
26
+ const client = await PrestClient.fromKratosSession(
27
+ "http://localhost:4433", // Kratos public URL
28
+ "http://localhost:3000", // pREST URL (optional)
29
+ );
30
+ if (!client) throw new Error("No valid Kratos session");
31
+ ```
32
+
33
+ ## Catalog
34
+
35
+ ```ts
36
+ await client.databases(); // GET /databases
37
+ await client.schemas(); // GET /schemas
38
+ await client.tables(); // GET /tables
39
+ await client.tablesIn("yarsew", "public"); // GET /yarsew/public
40
+ await client.showTable("yarsew", "public", "users"); // GET /show/yarsew/public/users
41
+ ```
42
+
43
+ ## Select with typed filter
44
+
45
+ ```ts
46
+ interface Balance { id: number; actor_id: number; amount: number; status: string }
47
+
48
+ const rows = await client.select<Balance>("yarsew", "public", "billing_balances", {
49
+ where: {
50
+ actor_id: 42, // shorthand → eq.42
51
+ status: { eq: "active" },
52
+ amount: { gte: 100 },
53
+ name: { like: "foo%" },
54
+ },
55
+ select: ["id", "amount", "status"],
56
+ order: ["amount:desc"],
57
+ page: 1,
58
+ size: 20,
59
+ });
60
+ ```
61
+
62
+ ## Insert / Update / Delete
63
+
64
+ ```ts
65
+ // Insert single row
66
+ const [created] = await client.insert<Balance>(
67
+ "yarsew", "public", "billing_balances",
68
+ { actor_id: 42, amount: 99.95, status: "active" },
69
+ );
70
+
71
+ // Insert batch
72
+ await client.insertBatch("yarsew", "public", "billing_balances", [
73
+ { actor_id: 1, amount: 10 },
74
+ { actor_id: 2, amount: 20 },
75
+ ]);
76
+
77
+ // Update — filter rows, then mutate
78
+ await client.update<Balance>(
79
+ "yarsew", "public", "billing_balances",
80
+ { actor_id: 42 }, // WHERE
81
+ { status: "frozen" }, // SET
82
+ );
83
+
84
+ // Delete — filter rows
85
+ await client.delete("yarsew", "public", "billing_balances", { actor_id: 42 });
86
+ ```
87
+
88
+ ## Stored SQL queries
89
+
90
+ SQL files live under `<prest queries dir>/<location>/<script>.sql` and are invoked by name:
91
+
92
+ ```ts
93
+ // Calls /_QUERIES/reports/top_balances?min=1000
94
+ const top = await client.query<Balance>("reports", "top_balances", { min: 1000 });
95
+ ```
96
+
97
+ Inside the `.sql` file, params are available via pREST's template helpers:
98
+
99
+ ```sql
100
+ SELECT * FROM billing_balances
101
+ WHERE amount >= {{ sqlVal "min" }}
102
+ ORDER BY amount DESC
103
+ LIMIT 100
104
+ ```
105
+
106
+ ## Filter DSL reference
107
+
108
+ | JS shape | URL emitted | SQL |
109
+ |---|---|---|
110
+ | `{ field: 42 }` | `?field=eq.42` | `field = 42` |
111
+ | `{ field: "x" }` | `?field=eq.x` | `field = 'x'` |
112
+ | `{ field: { ne: 42 } }` | `?field=ne.42` | `field != 42` |
113
+ | `{ field: { gt: 100 } }` | `?field=gt.100` | `field > 100` |
114
+ | `{ field: { gte: 100 } }` | `?field=gte.100` | `field >= 100` |
115
+ | `{ field: { lt: 100 } }` | `?field=lt.100` | `field < 100` |
116
+ | `{ field: { lte: 100 } }` | `?field=lte.100` | `field <= 100` |
117
+ | `{ field: { in: [1,2,3] } }` | `?field=in.(1,2,3)` | `field IN (1,2,3)` |
118
+ | `{ field: { nin: [1,2] } }` | `?field=nin.(1,2)` | `field NOT IN (1,2)` |
119
+ | `{ field: { like: "foo%" } }` | `?field=like.foo%25` | `field LIKE 'foo%'` |
120
+ | `{ field: { ilike: "foo%" } }` | `?field=ilike.foo%25` | `field ILIKE 'foo%'` |
121
+ | `{ field: null }` | `?field=null` | `field IS NULL` |
122
+ | `{ field: { notnull: true } }` | `?field=notnull` | `field IS NOT NULL` |
123
+ | `{ field: true }` | `?field=true` | `field IS TRUE` |
124
+
125
+ Multiple fields are AND-ed. For OR across fields, use `SelectOpts.or`:
126
+
127
+ ```ts
128
+ client.select(..., {
129
+ or: [
130
+ { status: "active" },
131
+ { amount: { gt: 1000 } },
132
+ ],
133
+ });
134
+ // → ?_or=status=eq.active,amount=gt.1000
135
+ ```
136
+
137
+ ### `SelectOpts`
138
+
139
+ | Field | Maps to | Notes |
140
+ |---|---|---|
141
+ | `where` | `?field=op.value` | AND-ed; see table above |
142
+ | `select` | `_select=col1,col2` | column projection |
143
+ | `order` | `_order=col1,col2:desc` | suffix `:asc` / `:desc` per column |
144
+ | `page` + `size` | `_page`, `_size` | 1-indexed pagination |
145
+ | `limit` + `offset` | `_limit`, `_offset` | alternative pagination |
146
+ | `distinct` | `_distinct=true` | |
147
+ | `count` | `_count=true` | return row counts |
148
+ | `countFirst` | `_count_first=true` | single count object |
149
+ | `groupBy` | `_groupby=col1,col2` | |
150
+ | `or` | `_or=field=op.value,...` | OR-clause inside parens |
151
+ | `returning` | `_returning=col1,col2` | for update/delete |
152
+
153
+ ## Auth
154
+
155
+ pREST supports two auth modes:
156
+
157
+ ### 1. Database-backed (`[auth]` block in `prest.toml`)
158
+
159
+ ```ts
160
+ const client = new PrestClient("http://localhost:3000");
161
+ const token = await client.login("alice", "hunter2");
162
+ // subsequent requests now carry Authorization: Bearer <token>
163
+ ```
164
+
165
+ ### 2. Kratos session (forward-compat)
166
+
167
+ The pREST submodule is vanilla upstream — it does not yet wire Ory Kratos. The
168
+ parent `ai-orchestration` project documents a planned `[auth.kratos]` integration;
169
+ once that lands, `PrestClient.fromKratosSession()` will work exactly like the
170
+ sibling `alist-kratos-sdk`:
171
+
172
+ ```ts
173
+ const client = await PrestClient.fromKratosSession(
174
+ "http://localhost:4433",
175
+ "http://localhost:3000",
176
+ );
177
+ ```
178
+
179
+ In Node (no cookie jar), pass the session token explicitly:
180
+
181
+ ```ts
182
+ const client = await PrestClient.fromKratosSession(
183
+ "http://localhost:4433",
184
+ "http://localhost:3000",
185
+ process.env.KRATOS_SESSION_TOKEN,
186
+ );
187
+ ```
188
+
189
+ ## Low-level escape hatch
190
+
191
+ For endpoints not wrapped by the typed methods:
192
+
193
+ ```ts
194
+ const res = await client.request<{ some: shape }>("GET", "/custom/path", {
195
+ params: new URLSearchParams({ foo: "bar" }),
196
+ headers: { "X-Custom": "value" },
197
+ });
198
+ ```
199
+
200
+ Throws `PrestApiError` (with `.status` and `.body`) on non-2xx.
201
+
202
+ ## Browser vs Node
203
+
204
+ The SDK works in both browsers and Node 18+:
205
+
206
+ - `fromKratosSession()` reads the `ory_kratos_session` cookie in browsers; in Node pass the token explicitly.
207
+ - `fetch` is available natively in both runtimes.
208
+ - No DOM dependencies (only used for cookie reading).
209
+
210
+ ## Development
211
+
212
+ ```bash
213
+ npm install
214
+ npm run build # tsc → dist/
215
+ npm run dev # tsc --watch
216
+ node examples/filters.ts # verify filter serializer
217
+ ```
218
+
219
+ Releases are automated via changesets + GitHub Actions — see `CLAUDE.md` for the full flow.
@@ -0,0 +1,207 @@
1
+ /**
2
+ * prest-js-sdk
3
+ *
4
+ * TypeScript SDK for pREST (PostgreSQL REST API). Provides route-shaped methods
5
+ * for catalog/CRUD/stored-queries plus a typed filter DSL that serializes to
6
+ * pREST's `?field=op.value` URL syntax.
7
+ *
8
+ * Usage:
9
+ * import { PrestClient } from "prest-js-sdk";
10
+ *
11
+ * const client = new PrestClient("http://localhost:3000");
12
+ *
13
+ * // Catalog
14
+ * const dbs = await client.databases();
15
+ *
16
+ * // Query with typed filter
17
+ * const rows = await client.select<Balance>("yarsew", "public", "billing_balances", {
18
+ * where: { actor_id: { eq: 42 }, status: "active" },
19
+ * select: ["id", "balance"],
20
+ * order: ["balance:desc"],
21
+ * limit: 10,
22
+ * });
23
+ *
24
+ * // Insert
25
+ * const [row] = await client.insert<Balance>("yarsew", "public", "billing_balances", {
26
+ * actor_id: 42, balance: 100.50, status: "active",
27
+ * });
28
+ *
29
+ * // Update (filter + new values)
30
+ * const updated = await client.update<Balance>(
31
+ * "yarsew", "public", "billing_balances",
32
+ * { actor_id: 42 },
33
+ * { status: "frozen" },
34
+ * );
35
+ *
36
+ * // Delete
37
+ * await client.delete("yarsew", "public", "billing_balances", { actor_id: 42 });
38
+ *
39
+ * // Stored SQL (prest/etc/queries/reports/top_balances.sql)
40
+ * const top = await client.query<Balance>("reports", "top_balances", { min: 1000 });
41
+ *
42
+ * // Forward-compat Kratos auth (works once [auth.kratos] is wired into prest)
43
+ * const authed = await PrestClient.fromKratosSession(
44
+ * "http://localhost:4433",
45
+ * "http://localhost:3000",
46
+ * );
47
+ */
48
+ export interface PrestConfig {
49
+ /** pREST base URL, e.g. http://localhost:3000 */
50
+ prestUrl: string;
51
+ /** Optional bearer token (JWT from POST /auth, or Kratos session for forward-compat) */
52
+ authToken?: string;
53
+ /** Optional: pre-built Authorization header value (skips "Bearer " prefix) */
54
+ rawAuthHeader?: string;
55
+ /** Optional: extra headers merged into every request */
56
+ headers?: Record<string, string>;
57
+ }
58
+ /**
59
+ * Filter operators supported by pREST's `?field=op.value` syntax.
60
+ * Mirrors `prest/adapters/postgres/postgres.go` GetQueryOperator (line ~1474).
61
+ */
62
+ export type Operator = "eq" | "ne" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "any" | "some" | "all" | "null" | "notnull" | "true" | "nottrue" | "false" | "notfalse" | "like" | "ilike" | "nlike" | "nilike";
63
+ export type OpValue = string | number | (string | number)[];
64
+ /**
65
+ * Filter on table columns.
66
+ *
67
+ * - `{ field: value }` — shorthand for `{ field: { eq: value } }`
68
+ * - `{ field: null }` — IS NULL
69
+ * - `{ field: { op: value } }` — operator form, e.g. `{ age: { gt: 30 } }`
70
+ *
71
+ * Multiple fields are AND-ed. For OR across fields, use `SelectOpts.or`.
72
+ */
73
+ export type Filter = {
74
+ [field: string]: string | number | boolean | null | {
75
+ [op in Operator]?: OpValue;
76
+ };
77
+ };
78
+ export interface SelectOpts {
79
+ /** WHERE clause — AND-ed across fields */
80
+ where?: Filter;
81
+ /** Column selection — `_select=col1,col2` */
82
+ select?: string[];
83
+ /** Order — `_order=col1,col2:desc` */
84
+ order?: string[];
85
+ /** Page-based pagination (1-indexed) — `_page=N&_size=M` */
86
+ page?: number;
87
+ size?: number;
88
+ /** Offset-based pagination — `_limit=N&_offset=M` */
89
+ limit?: number;
90
+ offset?: number;
91
+ /** DISTINCT — `_distinct=true` */
92
+ distinct?: boolean;
93
+ /** COUNT rows instead of returning them — `_count=true` */
94
+ count?: boolean;
95
+ /** Return just the count as a single object — `_count_first=true` */
96
+ countFirst?: boolean;
97
+ /** GROUP BY columns — `_groupby=col1,col2` */
98
+ groupBy?: string[];
99
+ /** OR-clauses for the WHERE — joined with OR inside parens */
100
+ or?: Filter[];
101
+ /** Columns to return from update/delete — `_returning=col1,col2` */
102
+ returning?: string[];
103
+ }
104
+ export declare class PrestApiError extends Error {
105
+ readonly status: number;
106
+ readonly body?: unknown | undefined;
107
+ constructor(status: number, message: string, body?: unknown | undefined);
108
+ }
109
+ /**
110
+ * Serialize a Filter into pREST URL query params.
111
+ *
112
+ * Each field becomes one or more entries: `field=op.value`. Multiple ops on the
113
+ * same field are emitted as repeated query params (pREST AND-s them).
114
+ *
115
+ * @example
116
+ * serializeFilter({ actor_id: 42 })
117
+ * // → "actor_id=eq.42"
118
+ * serializeFilter({ age: { gt: 30 }, name: { like: "foo%" } })
119
+ * // → "age=gt.30&name=like.foo%25"
120
+ * serializeFilter({ id: { in: [1, 2, 3] }, status: null })
121
+ * // → "id=in.(1,2,3)&status=null"
122
+ */
123
+ export declare function serializeFilter(filter: Filter): URLSearchParams;
124
+ /**
125
+ * Serialize full SelectOpts into URLSearchParams (filter + modifiers).
126
+ */
127
+ export declare function serializeSelectOpts(opts: SelectOpts): URLSearchParams;
128
+ export declare class PrestClient {
129
+ private readonly prestUrl;
130
+ private authHeader;
131
+ private readonly extraHeaders;
132
+ constructor(config: PrestConfig | string);
133
+ /**
134
+ * Forward-compat factory: validate a Kratos session and build a PrestClient.
135
+ *
136
+ * The vanilla pREST submodule does not yet wire Kratos (the planned
137
+ * `[auth.kratos]` middleware is documented in the parent project's CLAUDE.md
138
+ * but not merged into the submodule). This helper validates the session
139
+ * against Kratos and stores it as a Bearer header, so it will Just Work
140
+ * once the integration lands. Today it's useful if you're running a patched
141
+ * prest build with Kratos auth.
142
+ *
143
+ * @param kratosUrl - Kratos public URL, e.g. http://localhost:4433
144
+ * @param prestUrl - pREST base URL, defaults to http://localhost:3000
145
+ * @param sessionToken - Optional token. Reads `ory_kratos_session` cookie if omitted (browser).
146
+ * @returns PrestClient, or null if no valid session was found.
147
+ */
148
+ static fromKratosSession(kratosUrl: string, prestUrl?: string, sessionToken?: string): Promise<PrestClient | null>;
149
+ /**
150
+ * Set or replace the auth token after construction.
151
+ * Useful after calling `login()`. Returns `this` for chaining.
152
+ */
153
+ setAuthToken(token: string): this;
154
+ /**
155
+ * Escape hatch for endpoints not covered by the typed methods.
156
+ * Throws PrestApiError on non-2xx.
157
+ */
158
+ request<T = unknown>(method: string, path: string, init?: {
159
+ body?: BodyInit | null;
160
+ headers?: Record<string, string>;
161
+ params?: URLSearchParams;
162
+ }): Promise<T>;
163
+ /** `GET /databases` — list database names. */
164
+ databases(): Promise<unknown>;
165
+ /** `GET /schemas` — list schema names. */
166
+ schemas(): Promise<unknown>;
167
+ /** `GET /tables` — list table names. */
168
+ tables(): Promise<unknown>;
169
+ /** `GET /{database}/{schema}` — list tables in a specific database/schema. */
170
+ tablesIn(database: string, schema: string): Promise<unknown>;
171
+ /** `GET /show/{database}/{schema}/{table}` — table description / columns. */
172
+ showTable(database: string, schema: string, table: string): Promise<Record<string, unknown>>;
173
+ /** `GET /{db}/{schema}/{table}` — SELECT with typed filter DSL. */
174
+ select<T = unknown>(database: string, schema: string, table: string, opts?: SelectOpts): Promise<T[]>;
175
+ /** `POST /{db}/{schema}/{table}` — insert a single row. */
176
+ insert<T = unknown>(database: string, schema: string, table: string, data: Record<string, unknown>): Promise<T[]>;
177
+ /** `POST /batch/{db}/{schema}/{table}` — insert multiple rows in one call. */
178
+ insertBatch<T = unknown>(database: string, schema: string, table: string, rows: Record<string, unknown>[]): Promise<T[]>;
179
+ /** `PUT /{db}/{schema}/{table}?filter` — update rows matching filter. */
180
+ update<T = unknown>(database: string, schema: string, table: string, where: Filter, data: Record<string, unknown>): Promise<T[]>;
181
+ /** `DELETE /{db}/{schema}/{table}?filter` — delete rows matching filter. */
182
+ delete<T = unknown>(database: string, schema: string, table: string, where: Filter): Promise<T[]>;
183
+ /**
184
+ * Execute a stored SQL script: `GET /_QUERIES/{location}/{script}`.
185
+ *
186
+ * Scripts live in `<prest queries dir>/<location>/<script>.sql` and can
187
+ * reference params as `{{ sqlVal "key" }}` / `{{ sqlList "key" }}` in
188
+ * pREST's template syntax.
189
+ *
190
+ * @param location - Folder name under prest's `queries` directory.
191
+ * @param script - `.sql` filename without the extension.
192
+ * @param params - Rendered as URL query params; accessible in the SQL template.
193
+ */
194
+ query<T = unknown>(location: string, script: string, params?: Record<string, string | number | boolean>): Promise<T[]>;
195
+ /** `GET /_health` — returns true on 2xx, false otherwise. */
196
+ health(): Promise<boolean>;
197
+ /**
198
+ * `POST /auth` — exchange username/password for a JWT.
199
+ * Stores the returned token and attaches it as `Authorization: Bearer <token>`
200
+ * on subsequent requests.
201
+ *
202
+ * Only works when pREST's `[auth]` block is enabled in `prest.toml`.
203
+ * Returns the token string.
204
+ */
205
+ login(username: string, password: string): Promise<string>;
206
+ }
207
+ //# sourceMappingURL=index.d.ts.map