@persql/sdk 1.2.0 → 1.3.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/dist/{chunk-GH75ERQ6.js → chunk-SIJU2P7U.js} +9 -2
- package/dist/chunk-SIJU2P7U.js.map +1 -0
- package/dist/cli.cjs +8 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +8 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +98 -1
- package/dist/index.d.ts +98 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-GH75ERQ6.js.map +0 -1
|
@@ -161,7 +161,14 @@ function runOne(db, sql, params) {
|
|
|
161
161
|
return { columns: cols, rows, rowsRead: rows.length, rowsWritten: 0 };
|
|
162
162
|
}
|
|
163
163
|
const info = stmt.run(...params);
|
|
164
|
-
return {
|
|
164
|
+
return {
|
|
165
|
+
columns: [],
|
|
166
|
+
rows: [],
|
|
167
|
+
rowsRead: 0,
|
|
168
|
+
rowsWritten: info.changes ?? 0,
|
|
169
|
+
changes: info.changes ?? 0,
|
|
170
|
+
lastInsertRowid: Number(info.lastInsertRowid ?? 0)
|
|
171
|
+
};
|
|
165
172
|
}
|
|
166
173
|
|
|
167
174
|
// src/index.ts
|
|
@@ -2044,4 +2051,4 @@ export {
|
|
|
2044
2051
|
PerSQLProposals,
|
|
2045
2052
|
PerSQLBranches
|
|
2046
2053
|
};
|
|
2047
|
-
//# sourceMappingURL=chunk-
|
|
2054
|
+
//# sourceMappingURL=chunk-SIJU2P7U.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/local.ts","../src/index.ts"],"sourcesContent":["// Local mode — runs SQL against a `better-sqlite3` file (or\n// `:memory:`) instead of the HTTP API. The peer dep is loaded\n// lazily so customers who only use the live SDK never pull\n// the native module.\n//\n// Surface intentionally narrow: query / batch / tables / explain\n// + the propose/apply pre-flight pair (the agent-shape primitive\n// that's worth keeping testable without a worker). Subscribe,\n// branches, approvals have no local equivalent and throw.\n\nimport type { BatchExpect, Statement } from \"./index\";\n\nfunction checkLocalExpect(\n e: BatchExpect,\n r: RawQueryResult\n): string | null {\n const rows = r.rows.length;\n if (e.rows != null && rows !== e.rows) {\n return `expected rows=${e.rows}, got ${rows}`;\n }\n if (e.rowsAtLeast != null && rows < e.rowsAtLeast) {\n return `expected rows>=${e.rowsAtLeast}, got ${rows}`;\n }\n if (e.rowsAtMost != null && rows > e.rowsAtMost) {\n return `expected rows<=${e.rowsAtMost}, got ${rows}`;\n }\n if (e.rowsWritten != null && r.rowsWritten !== e.rowsWritten) {\n return `expected rowsWritten=${e.rowsWritten}, got ${r.rowsWritten}`;\n }\n if (e.rowsWrittenAtLeast != null && r.rowsWritten < e.rowsWrittenAtLeast) {\n return `expected rowsWritten>=${e.rowsWrittenAtLeast}, got ${r.rowsWritten}`;\n }\n if (e.rowsWrittenAtMost != null && r.rowsWritten > e.rowsWrittenAtMost) {\n return `expected rowsWritten<=${e.rowsWrittenAtMost}, got ${r.rowsWritten}`;\n }\n return null;\n}\n\ninterface LocalProposal {\n sql: string;\n params: unknown[];\n expiresAt: number;\n}\n\nconst PROPOSAL_TTL_DEFAULT_SEC = 600;\nconst PROPOSAL_TTL_MAX_SEC = 3600;\n\nfunction newLocalProposalId(): string {\n // pmut_local_<16 hex> — distinguishable from server-issued tokens\n // so a stray cross-mode redemption fails loud.\n const buf = new Uint8Array(8);\n crypto.getRandomValues(buf);\n let hex = \"\";\n for (const b of buf) hex += b.toString(16).padStart(2, \"0\");\n return `pmut_local_${hex}`;\n}\n\ninterface BetterSqliteStmt {\n reader: boolean;\n raw(toggle: boolean): BetterSqliteStmt;\n columns(): Array<{ name: string }>;\n all(...params: unknown[]): unknown[];\n run(...params: unknown[]): { changes: number; lastInsertRowid: number | bigint };\n}\n\ninterface BetterSqliteDb {\n prepare(sql: string): BetterSqliteStmt;\n transaction<T>(fn: () => T): () => T;\n pragma(s: string): unknown;\n close(): void;\n}\n\n/** Wire-shape query result — columns plus positional rows, before the SDK reshapes rows into objects. */\nexport interface RawQueryResult {\n columns: string[];\n rows: unknown[][];\n rowsRead: number;\n rowsWritten: number;\n changes?: number;\n lastInsertRowid?: number;\n}\n\n/** In-process driver backing `new PerSQL({ local })` — runs SQL through `better-sqlite3` instead of the HTTP API. */\nexport class LocalDriver {\n private db: BetterSqliteDb | null = null;\n private readonly proposals = new Map<string, LocalProposal>();\n\n constructor(private readonly path: string) {}\n\n private async open(): Promise<BetterSqliteDb> {\n if (this.db) return this.db;\n // String-via-variable defeats TypeScript's static module\n // resolution so the optional peer dep doesn't need its type\n // declarations at SDK build time.\n const moduleName = \"better-sqlite3\";\n let mod: unknown;\n try {\n mod = await import(moduleName);\n } catch {\n throw new Error(\n \"PerSQL local mode requires the `better-sqlite3` peer dep. \" +\n \"Install with `npm i -D better-sqlite3` (or pnpm/yarn equivalent).\"\n );\n }\n const m = mod as { default?: unknown };\n const Ctor = (m.default ?? mod) as new (path: string) => BetterSqliteDb;\n this.db = new Ctor(this.path);\n this.db.pragma(\"foreign_keys = ON\");\n return this.db;\n }\n\n async query(sql: string, params: unknown[]): Promise<RawQueryResult> {\n const db = await this.open();\n return runOne(db, sql, params);\n }\n\n async batch(\n statements: Statement[],\n transaction: boolean\n ): Promise<RawQueryResult[]> {\n const db = await this.open();\n const exec = () =>\n statements.map((s, i) => {\n const r = runOne(db, s.sql, s.params ?? []);\n if (s.expect) {\n const violation = checkLocalExpect(s.expect, r);\n if (violation) {\n throw new Error(`Assertion failed on statement ${i}: ${violation}`);\n }\n }\n return r;\n });\n if (transaction) return db.transaction(exec)();\n return exec();\n }\n\n async tables(): Promise<Array<{ name: string; rowCount: number }>> {\n const db = await this.open();\n const rows = runOne(\n db,\n \"SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name\",\n []\n ).rows as Array<[string]>;\n return rows.map(([name]) => {\n const c = runOne(db, `SELECT COUNT(*) FROM \"${name.replace(/\"/g, '\"\"')}\"`, [])\n .rows[0] as [number];\n return { name, rowCount: Number(c?.[0] ?? 0) };\n });\n }\n\n async explain(\n sql: string,\n params: unknown[]\n ): Promise<Array<{ id: number; parent: number; detail: string }>> {\n const db = await this.open();\n const r = runOne(db, `EXPLAIN QUERY PLAN ${sql}`, params);\n // EXPLAIN QUERY PLAN returns rows: id, parent, notused, detail\n return (r.rows as Array<[number, number, number, string]>).map((row) => ({\n id: Number(row[0]),\n parent: Number(row[1]),\n detail: String(row[3]),\n }));\n }\n\n async propose(\n sql: string,\n params: unknown[],\n ttlSec?: number\n ): Promise<{\n sql: string;\n plan: unknown[][];\n estimatedAffectedRows: number | null;\n executionToken: string;\n expiresAt: string;\n action: \"read\" | \"write\" | \"admin\";\n }> {\n const db = await this.open();\n const planRaw = runOne(db, `EXPLAIN QUERY PLAN ${sql}`, params).rows;\n const plan = planRaw as unknown[][];\n const ttl = Math.min(\n Math.max(1, Math.floor(ttlSec ?? PROPOSAL_TTL_DEFAULT_SEC)),\n PROPOSAL_TTL_MAX_SEC\n );\n const expiresAt = Date.now() + ttl * 1000;\n const executionToken = newLocalProposalId();\n this.proposals.set(executionToken, { sql, params, expiresAt });\n this.gcProposals();\n return {\n sql,\n plan,\n estimatedAffectedRows: null,\n executionToken,\n expiresAt: new Date(expiresAt).toISOString(),\n action: actionForSql(sql),\n };\n }\n\n async apply(executionToken: string): Promise<RawQueryResult> {\n const rec = this.proposals.get(executionToken);\n if (!rec) {\n throw new Error(\n \"PerSQL: executionToken is unknown, expired, or already redeemed\"\n );\n }\n this.proposals.delete(executionToken);\n if (rec.expiresAt < Date.now()) {\n throw new Error(\"PerSQL: executionToken has expired\");\n }\n return this.query(rec.sql, rec.params);\n }\n\n private gcProposals(): void {\n const now = Date.now();\n for (const [k, v] of this.proposals) {\n if (v.expiresAt < now) this.proposals.delete(k);\n }\n }\n\n close(): void {\n if (this.db) {\n try {\n this.db.close();\n } catch {\n // ignore\n }\n this.db = null;\n }\n }\n}\n\nfunction actionForSql(sql: string): \"read\" | \"write\" | \"admin\" {\n const head = sql.trim().slice(0, 24).toLowerCase();\n if (\n head.startsWith(\"create\") ||\n head.startsWith(\"drop\") ||\n head.startsWith(\"alter\")\n ) {\n return \"admin\";\n }\n if (\n head.startsWith(\"insert\") ||\n head.startsWith(\"update\") ||\n head.startsWith(\"delete\") ||\n head.startsWith(\"replace\")\n ) {\n return \"write\";\n }\n return \"read\";\n}\n\nfunction runOne(\n db: BetterSqliteDb,\n sql: string,\n params: unknown[]\n): RawQueryResult {\n const stmt = db.prepare(sql);\n if (stmt.reader) {\n const cols = stmt.columns().map((c) => c.name);\n const rows = stmt.raw(true).all(...params) as unknown[][];\n return { columns: cols, rows, rowsRead: rows.length, rowsWritten: 0 };\n }\n const info = stmt.run(...params);\n return {\n columns: [],\n rows: [],\n rowsRead: 0,\n rowsWritten: info.changes ?? 0,\n changes: info.changes ?? 0,\n lastInsertRowid: Number(info.lastInsertRowid ?? 0),\n };\n}\n","/**\n * @persql/sdk — Talk to your PerSQL databases from anywhere.\n *\n * @example\n * const persql = new PerSQL({ token: process.env.PERSQL_TOKEN! });\n * const db = persql.database(\"acme/orders\");\n * const rows = await db.query<{ id: number; email: string }>(\n * \"SELECT id, email FROM customers WHERE id = ?\",\n * [42]\n * );\n */\n\nimport { LocalDriver } from \"./local\";\nexport type { RawQueryResult } from \"./local\";\n\n/** Machine-readable category of a SQL failure, parsed from the engine's error message. */\nexport type SqlErrorKind =\n | \"unique_violation\"\n | \"not_null_violation\"\n | \"fk_violation\"\n | \"check_violation\"\n | \"unknown_table\"\n | \"unknown_column\"\n | \"syntax_error\"\n | \"type_mismatch\"\n | \"database_locked\"\n | \"too_many_params\"\n | \"readonly\"\n | \"unknown\";\n\n/**\n * Structured SQL error envelope — the failure kind plus the table,\n * column, constraint, and hint parsed from the engine message.\n * Available as `PerSQLError.detail` so callers can branch on\n * `detail.kind` instead of string-matching messages.\n */\nexport interface SqlErrorDetail {\n kind: SqlErrorKind;\n message: string;\n table?: string;\n column?: string;\n columns?: Array<{ table: string; column: string }>;\n constraint?: string;\n near?: string;\n hint?: string;\n}\n\n/** Constructor options for `PerSQL`. */\nexport interface PerSQLOptions {\n /** Bearer token. Get one at https://console.persql.com → Tokens. */\n token?: string;\n /** API base URL. Defaults to https://api.persql.com */\n baseURL?: string;\n /** Custom fetch implementation (defaults to global fetch). */\n fetch?: typeof fetch;\n /**\n * Run against a local SQLite file (via the `better-sqlite3` peer\n * dependency) instead of the HTTP API. Pass `\":memory:\"` for an\n * in-memory test database. When set, `token` is not required and\n * network features (`subscribe`) throw — they have no local\n * equivalent.\n *\n * ```ts\n * const persql = new PerSQL({ local: \":memory:\" });\n * const db = persql.database(\"test/db\");\n * await db.query(\"CREATE TABLE t (id INTEGER)\");\n * ```\n */\n local?: string;\n}\n\n/**\n * Result of a SQL statement — column names, positional rows, and the\n * same rows reshaped as objects (`data`).\n */\nexport interface QueryResult<T = Record<string, unknown>> {\n /** Column names in result-set order. */\n columns: string[];\n /** Rows as positional arrays (faster wire format). */\n rows: unknown[][];\n /** Rows reshaped as objects keyed by column name. */\n data: T[];\n rowsRead: number;\n rowsWritten: number;\n /**\n * SQLite `changes()` after a write statement — the exact affected-row\n * count ORMs expect (`rowsWritten` also counts index writes). Absent\n * on reads, DDL, and servers older than this field.\n */\n changes?: number;\n /** SQLite `last_insert_rowid()` after a write statement. Absent on reads and DDL. */\n lastInsertRowid?: number;\n /**\n * Per-call usage and cost the server echoes on `query()`. Undefined in\n * local mode (no server) and on the per-statement results of `batch()`\n * (a batch reports one aggregate meta, not one per statement).\n */\n meta?: QueryMeta;\n}\n\n/**\n * Usage and cost the server attaches to a query response. `costUsd` is\n * computed from the public rate card — the same numbers the spend report\n * uses. `snapshot` is set when the auto-snapshot pipeline took a labeled\n * bookmark before a destructive call.\n */\nexport interface QueryMeta {\n rowsRead: number;\n rowsWritten: number;\n durationMs: number;\n statementCount: number;\n costUsd: number;\n snapshot: { id: string; label: string } | null;\n queryLogId: string;\n}\n\n/** Options for `db.batch()` — transaction wrapping and idempotency / plan-replay keys. */\nexport interface BatchOptions {\n /** Wrap all statements in BEGIN/COMMIT. Rolls back on first error. */\n transaction?: boolean;\n /** Pass an Idempotency-Key for safe retries. */\n idempotencyKey?: string;\n /**\n * Multi-step plan idempotency. Pair `planKey` (stable across the\n * agent's plan) with `planStep` (stable per step). On retry, every\n * step that already succeeded replays from cache; failed and\n * never-reached steps re-run.\n */\n planKey?: string;\n planStep?: string;\n}\n\n/**\n * Metadata returned by `PerSQL.fromHandoff` describing what the\n * minted token can touch. The token itself is already wired into the\n * returned client; this is just the handoff's resource info so the\n * agent doesn't have to round-trip again to know its scope.\n */\nexport interface HandoffClaim {\n tokenId: string;\n databaseId: string;\n databaseSlug: string;\n namespaceSlug: string;\n branchRef: string | null;\n role: \"read\" | \"write\" | \"admin\";\n}\n\n/**\n * Engine telemetry row — one entry per /v1/query or /v1/batch call.\n * Returned by `db.queryLog()`. The same data is also exposed inside\n * the DO as `_persql_meta_query_log` so agents can SELECT/JOIN it\n * alongside their own tables.\n */\nexport interface QueryLogEntry {\n id: string;\n ts: number;\n sqlText: string;\n paramsJson: string | null;\n status: \"ok\" | \"error\";\n errorMessage: string | null;\n rowsRead: number;\n rowsWritten: number;\n durationMs: number;\n statementCount: number;\n tokenId: string | null;\n snapshotId: string | null;\n}\n\n/**\n * Output of `db.describe()`. Mirrors the schema graph with any\n * stored semantic docs folded in. Designed to be JSON-stringified\n * straight into an LLM prompt.\n */\nexport interface DescribeBundle {\n databaseDescription: string | null;\n tables: Array<{\n table: string;\n description: string;\n columns: Array<{\n name: string;\n type: string;\n pk: boolean;\n notNull: boolean;\n description: string;\n }>;\n foreignKeys: Array<{ from: string; toTable: string; toColumn: string }>;\n }>;\n}\n\n/** Output of `db.search(query)`. */\nexport interface SchemaSearchResponse {\n query: string;\n hits: Array<{\n kind: \"table\" | \"column\";\n table: string;\n column: string | null;\n description: string;\n score: number;\n }>;\n}\n\n/** Output of `db.doctor()`. */\nexport interface SchemaDoctorReport {\n findings: Array<{\n code: string;\n severity: \"info\" | \"warning\" | \"error\";\n table: string;\n column: string | null;\n message: string;\n suggestion: string;\n }>;\n tablesScanned: number;\n generatedAt: string;\n}\n\n/** Per-call options for `db.query()` — idempotency and plan-replay keys. */\nexport interface QueryOptions {\n idempotencyKey?: string;\n /** See `BatchOptions.planKey`. */\n planKey?: string;\n /** See `BatchOptions.planStep`. */\n planStep?: string;\n}\n\n/** One user table and its row count, as returned by `db.tables()`. */\nexport interface TableInfo {\n name: string;\n rowCount: number;\n}\n\n/**\n * Per-statement assertion attached to a `batch` entry. Evaluated\n * server-side inside the same transactionSync as the statement —\n * a violation throws, which rolls a transactional batch back. For\n * non-transactional batches, the rest of the batch does not run.\n *\n * Use this to write defensive multi-step writes without a follow-up\n * read: `UPDATE … WHERE id = ?` with `expect: { rowsWritten: 1 }`\n * fails fast if zero rows match.\n *\n * Shape mirrors `@persql/shared`'s `BatchExpect`. Inlined here so the\n * published npm package has no monorepo-only deps.\n */\nexport interface BatchExpect {\n /** Result has exactly this many rows. */\n rows?: number;\n rowsAtLeast?: number;\n rowsAtMost?: number;\n /** Statement wrote exactly this many rows. */\n rowsWritten?: number;\n rowsWrittenAtLeast?: number;\n rowsWrittenAtMost?: number;\n}\n\n/** One entry of a `db.batch()` call — SQL, positional params, and an optional server-side assertion. */\nexport interface Statement {\n sql: string;\n params?: unknown[];\n expect?: BatchExpect;\n}\n\n/**\n * Returned by `client.me()` — the bearer token's namespace, scope, and\n * current prepaid balance. Agents call this to learn what they're\n * allowed to touch and how much credit remains before the gate returns\n * 402.\n */\nexport interface WhoamiInfo {\n namespaceId: string;\n namespaceSlug: string;\n tokenId: string;\n role: \"admin\" | \"readwrite\" | \"readonly\";\n scopes: unknown[];\n tableScope: string[] | null;\n balanceUsdMicros: number | null;\n}\n\n/** Output of `db.sampleTable(...)`. */\nexport interface TableSample {\n table: string;\n rowCount: number;\n rows: Array<Record<string, unknown>>;\n columns: Array<{\n name: string;\n type: string;\n pk: boolean;\n notNull: boolean;\n nullCount: number;\n distinctCount: number;\n min: unknown;\n max: unknown;\n }>;\n}\n\n/** Output of `db.validate(...)`. */\nexport type ValidateResult =\n | { ok: true }\n | { ok: false; error: string; errorDetail?: SqlErrorDetail };\n\n/**\n * Thrown for any failed API call. `status` carries the HTTP status;\n * `detail` (set on /query and /batch failures) is the parsed SQL\n * error envelope.\n */\nexport class PerSQLError extends Error {\n status: number;\n // Set on /v1/query and /v1/batch failures with a parsed envelope\n // (kind, table, column, hint, etc.) so callers can branch on\n // `error.detail.kind` instead of string-matching the message.\n detail?: SqlErrorDetail;\n constructor(status: number, message: string, detail?: SqlErrorDetail) {\n super(message);\n this.name = \"PerSQLError\";\n this.status = status;\n this.detail = detail;\n }\n}\n\n/** Thrown on HTTP 429. `retryAfterSeconds` echoes the server's Retry-After header. */\nexport class RateLimitError extends PerSQLError {\n retryAfterSeconds: number;\n constructor(retryAfterSeconds: number, message = \"Rate limit exceeded\") {\n super(429, message);\n this.name = \"RateLimitError\";\n this.retryAfterSeconds = retryAfterSeconds;\n }\n}\n\n/** One approval rule a blocked write matched — which glob hit which table, and whether it requires approval or denies outright. */\nexport interface ApprovalRuleHit {\n ruleId: string;\n tableGlob: string;\n action: \"require_approval\" | \"deny\";\n matchedTable: string;\n note: string | null;\n}\n\n/**\n * Thrown when a write hits an approval rule. The agent can either\n * stop and surface `approvalUrl` to a human, or poll\n * `db.approvals.poll(approvalToken)` until a member decides; once\n * approved, redeem with `db.approvals.redeem(approvalToken)`.\n */\nexport class ApprovalRequiredError extends PerSQLError {\n approvalToken: string;\n approvalUrl: string;\n hits: ApprovalRuleHit[];\n expiresAt: string;\n constructor(opts: {\n message: string;\n approvalToken: string;\n approvalUrl: string;\n hits: ApprovalRuleHit[];\n expiresAt: string;\n }) {\n super(403, opts.message);\n this.name = \"ApprovalRequiredError\";\n this.approvalToken = opts.approvalToken;\n this.approvalUrl = opts.approvalUrl;\n this.hits = opts.hits;\n this.expiresAt = opts.expiresAt;\n }\n}\n\n/**\n * Entry point of the SDK. Construct with a bearer token — or with\n * `{ local: \":memory:\" }` for an in-process SQLite test database —\n * then call `database()` for a handle to query.\n *\n * ```ts\n * const persql = new PerSQL({ token: process.env.PERSQL_TOKEN! });\n * const db = persql.database(\"acme/orders\");\n * ```\n */\nexport class PerSQL {\n /** @internal — exposed read-only so PerSQLDatabase can build URLs. */\n readonly token: string;\n /** @internal — same. */\n readonly baseURL: string;\n /** @internal — set when running in local mode. */\n readonly local: LocalDriver | null;\n private readonly _fetch: typeof fetch;\n\n constructor(opts: PerSQLOptions) {\n if (opts.local) {\n this.local = new LocalDriver(opts.local);\n this.token = \"\";\n this.baseURL = \"\";\n this._fetch = opts.fetch ?? (globalThis.fetch?.bind(globalThis) as typeof fetch);\n return;\n }\n if (!opts.token) {\n throw new Error(\n 'PerSQL: token is required (or pass { local: \":memory:\" } for tests)'\n );\n }\n this.local = null;\n this.token = opts.token;\n this.baseURL = (opts.baseURL ?? \"https://api.persql.com\").replace(/\\/$/, \"\");\n this._fetch = opts.fetch ?? globalThis.fetch.bind(globalThis);\n }\n\n /** Close the local SQLite connection (no-op in HTTP mode). */\n close(): void {\n this.local?.close();\n }\n\n /**\n * Resolve the bearer token's namespace + live usage. Use this once\n * per agent run so you know the slug to put in URLs and how much\n * monthly budget / prepaid balance remains before a 402.\n *\n * Throws in local mode — no server, nothing to ask.\n */\n async me(): Promise<WhoamiInfo> {\n if (this.local) {\n throw new Error(\"PerSQL: me() is not available in local mode.\");\n }\n return this.request<WhoamiInfo>(\"GET\", \"/v1/me\");\n }\n\n /**\n * Redeem a handoff token (`phand_…`) for a regular PerSQL client\n * scoped to the handed-off (database, branch, role). Single use:\n * the handoff token is consumed by the call.\n *\n * Common pattern — agent A pins a branch and hands the token to\n * agent B; agent B does:\n *\n * const persql = await PerSQL.fromHandoff(handoffToken);\n * const db = persql.database(persql.handedOff!.namespaceSlug, persql.handedOff!.databaseSlug);\n */\n static async fromHandoff(\n handoffToken: string,\n opts: {\n baseURL?: string;\n name?: string;\n fetch?: typeof fetch;\n } = {}\n ): Promise<PerSQL & { handedOff: HandoffClaim }> {\n const baseURL = (opts.baseURL ?? \"https://api.persql.com\").replace(/\\/$/, \"\");\n const fetcher = opts.fetch ?? globalThis.fetch.bind(globalThis);\n const res = await fetcher(`${baseURL}/v1/handoff/claim`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token: handoffToken, name: opts.name }),\n });\n type Envelope = {\n success: boolean;\n data?: HandoffClaim & { plaintext: string };\n error?: string;\n };\n const envelope = (await res.json().catch(() => null)) as Envelope | null;\n if (!res.ok || !envelope?.success || !envelope.data) {\n throw new PerSQLError(\n res.status,\n envelope?.error ?? `Handoff claim failed (${res.status})`\n );\n }\n const { plaintext, ...handedOff } = envelope.data;\n const client = new PerSQL({ token: plaintext, baseURL, fetch: opts.fetch });\n return Object.assign(client, { handedOff });\n }\n\n /**\n * Reference a database by its `<namespace>/<slug>` path.\n * Both forms work: `db(\"acme/orders\")` or `db(\"acme\", \"orders\")`.\n */\n database(path: string): PerSQLDatabase;\n database(namespace: string, slug: string): PerSQLDatabase;\n database(a: string, b?: string): PerSQLDatabase {\n if (b !== undefined) return new PerSQLDatabase(this, a, b);\n const [ns, slug] = a.split(\"/\");\n if (!ns || !slug) {\n throw new Error('PerSQL: database path must be \"<namespace>/<slug>\"');\n }\n return new PerSQLDatabase(this, ns, slug);\n }\n\n /**\n * Provision and list databases in the token's namespace. `create`\n * needs an unscoped admin token; `database()` then gives you a handle\n * to query the result.\n */\n get databases(): PerSQLDatabases {\n return new PerSQLDatabases(this);\n }\n\n /** @internal */\n async request<T>(\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n body?: unknown,\n headers?: Record<string, string>\n ): Promise<T> {\n return (await this.requestWithMeta<T>(method, path, body, headers)).data;\n }\n\n /**\n * @internal — like `request`, but also surfaces the response `meta`\n * envelope (usage + `costUsd`) that the data-only `request` drops.\n */\n async requestWithMeta<T>(\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n body?: unknown,\n headers?: Record<string, string>\n ): Promise<{ data: T; meta?: QueryMeta }> {\n const res = await this._fetch(`${this.baseURL}${path}`, {\n method,\n headers: {\n Authorization: `Bearer ${this.token}`,\n \"Content-Type\": \"application/json\",\n ...(headers ?? {}),\n },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n\n if (res.status === 429) {\n const retryAfter = Number(res.headers.get(\"retry-after\") ?? \"60\");\n throw new RateLimitError(retryAfter);\n }\n\n type Envelope = {\n success: boolean;\n data?: T;\n meta?: QueryMeta;\n error?: string;\n errorDetail?: SqlErrorDetail;\n approvalToken?: string;\n approvalUrl?: string;\n hits?: ApprovalRuleHit[];\n expiresAt?: string;\n };\n let envelope: Envelope | null = null;\n try {\n envelope = (await res.json()) as Envelope;\n } catch {\n // empty body\n }\n\n if (!res.ok || !envelope?.success) {\n const message = envelope?.error ?? `Request failed (${res.status})`;\n if (\n res.status === 403 &&\n envelope?.approvalToken &&\n envelope?.approvalUrl &&\n envelope?.expiresAt\n ) {\n throw new ApprovalRequiredError({\n message,\n approvalToken: envelope.approvalToken,\n approvalUrl: envelope.approvalUrl,\n hits: envelope.hits ?? [],\n expiresAt: envelope.expiresAt,\n });\n }\n throw new PerSQLError(res.status, message, envelope?.errorDetail);\n }\n return { data: envelope.data as T, meta: envelope.meta };\n }\n\n /** @internal — raw fetch returning the underlying Response. */\n fetchRaw(method: \"GET\", path: string): Promise<Response> {\n return this._fetch(`${this.baseURL}${path}`, {\n method,\n headers: { Authorization: `Bearer ${this.token}` },\n });\n }\n\n /**\n * File a support ticket directly from your SDK code. Tickets land in\n * the customer console at `/support`; staff reply from the admin\n * app. Useful for agents and background jobs that hit a PerSQL\n * error and want a human to see it.\n *\n * ```ts\n * try {\n * await db.query(\"UPDATE ...\");\n * } catch (err) {\n * await persql.support.createTicket({\n * subject: \"Branch merge keeps 500ing\",\n * body: \"Repro: ...\",\n * error: err,\n * });\n * }\n * ```\n */\n get support(): SupportClient {\n return new SupportClient(this);\n }\n}\n\n/** Input for `persql.support.createTicket()`. */\nexport interface CreateSupportTicketOptions {\n subject: string;\n body: string;\n /** Optional error to attach for triage (PerSQLError or any throwable). */\n error?: unknown;\n /** Caller-supplied extras merged into the ticket's diagnostic context. */\n errorContext?: Record<string, unknown>;\n}\n\nfunction errorContextFor(err: unknown): Record<string, unknown> {\n if (err instanceof PerSQLError) {\n return {\n errorName: err.name,\n errorMessage: err.message,\n status: err.status,\n detail: err.detail ?? null,\n };\n }\n if (err instanceof Error) {\n return { errorName: err.name, errorMessage: err.message };\n }\n if (err !== undefined && err !== null) {\n return { errorMessage: String(err) };\n }\n return {};\n}\n\n/** Files support tickets from SDK code. Reached via `persql.support`. */\nexport class SupportClient {\n constructor(private readonly client: PerSQL) {}\n\n async createTicket(\n opts: CreateSupportTicketOptions\n ): Promise<{ id: string }> {\n if (this.client.local) {\n throw new Error(\"support.createTicket is not supported in local mode\");\n }\n const errorContext: Record<string, unknown> = {\n ...errorContextFor(opts.error),\n ...(opts.errorContext ?? {}),\n };\n return this.client.request<{ id: string }>(\n \"POST\",\n \"/v1/support/tickets\",\n {\n subject: opts.subject,\n body: opts.body,\n errorContext:\n Object.keys(errorContext).length > 0 ? errorContext : undefined,\n }\n );\n }\n}\n\n/** Database metadata as returned by `persql.databases.create()` and `list()`. */\nexport interface DatabaseInfo {\n id: string;\n namespaceId: string;\n slug: string;\n name: string;\n status: string;\n region: string;\n forkedFromId: string | null;\n forkedAt: string | null;\n expiresAt: string | null;\n branchRef: string | null;\n createdAt: string;\n updatedAt: string;\n}\n\n/** Input for `persql.databases.create()`. */\nexport interface CreateDatabaseOptions {\n /** Display name, 1-50 chars. */\n name: string;\n /** URL slug; derived from `name` when omitted. */\n slug?: string;\n /** Region hint: auto, wnam, enam, weur, eeur, apac. Default: auto. */\n region?: string;\n /** Auto-delete after N days (1..30). Null/undefined = keep until deleted. */\n ttlDays?: number | null;\n}\n\n/**\n * Namespace-level database management. Reached via `persql.databases`.\n * Both calls require a server-mode (non-local) client.\n */\nexport class PerSQLDatabases {\n constructor(private readonly client: PerSQL) {}\n\n /**\n * Provision a new isolated database and return its metadata. Requires\n * an unscoped admin token (scoped tokens can't create databases).\n */\n async create(opts: CreateDatabaseOptions): Promise<DatabaseInfo> {\n if (this.client.local) {\n throw new Error(\n \"PerSQL: databases.create() needs a server-mode token. Pass a real token to `new PerSQL({ token })` to provision databases.\"\n );\n }\n return this.client.request<DatabaseInfo>(\"POST\", \"/v1/databases\", {\n name: opts.name,\n slug: opts.slug,\n region: opts.region,\n ttlDays: opts.ttlDays,\n });\n }\n\n /** List databases in the token's namespace, newest first (paginated). */\n async list(\n opts: { cursor?: string; pageSize?: number } = {}\n ): Promise<{ data: DatabaseInfo[]; nextCursor: string | null }> {\n if (this.client.local) {\n throw new Error(\"PerSQL: databases.list() needs a server-mode token.\");\n }\n const qs = new URLSearchParams();\n if (opts.cursor) qs.set(\"cursor\", opts.cursor);\n if (opts.pageSize) qs.set(\"pageSize\", String(opts.pageSize));\n const tail = qs.toString() ? `?${qs.toString()}` : \"\";\n const res = await this.client.fetchRaw(\"GET\", `/v1/databases${tail}`);\n const body = (await res.json()) as {\n success: boolean;\n data?: DatabaseInfo[];\n error?: string;\n nextCursor?: string | null;\n };\n if (!res.ok || !body.success) {\n throw new PerSQLError(res.status, body.error ?? `Request failed (${res.status})`);\n }\n return { data: body.data ?? [], nextCursor: body.nextCursor ?? null };\n }\n}\n\n/**\n * Handle to one database, addressed as `<namespace>/<slug>`. Obtained\n * via `persql.database(...)`; all query, schema, branch, approval, and\n * tool helpers live here.\n */\nexport class PerSQLDatabase {\n constructor(\n private readonly client: PerSQL,\n public readonly namespace: string,\n public readonly slug: string\n ) {}\n\n /** Run a single SQL statement. */\n async query<T = Record<string, unknown>>(\n sql: string,\n params: unknown[] = [],\n options: QueryOptions = {}\n ): Promise<QueryResult<T>> {\n if (this.client.local) {\n const raw = await this.client.local.query(sql, params);\n return { ...raw, data: rowsToObjects<T>(raw.columns, raw.rows) };\n }\n const headers: Record<string, string> = {};\n if (options.idempotencyKey) headers[\"Idempotency-Key\"] = options.idempotencyKey;\n if (options.planKey) headers[\"Plan-Key\"] = options.planKey;\n if (options.planStep) headers[\"Plan-Step\"] = options.planStep;\n const { data: raw, meta } = await this.client.requestWithMeta<{\n columns: string[];\n rows: unknown[][];\n rowsRead: number;\n rowsWritten: number;\n }>(\n \"POST\",\n `/v1/db/${this.namespace}/${this.slug}/query`,\n { sql, params },\n headers\n );\n return {\n ...raw,\n data: rowsToObjects<T>(raw.columns, raw.rows),\n meta,\n };\n }\n\n /** Run multiple statements in one round-trip, optionally in a transaction. */\n async batch<T = Record<string, unknown>>(\n statements: Statement[],\n options: BatchOptions = {}\n ): Promise<QueryResult<T>[]> {\n if (this.client.local) {\n const raw = await this.client.local.batch(\n statements,\n options.transaction ?? false\n );\n return raw.map((r) => ({ ...r, data: rowsToObjects<T>(r.columns, r.rows) }));\n }\n const headers: Record<string, string> = {};\n if (options.idempotencyKey) headers[\"Idempotency-Key\"] = options.idempotencyKey;\n if (options.planKey) headers[\"Plan-Key\"] = options.planKey;\n if (options.planStep) headers[\"Plan-Step\"] = options.planStep;\n const raw = await this.client.request<\n Array<{\n columns: string[];\n rows: unknown[][];\n rowsRead: number;\n rowsWritten: number;\n }>\n >(\n \"POST\",\n `/v1/db/${this.namespace}/${this.slug}/batch`,\n { statements, transaction: options.transaction ?? false },\n headers\n );\n return raw.map((r) => ({ ...r, data: rowsToObjects<T>(r.columns, r.rows) }));\n }\n\n /** Convenience for a transactional batch. */\n transaction<T = Record<string, unknown>>(\n statements: Statement[],\n options: Omit<BatchOptions, \"transaction\"> = {}\n ): Promise<QueryResult<T>[]> {\n return this.batch<T>(statements, { ...options, transaction: true });\n }\n\n /**\n * Mint a short-lived session JWT for an end user. The server (which\n * holds the bearer token) calls this and hands the resulting token\n * to an untrusted client (browser, mobile app, agent run). The\n * client uses the JWT to call this database's published `/p/*`\n * endpoints on behalf of `userId`. TTL defaults to 1 hour; max 24h.\n */\n async createSession(opts: {\n userId: string;\n email?: string;\n expiresIn?: number;\n }): Promise<{ token: string; expiresAt: string; expiresIn: number }> {\n if (this.client.local) {\n throw new Error(\"createSession is not supported in local mode\");\n }\n return this.client.request<{\n token: string;\n expiresAt: string;\n expiresIn: number;\n }>(\"POST\", \"/v1/sessions\", {\n namespaceSlug: this.namespace,\n databaseSlug: this.slug,\n userId: opts.userId,\n email: opts.email,\n expiresIn: opts.expiresIn,\n });\n }\n\n /**\n * Engine telemetry — recent /v1/query and /v1/batch calls issued\n * against this database. Backed by the in-DO `_persql_meta_query_log`\n * table; 7-day retention. Useful for agents that need to replay\n * what they (or another agent) did, audit cost, or stream a live\n * tail via `db.subscribe`.\n */\n async queryLog(opts: {\n since?: string | Date;\n until?: string | Date;\n tokenId?: string;\n status?: \"ok\" | \"error\";\n cursor?: string;\n pageSize?: number;\n } = {}): Promise<{\n data: QueryLogEntry[];\n nextCursor: string | null;\n }> {\n if (this.client.local) {\n throw new Error(\"PerSQL: queryLog is not available in local mode.\");\n }\n const qs = new URLSearchParams();\n if (opts.since) {\n qs.set(\n \"since\",\n typeof opts.since === \"string\" ? opts.since : opts.since.toISOString()\n );\n }\n if (opts.until) {\n qs.set(\n \"until\",\n typeof opts.until === \"string\" ? opts.until : opts.until.toISOString()\n );\n }\n if (opts.tokenId) qs.set(\"tokenId\", opts.tokenId);\n if (opts.status) qs.set(\"status\", opts.status);\n if (opts.cursor) qs.set(\"cursor\", opts.cursor);\n if (opts.pageSize) qs.set(\"pageSize\", String(opts.pageSize));\n const tail = qs.toString() ? `?${qs.toString()}` : \"\";\n const res = await this.client.fetchRaw(\n \"GET\",\n `/v1/db/${this.namespace}/${this.slug}/queries${tail}`\n );\n const body = (await res.json()) as {\n success: boolean;\n data?: QueryLogEntry[];\n error?: string;\n nextCursor?: string | null;\n };\n if (!res.ok || !body.success) {\n throw new PerSQLError(res.status, body.error ?? `Request failed (${res.status})`);\n }\n return { data: body.data ?? [], nextCursor: body.nextCursor ?? null };\n }\n\n /**\n * Returns a structured description of the database — columns, FK\n * graph, and any human-/AI-authored docs persisted via\n * `db.describe(...)`. The shape is designed for direct injection\n * into an LLM prompt: one round-trip and the agent has everything\n * it needs to write correct SQL.\n */\n async describe(): Promise<DescribeBundle> {\n if (this.client.local) {\n throw new Error(\n \"PerSQL: describe is not available in local mode (yet).\"\n );\n }\n return this.client.request<DescribeBundle>(\n \"GET\",\n `/v1/db/${this.namespace}/${this.slug}/describe`\n );\n }\n\n /**\n * Persist semantic descriptions for the database / tables / columns.\n * Pass any subset — only the fields you set are updated. Requires\n * an admin-role token because docs change how every other client\n * (and every agent) interprets the schema.\n */\n async setDescription(input: {\n databaseDescription?: string;\n tables?: Array<{\n table: string;\n description?: string;\n columns?: Array<{ column: string; description: string }>;\n }>;\n }): Promise<DescribeBundle> {\n if (this.client.local) {\n throw new Error(\"PerSQL: setDescription is not available in local mode.\");\n }\n return this.client.request<DescribeBundle>(\n \"PUT\",\n `/v1/db/${this.namespace}/${this.slug}/describe`,\n input\n );\n }\n\n /**\n * Natural-language ranked search across table names, column names,\n * and any descriptions you've stored via `setDescription`. Use this\n * before writing SQL when you don't know the schema cold — one call\n * narrows a 200-table DB down to the handful that match the intent.\n */\n async search(query: string, opts: { limit?: number } = {}): Promise<SchemaSearchResponse> {\n if (this.client.local) {\n throw new Error(\"PerSQL: search is not available in local mode.\");\n }\n const qs = new URLSearchParams({ q: query });\n if (opts.limit) qs.set(\"limit\", String(opts.limit));\n return this.client.request<SchemaSearchResponse>(\n \"GET\",\n `/v1/db/${this.namespace}/${this.slug}/search?${qs.toString()}`\n );\n }\n\n /**\n * Lints the schema for issues that hurt LLM consumption: missing\n * primary keys, ambiguous column names (\"data\", \"value\"), unindexed\n * foreign keys, etc. Pure read-only analysis — emits suggestions\n * for the agent to act on, never modifies the schema itself.\n */\n async doctor(): Promise<SchemaDoctorReport> {\n if (this.client.local) {\n throw new Error(\"PerSQL: doctor is not available in local mode.\");\n }\n return this.client.request<SchemaDoctorReport>(\n \"GET\",\n `/v1/db/${this.namespace}/${this.slug}/doctor`\n );\n }\n\n /** List user-defined tables in this database. */\n async tables(): Promise<TableInfo[]> {\n if (this.client.local) return this.client.local.tables();\n return this.client.request<TableInfo[]>(\n \"GET\",\n `/v1/db/${this.namespace}/${this.slug}/tables`\n );\n }\n\n /**\n * Returns SQLite's `EXPLAIN QUERY PLAN` output for the given SQL.\n * Read-only — does not execute the statement.\n */\n async explain(\n sql: string,\n params: unknown[] = []\n ): Promise<Array<{ id: number; parent: number; detail: string }>> {\n if (this.client.local) return this.client.local.explain(sql, params);\n return this.client.request<\n Array<{ id: number; parent: number; detail: string }>\n >(\"POST\", `/v1/db/${this.namespace}/${this.slug}/explain`, { sql, params });\n }\n\n /**\n * Parse + bind-check a SQL statement without executing it. Faster\n * and cheaper than running the query just to catch unknown columns\n * or wrong param counts.\n *\n * Returns `{ ok: true }` on success or `{ ok: false, error, errorDetail }`\n * with the same `errorDetail` envelope as `PerSQLError.detail`.\n */\n async validate(sql: string, params: unknown[] = []): Promise<ValidateResult> {\n if (this.client.local) {\n throw new Error(\"PerSQL: validate is not available in local mode.\");\n }\n const data = await this.client.request<\n | { ok: true }\n | { ok: false; error: string }\n >(\n \"POST\",\n `/v1/db/${this.namespace}/${this.slug}/validate`,\n { sql, params }\n );\n return data as ValidateResult;\n }\n\n /**\n * Compact text rendering of the database's schema — one line per\n * table with columns, types, PKs, and FK arrows inlined. Designed\n * to stuff into an LLM prompt with minimum token overhead. See\n * `db.describe()` for the structured form.\n */\n async describeCompact(): Promise<string> {\n if (this.client.local) {\n throw new Error(\"PerSQL: describeCompact is not available in local mode.\");\n }\n const data = await this.client.request<{ text: string }>(\n \"GET\",\n `/v1/db/${this.namespace}/${this.slug}/describe?format=compact`\n );\n return data.text;\n }\n\n /**\n * First N rows of a table plus per-column stats (null count,\n * distinct count, min, max). One call to size up an unfamiliar\n * table — replaces a hand-rolled `SELECT *`, `COUNT(*)`, and\n * `PRAGMA table_info` sequence.\n *\n * `n` defaults to 10 and is capped at 100.\n */\n async sampleTable(\n table: string,\n opts: { n?: number } = {}\n ): Promise<TableSample> {\n if (this.client.local) {\n throw new Error(\"PerSQL: sampleTable is not available in local mode.\");\n }\n const qs = opts.n ? `?n=${Math.max(1, Math.min(100, opts.n | 0))}` : \"\";\n return this.client.request<TableSample>(\n \"GET\",\n `/v1/db/${this.namespace}/${this.slug}/tables/${encodeURIComponent(\n table\n )}/sample${qs}`\n );\n }\n\n /**\n * Introspect the database schema. Returns one entry per user table\n * with column definitions, suitable for codegen tools (the\n * `persql-codegen` CLI uses this to emit Drizzle schema files).\n */\n async schema(): Promise<DatabaseSchema> {\n const tables = await this.tables();\n const out: DatabaseSchema = { tables: [] };\n for (const t of tables) {\n const r = await this.query<{\n cid: number;\n name: string;\n type: string;\n notnull: number;\n dflt_value: unknown;\n pk: number;\n }>(`PRAGMA table_info(\"${t.name.replace(/\"/g, '\"\"')}\")`);\n out.tables.push({\n name: t.name,\n columns: r.data.map((c) => ({\n name: c.name,\n type: c.type,\n notNull: !!c.notnull,\n primaryKey: !!c.pk,\n default: c.dflt_value === null ? null : String(c.dflt_value),\n })),\n });\n }\n return out;\n }\n\n /**\n * Manage preview/PR-style branches of this database. Each branch is\n * its own DO with its own SQLite file; create-or-reset by ref is\n * idempotent (PUT semantics) so CI pipelines can call it on every\n * build. Requires an admin-role bearer token for create / delete /\n * merge; list is open to any role.\n */\n get branches(): PerSQLBranches {\n if (this.client.local) {\n throw new Error(\n \"PerSQL: branches model fork-by-Durable-Object — not available in local mode. Use a server-mode token to call branches.upsert/claim/merge, or stub branch isolation in tests by spinning up multiple `new PerSQL({ local: ':memory:' })` instances.\"\n );\n }\n return new PerSQLBranches(this.client, this.namespace, this.slug);\n }\n\n /**\n * Redeem an approval that was minted when a write hit a\n * `require_approval` rule. Throws `ApprovalRequiredError` until a\n * namespace member decides; on approve, runs the original SQL.\n */\n get approvals(): PerSQLApprovals {\n if (this.client.local) {\n throw new Error(\n \"PerSQL: approvals require a server-side approval gate — not available in local mode. Local mode runs every statement immediately; use a server-mode token if you need the require_approval rule.\"\n );\n }\n return new PerSQLApprovals(this.client, this.namespace, this.slug);\n }\n\n /**\n * Manage the require_approval / deny rules for this database. Reads\n * are open to any bearer with read access; create + delete require\n * an admin-role bearer token.\n */\n get approvalRules(): PerSQLApprovalRules {\n if (this.client.local) {\n throw new Error(\n \"PerSQL: approval rules live on the server; local mode does not enforce them.\"\n );\n }\n return new PerSQLApprovalRules(this.client, this.namespace, this.slug);\n }\n\n /**\n * Pre-flight a write before running it. `propose()` validates the\n * SQL via EXPLAIN, estimates affected rows, and returns a single-use\n * `executionToken` to redeem with `apply()`. Use this when an agent\n * (or its parent / a human) should review a mutation before it runs.\n * Works in both HTTP and local modes — local mode keeps the\n * executionToken in-process.\n */\n get proposals(): PerSQLProposals {\n return new PerSQLProposals(this.client, this.namespace, this.slug);\n }\n\n /**\n * Subscribe to row-changes via WebSocket — the SQL equivalent of\n * Postgres `LISTEN`. The callback fires once per write that\n * matches the table filter. Returns an `unsubscribe` function;\n * call it to close the socket.\n *\n * ```ts\n * const off = db.subscribe({\n * tables: [\"orders\"],\n * onChange: (e) => console.log(e.kind, e.table),\n * });\n * // …later\n * off();\n * ```\n *\n * Authentication uses the `persql.bearer.<token>` sub-protocol so\n * the token doesn't leak via URL logs. In environments without\n * sub-protocol support (some serverless WebSocket clients), the\n * fallback `?token=` query string is also accepted by the\n * server.\n */\n subscribe(options: SubscribeOptions): () => void {\n if (this.client.local) {\n throw new Error(\n \"PerSQL: subscribe requires the DO's WebSocket fan-out — not available in local mode. Use a server-mode token to call subscribe().\"\n );\n }\n const baseHttp = this.client.baseURL;\n const wsBase = baseHttp.replace(/^http/, \"ws\");\n const tablesParam =\n options.tables && options.tables.length > 0\n ? `?tables=${encodeURIComponent(options.tables.join(\",\"))}`\n : \"\";\n const url = `${wsBase}/v1/db/${this.namespace}/${this.slug}/subscribe${tablesParam}`;\n const ws = new WebSocket(url, [`persql.bearer.${this.client.token}`]);\n let closed = false;\n ws.addEventListener(\"message\", (ev) => {\n try {\n const msg = JSON.parse(String((ev as MessageEvent).data)) as {\n type: string;\n table?: string;\n kind?: SubscribeChangeKind;\n message?: string;\n tables?: string[] | \"*\";\n };\n if (msg.type === \"change\" && msg.table && msg.kind) {\n options.onChange({ table: msg.table, kind: msg.kind });\n } else if (msg.type === \"error\") {\n options.onError?.(new Error(msg.message ?? \"Subscription error\"));\n } else if (msg.type === \"subscribed\") {\n options.onReady?.(msg.tables ?? \"*\");\n }\n } catch {\n // ignore malformed frame\n }\n });\n ws.addEventListener(\"error\", () => {\n options.onError?.(new Error(\"WebSocket error\"));\n });\n ws.addEventListener(\"close\", () => {\n if (!closed) options.onClose?.();\n });\n return () => {\n closed = true;\n try {\n ws.close();\n } catch {\n // ignore\n }\n };\n }\n\n /**\n * Long-poll for row-changes on this database. Returns immediately\n * if changes newer than `since` are already buffered; otherwise\n * blocks server-side for up to `waitMs` (default 25s, max 25s).\n *\n * Most callers want `changes()` instead — an async iterator that\n * loops `waitForChanges` forever, surfacing each batch as it\n * arrives.\n */\n async waitForChanges(opts: {\n since?: number;\n waitMs?: number;\n tables?: string[];\n } = {}): Promise<{\n changes: Array<{ seq: number; ts: number; table: string; kind: SubscribeChangeKind }>;\n cursor: number;\n restarted: boolean;\n }> {\n if (this.client.local) {\n throw new Error(\n \"PerSQL: waitForChanges requires the DO change ring — not available in local mode.\"\n );\n }\n const qs = new URLSearchParams();\n if (typeof opts.since === \"number\") qs.set(\"since\", String(opts.since));\n if (typeof opts.waitMs === \"number\") qs.set(\"waitMs\", String(opts.waitMs));\n if (opts.tables && opts.tables.length > 0) qs.set(\"tables\", opts.tables.join(\",\"));\n const q = qs.toString();\n return this.client.request(\n \"GET\",\n `/v1/db/${this.namespace}/${this.slug}/changes${q ? `?${q}` : \"\"}`\n );\n }\n\n /**\n * Async-iterator change feed. Loops `waitForChanges` forever and\n * yields one batch per server response. Pass an `AbortSignal` to\n * stop the loop cleanly.\n *\n * ```ts\n * const ctl = new AbortController();\n * for await (const batch of db.changes({ signal: ctl.signal })) {\n * for (const c of batch.changes) console.log(c.kind, c.table);\n * }\n * ```\n */\n async *changes(opts: {\n since?: number;\n tables?: string[];\n waitMs?: number;\n signal?: AbortSignal;\n } = {}): AsyncGenerator<{\n changes: Array<{ seq: number; ts: number; table: string; kind: SubscribeChangeKind }>;\n cursor: number;\n restarted: boolean;\n }> {\n let cursor = opts.since ?? 0;\n while (!opts.signal?.aborted) {\n const batch = await this.waitForChanges({\n since: cursor,\n waitMs: opts.waitMs,\n tables: opts.tables,\n });\n cursor = batch.cursor;\n yield batch;\n }\n }\n\n /**\n * Returns the callback shape `drizzle-orm/sqlite-proxy` expects.\n * Pair with `drizzle()` from that module to get a typed,\n * fluent ORM client over the PerSQL HTTP API:\n *\n * ```ts\n * import { drizzle } from \"drizzle-orm/sqlite-proxy\";\n * import { PerSQL } from \"@persql/sdk\";\n *\n * const persql = new PerSQL({ token });\n * const db = drizzle(persql.database(\"acme/orders\").driver());\n * ```\n *\n * Drizzle's `prepare` interface maps onto our `query` /\n * `batch`; `method` tells us how to shape the rows.\n */\n driver(): SqliteProxyDriver {\n const callback: SqliteProxyDriver = async (sql, params, method) => {\n const result = await this.query(sql, params ?? []);\n // Drizzle's `get` and `values` expect a tuple of column values\n // (rows[0]); `all` and `run` expect an array of tuples.\n if (method === \"values\" || method === \"get\") {\n return { rows: result.rows[0] ?? [] };\n }\n return { rows: result.rows };\n };\n return callback;\n }\n\n /**\n * Returns a single SQL-query tool definition in every shape PerSQL\n * supports (Anthropic, OpenAI Chat, Vercel AI SDK, Mastra, LangChain,\n * OpenAI Agents SDK). Same input contract as `asTools()` — the only\n * difference is one fat `query` tool instead of typed-per-table tools.\n *\n * Pair the format-specific fields with `runTool` (or use the bundled\n * `execute`/`invoke` callbacks, which call `runTool` internally).\n */\n asTool(name = \"persql_query\"): SingleToolBundle {\n const description = `Run a SQL query against the PerSQL database \"${this.namespace}/${this.slug}\". A single result is capped at 100,000 rows and the query errors above that — add a LIMIT for large tables. Use parameter binding (?) to avoid injection.`;\n const inputSchema = {\n type: \"object\",\n properties: {\n sql: { type: \"string\", description: \"SQLite SQL statement\" },\n params: {\n type: \"array\",\n items: {},\n description: \"Positional parameters for the SQL statement\",\n },\n },\n required: [\"sql\"],\n // OpenAI strict function-calling rejects a schema without this; the\n // per-table asTools() schemas already set it. Keep them consistent.\n additionalProperties: false,\n } as const;\n const execute = (input: Record<string, unknown>) =>\n this.runTool({\n sql: String(input.sql ?? \"\"),\n params: Array.isArray(input.params) ? (input.params as unknown[]) : [],\n });\n return {\n anthropic: { name, description, input_schema: inputSchema },\n openai: {\n type: \"function\" as const,\n function: { name, description, parameters: inputSchema },\n },\n aiSdk: () => ({\n [name]: { description, inputSchema, execute },\n }),\n mastra: () => ({\n [name]: {\n id: name,\n description,\n inputSchema,\n execute: ({ context }) => execute(context),\n },\n }),\n langchain: () => [\n { name, description, schema: inputSchema, invoke: execute },\n ],\n openaiAgents: () => [\n {\n type: \"function\" as const,\n name,\n description,\n parameters: inputSchema,\n invoke: execute,\n },\n ],\n };\n }\n\n /**\n * Executes a tool-call payload returned from the model. Pair with `asTool`.\n */\n runTool(input: { sql: string; params?: unknown[] }): Promise<QueryResult> {\n return this.query(input.sql, input.params ?? []);\n }\n\n /**\n * Generate a *bundle* of typed tools — one per table — instead of one\n * generic `query` tool. Agents perform dramatically better with narrow\n * typed surfaces than they do with one fat SQL function. Each table\n * gets:\n * - `select_<table>(where?, limit?, orderBy?)` — typed column filter\n * - `count_<table>(where?)` — quick row count\n * - `describe_<table>()` — columns, row count, foreign keys\n * Plus a fallback `sql_query(sql, params)` for anything the typed\n * tools can't express.\n *\n * The returned `run(name, input)` dispatcher executes whichever tool\n * the model invoked. Format the tools for the LLM via the\n * `anthropic` or `openai` arrays (matches the shapes of `asTool`).\n *\n * ```ts\n * const tools = await db.asTools();\n * const reply = await anthropic.messages.create({\n * model: \"claude-opus-4-7\",\n * tools: tools.anthropic,\n * messages: [...],\n * });\n * for (const block of reply.content) {\n * if (block.type === \"tool_use\") {\n * const result = await tools.run(block.name, block.input);\n * }\n * }\n * ```\n */\n async asTools(): Promise<DatabaseToolBundle> {\n const schema = await this.schema();\n const anthropic: AnthropicTool[] = [];\n const openai: OpenAiTool[] = [];\n\n for (const t of schema.tables) {\n const safe = sanitizeToolPart(t.name);\n const columnList = t.columns\n .map((c) => `${c.name} ${c.type}${c.notNull ? \" NOT NULL\" : \"\"}${c.primaryKey ? \" PRIMARY KEY\" : \"\"}`)\n .join(\", \");\n const whereProps: Record<string, { type: string[]; description?: string }> = {};\n for (const c of t.columns) {\n whereProps[c.name] = {\n type: [\"string\", \"number\", \"boolean\", \"null\"],\n description: `Equality filter on ${t.name}.${c.name} (${c.type})`,\n };\n }\n\n const selectName = `select_${safe}`;\n const selectDesc =\n `Read rows from ${t.name}. Columns: ${columnList}. ` +\n `Use \\`where\\` for equality predicates, \\`orderBy\\` to sort, \\`limit\\` to bound the result (default 100, max 1000).`;\n const selectInput = {\n type: \"object\" as const,\n properties: {\n where: {\n type: \"object\" as const,\n description: \"Equality filter — keys are column names, values are scalars.\",\n properties: whereProps,\n additionalProperties: false,\n },\n orderBy: {\n type: \"string\" as const,\n description: \"Column name optionally followed by ASC/DESC.\",\n },\n limit: {\n type: \"integer\" as const,\n minimum: 1,\n maximum: 1000,\n default: 100,\n },\n },\n additionalProperties: false,\n };\n anthropic.push({ name: selectName, description: selectDesc, input_schema: selectInput });\n openai.push({\n type: \"function\",\n function: { name: selectName, description: selectDesc, parameters: selectInput },\n });\n\n const countName = `count_${safe}`;\n const countDesc = `Count rows in ${t.name}, optionally filtered by equality on any column.`;\n const countInput = {\n type: \"object\" as const,\n properties: {\n where: {\n type: \"object\" as const,\n properties: whereProps,\n additionalProperties: false,\n },\n },\n additionalProperties: false,\n };\n anthropic.push({ name: countName, description: countDesc, input_schema: countInput });\n openai.push({\n type: \"function\",\n function: { name: countName, description: countDesc, parameters: countInput },\n });\n\n const descName = `describe_${safe}`;\n const descDesc = `Return columns, row count, and foreign keys for ${t.name}.`;\n const descInput = {\n type: \"object\" as const,\n properties: {},\n additionalProperties: false,\n };\n anthropic.push({ name: descName, description: descDesc, input_schema: descInput });\n openai.push({\n type: \"function\",\n function: { name: descName, description: descDesc, parameters: descInput },\n });\n\n // Mutating per-table tools. We emit these for every user table —\n // the bearer's role still gates execution server-side, so a\n // readonly token calling `insert_*` will get a 403. Skipping\n // generation by role would mean a token upgrade requires a tool\n // re-render at the agent layer.\n const valueProps: Record<\n string,\n { type: string[]; description?: string }\n > = {};\n const requiredForInsert: string[] = [];\n for (const c of t.columns) {\n valueProps[c.name] = {\n type: [\"string\", \"number\", \"boolean\", \"null\"],\n description: `${t.name}.${c.name} (${c.type})${c.notNull ? \" NOT NULL\" : \"\"}`,\n };\n if (c.notNull && !c.primaryKey) {\n // PKs are usually integer-autoinc — leave them optional even\n // when notNull. If the user has a non-rowid PK they'd want to\n // pass it explicitly anyway and the server will fail loudly.\n requiredForInsert.push(c.name);\n }\n }\n\n const insertName = `insert_${safe}`;\n const insertDesc =\n `Insert one row into ${t.name}. ` +\n `Provide column values in \\`values\\`. Required (NOT NULL): ${requiredForInsert.join(\", \") || \"(none)\"}.`;\n const insertInput = {\n type: \"object\" as const,\n properties: {\n values: {\n type: \"object\" as const,\n description: \"Column → value map for the new row.\",\n properties: valueProps,\n required: requiredForInsert,\n additionalProperties: false,\n },\n },\n required: [\"values\"],\n additionalProperties: false,\n };\n anthropic.push({ name: insertName, description: insertDesc, input_schema: insertInput });\n openai.push({\n type: \"function\",\n function: { name: insertName, description: insertDesc, parameters: insertInput },\n });\n\n const updateName = `update_${safe}`;\n const updateDesc =\n `Update rows in ${t.name} matching \\`where\\` (equality on any column) ` +\n `with the columns provided in \\`set\\`. Both must be non-empty — to clear the filter use \\`sql_query\\`.`;\n const updateInput = {\n type: \"object\" as const,\n properties: {\n where: {\n type: \"object\" as const,\n properties: whereProps,\n additionalProperties: false,\n },\n set: {\n type: \"object\" as const,\n properties: valueProps,\n additionalProperties: false,\n },\n },\n required: [\"where\", \"set\"],\n additionalProperties: false,\n };\n anthropic.push({ name: updateName, description: updateDesc, input_schema: updateInput });\n openai.push({\n type: \"function\",\n function: { name: updateName, description: updateDesc, parameters: updateInput },\n });\n\n const deleteName = `delete_${safe}`;\n const deleteDesc =\n `Delete rows from ${t.name} matching \\`where\\`. \\`where\\` must be non-empty — ` +\n `to truncate use \\`sql_query\\` with an explicit DELETE.`;\n const deleteInput = {\n type: \"object\" as const,\n properties: {\n where: {\n type: \"object\" as const,\n properties: whereProps,\n additionalProperties: false,\n },\n },\n required: [\"where\"],\n additionalProperties: false,\n };\n anthropic.push({ name: deleteName, description: deleteDesc, input_schema: deleteInput });\n openai.push({\n type: \"function\",\n function: { name: deleteName, description: deleteDesc, parameters: deleteInput },\n });\n }\n\n const sqlName = \"sql_query\";\n const sqlDesc =\n `Run an arbitrary parameterised SQL statement against the PerSQL database \"${this.namespace}/${this.slug}\". ` +\n `Prefer the table-specific select_/count_/describe_ tools when they fit; fall back to this for joins, aggregates, or DDL.`;\n const sqlInput = {\n type: \"object\" as const,\n properties: {\n sql: { type: \"string\" as const },\n params: { type: \"array\" as const, items: {} },\n },\n required: [\"sql\"],\n additionalProperties: false,\n };\n anthropic.push({ name: sqlName, description: sqlDesc, input_schema: sqlInput });\n openai.push({\n type: \"function\",\n function: { name: sqlName, description: sqlDesc, parameters: sqlInput },\n });\n\n // ---- Discovery tools ---------------------------------------------------\n // What an agent should call BEFORE writing SQL on an unfamiliar\n // database. These don't take args (or just one), are read-scoped,\n // and answer \"what's in here?\" / \"what should I avoid?\".\n const describeDbName = \"describe_database\";\n const describeDbDesc =\n `Return the full schema graph plus stored semantic descriptions for \"${this.namespace}/${this.slug}\". ` +\n `Call this FIRST on any unfamiliar database — it includes table descriptions, column docs, and foreign keys ` +\n `in one shot, sized to JSON-stringify into a system prompt.`;\n const describeDbInput = {\n type: \"object\" as const,\n properties: {},\n additionalProperties: false,\n };\n anthropic.push({\n name: describeDbName,\n description: describeDbDesc,\n input_schema: describeDbInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: describeDbName,\n description: describeDbDesc,\n parameters: describeDbInput,\n },\n });\n\n const searchSchemaName = \"search_schema\";\n const searchSchemaDesc =\n `Natural-language ranked search across table names, column names, and stored descriptions. ` +\n `Use this when you have a goal (\"billing addresses\", \"abandoned carts\") but don't know which table holds it.`;\n const searchSchemaInput = {\n type: \"object\" as const,\n properties: {\n q: {\n type: \"string\" as const,\n description: \"Free-text query — table/column/description tokens are matched.\",\n },\n limit: {\n type: \"integer\" as const,\n minimum: 1,\n maximum: 100,\n default: 25,\n },\n },\n required: [\"q\"] as const,\n additionalProperties: false,\n };\n anthropic.push({\n name: searchSchemaName,\n description: searchSchemaDesc,\n input_schema: searchSchemaInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: searchSchemaName,\n description: searchSchemaDesc,\n parameters: searchSchemaInput,\n },\n });\n\n const doctorName = \"schema_doctor\";\n const doctorDesc =\n `Lint the schema for LLM-hostile patterns — missing primary keys, ambiguous column names, unindexed foreign keys. ` +\n `Read-only; useful before generating SQL so you know what the schema gets wrong.`;\n const doctorInput = {\n type: \"object\" as const,\n properties: {},\n additionalProperties: false,\n };\n anthropic.push({\n name: doctorName,\n description: doctorDesc,\n input_schema: doctorInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: doctorName,\n description: doctorDesc,\n parameters: doctorInput,\n },\n });\n\n // ---- Safety primitives -------------------------------------------------\n // Pre-flight a write before running it. Use propose_mutation for\n // anything that touches > a handful of rows, then either run\n // apply_mutation if the plan looks right, or discard the token.\n const proposeName = \"propose_mutation\";\n const proposeDesc =\n `Pre-flight a SQL write — EXPLAIN-validate, estimate affected rows, and return a single-use executionToken. ` +\n `Nothing is mutated until apply_mutation is called with that token. Use for any UPDATE/DELETE that isn't tightly ` +\n `scoped to a single PK, or any INSERT batch you want to verify.`;\n const proposeInput = {\n type: \"object\" as const,\n properties: {\n sql: { type: \"string\" as const, description: \"SQLite SQL statement.\" },\n params: { type: \"array\" as const, items: {} },\n ttlSec: {\n type: \"integer\" as const,\n minimum: 30,\n maximum: 3600,\n description: \"Token TTL in seconds. Default 600 (10 min).\",\n },\n },\n required: [\"sql\"] as const,\n additionalProperties: false,\n };\n anthropic.push({\n name: proposeName,\n description: proposeDesc,\n input_schema: proposeInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: proposeName,\n description: proposeDesc,\n parameters: proposeInput,\n },\n });\n\n const applyName = \"apply_mutation\";\n const applyDesc =\n `Redeem an executionToken returned by propose_mutation. Single-use — calling twice fails. ` +\n `The actual write runs through the same auto-snapshot + query-log + pricing pipeline as a normal SQL call.`;\n const applyInput = {\n type: \"object\" as const,\n properties: {\n executionToken: {\n type: \"string\" as const,\n description: \"pmut_… token from propose_mutation.\",\n },\n },\n required: [\"executionToken\"] as const,\n additionalProperties: false,\n };\n anthropic.push({\n name: applyName,\n description: applyDesc,\n input_schema: applyInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: applyName,\n description: applyDesc,\n parameters: applyInput,\n },\n });\n\n // ---- Telemetry ---------------------------------------------------------\n // Self-debugging. After a failed write the agent should consult\n // this rather than guess at what went wrong.\n const queryLogName = \"recent_queries\";\n const queryLogDesc =\n `Recent /query and /batch calls against this database — durations, errors, statement counts. ` +\n `Use to debug a failed write you just made, or to spot N+1 patterns in your own behavior.`;\n const queryLogInput = {\n type: \"object\" as const,\n properties: {\n since: {\n type: \"string\" as const,\n description: \"ISO timestamp lower bound.\",\n },\n status: {\n type: \"string\" as const,\n enum: [\"ok\", \"error\"] as const,\n },\n pageSize: {\n type: \"integer\" as const,\n minimum: 1,\n maximum: 200,\n default: 50,\n },\n },\n additionalProperties: false,\n };\n anthropic.push({\n name: queryLogName,\n description: queryLogDesc,\n input_schema: queryLogInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: queryLogName,\n description: queryLogDesc,\n parameters: queryLogInput,\n },\n });\n\n // ---- Branch-management tools ------------------------------------------\n // Branches are full per-database SQLite forks an agent can use as\n // a sandbox — try a migration on a branch, verify the result, then\n // merge or discard. Requires an admin-role bearer token; if the\n // token can't, the server replies 403 which propagates as\n // PerSQLError to the agent.\n const dbRef = `\"${this.namespace}/${this.slug}\"`;\n const branchesList = \"branches_list\";\n const branchesListInput = {\n type: \"object\" as const,\n properties: {},\n additionalProperties: false,\n };\n const branchesListDesc =\n `List preview branches of ${dbRef}. Each branch is its own ` +\n `SQLite database forked from the parent at create time.`;\n anthropic.push({\n name: branchesList,\n description: branchesListDesc,\n input_schema: branchesListInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: branchesList,\n description: branchesListDesc,\n parameters: branchesListInput,\n },\n });\n\n const branchesCreate = \"branches_create\";\n const branchesCreateInput = {\n type: \"object\" as const,\n properties: {\n ref: {\n type: \"string\" as const,\n description:\n \"Stable identifier for the branch (e.g. 'pr-42' or 'agent-run-7c2f'). PUT semantics — the same ref re-runs as a reset from the parent's current state.\",\n },\n name: {\n type: \"string\" as const,\n description: \"Optional human-readable name.\",\n },\n ttlDays: {\n type: [\"integer\", \"null\"] as const,\n minimum: 1,\n maximum: 30,\n description:\n \"Auto-delete after N days (1..30). Use for ephemeral / scratch experiments.\",\n },\n },\n required: [\"ref\"] as const,\n additionalProperties: false,\n };\n const branchesCreateDesc =\n `Create-or-reset a branch of ${dbRef} keyed by ref. Idempotent: ` +\n `repeat the same ref to refresh from the current parent. Requires an ` +\n `admin-role token.`;\n anthropic.push({\n name: branchesCreate,\n description: branchesCreateDesc,\n input_schema: branchesCreateInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: branchesCreate,\n description: branchesCreateDesc,\n parameters: branchesCreateInput,\n },\n });\n\n const branchesDelete = \"branches_delete\";\n const branchesDeleteInput = {\n type: \"object\" as const,\n properties: {\n ref: { type: \"string\" as const, description: \"The branch ref to delete.\" },\n },\n required: [\"ref\"] as const,\n additionalProperties: false,\n };\n const branchesDeleteDesc =\n `Delete a branch of ${dbRef}. Removes the branch's database and ` +\n `all of its data. Requires an admin-role token.`;\n anthropic.push({\n name: branchesDelete,\n description: branchesDeleteDesc,\n input_schema: branchesDeleteInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: branchesDelete,\n description: branchesDeleteDesc,\n parameters: branchesDeleteInput,\n },\n });\n\n const branchesMergeInput = {\n type: \"object\" as const,\n properties: {\n ref: { type: \"string\" as const, description: \"The branch ref to apply.\" },\n mode: {\n type: \"string\" as const,\n enum: [\"schema\", \"promote\"] as const,\n description:\n \"schema (default): apply the DDL delta — adds, plus replaces for views/triggers/indexes. Refuses table-shape changes. promote: replace the parent's full contents with the branch's (the parent keeps its identity).\",\n },\n dropRemoved: {\n type: \"boolean\" as const,\n description:\n \"Schema mode only — also drop objects present in the parent but absent in the branch.\",\n },\n },\n required: [\"ref\"] as const,\n additionalProperties: false,\n };\n const branchesPreview = \"branches_preview_merge\";\n const branchesPreviewDesc =\n `Preview merging a branch of ${dbRef} back into its parent — ` +\n `returns the plan (added/changed/removed objects) without writing. ` +\n `Use this before branches_merge to show the user what will happen.`;\n anthropic.push({\n name: branchesPreview,\n description: branchesPreviewDesc,\n input_schema: branchesMergeInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: branchesPreview,\n description: branchesPreviewDesc,\n parameters: branchesMergeInput,\n },\n });\n\n const claimBranchName = \"claim_branch\";\n const claimBranchDesc =\n `One-shot lease: create a fresh branch of ${dbRef} AND mint a scoped psql_live_ token in the same call. ` +\n `Use this when delegating work to a sub-agent — return the token to the sub-agent, walk away, and the branch + ` +\n `token both expire when the lease ends. Requires an admin-role token.`;\n const claimBranchInput = {\n type: \"object\" as const,\n properties: {\n purpose: {\n type: \"string\" as const,\n description:\n \"Free-text label baked into the auto-generated branch ref (e.g. 'agent-run-fix-issue-742').\",\n },\n ttlSec: {\n type: \"integer\" as const,\n minimum: 60,\n maximum: 60 * 60 * 24 * 30,\n description: \"Lease duration in seconds. Default 3600 (1 hour).\",\n },\n role: {\n type: \"string\" as const,\n enum: [\"read\", \"write\", \"admin\"] as const,\n description: \"Role for the minted token. Default 'write'.\",\n },\n },\n additionalProperties: false,\n };\n anthropic.push({\n name: claimBranchName,\n description: claimBranchDesc,\n input_schema: claimBranchInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: claimBranchName,\n description: claimBranchDesc,\n parameters: claimBranchInput,\n },\n });\n\n const branchesMerge = \"branches_merge\";\n const branchesMergeDesc =\n `Apply a branch back into ${dbRef}. Auto-snapshots the parent first ` +\n `(rollback via /restore with the returned snapshotId). Requires an ` +\n `admin-role token.`;\n anthropic.push({\n name: branchesMerge,\n description: branchesMergeDesc,\n input_schema: branchesMergeInput,\n });\n openai.push({\n type: \"function\",\n function: {\n name: branchesMerge,\n description: branchesMergeDesc,\n parameters: branchesMergeInput,\n },\n });\n\n const tableBySafe = new Map<string, (typeof schema)[\"tables\"][number]>();\n for (const t of schema.tables) tableBySafe.set(sanitizeToolPart(t.name), t);\n\n const run = async (name: string, input: Record<string, unknown> = {}) => {\n if (name === sqlName) {\n const sql = String(input.sql ?? \"\");\n const params = Array.isArray(input.params) ? (input.params as unknown[]) : [];\n return this.query(sql, params);\n }\n if (name === describeDbName) {\n return this.describe();\n }\n if (name === searchSchemaName) {\n const q = String(input.q ?? \"\");\n if (!q) throw new Error(\"q is required\");\n const limit =\n typeof input.limit === \"number\" ? input.limit : undefined;\n return this.search(q, limit !== undefined ? { limit } : {});\n }\n if (name === doctorName) {\n return this.doctor();\n }\n if (name === proposeName) {\n const sql = String(input.sql ?? \"\");\n if (!sql) throw new Error(\"sql is required\");\n const params = Array.isArray(input.params)\n ? (input.params as unknown[])\n : undefined;\n const ttlSec =\n typeof input.ttlSec === \"number\" ? input.ttlSec : undefined;\n return this.proposals.propose(sql, {\n params,\n ttlSec,\n });\n }\n if (name === applyName) {\n const token = String(input.executionToken ?? \"\");\n if (!token) throw new Error(\"executionToken is required\");\n return this.proposals.apply(token);\n }\n if (name === queryLogName) {\n const opts: {\n since?: string;\n status?: \"ok\" | \"error\";\n pageSize?: number;\n } = {};\n if (typeof input.since === \"string\") opts.since = input.since;\n if (input.status === \"ok\" || input.status === \"error\")\n opts.status = input.status;\n if (typeof input.pageSize === \"number\") opts.pageSize = input.pageSize;\n return this.queryLog(opts);\n }\n if (name === claimBranchName) {\n const opts: {\n purpose?: string;\n ttlSec?: number;\n role?: \"read\" | \"write\" | \"admin\";\n } = {};\n if (typeof input.purpose === \"string\") opts.purpose = input.purpose;\n if (typeof input.ttlSec === \"number\") opts.ttlSec = input.ttlSec;\n if (\n input.role === \"read\" ||\n input.role === \"write\" ||\n input.role === \"admin\"\n )\n opts.role = input.role;\n return this.branches.claim(opts);\n }\n if (name === branchesList) {\n return this.branches.list();\n }\n if (name === branchesCreate) {\n const ref = String(input.ref ?? \"\");\n if (!ref) throw new Error(\"ref is required\");\n const ttl = input.ttlDays;\n return this.branches.upsert(ref, {\n name: typeof input.name === \"string\" ? input.name : undefined,\n ttlDays: typeof ttl === \"number\" ? ttl : ttl === null ? null : undefined,\n });\n }\n if (name === branchesDelete) {\n const ref = String(input.ref ?? \"\");\n if (!ref) throw new Error(\"ref is required\");\n return this.branches.delete(ref);\n }\n if (name === branchesPreview || name === branchesMerge) {\n const ref = String(input.ref ?? \"\");\n if (!ref) throw new Error(\"ref is required\");\n const mode =\n input.mode === \"promote\" ? \"promote\" : (\"schema\" as BranchMergeMode);\n return this.branches.merge(ref, {\n mode,\n preview: name === branchesPreview,\n dropRemoved: input.dropRemoved === true,\n });\n }\n const m = name.match(/^(select|count|describe|insert|update|delete)_(.+)$/);\n if (!m) throw new Error(`Unknown tool: ${name}`);\n const [, op, tableSafe] = m;\n const t = tableBySafe.get(tableSafe);\n if (!t) throw new Error(`Unknown table for tool ${name}`);\n const ident = quoteIdent(t.name);\n const colSetForT = new Set(t.columns.map((c) => c.name));\n if (op === \"insert\") {\n const values = (input.values ?? {}) as Record<string, unknown>;\n const cols = Object.keys(values);\n if (cols.length === 0) throw new Error(\"values must be non-empty\");\n for (const k of cols) {\n if (!colSetForT.has(k)) throw new Error(`Unknown column: ${k}`);\n }\n const placeholders = cols.map(() => \"?\").join(\", \");\n const colSql = cols.map(quoteIdent).join(\", \");\n return this.query(\n `INSERT INTO ${ident} (${colSql}) VALUES (${placeholders})`,\n cols.map((c) => values[c])\n );\n }\n if (op === \"update\") {\n const where = (input.where ?? {}) as Record<string, unknown>;\n const setObj = (input.set ?? {}) as Record<string, unknown>;\n const setKeys = Object.keys(setObj);\n const whereKeys = Object.keys(where);\n if (setKeys.length === 0) throw new Error(\"set must be non-empty\");\n if (whereKeys.length === 0)\n throw new Error(\"where must be non-empty — use sql_query for unfiltered updates\");\n for (const k of [...setKeys, ...whereKeys]) {\n if (!colSetForT.has(k)) throw new Error(`Unknown column: ${k}`);\n }\n const setSql = setKeys.map((k) => `${quoteIdent(k)} = ?`).join(\", \");\n const whereSqlParts: string[] = [];\n const whereParams: unknown[] = [];\n for (const k of whereKeys) {\n const v = where[k];\n if (v === null) {\n whereSqlParts.push(`${quoteIdent(k)} IS NULL`);\n } else {\n whereSqlParts.push(`${quoteIdent(k)} = ?`);\n whereParams.push(v);\n }\n }\n return this.query(\n `UPDATE ${ident} SET ${setSql} WHERE ${whereSqlParts.join(\" AND \")}`,\n [...setKeys.map((k) => setObj[k]), ...whereParams]\n );\n }\n if (op === \"delete\") {\n const where = (input.where ?? {}) as Record<string, unknown>;\n const whereKeys = Object.keys(where);\n if (whereKeys.length === 0)\n throw new Error(\"where must be non-empty — use sql_query for unfiltered deletes\");\n for (const k of whereKeys) {\n if (!colSetForT.has(k)) throw new Error(`Unknown column: ${k}`);\n }\n const whereSqlParts: string[] = [];\n const whereParams: unknown[] = [];\n for (const k of whereKeys) {\n const v = where[k];\n if (v === null) {\n whereSqlParts.push(`${quoteIdent(k)} IS NULL`);\n } else {\n whereSqlParts.push(`${quoteIdent(k)} = ?`);\n whereParams.push(v);\n }\n }\n return this.query(\n `DELETE FROM ${ident} WHERE ${whereSqlParts.join(\" AND \")}`,\n whereParams\n );\n }\n if (op === \"describe\") {\n const [info, fks, count] = await Promise.all([\n this.query(`PRAGMA table_info(${ident})`),\n this.query(`PRAGMA foreign_key_list(${ident})`),\n this.query(`SELECT COUNT(*) AS n FROM ${ident}`),\n ]);\n return {\n table: t.name,\n rowCount: Number((count.rows[0]?.[0] as number) ?? 0),\n columns: info.data,\n foreignKeys: fks.data,\n };\n }\n const where = (input.where ?? {}) as Record<string, unknown>;\n const colSet = new Set(t.columns.map((c) => c.name));\n const clauses: string[] = [];\n const params: unknown[] = [];\n for (const [k, v] of Object.entries(where)) {\n if (!colSet.has(k)) throw new Error(`Unknown column: ${k}`);\n if (v === null) {\n clauses.push(`${quoteIdent(k)} IS NULL`);\n } else {\n clauses.push(`${quoteIdent(k)} = ?`);\n params.push(v);\n }\n }\n const whereSql = clauses.length ? ` WHERE ${clauses.join(\" AND \")}` : \"\";\n\n if (op === \"count\") {\n const r = await this.query(`SELECT COUNT(*) AS n FROM ${ident}${whereSql}`, params);\n return { count: Number((r.rows[0]?.[0] as number) ?? 0) };\n }\n\n const limit = Math.min(1000, Math.max(1, Number(input.limit ?? 100)));\n let orderSql = \"\";\n if (typeof input.orderBy === \"string\" && input.orderBy.trim()) {\n const ob = input.orderBy.trim();\n const obMatch = ob.match(/^([A-Za-z_][A-Za-z0-9_]*)\\s*(asc|desc)?$/i);\n if (!obMatch) throw new Error(\"orderBy must be `<col>` or `<col> ASC|DESC`\");\n const [, col, dir] = obMatch;\n if (!colSet.has(col)) throw new Error(`Unknown column: ${col}`);\n orderSql = ` ORDER BY ${quoteIdent(col)} ${(dir ?? \"ASC\").toUpperCase()}`;\n }\n const r = await this.query(\n `SELECT * FROM ${ident}${whereSql}${orderSql} LIMIT ${limit}`,\n params\n );\n return r;\n };\n\n const aiSdk = (): Record<string, AiSdkTool> => {\n const out: Record<string, AiSdkTool> = {};\n for (const t of anthropic) {\n out[t.name] = {\n description: t.description,\n inputSchema: t.input_schema,\n execute: (input) => run(t.name, input),\n };\n }\n return out;\n };\n\n const mastra = (): Record<string, MastraTool> => {\n const out: Record<string, MastraTool> = {};\n for (const t of anthropic) {\n out[t.name] = {\n id: t.name,\n description: t.description,\n inputSchema: t.input_schema,\n execute: ({ context }) => run(t.name, context),\n };\n }\n return out;\n };\n\n const langchain = (): LangChainTool[] =>\n anthropic.map((t) => ({\n name: t.name,\n description: t.description,\n schema: t.input_schema,\n invoke: (input: Record<string, unknown>) => run(t.name, input),\n }));\n\n const openaiAgents = (): OpenAiAgentsTool[] =>\n anthropic.map((t) => ({\n type: \"function\" as const,\n name: t.name,\n description: t.description,\n parameters: t.input_schema,\n invoke: (input: Record<string, unknown>) => run(t.name, input),\n }));\n\n return { anthropic, openai, run, aiSdk, mastra, langchain, openaiAgents };\n }\n}\n\n// SQL identifiers in tool names — `.` in `schema.table` names, hyphens,\n// etc. — get sanitized to underscores so tool names match\n// `^[a-zA-Z0-9_-]+$` everywhere.\nfunction sanitizeToolPart(s: string): string {\n return s.replace(/[^A-Za-z0-9_]/g, \"_\");\n}\n\nfunction quoteIdent(s: string): string {\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\n}\n\n/** Tool definition in the Anthropic Messages API shape — one `tools` entry for `messages.create`. */\nexport interface AnthropicTool {\n name: string;\n description: string;\n input_schema: Record<string, unknown>;\n}\n\n/** Tool definition in the OpenAI Chat Completions shape — one `tools` entry for `chat.completions.create`. */\nexport interface OpenAiTool {\n type: \"function\";\n function: {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n };\n}\n\n/** Output of `db.asTool()` — one SQL-query tool rendered in every supported framework shape. */\nexport interface SingleToolBundle {\n /** Anthropic shape — pass as one entry of `tools` to messages.create. */\n anthropic: AnthropicTool;\n /** OpenAI Chat shape — pass as one entry of `tools` to chat.completions.create. */\n openai: OpenAiTool;\n /** Vercel AI SDK shape — spread into `streamText({ tools: { ...db.asTool().aiSdk() } })`. */\n aiSdk: () => Record<string, AiSdkTool>;\n /** Mastra shape — wrap with `createTool()` if you need the Mastra envelope. */\n mastra: () => Record<string, MastraTool>;\n /** LangChain/LangGraph shape — pass to `DynamicStructuredTool` or use `invoke` directly. */\n langchain: () => LangChainTool[];\n /** OpenAI Agents SDK shape — hand to `Agent({ tools: [...] })`. */\n openaiAgents: () => OpenAiAgentsTool[];\n}\n\n/** Output of `db.asTools()` — typed per-table tools plus the `run` dispatcher, in every supported framework shape. */\nexport interface DatabaseToolBundle {\n /** Tool definitions in Anthropic shape — pass as `tools` to messages.create. */\n anthropic: AnthropicTool[];\n /** Tool definitions in OpenAI shape — pass as `tools` to chat.completions.create. */\n openai: OpenAiTool[];\n /** Dispatch a model-emitted tool call back to the database. */\n run: (name: string, input?: Record<string, unknown>) => Promise<unknown>;\n /**\n * Vercel AI SDK shape — record of `{ [toolName]: { description, inputSchema, execute } }`.\n * Spread into `streamText({ tools: { ...db.asTools().aiSdk() } })`. The\n * `inputSchema` field is JSON Schema; pass through `jsonSchema()` from\n * the `ai` package if your version of AI SDK requires it explicitly.\n */\n aiSdk: () => Record<string, AiSdkTool>;\n /**\n * Mastra shape — record of `{ [toolName]: { id, description, inputSchema, execute } }`.\n * Useful for `createTool({...})` callsites. `inputSchema` is JSON Schema;\n * if Mastra's runtime needs a Zod schema, run it through `json-schema-to-zod`\n * or your preferred converter.\n */\n mastra: () => Record<string, MastraTool>;\n /**\n * LangChain shape — array of `{ name, description, schema, invoke }`.\n * Wrap with `DynamicStructuredTool` or pass `invoke` directly to a\n * custom agent loop.\n */\n langchain: () => LangChainTool[];\n /**\n * OpenAI Agents SDK shape — array of `{ type, name, description, parameters, invoke }`.\n * Hand to `Agent({ tools: [...] })`.\n */\n openaiAgents: () => OpenAiAgentsTool[];\n}\n\n/** Tool shape for the Vercel AI SDK — spread into `streamText({ tools })`. */\nexport interface AiSdkTool {\n description: string;\n inputSchema: Record<string, unknown>;\n execute: (input: Record<string, unknown>) => Promise<unknown>;\n}\n\n/** Tool shape for Mastra — wrap with `createTool()` if you need the Mastra envelope. */\nexport interface MastraTool {\n id: string;\n description: string;\n inputSchema: Record<string, unknown>;\n execute: (context: { context: Record<string, unknown> }) => Promise<unknown>;\n}\n\n/**\n * LangChain shape — pass to `DynamicStructuredTool` or use `invoke`\n * directly inside a custom agent. `schema` is JSON Schema; if your\n * LangChain version requires Zod, convert with `json-schema-to-zod`.\n */\nexport interface LangChainTool {\n name: string;\n description: string;\n schema: Record<string, unknown>;\n invoke: (input: Record<string, unknown>) => Promise<unknown>;\n}\n\n/**\n * OpenAI Agents SDK shape — assign as a tool in `Agent` config. The\n * Agents SDK uses `parameters` (JSON Schema) and a callable; our\n * `invoke` matches the `function_tool` callback signature.\n */\nexport interface OpenAiAgentsTool {\n type: \"function\";\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n invoke: (input: Record<string, unknown>) => Promise<unknown>;\n}\n\n/** Kind of row change reported by `db.subscribe()` and `db.changes()`. */\nexport type SubscribeChangeKind =\n | \"update\"\n | \"insert\"\n | \"delete\"\n | \"schema\"\n | \"unknown\";\n\n/** One row-change event delivered to `SubscribeOptions.onChange`. */\nexport interface SubscribeChange {\n table: string;\n kind: SubscribeChangeKind;\n}\n\n/** Options for `db.subscribe()` — table filter and event callbacks. */\nexport interface SubscribeOptions {\n /** Tables to listen to. Omit / empty / `[\"*\"]` = all tables. */\n tables?: string[];\n onChange: (change: SubscribeChange) => void;\n /** Fires once when the server confirms the subscription. */\n onReady?: (tables: string[] | \"*\") => void;\n onError?: (error: Error) => void;\n onClose?: () => void;\n}\n\n/**\n * Database row as returned by /v1 list/upsert branch responses.\n * Mirrors the `Database` DTO from @persql/shared but kept narrow on\n * purpose so the SDK doesn't drift if the server adds fields.\n */\nexport interface BranchInfo {\n id: string;\n namespaceId: string;\n slug: string;\n name: string;\n status: string;\n region: string;\n branchRef: string | null;\n forkedAt: string | null;\n expiresAt: string | null;\n createdAt: string;\n updatedAt: string;\n forkedFrom?: { id: string; slug: string; name: string };\n}\n\n/**\n * How a branch is applied back to its parent: `schema` applies the DDL\n * delta; `promote` replaces the parent's contents wholesale.\n */\nexport type BranchMergeMode = \"schema\" | \"promote\";\n\n/** One DDL operation in a branch-merge plan: create, drop, or replace. */\nexport type BranchMergePlanStep =\n | { op: \"create\"; type: string; name: string; sql: string }\n | { op: \"drop\"; type: string; name: string }\n | {\n op: \"replace\";\n type: string;\n name: string;\n beforeSql: string;\n afterSql: string;\n };\n\n/** Outcome of `db.branches.merge()` — what was applied, the pre-merge snapshot, and the plan when previewing. */\nexport interface BranchMergeResult {\n mode: BranchMergeMode;\n preview: boolean;\n applied: number;\n snapshotId: string | null;\n plan?: BranchMergePlanStep[];\n summary?: { added: number; changed: number; removed: number };\n note?: string;\n}\n\n/** Options for `db.branches.upsert()`. */\nexport interface BranchUpsertOptions {\n /** Human-readable name. Defaults to `<parent name> (<ref>)`. */\n name?: string;\n /** Region hint: auto, wnam, enam, weur, eeur, apac. Default: auto. */\n region?: string;\n /** Auto-delete after N days (1..30). Null/undefined = keep until deleted. */\n ttlDays?: number | null;\n}\n\n/** Options for `db.branches.merge()`. */\nexport interface BranchMergeOptions {\n /** Default `schema`. `promote` replaces parent contents wholesale. */\n mode?: BranchMergeMode;\n /** If true, returns the plan without writing. */\n preview?: boolean;\n /** Schema mode only — drop objects present in parent but not in branch. */\n dropRemoved?: boolean;\n /** Default true — captures `pre-merge:<ref>` snapshot of the parent. */\n snapshot?: boolean;\n}\n\n/** Output of `db.proposals.propose()` — the EXPLAIN plan, estimated affected rows, and the single-use execution token. */\nexport interface ProposalPlan {\n sql: string;\n plan: unknown[][];\n estimatedAffectedRows: number | null;\n executionToken: string;\n expiresAt: string;\n action: \"read\" | \"write\" | \"admin\";\n}\n\n/** Options for `db.proposals.propose()`. */\nexport interface ProposeOptions {\n params?: unknown[];\n ttlSec?: number;\n}\n\n/** Lifecycle state of an approval token, as returned by `db.approvals.get()` and `poll()`. */\nexport interface ApprovalStatus {\n status: \"pending\" | \"approved\" | \"denied\";\n hits: ApprovalRuleHit[];\n createdAt: string;\n expiresAt: string;\n decidedAt: string | null;\n}\n\n/** Pacing and cancellation options for `db.approvals.poll()`. */\nexport interface PollApprovalOptions {\n /** Default 2000ms. */\n intervalMs?: number;\n /** Default 10 minutes. */\n timeoutMs?: number;\n /** Cancellation signal. */\n signal?: AbortSignal;\n}\n\n/** Callbacks and pacing for `db.approvals.subscribe()`. */\nexport interface SubscribeApprovalOptions {\n onApprovalRequired?: (event: ApprovalEvent) => void;\n onApprovalResolved?: (event: ApprovalEvent) => void;\n /** Poll interval. Default 5000ms. */\n intervalMs?: number;\n /** Cancellation signal. */\n signal?: AbortSignal;\n /** Logged-by-default error sink. */\n onError?: (err: Error) => void;\n}\n\n/** One approval state change delivered by `db.approvals.subscribe()`. */\nexport interface ApprovalEvent {\n approvalToken: string;\n status: \"pending\" | \"approved\" | \"denied\";\n hits: ApprovalRuleHit[];\n}\n\n/**\n * Approval-token lifecycle for writes blocked by a require_approval\n * rule — look up, poll, subscribe, and redeem. Reached via\n * `db.approvals`.\n */\nexport class PerSQLApprovals {\n // Tokens this client has seen via subscribe — used to dedupe poll\n // results so onApprovalRequired fires once per token regardless of\n // how many subscribe ticks observe it.\n private readonly seen = new Map<string, \"pending\" | \"approved\" | \"denied\">();\n\n constructor(\n private readonly client: PerSQL,\n private readonly namespace: string,\n private readonly slug: string\n ) {}\n\n /**\n * Look up the status of an approval token without consuming it. The\n * bearer must match the one that minted the original 403; cross-bearer\n * lookup returns 403.\n */\n async get(approvalToken: string): Promise<ApprovalStatus> {\n return this.client.request<ApprovalStatus>(\n \"GET\",\n `/v1/db/${this.namespace}/${this.slug}/approval/${encodeURIComponent(\n approvalToken\n )}`\n );\n }\n\n /**\n * Poll until a reviewer decides (or the token expires). Resolves with\n * the final status — `approved` is your green light for `redeem()`.\n */\n async poll(\n approvalToken: string,\n opts: PollApprovalOptions = {}\n ): Promise<ApprovalStatus> {\n const intervalMs = Math.max(250, opts.intervalMs ?? 2000);\n const deadline = Date.now() + (opts.timeoutMs ?? 10 * 60 * 1000);\n while (true) {\n if (opts.signal?.aborted) {\n throw new Error(\"approval poll aborted\");\n }\n const status = await this.get(approvalToken);\n if (status.status !== \"pending\") return status;\n if (Date.now() > deadline) return status;\n await new Promise((r) => setTimeout(r, intervalMs));\n }\n }\n\n /**\n * Long-running poll subscription for new approval events on this\n * database. Returns a `stop()` handle. Webhook delivery is the push\n * path (events `approval_required` / `approval_resolved`); subscribe\n * is the pull fallback for clients that can't host a webhook.\n *\n * Today this iterates over a known set of tokens supplied by the\n * caller; an SDK-only client that wants discovery should pair this\n * with the webhook path. Pass tokens you already hold (e.g. from a\n * prior `ApprovalRequiredError`).\n */\n subscribe(\n tokens: string[],\n opts: SubscribeApprovalOptions\n ): { stop: () => void } {\n const intervalMs = Math.max(1000, opts.intervalMs ?? 5000);\n let cancelled = false;\n const onAbort = () => {\n cancelled = true;\n };\n opts.signal?.addEventListener(\"abort\", onAbort);\n const tick = async () => {\n for (const token of tokens) {\n if (cancelled) return;\n try {\n const status = await this.get(token);\n const prev = this.seen.get(token);\n if (status.status !== prev) {\n this.seen.set(token, status.status);\n const event: ApprovalEvent = {\n approvalToken: token,\n status: status.status,\n hits: status.hits,\n };\n if (status.status === \"pending\") {\n opts.onApprovalRequired?.(event);\n } else {\n opts.onApprovalResolved?.(event);\n }\n }\n } catch (e) {\n opts.onError?.(e instanceof Error ? e : new Error(String(e)));\n }\n }\n };\n const id = setInterval(() => {\n void tick();\n }, intervalMs);\n void tick();\n return {\n stop: () => {\n cancelled = true;\n clearInterval(id);\n opts.signal?.removeEventListener(\"abort\", onAbort);\n },\n };\n }\n\n /**\n * Redeem an approved approvalToken. The bearer must be the same one\n * that minted it, and the request must target the same database.\n * Returns the result of the originally-blocked query or batch.\n */\n async redeem<T = Record<string, unknown>>(\n approvalToken: string\n ): Promise<QueryResult<T> | QueryResult<T>[]> {\n const raw = await this.client.request<\n | {\n columns: string[];\n rows: unknown[][];\n rowsRead: number;\n rowsWritten: number;\n }\n | Array<{\n columns: string[];\n rows: unknown[][];\n rowsRead: number;\n rowsWritten: number;\n }>\n >(\"POST\", `/v1/db/${this.namespace}/${this.slug}/redeem_approval`, {\n approvalToken,\n });\n if (Array.isArray(raw)) {\n return raw.map((r) => ({\n ...r,\n data: rowsToObjects<T>(r.columns, r.rows),\n }));\n }\n return { ...raw, data: rowsToObjects<T>(raw.columns, raw.rows) };\n }\n}\n\n/** A require_approval / deny rule on a database, as returned by `db.approvalRules.list()`. */\nexport interface ApprovalRule {\n id: string;\n databaseId: string;\n tableGlob: string;\n action: \"require_approval\" | \"deny\";\n note: string | null;\n createdById: string;\n createdAt: string;\n}\n\n/** Input for `db.approvalRules.create()`. */\nexport interface CreateApprovalRuleInput {\n tableGlob: string;\n action: \"require_approval\" | \"deny\";\n note?: string;\n}\n\n/** Manage the require_approval / deny rules of a database. Reached via `db.approvalRules`. */\nexport class PerSQLApprovalRules {\n constructor(\n private readonly client: PerSQL,\n private readonly namespace: string,\n private readonly slug: string\n ) {}\n\n async list(): Promise<ApprovalRule[]> {\n return this.client.request<ApprovalRule[]>(\n \"GET\",\n `/v1/db/${this.namespace}/${this.slug}/approval-rules`\n );\n }\n\n /** Requires an admin-role bearer token. */\n async create(input: CreateApprovalRuleInput): Promise<ApprovalRule> {\n return this.client.request<ApprovalRule>(\n \"POST\",\n `/v1/db/${this.namespace}/${this.slug}/approval-rules`,\n input\n );\n }\n\n /** Requires an admin-role bearer token. */\n async delete(ruleId: string): Promise<{ deleted: true }> {\n return this.client.request<{ deleted: true }>(\n \"DELETE\",\n `/v1/db/${this.namespace}/${this.slug}/approval-rules/${encodeURIComponent(\n ruleId\n )}`\n );\n }\n}\n\n/**\n * Two-phase writes: `propose()` pre-flights the SQL and mints a\n * single-use execution token; `apply()` redeems it. Reached via\n * `db.proposals`.\n */\nexport class PerSQLProposals {\n constructor(\n private readonly client: PerSQL,\n private readonly namespace: string,\n private readonly slug: string\n ) {}\n\n /**\n * Pre-flight an SQL statement. EXPLAIN-validates, estimates affected\n * rows, and returns a single-use `executionToken` valid for 10 min\n * (override with `ttlSec`, max 1 hour). Nothing is mutated until\n * `apply()` is called.\n *\n * Local mode keeps the token in-process: single-use still holds, but\n * `estimatedAffectedRows` is always `null` (no server estimator) and a\n * stale/unknown token throws a plain `Error` rather than the HTTP\n * 404/403 of the server path.\n */\n async propose(sql: string, opts: ProposeOptions = {}): Promise<ProposalPlan> {\n if (this.client.local) {\n return this.client.local.propose(sql, opts.params ?? [], opts.ttlSec);\n }\n return this.client.request<ProposalPlan>(\n \"POST\",\n `/v1/db/${this.namespace}/${this.slug}/propose`,\n {\n sql,\n params: opts.params ?? [],\n ttlSec: opts.ttlSec,\n }\n );\n }\n\n /**\n * Redeem an `executionToken` from `propose()`. Single-use — calling\n * twice with the same token throws 404. The token is also pinned to\n * the originating bearer + database; cross-token redemption throws\n * 403.\n */\n async apply<T = Record<string, unknown>>(\n executionToken: string\n ): Promise<QueryResult<T>> {\n if (this.client.local) {\n const raw = await this.client.local.apply(executionToken);\n return { ...raw, data: rowsToObjects<T>(raw.columns, raw.rows) };\n }\n const raw = await this.client.request<{\n columns: string[];\n rows: unknown[][];\n rowsRead: number;\n rowsWritten: number;\n }>(\"POST\", `/v1/db/${this.namespace}/${this.slug}/apply`, { executionToken });\n return {\n ...raw,\n data: rowsToObjects<T>(raw.columns, raw.rows),\n };\n }\n}\n\n/** Output of `db.branches.claim()` — the fresh branch plus the scoped token minted for it. */\nexport interface ClaimedBranch {\n branchRef: string;\n databaseId: string;\n databaseSlug: string;\n namespaceSlug: string;\n /** Plaintext psql_live_/psql_test_ token. Returned once. */\n token: string;\n tokenId: string;\n role: \"read\" | \"write\" | \"admin\";\n expiresAt: string;\n outcome: \"created\" | \"reset\";\n}\n\n/** Options for `db.branches.claim()`. */\nexport interface ClaimBranchOptions {\n /** Explicit ref. Omit to auto-generate from `purpose`. */\n ref?: string;\n /** Free-form label baked into the auto-ref + token name. */\n purpose?: string;\n /** Lease length in seconds. Default 3600 (1 hour), max 30 days. */\n ttlSec?: number;\n /** Default \"write\". */\n role?: \"read\" | \"write\" | \"admin\";\n region?: string;\n}\n\n/**\n * Branch management for one database — list, create-or-reset, delete,\n * merge, pin (handoff), claim (lease), and migration rendering.\n * Reached via `db.branches`.\n */\nexport class PerSQLBranches {\n constructor(\n private readonly client: PerSQL,\n private readonly namespace: string,\n private readonly slug: string\n ) {}\n\n /**\n * One-shot lease — create or reset a branch with a TTL and mint a\n * scoped token in the same call. Use at the start of an agent run\n * instead of chaining create + token mint.\n */\n async claim(opts: ClaimBranchOptions = {}): Promise<ClaimedBranch> {\n return this.client.request<ClaimedBranch>(\n \"POST\",\n `/v1/db/${this.namespace}/${this.slug}/claim_branch`,\n opts\n );\n }\n\n /** List branches of this database. Any-role token. */\n async list(opts: { cursor?: string; pageSize?: number } = {}): Promise<{\n data: BranchInfo[];\n nextCursor: string | null;\n }> {\n const qs = new URLSearchParams();\n if (opts.cursor) qs.set(\"cursor\", opts.cursor);\n if (opts.pageSize) qs.set(\"pageSize\", String(opts.pageSize));\n const tail = qs.toString() ? `?${qs.toString()}` : \"\";\n // The list endpoint returns the data envelope plus a `nextCursor`\n // sibling; request the raw envelope by going through fetchRaw.\n const res = await this.client.fetchRaw(\n \"GET\",\n `/v1/db/${this.namespace}/${this.slug}/branches${tail}`\n );\n const body = (await res.json()) as {\n success: boolean;\n data?: BranchInfo[];\n error?: string;\n nextCursor?: string | null;\n };\n if (!res.ok || !body.success) {\n throw new PerSQLError(res.status, body.error ?? `Request failed (${res.status})`);\n }\n return { data: body.data ?? [], nextCursor: body.nextCursor ?? null };\n }\n\n /**\n * Create-or-reset a branch by ref. Idempotent: re-PUTting the same\n * ref refreshes the branch from the parent's current state.\n * Requires an admin-role token.\n */\n async upsert(\n ref: string,\n opts: BranchUpsertOptions = {}\n ): Promise<BranchInfo> {\n return this.client.request<BranchInfo>(\n \"PUT\",\n `/v1/db/${this.namespace}/${this.slug}/branches/${encodeURIComponent(ref)}`,\n {\n name: opts.name,\n region: opts.region,\n ttlDays: opts.ttlDays ?? null,\n }\n );\n }\n\n /** Delete a branch by ref. Requires an admin-role token. */\n async delete(ref: string): Promise<{ deleted: true }> {\n return this.client.request<{ deleted: true }>(\n \"DELETE\",\n `/v1/db/${this.namespace}/${this.slug}/branches/${encodeURIComponent(ref)}`\n );\n }\n\n /**\n * Apply a branch back into its parent. `preview: true` returns the\n * plan without writing. Requires an admin-role token.\n */\n async merge(\n ref: string,\n opts: BranchMergeOptions = {}\n ): Promise<BranchMergeResult> {\n return this.client.request<BranchMergeResult>(\n \"POST\",\n `/v1/db/${this.namespace}/${this.slug}/branches/${encodeURIComponent(ref)}/merge`,\n {\n mode: opts.mode ?? \"schema\",\n preview: opts.preview === true,\n dropRemoved: opts.dropRemoved === true,\n snapshot: opts.snapshot !== false,\n }\n );\n }\n\n /** Convenience for `merge(ref, { preview: true, ...opts })`. */\n preview(\n ref: string,\n opts: Omit<BranchMergeOptions, \"preview\"> = {}\n ): Promise<BranchMergeResult> {\n return this.merge(ref, { ...opts, preview: true });\n }\n\n /**\n * Mint a single-use handoff token for this branch. The receiving\n * agent calls `PerSQL.fromHandoff(token)` to redeem it for a\n * regular bearer token scoped to exactly this (database, branch,\n * role) — the agent that minted the handoff never has to share\n * its own token. Single-use, ≤24h TTL.\n */\n async pin(\n ref: string,\n opts: { role?: \"read\" | \"write\" | \"admin\"; ttlSec?: number } = {}\n ): Promise<{\n token: string;\n expiresAt: string;\n role: \"read\" | \"write\" | \"admin\";\n databaseId: string;\n branchRef: string | null;\n }> {\n return this.client.request(\n \"POST\",\n `/v1/db/${this.namespace}/${this.slug}/branches/${encodeURIComponent(ref)}/pin`,\n { role: opts.role ?? \"write\", ttlSec: opts.ttlSec }\n );\n }\n\n /**\n * Render the branch's schema delta as a committable SQL migration.\n * Read-only. Returns `{ name, sql, plan, summary }` — `name` is a\n * timestamped filename (`YYYYMMDDHHMMSS_branch_<ref>.sql`) safe to\n * write to disk; `sql` is the migration body wrapped in a single\n * BEGIN/COMMIT.\n */\n async migration(\n ref: string,\n opts: { dropRemoved?: boolean } = {}\n ): Promise<{\n name: string;\n sql: string;\n plan: BranchMergePlanStep[];\n summary: { added: number; changed: number; removed: number };\n }> {\n return this.client.request(\n \"POST\",\n `/v1/db/${this.namespace}/${this.slug}/branches/${encodeURIComponent(ref)}/migration`,\n { dropRemoved: opts.dropRemoved === true }\n );\n }\n}\n\n/**\n * Schema returned by `db.schema()`. One entry per user table.\n */\nexport interface DatabaseSchema {\n tables: Array<{\n name: string;\n columns: Array<{\n name: string;\n /** SQLite column type (TEXT, INTEGER, REAL, BLOB, NUMERIC). */\n type: string;\n notNull: boolean;\n primaryKey: boolean;\n default: string | null;\n }>;\n }>;\n}\n\n/**\n * Callback shape used by Drizzle's `drizzle-orm/sqlite-proxy`.\n * Returned by `db.driver()` so callers can plug PerSQL into Drizzle\n * without taking a hard dep on it.\n */\nexport type SqliteProxyDriver = (\n sql: string,\n params: unknown[],\n method: \"all\" | \"run\" | \"get\" | \"values\"\n) => Promise<{ rows: unknown }>;\n\nfunction rowsToObjects<T>(columns: string[], rows: unknown[][]): T[] {\n return rows.map((r) => {\n const obj: Record<string, unknown> = {};\n for (let i = 0; i < columns.length; i++) obj[columns[i]!] = r[i];\n return obj as T;\n });\n}\n"],"mappings":"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","names":["raw","params","limit","where","r"]}
|
package/dist/cli.cjs
CHANGED
|
@@ -167,7 +167,14 @@ function runOne(db, sql, params) {
|
|
|
167
167
|
return { columns: cols, rows, rowsRead: rows.length, rowsWritten: 0 };
|
|
168
168
|
}
|
|
169
169
|
const info = stmt.run(...params);
|
|
170
|
-
return {
|
|
170
|
+
return {
|
|
171
|
+
columns: [],
|
|
172
|
+
rows: [],
|
|
173
|
+
rowsRead: 0,
|
|
174
|
+
rowsWritten: info.changes ?? 0,
|
|
175
|
+
changes: info.changes ?? 0,
|
|
176
|
+
lastInsertRowid: Number(info.lastInsertRowid ?? 0)
|
|
177
|
+
};
|
|
171
178
|
}
|
|
172
179
|
|
|
173
180
|
// src/index.ts
|