@persql/sdk 0.1.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.
- package/README.md +146 -0
- package/dist/chunk-CDNTQOBK.js +1737 -0
- package/dist/chunk-CDNTQOBK.js.map +1 -0
- package/dist/cli.cjs +1827 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.js +103 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +1772 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +926 -0
- package/dist/index.d.ts +926 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,926 @@
|
|
|
1
|
+
interface RawQueryResult {
|
|
2
|
+
columns: string[];
|
|
3
|
+
rows: unknown[][];
|
|
4
|
+
rowsRead: number;
|
|
5
|
+
rowsWritten: number;
|
|
6
|
+
}
|
|
7
|
+
declare class LocalDriver {
|
|
8
|
+
private readonly path;
|
|
9
|
+
private db;
|
|
10
|
+
private readonly proposals;
|
|
11
|
+
constructor(path: string);
|
|
12
|
+
private open;
|
|
13
|
+
query(sql: string, params: unknown[]): Promise<RawQueryResult>;
|
|
14
|
+
batch(statements: Statement[], transaction: boolean): Promise<RawQueryResult[]>;
|
|
15
|
+
tables(): Promise<Array<{
|
|
16
|
+
name: string;
|
|
17
|
+
rowCount: number;
|
|
18
|
+
}>>;
|
|
19
|
+
explain(sql: string, params: unknown[]): Promise<Array<{
|
|
20
|
+
id: number;
|
|
21
|
+
parent: number;
|
|
22
|
+
detail: string;
|
|
23
|
+
}>>;
|
|
24
|
+
propose(sql: string, params: unknown[], ttlSec?: number): Promise<{
|
|
25
|
+
sql: string;
|
|
26
|
+
plan: unknown[][];
|
|
27
|
+
estimatedAffectedRows: number | null;
|
|
28
|
+
executionToken: string;
|
|
29
|
+
expiresAt: string;
|
|
30
|
+
action: "read" | "write" | "admin";
|
|
31
|
+
}>;
|
|
32
|
+
apply(executionToken: string): Promise<RawQueryResult>;
|
|
33
|
+
private gcProposals;
|
|
34
|
+
close(): void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @persql/sdk — Talk to your PerSQL databases from anywhere.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* const persql = new PerSQL({ token: process.env.PERSQL_TOKEN! });
|
|
42
|
+
* const db = persql.database("acme/orders");
|
|
43
|
+
* const rows = await db.query<{ id: number; email: string }>(
|
|
44
|
+
* "SELECT id, email FROM customers WHERE id = ?",
|
|
45
|
+
* [42]
|
|
46
|
+
* );
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
type SqlErrorKind = "unique_violation" | "not_null_violation" | "fk_violation" | "check_violation" | "unknown_table" | "unknown_column" | "syntax_error" | "type_mismatch" | "database_locked" | "too_many_params" | "readonly" | "unknown";
|
|
50
|
+
interface SqlErrorDetail {
|
|
51
|
+
kind: SqlErrorKind;
|
|
52
|
+
message: string;
|
|
53
|
+
table?: string;
|
|
54
|
+
column?: string;
|
|
55
|
+
columns?: Array<{
|
|
56
|
+
table: string;
|
|
57
|
+
column: string;
|
|
58
|
+
}>;
|
|
59
|
+
constraint?: string;
|
|
60
|
+
near?: string;
|
|
61
|
+
hint?: string;
|
|
62
|
+
}
|
|
63
|
+
interface PerSQLOptions {
|
|
64
|
+
/** Bearer token. Get one at https://console.persql.com → Tokens. */
|
|
65
|
+
token?: string;
|
|
66
|
+
/** API base URL. Defaults to https://api.persql.com */
|
|
67
|
+
baseURL?: string;
|
|
68
|
+
/** Custom fetch implementation (defaults to global fetch). */
|
|
69
|
+
fetch?: typeof fetch;
|
|
70
|
+
/**
|
|
71
|
+
* Run against a local SQLite file (via the `better-sqlite3` peer
|
|
72
|
+
* dependency) instead of the HTTP API. Pass `":memory:"` for an
|
|
73
|
+
* in-memory test database. When set, `token` is not required and
|
|
74
|
+
* network features (`vectors`, `blob`, `subscribe`) throw —
|
|
75
|
+
* they have no local equivalent.
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* const persql = new PerSQL({ local: ":memory:" });
|
|
79
|
+
* const db = persql.database("test/db");
|
|
80
|
+
* await db.query("CREATE TABLE t (id INTEGER)");
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
local?: string;
|
|
84
|
+
}
|
|
85
|
+
interface QueryResult<T = Record<string, unknown>> {
|
|
86
|
+
/** Column names in result-set order. */
|
|
87
|
+
columns: string[];
|
|
88
|
+
/** Rows as positional arrays (faster wire format). */
|
|
89
|
+
rows: unknown[][];
|
|
90
|
+
/** Rows reshaped as objects keyed by column name. */
|
|
91
|
+
data: T[];
|
|
92
|
+
rowsRead: number;
|
|
93
|
+
rowsWritten: number;
|
|
94
|
+
}
|
|
95
|
+
interface BatchOptions {
|
|
96
|
+
/** Wrap all statements in BEGIN/COMMIT. Rolls back on first error. */
|
|
97
|
+
transaction?: boolean;
|
|
98
|
+
/** Pass an Idempotency-Key for safe retries. */
|
|
99
|
+
idempotencyKey?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Multi-step plan idempotency. Pair `planKey` (stable across the
|
|
102
|
+
* agent's plan) with `planStep` (stable per step). On retry, every
|
|
103
|
+
* step that already succeeded replays from cache; failed and
|
|
104
|
+
* never-reached steps re-run.
|
|
105
|
+
*/
|
|
106
|
+
planKey?: string;
|
|
107
|
+
planStep?: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Metadata returned by `PerSQL.fromHandoff` describing what the
|
|
111
|
+
* minted token can touch. The token itself is already wired into the
|
|
112
|
+
* returned client; this is just the handoff's resource info so the
|
|
113
|
+
* agent doesn't have to round-trip again to know its scope.
|
|
114
|
+
*/
|
|
115
|
+
interface HandoffClaim {
|
|
116
|
+
tokenId: string;
|
|
117
|
+
databaseId: string;
|
|
118
|
+
databaseSlug: string;
|
|
119
|
+
namespaceSlug: string;
|
|
120
|
+
branchRef: string | null;
|
|
121
|
+
role: "read" | "write" | "admin";
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Engine telemetry row — one entry per /v1/query or /v1/batch call.
|
|
125
|
+
* Returned by `db.queryLog()`. The same data is also exposed inside
|
|
126
|
+
* the DO as `_persql_meta_query_log` so agents can SELECT/JOIN it
|
|
127
|
+
* alongside their own tables.
|
|
128
|
+
*/
|
|
129
|
+
interface QueryLogEntry {
|
|
130
|
+
id: string;
|
|
131
|
+
ts: number;
|
|
132
|
+
sqlText: string;
|
|
133
|
+
paramsJson: string | null;
|
|
134
|
+
status: "ok" | "error";
|
|
135
|
+
errorMessage: string | null;
|
|
136
|
+
rowsRead: number;
|
|
137
|
+
rowsWritten: number;
|
|
138
|
+
durationMs: number;
|
|
139
|
+
statementCount: number;
|
|
140
|
+
tokenId: string | null;
|
|
141
|
+
snapshotId: string | null;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Output of `db.describe()`. Mirrors the schema graph with any
|
|
145
|
+
* stored semantic docs folded in. Designed to be JSON-stringified
|
|
146
|
+
* straight into an LLM prompt.
|
|
147
|
+
*/
|
|
148
|
+
interface DescribeBundle {
|
|
149
|
+
databaseDescription: string | null;
|
|
150
|
+
tables: Array<{
|
|
151
|
+
table: string;
|
|
152
|
+
description: string;
|
|
153
|
+
columns: Array<{
|
|
154
|
+
name: string;
|
|
155
|
+
type: string;
|
|
156
|
+
pk: boolean;
|
|
157
|
+
notNull: boolean;
|
|
158
|
+
description: string;
|
|
159
|
+
}>;
|
|
160
|
+
foreignKeys: Array<{
|
|
161
|
+
from: string;
|
|
162
|
+
toTable: string;
|
|
163
|
+
toColumn: string;
|
|
164
|
+
}>;
|
|
165
|
+
}>;
|
|
166
|
+
}
|
|
167
|
+
/** Output of `db.search(query)`. */
|
|
168
|
+
interface SchemaSearchResponse {
|
|
169
|
+
query: string;
|
|
170
|
+
hits: Array<{
|
|
171
|
+
kind: "table" | "column";
|
|
172
|
+
table: string;
|
|
173
|
+
column: string | null;
|
|
174
|
+
description: string;
|
|
175
|
+
score: number;
|
|
176
|
+
}>;
|
|
177
|
+
}
|
|
178
|
+
/** Output of `db.doctor()`. */
|
|
179
|
+
interface SchemaDoctorReport {
|
|
180
|
+
findings: Array<{
|
|
181
|
+
code: string;
|
|
182
|
+
severity: "info" | "warning" | "error";
|
|
183
|
+
table: string;
|
|
184
|
+
column: string | null;
|
|
185
|
+
message: string;
|
|
186
|
+
suggestion: string;
|
|
187
|
+
}>;
|
|
188
|
+
tablesScanned: number;
|
|
189
|
+
generatedAt: string;
|
|
190
|
+
}
|
|
191
|
+
interface QueryOptions {
|
|
192
|
+
idempotencyKey?: string;
|
|
193
|
+
/** See `BatchOptions.planKey`. */
|
|
194
|
+
planKey?: string;
|
|
195
|
+
/** See `BatchOptions.planStep`. */
|
|
196
|
+
planStep?: string;
|
|
197
|
+
}
|
|
198
|
+
interface TableInfo {
|
|
199
|
+
name: string;
|
|
200
|
+
rowCount: number;
|
|
201
|
+
}
|
|
202
|
+
interface Statement {
|
|
203
|
+
sql: string;
|
|
204
|
+
params?: unknown[];
|
|
205
|
+
}
|
|
206
|
+
declare class PerSQLError extends Error {
|
|
207
|
+
status: number;
|
|
208
|
+
detail?: SqlErrorDetail;
|
|
209
|
+
constructor(status: number, message: string, detail?: SqlErrorDetail);
|
|
210
|
+
}
|
|
211
|
+
declare class RateLimitError extends PerSQLError {
|
|
212
|
+
retryAfterSeconds: number;
|
|
213
|
+
constructor(retryAfterSeconds: number, message?: string);
|
|
214
|
+
}
|
|
215
|
+
interface ApprovalRuleHit {
|
|
216
|
+
ruleId: string;
|
|
217
|
+
tableGlob: string;
|
|
218
|
+
action: "require_approval" | "deny";
|
|
219
|
+
matchedTable: string;
|
|
220
|
+
note: string | null;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Thrown when a write hits an approval rule. The agent can either
|
|
224
|
+
* stop and surface `approvalUrl` to a human, or poll
|
|
225
|
+
* `db.approvals.poll(approvalToken)` until a member decides; once
|
|
226
|
+
* approved, redeem with `db.approvals.redeem(approvalToken)`.
|
|
227
|
+
*/
|
|
228
|
+
declare class ApprovalRequiredError extends PerSQLError {
|
|
229
|
+
approvalToken: string;
|
|
230
|
+
approvalUrl: string;
|
|
231
|
+
hits: ApprovalRuleHit[];
|
|
232
|
+
expiresAt: string;
|
|
233
|
+
constructor(opts: {
|
|
234
|
+
message: string;
|
|
235
|
+
approvalToken: string;
|
|
236
|
+
approvalUrl: string;
|
|
237
|
+
hits: ApprovalRuleHit[];
|
|
238
|
+
expiresAt: string;
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
declare class PerSQL {
|
|
242
|
+
/** @internal — exposed read-only so PerSQLDatabase can build URLs. */
|
|
243
|
+
readonly token: string;
|
|
244
|
+
/** @internal — same. */
|
|
245
|
+
readonly baseURL: string;
|
|
246
|
+
/** @internal — set when running in local mode. */
|
|
247
|
+
readonly local: LocalDriver | null;
|
|
248
|
+
private readonly _fetch;
|
|
249
|
+
constructor(opts: PerSQLOptions);
|
|
250
|
+
/** Close the local SQLite connection (no-op in HTTP mode). */
|
|
251
|
+
close(): void;
|
|
252
|
+
/**
|
|
253
|
+
* Redeem a handoff token (`phand_…`) for a regular PerSQL client
|
|
254
|
+
* scoped to the handed-off (database, branch, role). Single use:
|
|
255
|
+
* the handoff token is consumed by the call.
|
|
256
|
+
*
|
|
257
|
+
* Common pattern — agent A pins a branch and hands the token to
|
|
258
|
+
* agent B; agent B does:
|
|
259
|
+
*
|
|
260
|
+
* const persql = await PerSQL.fromHandoff(handoffToken);
|
|
261
|
+
* const db = persql.database(persql.handedOff!.namespaceSlug, persql.handedOff!.databaseSlug);
|
|
262
|
+
*/
|
|
263
|
+
static fromHandoff(handoffToken: string, opts?: {
|
|
264
|
+
baseURL?: string;
|
|
265
|
+
name?: string;
|
|
266
|
+
fetch?: typeof fetch;
|
|
267
|
+
}): Promise<PerSQL & {
|
|
268
|
+
handedOff: HandoffClaim;
|
|
269
|
+
}>;
|
|
270
|
+
/**
|
|
271
|
+
* Reference a database by its `<namespace>/<slug>` path.
|
|
272
|
+
* Both forms work: `db("acme/orders")` or `db("acme", "orders")`.
|
|
273
|
+
*/
|
|
274
|
+
database(path: string): PerSQLDatabase;
|
|
275
|
+
database(namespace: string, slug: string): PerSQLDatabase;
|
|
276
|
+
/** @internal */
|
|
277
|
+
request<T>(method: "GET" | "POST" | "PUT" | "DELETE", path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
278
|
+
/** @internal — raw upload (e.g. blob PUT) returning the ApiResponse data. */
|
|
279
|
+
requestRaw<T>(method: "PUT" | "POST", path: string, body: ArrayBuffer | Blob | ReadableStream | string, contentType?: string): Promise<T>;
|
|
280
|
+
/** @internal — raw fetch returning the underlying Response (used by blob GET). */
|
|
281
|
+
fetchRaw(method: "GET", path: string): Promise<Response>;
|
|
282
|
+
}
|
|
283
|
+
declare class PerSQLDatabase {
|
|
284
|
+
private readonly client;
|
|
285
|
+
readonly namespace: string;
|
|
286
|
+
readonly slug: string;
|
|
287
|
+
constructor(client: PerSQL, namespace: string, slug: string);
|
|
288
|
+
/** Run a single SQL statement. */
|
|
289
|
+
query<T = Record<string, unknown>>(sql: string, params?: unknown[], options?: QueryOptions): Promise<QueryResult<T>>;
|
|
290
|
+
/** Run multiple statements in one round-trip, optionally in a transaction. */
|
|
291
|
+
batch<T = Record<string, unknown>>(statements: Statement[], options?: BatchOptions): Promise<QueryResult<T>[]>;
|
|
292
|
+
/** Convenience for a transactional batch. */
|
|
293
|
+
transaction<T = Record<string, unknown>>(statements: Statement[], options?: Omit<BatchOptions, "transaction">): Promise<QueryResult<T>[]>;
|
|
294
|
+
/**
|
|
295
|
+
* Engine telemetry — recent /v1/query and /v1/batch calls issued
|
|
296
|
+
* against this database. Backed by the in-DO `_persql_meta_query_log`
|
|
297
|
+
* table; 7-day retention. Useful for agents that need to replay
|
|
298
|
+
* what they (or another agent) did, audit cost, or stream a live
|
|
299
|
+
* tail via `db.subscribe`.
|
|
300
|
+
*/
|
|
301
|
+
queryLog(opts?: {
|
|
302
|
+
since?: string | Date;
|
|
303
|
+
until?: string | Date;
|
|
304
|
+
tokenId?: string;
|
|
305
|
+
status?: "ok" | "error";
|
|
306
|
+
cursor?: string;
|
|
307
|
+
pageSize?: number;
|
|
308
|
+
}): Promise<{
|
|
309
|
+
data: QueryLogEntry[];
|
|
310
|
+
nextCursor: string | null;
|
|
311
|
+
}>;
|
|
312
|
+
/**
|
|
313
|
+
* Returns a structured description of the database — columns, FK
|
|
314
|
+
* graph, and any human-/AI-authored docs persisted via
|
|
315
|
+
* `db.describe(...)`. The shape is designed for direct injection
|
|
316
|
+
* into an LLM prompt: one round-trip and the agent has everything
|
|
317
|
+
* it needs to write correct SQL.
|
|
318
|
+
*/
|
|
319
|
+
describe(): Promise<DescribeBundle>;
|
|
320
|
+
/**
|
|
321
|
+
* Persist semantic descriptions for the database / tables / columns.
|
|
322
|
+
* Pass any subset — only the fields you set are updated. Requires
|
|
323
|
+
* an admin-role token because docs change how every other client
|
|
324
|
+
* (and every agent) interprets the schema.
|
|
325
|
+
*/
|
|
326
|
+
setDescription(input: {
|
|
327
|
+
databaseDescription?: string;
|
|
328
|
+
tables?: Array<{
|
|
329
|
+
table: string;
|
|
330
|
+
description?: string;
|
|
331
|
+
columns?: Array<{
|
|
332
|
+
column: string;
|
|
333
|
+
description: string;
|
|
334
|
+
}>;
|
|
335
|
+
}>;
|
|
336
|
+
}): Promise<DescribeBundle>;
|
|
337
|
+
/**
|
|
338
|
+
* Natural-language ranked search across table names, column names,
|
|
339
|
+
* and any descriptions you've stored via `setDescription`. Use this
|
|
340
|
+
* before writing SQL when you don't know the schema cold — one call
|
|
341
|
+
* narrows a 200-table DB down to the handful that match the intent.
|
|
342
|
+
*/
|
|
343
|
+
search(query: string, opts?: {
|
|
344
|
+
limit?: number;
|
|
345
|
+
}): Promise<SchemaSearchResponse>;
|
|
346
|
+
/**
|
|
347
|
+
* Lints the schema for issues that hurt LLM consumption: missing
|
|
348
|
+
* primary keys, ambiguous column names ("data", "value"), unindexed
|
|
349
|
+
* foreign keys, etc. Pure read-only analysis — emits suggestions
|
|
350
|
+
* for the agent to act on, never modifies the schema itself.
|
|
351
|
+
*/
|
|
352
|
+
doctor(): Promise<SchemaDoctorReport>;
|
|
353
|
+
/** List user-defined tables in this database. */
|
|
354
|
+
tables(): Promise<TableInfo[]>;
|
|
355
|
+
/**
|
|
356
|
+
* Returns SQLite's `EXPLAIN QUERY PLAN` output for the given SQL.
|
|
357
|
+
* Read-only — does not execute the statement.
|
|
358
|
+
*/
|
|
359
|
+
explain(sql: string, params?: unknown[]): Promise<Array<{
|
|
360
|
+
id: number;
|
|
361
|
+
parent: number;
|
|
362
|
+
detail: string;
|
|
363
|
+
}>>;
|
|
364
|
+
/**
|
|
365
|
+
* Introspect the database schema. Returns one entry per user table
|
|
366
|
+
* with column definitions, suitable for codegen tools (the
|
|
367
|
+
* `persql-codegen` CLI uses this to emit Drizzle schema files).
|
|
368
|
+
*/
|
|
369
|
+
schema(): Promise<DatabaseSchema>;
|
|
370
|
+
/**
|
|
371
|
+
* Per-database semantic search via Cloudflare Vectorize. Use
|
|
372
|
+
* `vectors.upsert` to embed and store rows; `vectors.query` to
|
|
373
|
+
* retrieve the most similar by free text. Embeddings are computed
|
|
374
|
+
* server-side using bge-base-en-v1.5 (768 dim, cosine distance).
|
|
375
|
+
*/
|
|
376
|
+
get vectors(): PerSQLVectors;
|
|
377
|
+
/**
|
|
378
|
+
* Manage preview/PR-style branches of this database. Each branch is
|
|
379
|
+
* its own DO with its own SQLite file; create-or-reset by ref is
|
|
380
|
+
* idempotent (PUT semantics) so CI pipelines can call it on every
|
|
381
|
+
* build. Requires an admin-role bearer token for create / delete /
|
|
382
|
+
* merge; list is open to any role.
|
|
383
|
+
*/
|
|
384
|
+
get branches(): PerSQLBranches;
|
|
385
|
+
/**
|
|
386
|
+
* Redeem an approval that was minted when a write hit a
|
|
387
|
+
* `require_approval` rule. Throws `ApprovalRequiredError` until a
|
|
388
|
+
* namespace member decides; on approve, runs the original SQL.
|
|
389
|
+
*/
|
|
390
|
+
get approvals(): PerSQLApprovals;
|
|
391
|
+
/**
|
|
392
|
+
* Pre-flight a write before running it. `propose()` validates the
|
|
393
|
+
* SQL via EXPLAIN, estimates affected rows, and returns a single-use
|
|
394
|
+
* `executionToken` to redeem with `apply()`. Use this when an agent
|
|
395
|
+
* (or its parent / a human) should review a mutation before it runs.
|
|
396
|
+
* Works in both HTTP and local modes — local mode keeps the
|
|
397
|
+
* executionToken in-process.
|
|
398
|
+
*/
|
|
399
|
+
get proposals(): PerSQLProposals;
|
|
400
|
+
/**
|
|
401
|
+
* Per-database BLOB storage backed by R2. Use this for anything
|
|
402
|
+
* larger than a SQLite cell (images, PDFs, model weights). Each
|
|
403
|
+
* database has its own private namespace; keys may be hierarchical
|
|
404
|
+
* (`avatars/2025/foo.jpg`) but never start with `/`.
|
|
405
|
+
*/
|
|
406
|
+
get blob(): PerSQLBlob;
|
|
407
|
+
/**
|
|
408
|
+
* Subscribe to row-changes via WebSocket — the SQL equivalent of
|
|
409
|
+
* Postgres `LISTEN`. The callback fires once per write that
|
|
410
|
+
* matches the table filter. Returns an `unsubscribe` function;
|
|
411
|
+
* call it to close the socket.
|
|
412
|
+
*
|
|
413
|
+
* ```ts
|
|
414
|
+
* const off = db.subscribe({
|
|
415
|
+
* tables: ["orders"],
|
|
416
|
+
* onChange: (e) => console.log(e.kind, e.table),
|
|
417
|
+
* });
|
|
418
|
+
* // …later
|
|
419
|
+
* off();
|
|
420
|
+
* ```
|
|
421
|
+
*
|
|
422
|
+
* Authentication uses the `persql.bearer.<token>` sub-protocol so
|
|
423
|
+
* the token doesn't leak via URL logs. In environments without
|
|
424
|
+
* sub-protocol support (some serverless WebSocket clients), the
|
|
425
|
+
* fallback `?token=` query string is also accepted by the
|
|
426
|
+
* server.
|
|
427
|
+
*/
|
|
428
|
+
subscribe(options: SubscribeOptions): () => void;
|
|
429
|
+
/**
|
|
430
|
+
* Returns the callback shape `drizzle-orm/sqlite-proxy` expects.
|
|
431
|
+
* Pair with `drizzle()` from that module to get a typed,
|
|
432
|
+
* fluent ORM client over the PerSQL HTTP API:
|
|
433
|
+
*
|
|
434
|
+
* ```ts
|
|
435
|
+
* import { drizzle } from "drizzle-orm/sqlite-proxy";
|
|
436
|
+
* import { PerSQL } from "@persql/sdk";
|
|
437
|
+
*
|
|
438
|
+
* const persql = new PerSQL({ token });
|
|
439
|
+
* const db = drizzle(persql.database("acme/orders").driver());
|
|
440
|
+
* ```
|
|
441
|
+
*
|
|
442
|
+
* Drizzle's `prepare` interface maps onto our `query` /
|
|
443
|
+
* `batch`; `method` tells us how to shape the rows.
|
|
444
|
+
*/
|
|
445
|
+
driver(): SqliteProxyDriver;
|
|
446
|
+
/**
|
|
447
|
+
* Returns a tool definition for use with Anthropic / OpenAI / function-calling
|
|
448
|
+
* agents. Pair it with `runTool` to execute the call.
|
|
449
|
+
*/
|
|
450
|
+
asTool(name?: string): {
|
|
451
|
+
anthropic: {
|
|
452
|
+
name: string;
|
|
453
|
+
description: string;
|
|
454
|
+
input_schema: {
|
|
455
|
+
type: string;
|
|
456
|
+
properties: {
|
|
457
|
+
sql: {
|
|
458
|
+
type: string;
|
|
459
|
+
description: string;
|
|
460
|
+
};
|
|
461
|
+
params: {
|
|
462
|
+
type: string;
|
|
463
|
+
items: {};
|
|
464
|
+
description: string;
|
|
465
|
+
};
|
|
466
|
+
};
|
|
467
|
+
required: string[];
|
|
468
|
+
};
|
|
469
|
+
};
|
|
470
|
+
openai: {
|
|
471
|
+
type: "function";
|
|
472
|
+
function: {
|
|
473
|
+
name: string;
|
|
474
|
+
description: string;
|
|
475
|
+
parameters: {
|
|
476
|
+
type: string;
|
|
477
|
+
properties: {
|
|
478
|
+
sql: {
|
|
479
|
+
type: string;
|
|
480
|
+
};
|
|
481
|
+
params: {
|
|
482
|
+
type: string;
|
|
483
|
+
items: {};
|
|
484
|
+
};
|
|
485
|
+
};
|
|
486
|
+
required: string[];
|
|
487
|
+
};
|
|
488
|
+
};
|
|
489
|
+
};
|
|
490
|
+
};
|
|
491
|
+
/**
|
|
492
|
+
* Executes a tool-call payload returned from the model. Pair with `asTool`.
|
|
493
|
+
*/
|
|
494
|
+
runTool(input: {
|
|
495
|
+
sql: string;
|
|
496
|
+
params?: unknown[];
|
|
497
|
+
}): Promise<QueryResult<Record<string, unknown>>>;
|
|
498
|
+
/**
|
|
499
|
+
* Generate a *bundle* of typed tools — one per table — instead of one
|
|
500
|
+
* generic `query` tool. Agents perform dramatically better with narrow
|
|
501
|
+
* typed surfaces than they do with one fat SQL function. Each table
|
|
502
|
+
* gets:
|
|
503
|
+
* - `select_<table>(where?, limit?, orderBy?)` — typed column filter
|
|
504
|
+
* - `count_<table>(where?)` — quick row count
|
|
505
|
+
* - `describe_<table>()` — columns, row count, foreign keys
|
|
506
|
+
* Plus a fallback `sql_query(sql, params)` for anything the typed
|
|
507
|
+
* tools can't express.
|
|
508
|
+
*
|
|
509
|
+
* The returned `run(name, input)` dispatcher executes whichever tool
|
|
510
|
+
* the model invoked. Format the tools for the LLM via the
|
|
511
|
+
* `anthropic` or `openai` arrays (matches the shapes of `asTool`).
|
|
512
|
+
*
|
|
513
|
+
* ```ts
|
|
514
|
+
* const tools = await db.asTools();
|
|
515
|
+
* const reply = await anthropic.messages.create({
|
|
516
|
+
* model: "claude-opus-4-7",
|
|
517
|
+
* tools: tools.anthropic,
|
|
518
|
+
* messages: [...],
|
|
519
|
+
* });
|
|
520
|
+
* for (const block of reply.content) {
|
|
521
|
+
* if (block.type === "tool_use") {
|
|
522
|
+
* const result = await tools.run(block.name, block.input);
|
|
523
|
+
* }
|
|
524
|
+
* }
|
|
525
|
+
* ```
|
|
526
|
+
*/
|
|
527
|
+
asTools(): Promise<DatabaseToolBundle>;
|
|
528
|
+
}
|
|
529
|
+
interface AnthropicTool {
|
|
530
|
+
name: string;
|
|
531
|
+
description: string;
|
|
532
|
+
input_schema: Record<string, unknown>;
|
|
533
|
+
}
|
|
534
|
+
interface OpenAiTool {
|
|
535
|
+
type: "function";
|
|
536
|
+
function: {
|
|
537
|
+
name: string;
|
|
538
|
+
description: string;
|
|
539
|
+
parameters: Record<string, unknown>;
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
interface DatabaseToolBundle {
|
|
543
|
+
/** Tool definitions in Anthropic shape — pass as `tools` to messages.create. */
|
|
544
|
+
anthropic: AnthropicTool[];
|
|
545
|
+
/** Tool definitions in OpenAI shape — pass as `tools` to chat.completions.create. */
|
|
546
|
+
openai: OpenAiTool[];
|
|
547
|
+
/** Dispatch a model-emitted tool call back to the database. */
|
|
548
|
+
run: (name: string, input?: Record<string, unknown>) => Promise<unknown>;
|
|
549
|
+
/**
|
|
550
|
+
* Vercel AI SDK shape — record of `{ [toolName]: { description, inputSchema, execute } }`.
|
|
551
|
+
* Spread into `streamText({ tools: { ...db.asTools().aiSdk() } })`. The
|
|
552
|
+
* `inputSchema` field is JSON Schema; pass through `jsonSchema()` from
|
|
553
|
+
* the `ai` package if your version of AI SDK requires it explicitly.
|
|
554
|
+
*/
|
|
555
|
+
aiSdk: () => Record<string, AiSdkTool>;
|
|
556
|
+
/**
|
|
557
|
+
* Mastra shape — record of `{ [toolName]: { id, description, inputSchema, execute } }`.
|
|
558
|
+
* Useful for `createTool({...})` callsites. `inputSchema` is JSON Schema;
|
|
559
|
+
* if Mastra's runtime needs a Zod schema, run it through `json-schema-to-zod`
|
|
560
|
+
* or your preferred converter.
|
|
561
|
+
*/
|
|
562
|
+
mastra: () => Record<string, MastraTool>;
|
|
563
|
+
/**
|
|
564
|
+
* LangChain shape — array of `{ name, description, schema, invoke }`.
|
|
565
|
+
* Wrap with `DynamicStructuredTool` or pass `invoke` directly to a
|
|
566
|
+
* custom agent loop.
|
|
567
|
+
*/
|
|
568
|
+
langchain: () => LangChainTool[];
|
|
569
|
+
/**
|
|
570
|
+
* OpenAI Agents SDK shape — array of `{ type, name, description, parameters, invoke }`.
|
|
571
|
+
* Hand to `Agent({ tools: [...] })`.
|
|
572
|
+
*/
|
|
573
|
+
openaiAgents: () => OpenAiAgentsTool[];
|
|
574
|
+
}
|
|
575
|
+
interface AiSdkTool {
|
|
576
|
+
description: string;
|
|
577
|
+
inputSchema: Record<string, unknown>;
|
|
578
|
+
execute: (input: Record<string, unknown>) => Promise<unknown>;
|
|
579
|
+
}
|
|
580
|
+
interface MastraTool {
|
|
581
|
+
id: string;
|
|
582
|
+
description: string;
|
|
583
|
+
inputSchema: Record<string, unknown>;
|
|
584
|
+
execute: (context: {
|
|
585
|
+
context: Record<string, unknown>;
|
|
586
|
+
}) => Promise<unknown>;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* LangChain shape — pass to `DynamicStructuredTool` or use `invoke`
|
|
590
|
+
* directly inside a custom agent. `schema` is JSON Schema; if your
|
|
591
|
+
* LangChain version requires Zod, convert with `json-schema-to-zod`.
|
|
592
|
+
*/
|
|
593
|
+
interface LangChainTool {
|
|
594
|
+
name: string;
|
|
595
|
+
description: string;
|
|
596
|
+
schema: Record<string, unknown>;
|
|
597
|
+
invoke: (input: Record<string, unknown>) => Promise<unknown>;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* OpenAI Agents SDK shape — assign as a tool in `Agent` config. The
|
|
601
|
+
* Agents SDK uses `parameters` (JSON Schema) and a callable; our
|
|
602
|
+
* `invoke` matches the `function_tool` callback signature.
|
|
603
|
+
*/
|
|
604
|
+
interface OpenAiAgentsTool {
|
|
605
|
+
type: "function";
|
|
606
|
+
name: string;
|
|
607
|
+
description: string;
|
|
608
|
+
parameters: Record<string, unknown>;
|
|
609
|
+
invoke: (input: Record<string, unknown>) => Promise<unknown>;
|
|
610
|
+
}
|
|
611
|
+
type SubscribeChangeKind = "update" | "insert" | "delete" | "schema" | "unknown";
|
|
612
|
+
interface SubscribeChange {
|
|
613
|
+
table: string;
|
|
614
|
+
kind: SubscribeChangeKind;
|
|
615
|
+
}
|
|
616
|
+
interface SubscribeOptions {
|
|
617
|
+
/** Tables to listen to. Omit / empty / `["*"]` = all tables. */
|
|
618
|
+
tables?: string[];
|
|
619
|
+
onChange: (change: SubscribeChange) => void;
|
|
620
|
+
/** Fires once when the server confirms the subscription. */
|
|
621
|
+
onReady?: (tables: string[] | "*") => void;
|
|
622
|
+
onError?: (error: Error) => void;
|
|
623
|
+
onClose?: () => void;
|
|
624
|
+
}
|
|
625
|
+
interface BlobListItem {
|
|
626
|
+
key: string;
|
|
627
|
+
sizeBytes: number;
|
|
628
|
+
etag: string;
|
|
629
|
+
uploadedAt: string;
|
|
630
|
+
contentType?: string;
|
|
631
|
+
}
|
|
632
|
+
interface BlobListResponse {
|
|
633
|
+
items: BlobListItem[];
|
|
634
|
+
truncated: boolean;
|
|
635
|
+
cursor?: string;
|
|
636
|
+
}
|
|
637
|
+
declare class PerSQLBlob {
|
|
638
|
+
private readonly client;
|
|
639
|
+
private readonly namespace;
|
|
640
|
+
private readonly slug;
|
|
641
|
+
constructor(client: PerSQL, namespace: string, slug: string);
|
|
642
|
+
/** Upload a blob. Body can be ArrayBuffer, Blob, ReadableStream, or string. */
|
|
643
|
+
put(key: string, body: ArrayBuffer | Blob | ReadableStream | string, opts?: {
|
|
644
|
+
contentType?: string;
|
|
645
|
+
}): Promise<{
|
|
646
|
+
key: string;
|
|
647
|
+
sizeBytes: number;
|
|
648
|
+
etag: string;
|
|
649
|
+
}>;
|
|
650
|
+
/** Fetch a blob. Returns null if missing. */
|
|
651
|
+
get(key: string): Promise<Response | null>;
|
|
652
|
+
/** Delete a blob. */
|
|
653
|
+
delete(key: string): Promise<void>;
|
|
654
|
+
/** List blobs by prefix. */
|
|
655
|
+
list(opts?: {
|
|
656
|
+
prefix?: string;
|
|
657
|
+
cursor?: string;
|
|
658
|
+
limit?: number;
|
|
659
|
+
}): Promise<BlobListResponse>;
|
|
660
|
+
}
|
|
661
|
+
interface VectorUpsertItem {
|
|
662
|
+
id: string;
|
|
663
|
+
text: string;
|
|
664
|
+
metadata?: Record<string, string | number | boolean>;
|
|
665
|
+
}
|
|
666
|
+
interface VectorMatch {
|
|
667
|
+
id: string;
|
|
668
|
+
score: number;
|
|
669
|
+
metadata: Record<string, unknown>;
|
|
670
|
+
}
|
|
671
|
+
declare class PerSQLVectors {
|
|
672
|
+
private readonly client;
|
|
673
|
+
private readonly namespace;
|
|
674
|
+
private readonly slug;
|
|
675
|
+
constructor(client: PerSQL, namespace: string, slug: string);
|
|
676
|
+
/** Embed and upsert up to 100 items in one call. */
|
|
677
|
+
upsert(items: VectorUpsertItem[]): Promise<{
|
|
678
|
+
count: number;
|
|
679
|
+
}>;
|
|
680
|
+
/** Top-K nearest neighbours by free-text query. */
|
|
681
|
+
query(text: string, opts?: {
|
|
682
|
+
topK?: number;
|
|
683
|
+
filter?: Record<string, string | number | boolean>;
|
|
684
|
+
}): Promise<VectorMatch[]>;
|
|
685
|
+
/** Delete vectors by id. Up to 1000 ids per call. */
|
|
686
|
+
delete(ids: string[]): Promise<{
|
|
687
|
+
count: number;
|
|
688
|
+
}>;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Database row as returned by /v1 list/upsert branch responses.
|
|
692
|
+
* Mirrors the `Database` DTO from @persql/shared but kept narrow on
|
|
693
|
+
* purpose so the SDK doesn't drift if the server adds fields.
|
|
694
|
+
*/
|
|
695
|
+
interface BranchInfo {
|
|
696
|
+
id: string;
|
|
697
|
+
namespaceId: string;
|
|
698
|
+
slug: string;
|
|
699
|
+
name: string;
|
|
700
|
+
status: string;
|
|
701
|
+
region: string;
|
|
702
|
+
branchRef: string | null;
|
|
703
|
+
forkedAt: string | null;
|
|
704
|
+
expiresAt: string | null;
|
|
705
|
+
createdAt: string;
|
|
706
|
+
updatedAt: string;
|
|
707
|
+
forkedFrom?: {
|
|
708
|
+
id: string;
|
|
709
|
+
slug: string;
|
|
710
|
+
name: string;
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
type BranchMergeMode = "schema" | "promote";
|
|
714
|
+
type BranchMergePlanStep = {
|
|
715
|
+
op: "create";
|
|
716
|
+
type: string;
|
|
717
|
+
name: string;
|
|
718
|
+
sql: string;
|
|
719
|
+
} | {
|
|
720
|
+
op: "drop";
|
|
721
|
+
type: string;
|
|
722
|
+
name: string;
|
|
723
|
+
} | {
|
|
724
|
+
op: "replace";
|
|
725
|
+
type: string;
|
|
726
|
+
name: string;
|
|
727
|
+
beforeSql: string;
|
|
728
|
+
afterSql: string;
|
|
729
|
+
};
|
|
730
|
+
interface BranchMergeResult {
|
|
731
|
+
mode: BranchMergeMode;
|
|
732
|
+
preview: boolean;
|
|
733
|
+
applied: number;
|
|
734
|
+
snapshotId: string | null;
|
|
735
|
+
plan?: BranchMergePlanStep[];
|
|
736
|
+
summary?: {
|
|
737
|
+
added: number;
|
|
738
|
+
changed: number;
|
|
739
|
+
removed: number;
|
|
740
|
+
};
|
|
741
|
+
note?: string;
|
|
742
|
+
}
|
|
743
|
+
interface BranchUpsertOptions {
|
|
744
|
+
/** Human-readable name. Defaults to `<parent name> (<ref>)`. */
|
|
745
|
+
name?: string;
|
|
746
|
+
/** Region hint: auto, wnam, enam, weur, eeur, apac. Default: auto. */
|
|
747
|
+
region?: string;
|
|
748
|
+
/** Auto-delete after N days (1..30). Null/undefined = keep until deleted. */
|
|
749
|
+
ttlDays?: number | null;
|
|
750
|
+
}
|
|
751
|
+
interface BranchMergeOptions {
|
|
752
|
+
/** Default `schema`. `promote` replaces parent contents wholesale. */
|
|
753
|
+
mode?: BranchMergeMode;
|
|
754
|
+
/** If true, returns the plan without writing. */
|
|
755
|
+
preview?: boolean;
|
|
756
|
+
/** Schema mode only — drop objects present in parent but not in branch. */
|
|
757
|
+
dropRemoved?: boolean;
|
|
758
|
+
/** Default true — captures `pre-merge:<ref>` snapshot of the parent. */
|
|
759
|
+
snapshot?: boolean;
|
|
760
|
+
}
|
|
761
|
+
interface ProposalPlan {
|
|
762
|
+
sql: string;
|
|
763
|
+
plan: unknown[][];
|
|
764
|
+
estimatedAffectedRows: number | null;
|
|
765
|
+
executionToken: string;
|
|
766
|
+
expiresAt: string;
|
|
767
|
+
action: "read" | "write" | "admin";
|
|
768
|
+
}
|
|
769
|
+
interface ProposeOptions {
|
|
770
|
+
params?: unknown[];
|
|
771
|
+
ttlSec?: number;
|
|
772
|
+
}
|
|
773
|
+
declare class PerSQLApprovals {
|
|
774
|
+
private readonly client;
|
|
775
|
+
private readonly namespace;
|
|
776
|
+
private readonly slug;
|
|
777
|
+
constructor(client: PerSQL, namespace: string, slug: string);
|
|
778
|
+
/**
|
|
779
|
+
* Redeem an approved approvalToken. The bearer must be the same one
|
|
780
|
+
* that minted it, and the request must target the same database.
|
|
781
|
+
* Returns the result of the originally-blocked query or batch.
|
|
782
|
+
*/
|
|
783
|
+
redeem<T = Record<string, unknown>>(approvalToken: string): Promise<QueryResult<T> | QueryResult<T>[]>;
|
|
784
|
+
}
|
|
785
|
+
declare class PerSQLProposals {
|
|
786
|
+
private readonly client;
|
|
787
|
+
private readonly namespace;
|
|
788
|
+
private readonly slug;
|
|
789
|
+
constructor(client: PerSQL, namespace: string, slug: string);
|
|
790
|
+
/**
|
|
791
|
+
* Pre-flight an SQL statement. EXPLAIN-validates, estimates affected
|
|
792
|
+
* rows, and returns a single-use `executionToken` valid for 10 min
|
|
793
|
+
* (override with `ttlSec`, max 1 hour). Nothing is mutated until
|
|
794
|
+
* `apply()` is called.
|
|
795
|
+
*/
|
|
796
|
+
propose(sql: string, opts?: ProposeOptions): Promise<ProposalPlan>;
|
|
797
|
+
/**
|
|
798
|
+
* Redeem an `executionToken` from `propose()`. Single-use — calling
|
|
799
|
+
* twice with the same token throws 404. The token is also pinned to
|
|
800
|
+
* the originating bearer + database; cross-token redemption throws
|
|
801
|
+
* 403.
|
|
802
|
+
*/
|
|
803
|
+
apply<T = Record<string, unknown>>(executionToken: string): Promise<QueryResult<T>>;
|
|
804
|
+
}
|
|
805
|
+
interface ClaimedBranch {
|
|
806
|
+
branchRef: string;
|
|
807
|
+
databaseId: string;
|
|
808
|
+
databaseSlug: string;
|
|
809
|
+
namespaceSlug: string;
|
|
810
|
+
/** Plaintext psql_live_/psql_test_ token. Returned once. */
|
|
811
|
+
token: string;
|
|
812
|
+
tokenId: string;
|
|
813
|
+
role: "read" | "write" | "admin";
|
|
814
|
+
expiresAt: string;
|
|
815
|
+
outcome: "created" | "reset";
|
|
816
|
+
}
|
|
817
|
+
interface ClaimBranchOptions {
|
|
818
|
+
/** Explicit ref. Omit to auto-generate from `purpose`. */
|
|
819
|
+
ref?: string;
|
|
820
|
+
/** Free-form label baked into the auto-ref + token name. */
|
|
821
|
+
purpose?: string;
|
|
822
|
+
/** Lease length in seconds. Default 3600 (1 hour), max 30 days. */
|
|
823
|
+
ttlSec?: number;
|
|
824
|
+
/** Default "write". */
|
|
825
|
+
role?: "read" | "write" | "admin";
|
|
826
|
+
region?: string;
|
|
827
|
+
}
|
|
828
|
+
declare class PerSQLBranches {
|
|
829
|
+
private readonly client;
|
|
830
|
+
private readonly namespace;
|
|
831
|
+
private readonly slug;
|
|
832
|
+
constructor(client: PerSQL, namespace: string, slug: string);
|
|
833
|
+
/**
|
|
834
|
+
* One-shot lease — create or reset a branch with a TTL and mint a
|
|
835
|
+
* scoped token in the same call. Use at the start of an agent run
|
|
836
|
+
* instead of chaining create + token mint.
|
|
837
|
+
*/
|
|
838
|
+
claim(opts?: ClaimBranchOptions): Promise<ClaimedBranch>;
|
|
839
|
+
/** List branches of this database. Any-role token. */
|
|
840
|
+
list(opts?: {
|
|
841
|
+
cursor?: string;
|
|
842
|
+
pageSize?: number;
|
|
843
|
+
}): Promise<{
|
|
844
|
+
data: BranchInfo[];
|
|
845
|
+
nextCursor: string | null;
|
|
846
|
+
}>;
|
|
847
|
+
/**
|
|
848
|
+
* Create-or-reset a branch by ref. Idempotent: re-PUTting the same
|
|
849
|
+
* ref refreshes the branch from the parent's current state.
|
|
850
|
+
* Requires an admin-role token.
|
|
851
|
+
*/
|
|
852
|
+
upsert(ref: string, opts?: BranchUpsertOptions): Promise<BranchInfo>;
|
|
853
|
+
/** Delete a branch by ref. Requires an admin-role token. */
|
|
854
|
+
delete(ref: string): Promise<{
|
|
855
|
+
deleted: true;
|
|
856
|
+
}>;
|
|
857
|
+
/**
|
|
858
|
+
* Apply a branch back into its parent. `preview: true` returns the
|
|
859
|
+
* plan without writing. Requires an admin-role token.
|
|
860
|
+
*/
|
|
861
|
+
merge(ref: string, opts?: BranchMergeOptions): Promise<BranchMergeResult>;
|
|
862
|
+
/** Convenience for `merge(ref, { preview: true, ...opts })`. */
|
|
863
|
+
preview(ref: string, opts?: Omit<BranchMergeOptions, "preview">): Promise<BranchMergeResult>;
|
|
864
|
+
/**
|
|
865
|
+
* Mint a single-use handoff token for this branch. The receiving
|
|
866
|
+
* agent calls `PerSQL.fromHandoff(token)` to redeem it for a
|
|
867
|
+
* regular bearer token scoped to exactly this (database, branch,
|
|
868
|
+
* role) — the agent that minted the handoff never has to share
|
|
869
|
+
* its own token. Single-use, ≤24h TTL.
|
|
870
|
+
*/
|
|
871
|
+
pin(ref: string, opts?: {
|
|
872
|
+
role?: "read" | "write" | "admin";
|
|
873
|
+
ttlSec?: number;
|
|
874
|
+
}): Promise<{
|
|
875
|
+
token: string;
|
|
876
|
+
expiresAt: string;
|
|
877
|
+
role: "read" | "write" | "admin";
|
|
878
|
+
databaseId: string;
|
|
879
|
+
branchRef: string | null;
|
|
880
|
+
}>;
|
|
881
|
+
/**
|
|
882
|
+
* Render the branch's schema delta as a committable SQL migration.
|
|
883
|
+
* Read-only. Returns `{ name, sql, plan, summary }` — `name` is a
|
|
884
|
+
* timestamped filename (`YYYYMMDDHHMMSS_branch_<ref>.sql`) safe to
|
|
885
|
+
* write to disk; `sql` is the migration body wrapped in a single
|
|
886
|
+
* BEGIN/COMMIT.
|
|
887
|
+
*/
|
|
888
|
+
migration(ref: string, opts?: {
|
|
889
|
+
dropRemoved?: boolean;
|
|
890
|
+
}): Promise<{
|
|
891
|
+
name: string;
|
|
892
|
+
sql: string;
|
|
893
|
+
plan: BranchMergePlanStep[];
|
|
894
|
+
summary: {
|
|
895
|
+
added: number;
|
|
896
|
+
changed: number;
|
|
897
|
+
removed: number;
|
|
898
|
+
};
|
|
899
|
+
}>;
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Schema returned by `db.schema()`. One entry per user table.
|
|
903
|
+
*/
|
|
904
|
+
interface DatabaseSchema {
|
|
905
|
+
tables: Array<{
|
|
906
|
+
name: string;
|
|
907
|
+
columns: Array<{
|
|
908
|
+
name: string;
|
|
909
|
+
/** SQLite column type (TEXT, INTEGER, REAL, BLOB, NUMERIC). */
|
|
910
|
+
type: string;
|
|
911
|
+
notNull: boolean;
|
|
912
|
+
primaryKey: boolean;
|
|
913
|
+
default: string | null;
|
|
914
|
+
}>;
|
|
915
|
+
}>;
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Callback shape used by Drizzle's `drizzle-orm/sqlite-proxy`.
|
|
919
|
+
* Returned by `db.driver()` so callers can plug PerSQL into Drizzle
|
|
920
|
+
* without taking a hard dep on it.
|
|
921
|
+
*/
|
|
922
|
+
type SqliteProxyDriver = (sql: string, params: unknown[], method: "all" | "run" | "get" | "values") => Promise<{
|
|
923
|
+
rows: unknown;
|
|
924
|
+
}>;
|
|
925
|
+
|
|
926
|
+
export { type AiSdkTool, type AnthropicTool, ApprovalRequiredError, type ApprovalRuleHit, type BatchOptions, type BlobListItem, type BlobListResponse, type BranchInfo, type BranchMergeMode, type BranchMergeOptions, type BranchMergePlanStep, type BranchMergeResult, type BranchUpsertOptions, type ClaimBranchOptions, type ClaimedBranch, type DatabaseSchema, type DatabaseToolBundle, type DescribeBundle, type HandoffClaim, type LangChainTool, type MastraTool, type OpenAiAgentsTool, type OpenAiTool, PerSQL, PerSQLApprovals, PerSQLBlob, PerSQLBranches, PerSQLDatabase, PerSQLError, type PerSQLOptions, PerSQLProposals, PerSQLVectors, type ProposalPlan, type ProposeOptions, type QueryLogEntry, type QueryOptions, type QueryResult, RateLimitError, type RawQueryResult, type SchemaDoctorReport, type SchemaSearchResponse, type SqlErrorDetail, type SqlErrorKind, type SqliteProxyDriver, type Statement, type SubscribeChange, type SubscribeChangeKind, type SubscribeOptions, type TableInfo, type VectorMatch, type VectorUpsertItem };
|