@fadhilp/stateql 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -108,6 +108,7 @@ export declare class StateStore {
108
108
  ensureSession(name?: string): SessionRecord;
109
109
  createSession(name: string): SessionRecord;
110
110
  getSession(idOrName: string): SessionRecord | undefined;
111
+ getSessionByName(name: string): SessionRecord | undefined;
111
112
  listSessions(): SessionRecord[];
112
113
  closeSession(sessionId: string): void;
113
114
  addProfile(input: {
@@ -240,6 +241,7 @@ export declare class StateStore {
240
241
  knownResults(sessionId: string, limit: number): Array<ResultRecord & {
241
242
  alias: string | null;
242
243
  }>;
244
+ private deleteExpiredData;
243
245
  private recoverStaleCommittingTransactions;
244
246
  private migrate;
245
247
  }
package/dist/src/store.js CHANGED
@@ -16,6 +16,7 @@ export class StateStore {
16
16
  this.db.exec("PRAGMA foreign_keys = ON");
17
17
  this.migrate();
18
18
  this.recoverStaleCommittingTransactions();
19
+ this.deleteExpiredData();
19
20
  }
20
21
  close() {
21
22
  this.db.close();
@@ -30,10 +31,20 @@ export class StateStore {
30
31
  return `${prefix}_${row.value}`;
31
32
  }
32
33
  ensureSession(name = "default") {
33
- const existing = this.getSession(name);
34
+ const existing = this.getSessionByName(name);
34
35
  if (existing)
35
36
  return existing;
36
- return this.createSession(name);
37
+ const closed = this.db
38
+ .prepare("SELECT id FROM sessions WHERE name = ? LIMIT 1")
39
+ .get(name);
40
+ if (!closed)
41
+ return this.createSession(name);
42
+ this.db
43
+ .prepare(`UPDATE sessions
44
+ SET status = 'active', active_transaction_id = NULL, updated_at = ?
45
+ WHERE id = ?`)
46
+ .run(this.now().toISOString(), closed.id);
47
+ return this.getSessionByName(name);
37
48
  }
38
49
  createSession(name) {
39
50
  const timestamp = this.now().toISOString();
@@ -52,6 +63,11 @@ export class StateStore {
52
63
  LIMIT 1`)
53
64
  .get(idOrName, idOrName);
54
65
  }
66
+ getSessionByName(name) {
67
+ return this.db
68
+ .prepare("SELECT * FROM sessions WHERE name = ? AND status = 'active' LIMIT 1")
69
+ .get(name);
70
+ }
55
71
  listSessions() {
56
72
  return this.db
57
73
  .prepare("SELECT * FROM sessions ORDER BY created_at")
@@ -462,6 +478,25 @@ export class StateStore {
462
478
  LIMIT ?`)
463
479
  .all(sessionId, limit);
464
480
  }
481
+ deleteExpiredData() {
482
+ const timestamp = this.now().toISOString();
483
+ this.db.exec("BEGIN IMMEDIATE");
484
+ try {
485
+ this.db
486
+ .prepare(`DELETE FROM aliases
487
+ WHERE result_id IN (
488
+ SELECT id FROM results WHERE expires_at <= ?
489
+ )`)
490
+ .run(timestamp);
491
+ this.db.prepare("DELETE FROM results WHERE expires_at <= ?").run(timestamp);
492
+ this.db.prepare("DELETE FROM plans WHERE expires_at <= ?").run(timestamp);
493
+ this.db.exec("COMMIT");
494
+ }
495
+ catch (error) {
496
+ this.db.exec("ROLLBACK");
497
+ throw error;
498
+ }
499
+ }
465
500
  recoverStaleCommittingTransactions() {
466
501
  const timestamp = this.now().toISOString();
467
502
  const cutoff = new Date(this.now().getTime() - 5 * 60_000).toISOString();
@@ -1,4 +1,4 @@
1
- export type Driver = "sqlite" | "postgres";
1
+ export type Driver = "sqlite" | "postgres" | "mysql";
2
2
  export type StateConfidence = "authoritative" | "transaction_snapshot" | "database_reported" | "local" | "ttl_based" | "unknown";
3
3
  export interface Warning {
4
4
  code: string;
@@ -34,7 +34,11 @@ export interface Failure {
34
34
  }
35
35
  export type Response<T> = Success<T> | Failure;
36
36
  export type SqlParameters = unknown[] | Record<string, unknown>;
37
- export interface StateQLOptions {
37
+ export interface ExecutionOptions {
38
+ timeoutMs?: number;
39
+ signal?: AbortSignal;
40
+ }
41
+ export interface StateQLOptions extends ExecutionOptions {
38
42
  home?: string;
39
43
  session?: string;
40
44
  previewRows?: number;
@@ -42,23 +46,24 @@ export interface StateQLOptions {
42
46
  resultTtlSeconds?: number;
43
47
  maxCellCharacters?: number;
44
48
  maxResultRows?: number;
49
+ maxResultBytes?: number;
45
50
  now?: () => Date;
46
51
  }
47
- export interface QueryOptions {
52
+ export interface QueryOptions extends ExecutionOptions {
48
53
  params?: SqlParameters;
49
54
  cache?: "auto" | "bypass" | "require";
50
55
  }
51
56
  export interface FilterOptions {
52
57
  params?: SqlParameters;
53
58
  }
54
- export interface ExecOptions {
59
+ export interface ExecOptions extends ExecutionOptions {
55
60
  params?: SqlParameters;
56
61
  replay?: boolean;
57
62
  idempotencyKey?: string;
58
63
  allowUnbounded?: boolean;
59
64
  allowDestructive?: boolean;
60
65
  }
61
- export interface ConnectOptions {
66
+ export interface ConnectOptions extends ExecutionOptions {
62
67
  name?: string;
63
68
  readOnly?: boolean;
64
69
  secretEnv?: string;
@@ -72,7 +77,7 @@ export interface RowsOptions {
72
77
  offset?: number;
73
78
  limit?: number;
74
79
  }
75
- export interface PlanOptions {
80
+ export interface PlanOptions extends ExecutionOptions {
76
81
  params?: SqlParameters;
77
82
  allowUnbounded?: boolean;
78
83
  allowDestructive?: boolean;
@@ -100,6 +105,7 @@ export interface BatchCommand {
100
105
  offset?: number;
101
106
  limit?: number;
102
107
  isolation?: string;
108
+ timeout_ms?: number;
103
109
  }
104
110
  export interface BatchOptions {
105
111
  continueOnError?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fadhilp/stateql",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Stateful, agent-oriented database CLI for safe result reuse",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,11 +25,12 @@
25
25
  ],
26
26
  "scripts": {
27
27
  "build": "tsc -p tsconfig.json",
28
- "test": "npm run build && node --test dist/test/stateql.test.js",
28
+ "test": "npm run build && node --test dist/test/cli.test.js dist/test/mysql.test.js dist/test/postgres.test.js dist/test/query.test.js dist/test/sqlite.test.js dist/test/store.test.js dist/test/terminal.test.js dist/test/transaction.test.js dist/test/write.test.js",
29
29
  "prepack": "npm test"
30
30
  },
31
31
  "keywords": [
32
32
  "database",
33
+ "mysql",
33
34
  "sqlite",
34
35
  "postgresql",
35
36
  "cli",
@@ -41,12 +42,14 @@
41
42
  "node": ">=22.5"
42
43
  },
43
44
  "dependencies": {
45
+ "mysql2": "^3.23.1",
44
46
  "node-sql-parser": "^5.4.0",
45
47
  "pg": "^8.16.3"
46
48
  },
47
49
  "devDependencies": {
48
50
  "@types/node": "^24.0.0",
49
51
  "@types/pg": "^8.15.5",
52
+ "node-pty": "^1.1.0",
50
53
  "typescript": "^7.0.0"
51
54
  }
52
55
  }