@fadhilp/stateql 0.2.0 → 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/dist/src/cli.js CHANGED
@@ -36,7 +36,7 @@ const parsed = parseArgs({
36
36
  const [command, subcommand, ...rest] = parsed.positionals;
37
37
  const values = parsed.values;
38
38
  if (values.version) {
39
- console.log("0.1.2");
39
+ console.log(packageVersion());
40
40
  process.exit(0);
41
41
  }
42
42
  if (values.help || !command) {
@@ -502,7 +502,7 @@ function extractHandle(data) {
502
502
  return undefined;
503
503
  }
504
504
  function helpText() {
505
- return `StateQL 0.1.2
505
+ return `StateQL ${packageVersion()}
506
506
 
507
507
  Usage: stql <command> [arguments] [options]
508
508
 
@@ -523,3 +523,7 @@ Deadline: --timeout-ms N (default: 30000). Ctrl+C cancels database work.
523
523
  Output: --output agent|json|jsonl|text|silent (default: agent).
524
524
  Batch/pipe accept JSON array files or JSONL streams. Stop on first error.`;
525
525
  }
526
+ function packageVersion() {
527
+ const packageJson = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8"));
528
+ return packageJson.version;
529
+ }
@@ -1,3 +1,3 @@
1
1
  export { StateQL } from "./stateql.js";
2
2
  export { StateQLError, exitCodeFor } from "./errors.js";
3
- export type { BatchCommand, BatchCommandName, BatchOptions, ConnectOptions, ExecOptions, ExecutionOptions, Failure, FilterOptions, PlanOptions, ProfileOptions, QueryOptions, Response, RowsOptions, SqlParameters, StateQLOptions, Success, } from "./types.js";
3
+ export type { BatchCommand, BatchCommandName, BatchOptions, ConnectOptions, ExecOptions, ExecutionOptions, Failure, FilterOptions, HistoryEntry, PlanOptions, ProfileOptions, QueryOptions, Response, RowsOptions, SqlParameters, StateQLOptions, StateQLSnapshot, Success, } from "./types.js";
@@ -1,4 +1,4 @@
1
- import type { BatchCommand, BatchOptions, ConnectOptions, ExecOptions, ExecutionOptions, FilterOptions, PlanOptions, ProfileOptions, QueryOptions, Response, RowsOptions, StateQLOptions } from "./types.js";
1
+ import type { BatchCommand, BatchOptions, ConnectOptions, ExecOptions, ExecutionOptions, FilterOptions, HistoryEntry, PlanOptions, ProfileOptions, QueryOptions, Response, RowsOptions, StateQLOptions, StateQLSnapshot } from "./types.js";
2
2
  export declare class StateQL {
3
3
  private readonly store;
4
4
  private readonly sessionName;
@@ -19,6 +19,9 @@ export declare class StateQL {
19
19
  showProfile(name: string): Promise<Response<unknown>>;
20
20
  removeProfile(name: string): Promise<Response<unknown>>;
21
21
  disconnect(): Promise<Response<unknown>>;
22
+ snapshot(options?: {
23
+ historyLimit?: number;
24
+ }): StateQLSnapshot;
22
25
  status(): Promise<Response<unknown>>;
23
26
  startSession(name: string): Promise<Response<unknown>>;
24
27
  listSessions(): Promise<Response<unknown>>;
@@ -42,7 +45,9 @@ export declare class StateQL {
42
45
  inspect(kind: string, table?: string, options?: ExecutionOptions): Promise<Response<unknown>>;
43
46
  plan(sql: string, options?: PlanOptions): Promise<Response<unknown>>;
44
47
  apply(planId: string, options?: ExecutionOptions): Promise<Response<unknown>>;
45
- history(limit?: number): Promise<Response<unknown>>;
48
+ history(limit?: number): Promise<Response<{
49
+ history: HistoryEntry[];
50
+ }>>;
46
51
  capabilities(): Promise<Response<unknown>>;
47
52
  executeCommand(command: BatchCommand): Promise<Response<unknown>>;
48
53
  batch(commands: Iterable<BatchCommand> | AsyncIterable<BatchCommand>, options?: BatchOptions): AsyncGenerator<Response<unknown>>;
@@ -9,6 +9,8 @@ import { operationData, paginationWarnings, profileData, rowsToCsv, sessionData,
9
9
  import { analyzeSql } from "./sql.js";
10
10
  import { StateStore, } from "./store.js";
11
11
  import { compactRows, defaultHome, hash, parseJson, redact, } from "./util.js";
12
+ const DEFAULT_SNAPSHOT_HISTORY_LIMIT = 50;
13
+ const MAX_SNAPSHOT_HISTORY_LIMIT = 100;
12
14
  export class StateQL {
13
15
  store;
14
16
  sessionName;
@@ -208,6 +210,58 @@ export class StateQL {
208
210
  return { data: { disconnected: true }, executed: true };
209
211
  });
210
212
  }
213
+ snapshot(options = {}) {
214
+ const session = this.store
215
+ .listSessions()
216
+ .find((candidate) => candidate.name === this.sessionName);
217
+ if (!session) {
218
+ throw new StateQLError("INVALID_COMMAND", "The active session was not found.");
219
+ }
220
+ const connection = this.store.activeConnection(session);
221
+ const transaction = session.active_transaction_id
222
+ ? this.store.getTransaction(session.active_transaction_id)
223
+ : undefined;
224
+ const historyLimit = positiveInteger(options.historyLimit ?? DEFAULT_SNAPSHOT_HISTORY_LIMIT, "historyLimit");
225
+ if (historyLimit > MAX_SNAPSHOT_HISTORY_LIMIT) {
226
+ throw new StateQLError("INVALID_COMMAND", `historyLimit cannot exceed ${MAX_SNAPSHOT_HISTORY_LIMIT}.`);
227
+ }
228
+ return {
229
+ session: {
230
+ session_id: session.id,
231
+ name: session.name,
232
+ status: session.status,
233
+ },
234
+ connection: connection
235
+ ? {
236
+ connection_id: connection.id,
237
+ name: connection.name,
238
+ status: "connected",
239
+ driver: connection.driver,
240
+ database: connection.database_name,
241
+ read_only: Boolean(connection.read_only),
242
+ }
243
+ : null,
244
+ transaction: transaction
245
+ ? { transaction_id: transaction.id, state: transaction.state }
246
+ : null,
247
+ state_version: connection ? version(connection) : null,
248
+ state_confidence: connection ? confidence(connection) : null,
249
+ recent_results: this.store.knownResults(session.id, 10).map((result) => ({
250
+ alias: result.alias,
251
+ handle: result.id,
252
+ rows: result.row_count,
253
+ })),
254
+ recent_operations: this.store
255
+ .recentOperations(session.id, 10)
256
+ .map((operation) => ({
257
+ handle: operation.id,
258
+ type: operation.statement_type,
259
+ affected_rows: operation.affected_rows,
260
+ status: operation.status,
261
+ })),
262
+ history: this.store.history(session.id, historyLimit).map(historyEntry),
263
+ };
264
+ }
211
265
  async status() {
212
266
  return this.run("status", async (session) => {
213
267
  const connection = this.store.activeConnection(session);
@@ -857,17 +911,7 @@ export class StateQL {
857
911
  data: {
858
912
  history: this.store
859
913
  .history(session.id, positiveInteger(limit, "limit"))
860
- .map((item) => ({
861
- command_id: item.id,
862
- timestamp: item.timestamp,
863
- session_id: item.session_id,
864
- command: item.command,
865
- handle: item.handle,
866
- executed: Boolean(item.executed),
867
- cached: Boolean(item.cached),
868
- success: Boolean(item.success),
869
- error_code: item.error_code,
870
- })),
914
+ .map(historyEntry),
871
915
  },
872
916
  }));
873
917
  }
@@ -1328,6 +1372,19 @@ export class StateQL {
1328
1372
  }
1329
1373
  }
1330
1374
  }
1375
+ function historyEntry(item) {
1376
+ return {
1377
+ command_id: item.id,
1378
+ timestamp: item.timestamp,
1379
+ session_id: item.session_id,
1380
+ command: item.command,
1381
+ handle: item.handle,
1382
+ executed: Boolean(item.executed),
1383
+ cached: Boolean(item.cached),
1384
+ success: Boolean(item.success),
1385
+ error_code: item.error_code,
1386
+ };
1387
+ }
1331
1388
  function markTransactionOutcomeUnknown(store, transactionId, sessionId) {
1332
1389
  try {
1333
1390
  store.markTransactionOutcomeUnknown(transactionId, sessionId);
@@ -33,6 +33,50 @@ 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
81
  export interface ExecutionOptions {
38
82
  timeoutMs?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fadhilp/stateql",
3
- "version": "0.2.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",