@fadhilp/stateql 0.5.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -23
- package/dist/src/adapters.d.ts +1 -0
- package/dist/src/adapters.js +19 -6
- package/dist/src/cli.js +48 -2
- package/dist/src/connection.d.ts +1 -0
- package/dist/src/connection.js +29 -3
- package/dist/src/index.d.ts +1 -1
- package/dist/src/migrations.js +22 -0
- package/dist/src/mongodb.d.ts +48 -0
- package/dist/src/mongodb.js +868 -0
- package/dist/src/response-data.js +12 -0
- package/dist/src/sql.d.ts +3 -1
- package/dist/src/sql.js +3 -0
- package/dist/src/stateql.d.ts +11 -3
- package/dist/src/stateql.js +730 -154
- package/dist/src/store.d.ts +8 -3
- package/dist/src/store.js +20 -14
- package/dist/src/types.d.ts +103 -2
- package/package.json +3 -2
package/dist/src/store.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DatabaseSync } from "node:sqlite";
|
|
2
|
-
import type { Column, Driver, Row, SqlParameters, StateConfidence } from "./types.js";
|
|
2
|
+
import type { Column, CommandOrigin, Driver, MongoWriteOutcome, Row, SqlParameters, StateConfidence } from "./types.js";
|
|
3
3
|
export interface SessionRecord {
|
|
4
4
|
id: string;
|
|
5
5
|
name: string;
|
|
@@ -61,6 +61,7 @@ export interface OperationRecord {
|
|
|
61
61
|
idempotency_key: string | null;
|
|
62
62
|
state_version_before: string;
|
|
63
63
|
state_version_after: string | null;
|
|
64
|
+
outcome_json: string | null;
|
|
64
65
|
created_at: string;
|
|
65
66
|
}
|
|
66
67
|
export interface TransactionRecord {
|
|
@@ -97,6 +98,7 @@ export interface HistoryRecord {
|
|
|
97
98
|
timestamp: string;
|
|
98
99
|
session_id: string;
|
|
99
100
|
actor_id: string;
|
|
101
|
+
origin: CommandOrigin;
|
|
100
102
|
command: string;
|
|
101
103
|
sql: string | null;
|
|
102
104
|
handle: string | null;
|
|
@@ -211,7 +213,7 @@ export declare class StateStore {
|
|
|
211
213
|
previous?: OperationRecord;
|
|
212
214
|
denied?: "membership" | "transaction";
|
|
213
215
|
};
|
|
214
|
-
finishOperation(operationId: string, affectedRows: number, stateVersion: string): OperationRecord;
|
|
216
|
+
finishOperation(operationId: string, affectedRows: number, stateVersion: string, outcome?: MongoWriteOutcome): OperationRecord;
|
|
215
217
|
failOperation(operationId: string): void;
|
|
216
218
|
markOperationOutcomeUnknown(operationId: string): void;
|
|
217
219
|
createTransaction(input: {
|
|
@@ -235,6 +237,7 @@ export declare class StateStore {
|
|
|
235
237
|
operations: Array<{
|
|
236
238
|
id: string;
|
|
237
239
|
affectedRows: number;
|
|
240
|
+
outcome?: MongoWriteOutcome;
|
|
238
241
|
}>;
|
|
239
242
|
}): string;
|
|
240
243
|
savePlan(input: {
|
|
@@ -260,6 +263,7 @@ export declare class StateStore {
|
|
|
260
263
|
operationId: string;
|
|
261
264
|
connectionId: string;
|
|
262
265
|
affectedRows: number;
|
|
266
|
+
outcome?: MongoWriteOutcome;
|
|
263
267
|
}): {
|
|
264
268
|
operation: OperationRecord;
|
|
265
269
|
stateVersion: string;
|
|
@@ -267,6 +271,7 @@ export declare class StateStore {
|
|
|
267
271
|
addHistory(input: {
|
|
268
272
|
sessionId: string;
|
|
269
273
|
actorId: string;
|
|
274
|
+
origin?: CommandOrigin;
|
|
270
275
|
command: string;
|
|
271
276
|
sql?: string;
|
|
272
277
|
handle?: string;
|
|
@@ -276,7 +281,7 @@ export declare class StateStore {
|
|
|
276
281
|
errorCode?: string;
|
|
277
282
|
id?: string;
|
|
278
283
|
}): HistoryRecord;
|
|
279
|
-
history(sessionId: string, limit: number): HistoryRecord[];
|
|
284
|
+
history(sessionId: string, limit: number, origin?: CommandOrigin): HistoryRecord[];
|
|
280
285
|
recentOperations(sessionId: string, limit: number): OperationRecord[];
|
|
281
286
|
knownResults(sessionId: string, limit: number): Array<ResultRecord & {
|
|
282
287
|
alias: string | null;
|
package/dist/src/store.js
CHANGED
|
@@ -480,12 +480,13 @@ export class StateStore {
|
|
|
480
480
|
throw error;
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
|
-
finishOperation(operationId, affectedRows, stateVersion) {
|
|
483
|
+
finishOperation(operationId, affectedRows, stateVersion, outcome) {
|
|
484
484
|
this.db
|
|
485
485
|
.prepare(`UPDATE operations
|
|
486
|
-
SET status = 'committed', affected_rows = ?, state_version_after =
|
|
486
|
+
SET status = 'committed', affected_rows = ?, state_version_after = ?,
|
|
487
|
+
outcome_json = ?
|
|
487
488
|
WHERE id = ?`)
|
|
488
|
-
.run(affectedRows, stateVersion, operationId);
|
|
489
|
+
.run(affectedRows, stateVersion, outcomeJson(outcome), operationId);
|
|
489
490
|
return this.getOperation(operationId);
|
|
490
491
|
}
|
|
491
492
|
failOperation(operationId) {
|
|
@@ -695,9 +696,10 @@ export class StateStore {
|
|
|
695
696
|
stateVersion = `sv_${row.version}`;
|
|
696
697
|
this.db
|
|
697
698
|
.prepare(`UPDATE operations
|
|
698
|
-
SET status = 'committed', affected_rows = ?, state_version_after =
|
|
699
|
+
SET status = 'committed', affected_rows = ?, state_version_after = ?,
|
|
700
|
+
outcome_json = ?
|
|
699
701
|
WHERE id = ?`)
|
|
700
|
-
.run(operation.affectedRows, stateVersion, operation.id);
|
|
702
|
+
.run(operation.affectedRows, stateVersion, outcomeJson(operation.outcome), operation.id);
|
|
701
703
|
}
|
|
702
704
|
this.db
|
|
703
705
|
.prepare(`UPDATE transactions
|
|
@@ -772,9 +774,10 @@ export class StateStore {
|
|
|
772
774
|
const stateVersion = `sv_${row.version}`;
|
|
773
775
|
this.db
|
|
774
776
|
.prepare(`UPDATE operations
|
|
775
|
-
SET status = 'committed', affected_rows = ?, state_version_after =
|
|
777
|
+
SET status = 'committed', affected_rows = ?, state_version_after = ?,
|
|
778
|
+
outcome_json = ?
|
|
776
779
|
WHERE id = ?`)
|
|
777
|
-
.run(input.affectedRows, stateVersion, input.operationId);
|
|
780
|
+
.run(input.affectedRows, stateVersion, outcomeJson(input.outcome), input.operationId);
|
|
778
781
|
this.db
|
|
779
782
|
.prepare(`UPDATE plans SET applied_operation_id = ?, claim_token = NULL
|
|
780
783
|
WHERE id = ? AND claim_token = ?`)
|
|
@@ -792,10 +795,10 @@ export class StateStore {
|
|
|
792
795
|
const id = input.id ?? this.nextId("cmd");
|
|
793
796
|
this.db
|
|
794
797
|
.prepare(`INSERT INTO history
|
|
795
|
-
(id, timestamp, session_id, actor_id, command, sql, handle,
|
|
796
|
-
cached, success, error_code)
|
|
797
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
798
|
-
.run(id, this.now().toISOString(), input.sessionId, input.actorId, input.command, boundedHistorySql(input.sql), input.handle ?? null, input.executed ? 1 : 0, input.cached ? 1 : 0, input.success ? 1 : 0, input.errorCode ?? null);
|
|
798
|
+
(id, timestamp, session_id, actor_id, origin, command, sql, handle,
|
|
799
|
+
executed, cached, success, error_code)
|
|
800
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
801
|
+
.run(id, this.now().toISOString(), input.sessionId, input.actorId, input.origin ?? "legacy", input.command, boundedHistorySql(input.sql), input.handle ?? null, input.executed ? 1 : 0, input.cached ? 1 : 0, input.success ? 1 : 0, input.errorCode ?? null);
|
|
799
802
|
this.db
|
|
800
803
|
.prepare(`DELETE FROM history
|
|
801
804
|
WHERE rowid IN (
|
|
@@ -809,13 +812,13 @@ export class StateStore {
|
|
|
809
812
|
.prepare("SELECT * FROM history WHERE id = ?")
|
|
810
813
|
.get(id);
|
|
811
814
|
}
|
|
812
|
-
history(sessionId, limit) {
|
|
815
|
+
history(sessionId, limit, origin) {
|
|
813
816
|
return this.db
|
|
814
817
|
.prepare(`SELECT * FROM history
|
|
815
|
-
WHERE session_id = ?
|
|
818
|
+
WHERE session_id = ?${origin === undefined ? "" : " AND origin = ?"}
|
|
816
819
|
ORDER BY rowid DESC
|
|
817
820
|
LIMIT ?`)
|
|
818
|
-
.all(sessionId, limit);
|
|
821
|
+
.all(...(origin === undefined ? [sessionId, limit] : [sessionId, origin, limit]));
|
|
819
822
|
}
|
|
820
823
|
recentOperations(sessionId, limit) {
|
|
821
824
|
return this.db
|
|
@@ -1011,6 +1014,9 @@ export class StateStore {
|
|
|
1011
1014
|
}
|
|
1012
1015
|
}
|
|
1013
1016
|
}
|
|
1017
|
+
function outcomeJson(outcome) {
|
|
1018
|
+
return outcome === undefined ? null : JSON.stringify(toJsonSafe(outcome));
|
|
1019
|
+
}
|
|
1014
1020
|
function boundedHistorySql(sql) {
|
|
1015
1021
|
if (sql === undefined)
|
|
1016
1022
|
return null;
|
package/dist/src/types.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type SqlDriver = "sqlite" | "postgres" | "mysql";
|
|
2
|
+
export type Driver = SqlDriver | "mongodb";
|
|
3
|
+
export type CommandOrigin = "legacy" | "user" | "model" | "system" | "api";
|
|
4
|
+
/** Trusted host metadata for one executeCommand call; never part of BatchCommand input. */
|
|
5
|
+
export interface CommandExecutionContext {
|
|
6
|
+
signal?: AbortSignal;
|
|
7
|
+
origin?: CommandOrigin;
|
|
8
|
+
}
|
|
2
9
|
export type CredentialAccess = "read" | "write";
|
|
3
10
|
export type CredentialOperation = "connect" | "query" | "inspect" | "plan" | "exec" | "apply" | "transaction.commit";
|
|
4
11
|
export interface CredentialRequest {
|
|
@@ -63,6 +70,7 @@ export interface HistoryEntry {
|
|
|
63
70
|
timestamp: string;
|
|
64
71
|
session_id: string;
|
|
65
72
|
actor_id: string;
|
|
73
|
+
origin: CommandOrigin;
|
|
66
74
|
command: string;
|
|
67
75
|
sql: string | null;
|
|
68
76
|
handle: string | null;
|
|
@@ -108,10 +116,84 @@ export interface StateQLSnapshot {
|
|
|
108
116
|
history: HistoryEntry[];
|
|
109
117
|
}
|
|
110
118
|
export type SqlParameters = unknown[] | Record<string, unknown>;
|
|
119
|
+
export type MongoDocument = Record<string, unknown>;
|
|
120
|
+
export interface MongoFindOptions {
|
|
121
|
+
projection?: MongoDocument;
|
|
122
|
+
sort?: MongoDocument | Array<[string, 1 | -1]>;
|
|
123
|
+
skip?: number;
|
|
124
|
+
limit?: number;
|
|
125
|
+
hint?: string | MongoDocument;
|
|
126
|
+
collation?: MongoDocument;
|
|
127
|
+
}
|
|
128
|
+
export interface MongoAggregateOptions {
|
|
129
|
+
allowDiskUse?: boolean;
|
|
130
|
+
hint?: string | MongoDocument;
|
|
131
|
+
collation?: MongoDocument;
|
|
132
|
+
}
|
|
133
|
+
export interface MongoMutationOptions {
|
|
134
|
+
upsert?: boolean;
|
|
135
|
+
collation?: MongoDocument;
|
|
136
|
+
hint?: string | MongoDocument;
|
|
137
|
+
}
|
|
138
|
+
export type MongoReadCommand = {
|
|
139
|
+
operation: "find";
|
|
140
|
+
collection: string;
|
|
141
|
+
filter?: MongoDocument;
|
|
142
|
+
options?: MongoFindOptions;
|
|
143
|
+
} | {
|
|
144
|
+
operation: "aggregate";
|
|
145
|
+
collection: string;
|
|
146
|
+
pipeline: MongoDocument[];
|
|
147
|
+
options?: MongoAggregateOptions;
|
|
148
|
+
};
|
|
149
|
+
export type MongoWriteCommand = {
|
|
150
|
+
operation: "insertOne";
|
|
151
|
+
collection: string;
|
|
152
|
+
document: MongoDocument;
|
|
153
|
+
options?: Record<string, never>;
|
|
154
|
+
} | {
|
|
155
|
+
operation: "insertMany";
|
|
156
|
+
collection: string;
|
|
157
|
+
documents: MongoDocument[];
|
|
158
|
+
options?: {
|
|
159
|
+
ordered?: boolean;
|
|
160
|
+
};
|
|
161
|
+
} | {
|
|
162
|
+
operation: "updateOne" | "updateMany";
|
|
163
|
+
collection: string;
|
|
164
|
+
filter: MongoDocument;
|
|
165
|
+
update: MongoDocument | MongoDocument[];
|
|
166
|
+
options?: MongoMutationOptions;
|
|
167
|
+
} | {
|
|
168
|
+
operation: "replaceOne";
|
|
169
|
+
collection: string;
|
|
170
|
+
filter: MongoDocument;
|
|
171
|
+
replacement: MongoDocument;
|
|
172
|
+
options?: MongoMutationOptions;
|
|
173
|
+
} | {
|
|
174
|
+
operation: "deleteOne" | "deleteMany";
|
|
175
|
+
collection: string;
|
|
176
|
+
filter: MongoDocument;
|
|
177
|
+
options?: Omit<MongoMutationOptions, "upsert">;
|
|
178
|
+
};
|
|
179
|
+
export interface MongoWriteOutcome {
|
|
180
|
+
acknowledged: boolean;
|
|
181
|
+
inserted_id?: unknown;
|
|
182
|
+
inserted_ids?: unknown[];
|
|
183
|
+
inserted_count?: number;
|
|
184
|
+
matched_count?: number;
|
|
185
|
+
modified_count?: number;
|
|
186
|
+
upserted_count?: number;
|
|
187
|
+
upserted_id?: unknown;
|
|
188
|
+
deleted_count?: number;
|
|
189
|
+
}
|
|
111
190
|
export interface ExecutionOptions {
|
|
112
191
|
timeoutMs?: number;
|
|
113
192
|
signal?: AbortSignal;
|
|
114
193
|
}
|
|
194
|
+
export interface HistoryOptions {
|
|
195
|
+
origin?: CommandOrigin;
|
|
196
|
+
}
|
|
115
197
|
export interface StateQLOptions extends ExecutionOptions {
|
|
116
198
|
home?: string;
|
|
117
199
|
session?: string;
|
|
@@ -133,6 +215,9 @@ export interface QueryOptions extends ExecutionOptions {
|
|
|
133
215
|
params?: SqlParameters;
|
|
134
216
|
cache?: "auto" | "bypass" | "require";
|
|
135
217
|
}
|
|
218
|
+
export interface MongoQueryOptions extends ExecutionOptions {
|
|
219
|
+
cache?: "auto" | "bypass" | "require";
|
|
220
|
+
}
|
|
136
221
|
export interface FilterOptions {
|
|
137
222
|
params?: SqlParameters;
|
|
138
223
|
}
|
|
@@ -143,6 +228,12 @@ export interface ExecOptions extends ExecutionOptions {
|
|
|
143
228
|
allowUnbounded?: boolean;
|
|
144
229
|
allowDestructive?: boolean;
|
|
145
230
|
}
|
|
231
|
+
export interface MongoExecOptions extends ExecutionOptions {
|
|
232
|
+
replay?: boolean;
|
|
233
|
+
idempotencyKey?: string;
|
|
234
|
+
allowUnbounded?: boolean;
|
|
235
|
+
allowDestructive?: boolean;
|
|
236
|
+
}
|
|
146
237
|
export interface ConnectOptions extends ExecutionOptions {
|
|
147
238
|
name?: string;
|
|
148
239
|
readOnly?: boolean;
|
|
@@ -162,7 +253,11 @@ export interface PlanOptions extends ExecutionOptions {
|
|
|
162
253
|
allowUnbounded?: boolean;
|
|
163
254
|
allowDestructive?: boolean;
|
|
164
255
|
}
|
|
165
|
-
export
|
|
256
|
+
export interface MongoPlanOptions extends ExecutionOptions {
|
|
257
|
+
allowUnbounded?: boolean;
|
|
258
|
+
allowDestructive?: boolean;
|
|
259
|
+
}
|
|
260
|
+
export type BatchCommandName = "connect" | "disconnect" | "status" | "profile.add" | "profile.list" | "profile.show" | "profile.remove" | "session.start" | "session.list" | "session.show" | "session.summary" | "session.close" | "query" | "filter" | "exec" | "show" | "rows" | "count" | "columns" | "alias.set" | "inspect" | "transaction.begin" | "transaction.status" | "transaction.commit" | "transaction.rollback" | "plan" | "mongo.query" | "mongo.exec" | "mongo.plan" | "apply" | "history" | "receipt" | "doctor" | "purge" | "capabilities";
|
|
166
261
|
export interface BatchCommand {
|
|
167
262
|
command: BatchCommandName;
|
|
168
263
|
target?: string;
|
|
@@ -174,6 +269,7 @@ export interface BatchCommand {
|
|
|
174
269
|
kind?: string;
|
|
175
270
|
table?: string;
|
|
176
271
|
params?: SqlParameters;
|
|
272
|
+
mongo?: MongoReadCommand | MongoWriteCommand;
|
|
177
273
|
cache?: "auto" | "bypass" | "require";
|
|
178
274
|
read_only?: boolean;
|
|
179
275
|
secret_env?: string;
|
|
@@ -186,11 +282,14 @@ export interface BatchCommand {
|
|
|
186
282
|
limit?: number;
|
|
187
283
|
isolation?: string;
|
|
188
284
|
timeout_ms?: number;
|
|
285
|
+
/** Retrieval filter for the history command; does not attribute this command. */
|
|
286
|
+
history_origin?: CommandOrigin;
|
|
189
287
|
scope?: "expired" | "results" | "history" | "all";
|
|
190
288
|
}
|
|
191
289
|
export interface BatchOptions {
|
|
192
290
|
continueOnError?: boolean;
|
|
193
291
|
maxCommands?: number;
|
|
292
|
+
executionContext?: CommandExecutionContext;
|
|
194
293
|
}
|
|
195
294
|
export interface Column {
|
|
196
295
|
name: string;
|
|
@@ -355,6 +454,7 @@ export interface OperationData {
|
|
|
355
454
|
state_version_before: string;
|
|
356
455
|
state_version_after: string | null;
|
|
357
456
|
replay_of?: string;
|
|
457
|
+
outcome?: MongoWriteOutcome;
|
|
358
458
|
}
|
|
359
459
|
export interface ExecData extends OperationData {
|
|
360
460
|
duplicate?: boolean;
|
|
@@ -421,6 +521,7 @@ export interface PurgeData {
|
|
|
421
521
|
export interface CapabilitiesData {
|
|
422
522
|
drivers: Driver[];
|
|
423
523
|
features: Record<string, boolean>;
|
|
524
|
+
driver_features?: Partial<Record<Driver, Record<string, boolean>>>;
|
|
424
525
|
}
|
|
425
526
|
export interface RemovedProfileData {
|
|
426
527
|
profile: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fadhilp/stateql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Stateful, agent-oriented database CLI for safe result reuse",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
],
|
|
26
26
|
"scripts": {
|
|
27
27
|
"build": "tsc -p tsconfig.json",
|
|
28
|
-
"test": "npm run build && node --test dist/test/cli.test.js dist/test/credential.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",
|
|
28
|
+
"test": "npm run build && node --test dist/test/cli.test.js dist/test/credential.test.js dist/test/mongodb.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
|
"release": "npm version",
|
|
30
30
|
"version": "npm install",
|
|
31
31
|
"prepack": "npm test"
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"node": ">=22.16"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
+
"mongodb": "^6.21.0",
|
|
47
48
|
"mysql2": "^3.23.1",
|
|
48
49
|
"node-sql-parser": "^5.4.0",
|
|
49
50
|
"pg": "^8.16.3"
|