@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/index.d.ts CHANGED
@@ -1,9 +1,13 @@
1
+ /** Wire-shape query result — columns plus positional rows, before the SDK reshapes rows into objects. */
1
2
  interface RawQueryResult {
2
3
  columns: string[];
3
4
  rows: unknown[][];
4
5
  rowsRead: number;
5
6
  rowsWritten: number;
7
+ changes?: number;
8
+ lastInsertRowid?: number;
6
9
  }
10
+ /** In-process driver backing `new PerSQL({ local })` — runs SQL through `better-sqlite3` instead of the HTTP API. */
7
11
  declare class LocalDriver {
8
12
  private readonly path;
9
13
  private db;
@@ -46,7 +50,14 @@ declare class LocalDriver {
46
50
  * );
47
51
  */
48
52
 
53
+ /** Machine-readable category of a SQL failure, parsed from the engine's error message. */
49
54
  type SqlErrorKind = "unique_violation" | "not_null_violation" | "fk_violation" | "check_violation" | "unknown_table" | "unknown_column" | "syntax_error" | "type_mismatch" | "database_locked" | "too_many_params" | "readonly" | "unknown";
55
+ /**
56
+ * Structured SQL error envelope — the failure kind plus the table,
57
+ * column, constraint, and hint parsed from the engine message.
58
+ * Available as `PerSQLError.detail` so callers can branch on
59
+ * `detail.kind` instead of string-matching messages.
60
+ */
50
61
  interface SqlErrorDetail {
51
62
  kind: SqlErrorKind;
52
63
  message: string;
@@ -60,6 +71,7 @@ interface SqlErrorDetail {
60
71
  near?: string;
61
72
  hint?: string;
62
73
  }
74
+ /** Constructor options for `PerSQL`. */
63
75
  interface PerSQLOptions {
64
76
  /** Bearer token. Get one at https://console.persql.com → Tokens. */
65
77
  token?: string;
@@ -82,6 +94,10 @@ interface PerSQLOptions {
82
94
  */
83
95
  local?: string;
84
96
  }
97
+ /**
98
+ * Result of a SQL statement — column names, positional rows, and the
99
+ * same rows reshaped as objects (`data`).
100
+ */
85
101
  interface QueryResult<T = Record<string, unknown>> {
86
102
  /** Column names in result-set order. */
87
103
  columns: string[];
@@ -91,6 +107,14 @@ interface QueryResult<T = Record<string, unknown>> {
91
107
  data: T[];
92
108
  rowsRead: number;
93
109
  rowsWritten: number;
110
+ /**
111
+ * SQLite `changes()` after a write statement — the exact affected-row
112
+ * count ORMs expect (`rowsWritten` also counts index writes). Absent
113
+ * on reads, DDL, and servers older than this field.
114
+ */
115
+ changes?: number;
116
+ /** SQLite `last_insert_rowid()` after a write statement. Absent on reads and DDL. */
117
+ lastInsertRowid?: number;
94
118
  /**
95
119
  * Per-call usage and cost the server echoes on `query()`. Undefined in
96
120
  * local mode (no server) and on the per-statement results of `batch()`
@@ -116,6 +140,7 @@ interface QueryMeta {
116
140
  } | null;
117
141
  queryLogId: string;
118
142
  }
143
+ /** Options for `db.batch()` — transaction wrapping and idempotency / plan-replay keys. */
119
144
  interface BatchOptions {
120
145
  /** Wrap all statements in BEGIN/COMMIT. Rolls back on first error. */
121
146
  transaction?: boolean;
@@ -212,6 +237,7 @@ interface SchemaDoctorReport {
212
237
  tablesScanned: number;
213
238
  generatedAt: string;
214
239
  }
240
+ /** Per-call options for `db.query()` — idempotency and plan-replay keys. */
215
241
  interface QueryOptions {
216
242
  idempotencyKey?: string;
217
243
  /** See `BatchOptions.planKey`. */
@@ -219,6 +245,7 @@ interface QueryOptions {
219
245
  /** See `BatchOptions.planStep`. */
220
246
  planStep?: string;
221
247
  }
248
+ /** One user table and its row count, as returned by `db.tables()`. */
222
249
  interface TableInfo {
223
250
  name: string;
224
251
  rowCount: number;
@@ -246,6 +273,7 @@ interface BatchExpect {
246
273
  rowsWrittenAtLeast?: number;
247
274
  rowsWrittenAtMost?: number;
248
275
  }
276
+ /** One entry of a `db.batch()` call — SQL, positional params, and an optional server-side assertion. */
249
277
  interface Statement {
250
278
  sql: string;
251
279
  params?: unknown[];
@@ -290,15 +318,22 @@ type ValidateResult = {
290
318
  error: string;
291
319
  errorDetail?: SqlErrorDetail;
292
320
  };
321
+ /**
322
+ * Thrown for any failed API call. `status` carries the HTTP status;
323
+ * `detail` (set on /query and /batch failures) is the parsed SQL
324
+ * error envelope.
325
+ */
293
326
  declare class PerSQLError extends Error {
294
327
  status: number;
295
328
  detail?: SqlErrorDetail;
296
329
  constructor(status: number, message: string, detail?: SqlErrorDetail);
297
330
  }
331
+ /** Thrown on HTTP 429. `retryAfterSeconds` echoes the server's Retry-After header. */
298
332
  declare class RateLimitError extends PerSQLError {
299
333
  retryAfterSeconds: number;
300
334
  constructor(retryAfterSeconds: number, message?: string);
301
335
  }
336
+ /** One approval rule a blocked write matched — which glob hit which table, and whether it requires approval or denies outright. */
302
337
  interface ApprovalRuleHit {
303
338
  ruleId: string;
304
339
  tableGlob: string;
@@ -325,6 +360,16 @@ declare class ApprovalRequiredError extends PerSQLError {
325
360
  expiresAt: string;
326
361
  });
327
362
  }
363
+ /**
364
+ * Entry point of the SDK. Construct with a bearer token — or with
365
+ * `{ local: ":memory:" }` for an in-process SQLite test database —
366
+ * then call `database()` for a handle to query.
367
+ *
368
+ * ```ts
369
+ * const persql = new PerSQL({ token: process.env.PERSQL_TOKEN! });
370
+ * const db = persql.database("acme/orders");
371
+ * ```
372
+ */
328
373
  declare class PerSQL {
329
374
  /** @internal — exposed read-only so PerSQLDatabase can build URLs. */
330
375
  readonly token: string;
@@ -406,6 +451,7 @@ declare class PerSQL {
406
451
  */
407
452
  get support(): SupportClient;
408
453
  }
454
+ /** Input for `persql.support.createTicket()`. */
409
455
  interface CreateSupportTicketOptions {
410
456
  subject: string;
411
457
  body: string;
@@ -414,6 +460,7 @@ interface CreateSupportTicketOptions {
414
460
  /** Caller-supplied extras merged into the ticket's diagnostic context. */
415
461
  errorContext?: Record<string, unknown>;
416
462
  }
463
+ /** Files support tickets from SDK code. Reached via `persql.support`. */
417
464
  declare class SupportClient {
418
465
  private readonly client;
419
466
  constructor(client: PerSQL);
@@ -421,6 +468,7 @@ declare class SupportClient {
421
468
  id: string;
422
469
  }>;
423
470
  }
471
+ /** Database metadata as returned by `persql.databases.create()` and `list()`. */
424
472
  interface DatabaseInfo {
425
473
  id: string;
426
474
  namespaceId: string;
@@ -435,6 +483,7 @@ interface DatabaseInfo {
435
483
  createdAt: string;
436
484
  updatedAt: string;
437
485
  }
486
+ /** Input for `persql.databases.create()`. */
438
487
  interface CreateDatabaseOptions {
439
488
  /** Display name, 1-50 chars. */
440
489
  name: string;
@@ -466,6 +515,11 @@ declare class PerSQLDatabases {
466
515
  nextCursor: string | null;
467
516
  }>;
468
517
  }
518
+ /**
519
+ * Handle to one database, addressed as `<namespace>/<slug>`. Obtained
520
+ * via `persql.database(...)`; all query, schema, branch, approval, and
521
+ * tool helpers live here.
522
+ */
469
523
  declare class PerSQLDatabase {
470
524
  private readonly client;
471
525
  readonly namespace: string;
@@ -730,7 +784,7 @@ declare class PerSQLDatabase {
730
784
  runTool(input: {
731
785
  sql: string;
732
786
  params?: unknown[];
733
- }): Promise<QueryResult<Record<string, unknown>>>;
787
+ }): Promise<QueryResult>;
734
788
  /**
735
789
  * Generate a *bundle* of typed tools — one per table — instead of one
736
790
  * generic `query` tool. Agents perform dramatically better with narrow
@@ -762,11 +816,13 @@ declare class PerSQLDatabase {
762
816
  */
763
817
  asTools(): Promise<DatabaseToolBundle>;
764
818
  }
819
+ /** Tool definition in the Anthropic Messages API shape — one `tools` entry for `messages.create`. */
765
820
  interface AnthropicTool {
766
821
  name: string;
767
822
  description: string;
768
823
  input_schema: Record<string, unknown>;
769
824
  }
825
+ /** Tool definition in the OpenAI Chat Completions shape — one `tools` entry for `chat.completions.create`. */
770
826
  interface OpenAiTool {
771
827
  type: "function";
772
828
  function: {
@@ -775,6 +831,7 @@ interface OpenAiTool {
775
831
  parameters: Record<string, unknown>;
776
832
  };
777
833
  }
834
+ /** Output of `db.asTool()` — one SQL-query tool rendered in every supported framework shape. */
778
835
  interface SingleToolBundle {
779
836
  /** Anthropic shape — pass as one entry of `tools` to messages.create. */
780
837
  anthropic: AnthropicTool;
@@ -789,6 +846,7 @@ interface SingleToolBundle {
789
846
  /** OpenAI Agents SDK shape — hand to `Agent({ tools: [...] })`. */
790
847
  openaiAgents: () => OpenAiAgentsTool[];
791
848
  }
849
+ /** Output of `db.asTools()` — typed per-table tools plus the `run` dispatcher, in every supported framework shape. */
792
850
  interface DatabaseToolBundle {
793
851
  /** Tool definitions in Anthropic shape — pass as `tools` to messages.create. */
794
852
  anthropic: AnthropicTool[];
@@ -822,11 +880,13 @@ interface DatabaseToolBundle {
822
880
  */
823
881
  openaiAgents: () => OpenAiAgentsTool[];
824
882
  }
883
+ /** Tool shape for the Vercel AI SDK — spread into `streamText({ tools })`. */
825
884
  interface AiSdkTool {
826
885
  description: string;
827
886
  inputSchema: Record<string, unknown>;
828
887
  execute: (input: Record<string, unknown>) => Promise<unknown>;
829
888
  }
889
+ /** Tool shape for Mastra — wrap with `createTool()` if you need the Mastra envelope. */
830
890
  interface MastraTool {
831
891
  id: string;
832
892
  description: string;
@@ -858,11 +918,14 @@ interface OpenAiAgentsTool {
858
918
  parameters: Record<string, unknown>;
859
919
  invoke: (input: Record<string, unknown>) => Promise<unknown>;
860
920
  }
921
+ /** Kind of row change reported by `db.subscribe()` and `db.changes()`. */
861
922
  type SubscribeChangeKind = "update" | "insert" | "delete" | "schema" | "unknown";
923
+ /** One row-change event delivered to `SubscribeOptions.onChange`. */
862
924
  interface SubscribeChange {
863
925
  table: string;
864
926
  kind: SubscribeChangeKind;
865
927
  }
928
+ /** Options for `db.subscribe()` — table filter and event callbacks. */
866
929
  interface SubscribeOptions {
867
930
  /** Tables to listen to. Omit / empty / `["*"]` = all tables. */
868
931
  tables?: string[];
@@ -895,7 +958,12 @@ interface BranchInfo {
895
958
  name: string;
896
959
  };
897
960
  }
961
+ /**
962
+ * How a branch is applied back to its parent: `schema` applies the DDL
963
+ * delta; `promote` replaces the parent's contents wholesale.
964
+ */
898
965
  type BranchMergeMode = "schema" | "promote";
966
+ /** One DDL operation in a branch-merge plan: create, drop, or replace. */
899
967
  type BranchMergePlanStep = {
900
968
  op: "create";
901
969
  type: string;
@@ -912,6 +980,7 @@ type BranchMergePlanStep = {
912
980
  beforeSql: string;
913
981
  afterSql: string;
914
982
  };
983
+ /** Outcome of `db.branches.merge()` — what was applied, the pre-merge snapshot, and the plan when previewing. */
915
984
  interface BranchMergeResult {
916
985
  mode: BranchMergeMode;
917
986
  preview: boolean;
@@ -925,6 +994,7 @@ interface BranchMergeResult {
925
994
  };
926
995
  note?: string;
927
996
  }
997
+ /** Options for `db.branches.upsert()`. */
928
998
  interface BranchUpsertOptions {
929
999
  /** Human-readable name. Defaults to `<parent name> (<ref>)`. */
930
1000
  name?: string;
@@ -933,6 +1003,7 @@ interface BranchUpsertOptions {
933
1003
  /** Auto-delete after N days (1..30). Null/undefined = keep until deleted. */
934
1004
  ttlDays?: number | null;
935
1005
  }
1006
+ /** Options for `db.branches.merge()`. */
936
1007
  interface BranchMergeOptions {
937
1008
  /** Default `schema`. `promote` replaces parent contents wholesale. */
938
1009
  mode?: BranchMergeMode;
@@ -943,6 +1014,7 @@ interface BranchMergeOptions {
943
1014
  /** Default true — captures `pre-merge:<ref>` snapshot of the parent. */
944
1015
  snapshot?: boolean;
945
1016
  }
1017
+ /** Output of `db.proposals.propose()` — the EXPLAIN plan, estimated affected rows, and the single-use execution token. */
946
1018
  interface ProposalPlan {
947
1019
  sql: string;
948
1020
  plan: unknown[][];
@@ -951,10 +1023,12 @@ interface ProposalPlan {
951
1023
  expiresAt: string;
952
1024
  action: "read" | "write" | "admin";
953
1025
  }
1026
+ /** Options for `db.proposals.propose()`. */
954
1027
  interface ProposeOptions {
955
1028
  params?: unknown[];
956
1029
  ttlSec?: number;
957
1030
  }
1031
+ /** Lifecycle state of an approval token, as returned by `db.approvals.get()` and `poll()`. */
958
1032
  interface ApprovalStatus {
959
1033
  status: "pending" | "approved" | "denied";
960
1034
  hits: ApprovalRuleHit[];
@@ -962,6 +1036,7 @@ interface ApprovalStatus {
962
1036
  expiresAt: string;
963
1037
  decidedAt: string | null;
964
1038
  }
1039
+ /** Pacing and cancellation options for `db.approvals.poll()`. */
965
1040
  interface PollApprovalOptions {
966
1041
  /** Default 2000ms. */
967
1042
  intervalMs?: number;
@@ -970,6 +1045,7 @@ interface PollApprovalOptions {
970
1045
  /** Cancellation signal. */
971
1046
  signal?: AbortSignal;
972
1047
  }
1048
+ /** Callbacks and pacing for `db.approvals.subscribe()`. */
973
1049
  interface SubscribeApprovalOptions {
974
1050
  onApprovalRequired?: (event: ApprovalEvent) => void;
975
1051
  onApprovalResolved?: (event: ApprovalEvent) => void;
@@ -980,11 +1056,17 @@ interface SubscribeApprovalOptions {
980
1056
  /** Logged-by-default error sink. */
981
1057
  onError?: (err: Error) => void;
982
1058
  }
1059
+ /** One approval state change delivered by `db.approvals.subscribe()`. */
983
1060
  interface ApprovalEvent {
984
1061
  approvalToken: string;
985
1062
  status: "pending" | "approved" | "denied";
986
1063
  hits: ApprovalRuleHit[];
987
1064
  }
1065
+ /**
1066
+ * Approval-token lifecycle for writes blocked by a require_approval
1067
+ * rule — look up, poll, subscribe, and redeem. Reached via
1068
+ * `db.approvals`.
1069
+ */
988
1070
  declare class PerSQLApprovals {
989
1071
  private readonly client;
990
1072
  private readonly namespace;
@@ -1023,6 +1105,7 @@ declare class PerSQLApprovals {
1023
1105
  */
1024
1106
  redeem<T = Record<string, unknown>>(approvalToken: string): Promise<QueryResult<T> | QueryResult<T>[]>;
1025
1107
  }
1108
+ /** A require_approval / deny rule on a database, as returned by `db.approvalRules.list()`. */
1026
1109
  interface ApprovalRule {
1027
1110
  id: string;
1028
1111
  databaseId: string;
@@ -1032,11 +1115,13 @@ interface ApprovalRule {
1032
1115
  createdById: string;
1033
1116
  createdAt: string;
1034
1117
  }
1118
+ /** Input for `db.approvalRules.create()`. */
1035
1119
  interface CreateApprovalRuleInput {
1036
1120
  tableGlob: string;
1037
1121
  action: "require_approval" | "deny";
1038
1122
  note?: string;
1039
1123
  }
1124
+ /** Manage the require_approval / deny rules of a database. Reached via `db.approvalRules`. */
1040
1125
  declare class PerSQLApprovalRules {
1041
1126
  private readonly client;
1042
1127
  private readonly namespace;
@@ -1050,6 +1135,11 @@ declare class PerSQLApprovalRules {
1050
1135
  deleted: true;
1051
1136
  }>;
1052
1137
  }
1138
+ /**
1139
+ * Two-phase writes: `propose()` pre-flights the SQL and mints a
1140
+ * single-use execution token; `apply()` redeems it. Reached via
1141
+ * `db.proposals`.
1142
+ */
1053
1143
  declare class PerSQLProposals {
1054
1144
  private readonly client;
1055
1145
  private readonly namespace;
@@ -1075,6 +1165,7 @@ declare class PerSQLProposals {
1075
1165
  */
1076
1166
  apply<T = Record<string, unknown>>(executionToken: string): Promise<QueryResult<T>>;
1077
1167
  }
1168
+ /** Output of `db.branches.claim()` — the fresh branch plus the scoped token minted for it. */
1078
1169
  interface ClaimedBranch {
1079
1170
  branchRef: string;
1080
1171
  databaseId: string;
@@ -1087,6 +1178,7 @@ interface ClaimedBranch {
1087
1178
  expiresAt: string;
1088
1179
  outcome: "created" | "reset";
1089
1180
  }
1181
+ /** Options for `db.branches.claim()`. */
1090
1182
  interface ClaimBranchOptions {
1091
1183
  /** Explicit ref. Omit to auto-generate from `purpose`. */
1092
1184
  ref?: string;
@@ -1098,6 +1190,11 @@ interface ClaimBranchOptions {
1098
1190
  role?: "read" | "write" | "admin";
1099
1191
  region?: string;
1100
1192
  }
1193
+ /**
1194
+ * Branch management for one database — list, create-or-reset, delete,
1195
+ * merge, pin (handoff), claim (lease), and migration rendering.
1196
+ * Reached via `db.branches`.
1197
+ */
1101
1198
  declare class PerSQLBranches {
1102
1199
  private readonly client;
1103
1200
  private readonly namespace;
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  PerSQLProposals,
11
11
  RateLimitError,
12
12
  SupportClient
13
- } from "./chunk-GH75ERQ6.js";
13
+ } from "./chunk-SIJU2P7U.js";
14
14
  export {
15
15
  ApprovalRequiredError,
16
16
  PerSQL,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@persql/sdk",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "TypeScript SDK for PerSQL — SQLite databases on the edge for AI agents",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -30,7 +30,7 @@
30
30
  "vitest": "^3.1.1"
31
31
  },
32
32
  "peerDependencies": {
33
- "better-sqlite3": "^11.0.0"
33
+ "better-sqlite3": "^11.0.0 || ^12.0.0"
34
34
  },
35
35
  "peerDependenciesMeta": {
36
36
  "better-sqlite3": {