@fadhilp/stateql 0.1.2 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -20
- package/dist/src/adapters.d.ts +15 -1
- package/dist/src/adapters.js +631 -181
- package/dist/src/cli.js +16 -3
- package/dist/src/connection.d.ts +10 -0
- package/dist/src/connection.js +51 -0
- package/dist/src/errors.js +6 -2
- package/dist/src/filter.d.ts +14 -0
- package/dist/src/filter.js +256 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/response-data.d.ts +8 -0
- package/dist/src/response-data.js +66 -0
- package/dist/src/sql.js +8 -2
- package/dist/src/sqlite-process.d.ts +1 -0
- package/dist/src/sqlite-process.js +240 -0
- package/dist/src/stateql.d.ts +15 -5
- package/dist/src/stateql.js +189 -397
- package/dist/src/store.d.ts +2 -0
- package/dist/src/store.js +37 -2
- package/dist/src/types.d.ts +56 -6
- package/package.json +5 -2
package/dist/src/store.d.ts
CHANGED
|
@@ -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.
|
|
34
|
+
const existing = this.getSessionByName(name);
|
|
34
35
|
if (existing)
|
|
35
36
|
return existing;
|
|
36
|
-
|
|
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();
|
package/dist/src/types.d.ts
CHANGED
|
@@ -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;
|
|
@@ -33,8 +33,56 @@ export interface Failure {
|
|
|
33
33
|
meta: ResponseMeta;
|
|
34
34
|
}
|
|
35
35
|
export type Response<T> = Success<T> | Failure;
|
|
36
|
+
export interface HistoryEntry {
|
|
37
|
+
command_id: string;
|
|
38
|
+
timestamp: string;
|
|
39
|
+
session_id: string;
|
|
40
|
+
command: string;
|
|
41
|
+
handle: string | null;
|
|
42
|
+
executed: boolean;
|
|
43
|
+
cached: boolean;
|
|
44
|
+
success: boolean;
|
|
45
|
+
error_code: string | null;
|
|
46
|
+
}
|
|
47
|
+
export interface StateQLSnapshot {
|
|
48
|
+
session: {
|
|
49
|
+
session_id: string;
|
|
50
|
+
name: string;
|
|
51
|
+
status: string;
|
|
52
|
+
};
|
|
53
|
+
connection: {
|
|
54
|
+
connection_id: string;
|
|
55
|
+
name: string;
|
|
56
|
+
status: "connected";
|
|
57
|
+
driver: Driver;
|
|
58
|
+
database: string;
|
|
59
|
+
read_only: boolean;
|
|
60
|
+
} | null;
|
|
61
|
+
transaction: {
|
|
62
|
+
transaction_id: string;
|
|
63
|
+
state: string;
|
|
64
|
+
} | null;
|
|
65
|
+
state_version: string | null;
|
|
66
|
+
state_confidence: StateConfidence | null;
|
|
67
|
+
recent_results: Array<{
|
|
68
|
+
alias: string | null;
|
|
69
|
+
handle: string;
|
|
70
|
+
rows: number;
|
|
71
|
+
}>;
|
|
72
|
+
recent_operations: Array<{
|
|
73
|
+
handle: string;
|
|
74
|
+
type: string;
|
|
75
|
+
affected_rows: number | null;
|
|
76
|
+
status: string;
|
|
77
|
+
}>;
|
|
78
|
+
history: HistoryEntry[];
|
|
79
|
+
}
|
|
36
80
|
export type SqlParameters = unknown[] | Record<string, unknown>;
|
|
37
|
-
export interface
|
|
81
|
+
export interface ExecutionOptions {
|
|
82
|
+
timeoutMs?: number;
|
|
83
|
+
signal?: AbortSignal;
|
|
84
|
+
}
|
|
85
|
+
export interface StateQLOptions extends ExecutionOptions {
|
|
38
86
|
home?: string;
|
|
39
87
|
session?: string;
|
|
40
88
|
previewRows?: number;
|
|
@@ -42,23 +90,24 @@ export interface StateQLOptions {
|
|
|
42
90
|
resultTtlSeconds?: number;
|
|
43
91
|
maxCellCharacters?: number;
|
|
44
92
|
maxResultRows?: number;
|
|
93
|
+
maxResultBytes?: number;
|
|
45
94
|
now?: () => Date;
|
|
46
95
|
}
|
|
47
|
-
export interface QueryOptions {
|
|
96
|
+
export interface QueryOptions extends ExecutionOptions {
|
|
48
97
|
params?: SqlParameters;
|
|
49
98
|
cache?: "auto" | "bypass" | "require";
|
|
50
99
|
}
|
|
51
100
|
export interface FilterOptions {
|
|
52
101
|
params?: SqlParameters;
|
|
53
102
|
}
|
|
54
|
-
export interface ExecOptions {
|
|
103
|
+
export interface ExecOptions extends ExecutionOptions {
|
|
55
104
|
params?: SqlParameters;
|
|
56
105
|
replay?: boolean;
|
|
57
106
|
idempotencyKey?: string;
|
|
58
107
|
allowUnbounded?: boolean;
|
|
59
108
|
allowDestructive?: boolean;
|
|
60
109
|
}
|
|
61
|
-
export interface ConnectOptions {
|
|
110
|
+
export interface ConnectOptions extends ExecutionOptions {
|
|
62
111
|
name?: string;
|
|
63
112
|
readOnly?: boolean;
|
|
64
113
|
secretEnv?: string;
|
|
@@ -72,7 +121,7 @@ export interface RowsOptions {
|
|
|
72
121
|
offset?: number;
|
|
73
122
|
limit?: number;
|
|
74
123
|
}
|
|
75
|
-
export interface PlanOptions {
|
|
124
|
+
export interface PlanOptions extends ExecutionOptions {
|
|
76
125
|
params?: SqlParameters;
|
|
77
126
|
allowUnbounded?: boolean;
|
|
78
127
|
allowDestructive?: boolean;
|
|
@@ -100,6 +149,7 @@ export interface BatchCommand {
|
|
|
100
149
|
offset?: number;
|
|
101
150
|
limit?: number;
|
|
102
151
|
isolation?: string;
|
|
152
|
+
timeout_ms?: number;
|
|
103
153
|
}
|
|
104
154
|
export interface BatchOptions {
|
|
105
155
|
continueOnError?: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fadhilp/stateql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.2",
|
|
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/
|
|
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
|
}
|