@fadhilp/stateql 0.1.1

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.
@@ -0,0 +1,112 @@
1
+ export type Driver = "sqlite" | "postgres";
2
+ export type StateConfidence = "authoritative" | "transaction_snapshot" | "database_reported" | "local" | "ttl_based" | "unknown";
3
+ export interface Warning {
4
+ code: string;
5
+ message: string;
6
+ }
7
+ export interface StateQLErrorShape {
8
+ code: string;
9
+ message: string;
10
+ retryable: boolean;
11
+ executed: boolean;
12
+ suggested_action?: string;
13
+ [key: string]: unknown;
14
+ }
15
+ export interface ResponseMeta {
16
+ duration_ms: number;
17
+ state_version?: string;
18
+ state_confidence?: StateConfidence;
19
+ }
20
+ export interface Success<T> {
21
+ ok: true;
22
+ command_id: string;
23
+ session_id: string;
24
+ data: T;
25
+ warnings: Warning[];
26
+ meta: ResponseMeta;
27
+ }
28
+ export interface Failure {
29
+ ok: false;
30
+ command_id: string;
31
+ session_id: string;
32
+ error: StateQLErrorShape;
33
+ meta: ResponseMeta;
34
+ }
35
+ export type Response<T> = Success<T> | Failure;
36
+ export type SqlParameters = unknown[] | Record<string, unknown>;
37
+ export interface StateQLOptions {
38
+ home?: string;
39
+ session?: string;
40
+ previewRows?: number;
41
+ cacheTtlSeconds?: number;
42
+ resultTtlSeconds?: number;
43
+ maxCellCharacters?: number;
44
+ maxResultRows?: number;
45
+ now?: () => Date;
46
+ }
47
+ export interface QueryOptions {
48
+ params?: SqlParameters;
49
+ cache?: "auto" | "bypass" | "require";
50
+ }
51
+ export interface FilterOptions {
52
+ params?: SqlParameters;
53
+ }
54
+ export interface ExecOptions {
55
+ params?: SqlParameters;
56
+ replay?: boolean;
57
+ idempotencyKey?: string;
58
+ allowUnbounded?: boolean;
59
+ allowDestructive?: boolean;
60
+ }
61
+ export interface ConnectOptions {
62
+ name?: string;
63
+ readOnly?: boolean;
64
+ secretEnv?: string;
65
+ profile?: string;
66
+ }
67
+ export interface ProfileOptions {
68
+ readOnly?: boolean;
69
+ secretEnv?: string;
70
+ }
71
+ export interface RowsOptions {
72
+ offset?: number;
73
+ limit?: number;
74
+ }
75
+ export interface PlanOptions {
76
+ params?: SqlParameters;
77
+ allowUnbounded?: boolean;
78
+ allowDestructive?: boolean;
79
+ }
80
+ 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" | "apply" | "history" | "receipt" | "capabilities";
81
+ export interface BatchCommand {
82
+ command: BatchCommandName;
83
+ target?: string;
84
+ sql?: string;
85
+ where?: string;
86
+ handle?: string;
87
+ name?: string;
88
+ as?: string;
89
+ kind?: string;
90
+ table?: string;
91
+ params?: SqlParameters;
92
+ cache?: "auto" | "bypass" | "require";
93
+ read_only?: boolean;
94
+ secret_env?: string;
95
+ profile?: string;
96
+ replay?: boolean;
97
+ idempotency_key?: string;
98
+ allow_unbounded?: boolean;
99
+ allow_destructive?: boolean;
100
+ offset?: number;
101
+ limit?: number;
102
+ isolation?: string;
103
+ }
104
+ export interface BatchOptions {
105
+ continueOnError?: boolean;
106
+ maxCommands?: number;
107
+ }
108
+ export interface Column {
109
+ name: string;
110
+ type: string;
111
+ }
112
+ export type Row = Record<string, unknown>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { Row } from "./types.js";
2
+ export declare function defaultHome(): string;
3
+ export declare function hash(value: unknown): string;
4
+ export declare function stableStringify(value: unknown): string;
5
+ export declare function parseJson<T>(value: string, fallback: T): T;
6
+ export declare function redact(value: string): string;
7
+ export declare function compactRows(rows: Row[], maxCellCharacters: number): Row[];
8
+ export declare function toJsonSafe<T>(value: T): T;
@@ -0,0 +1,75 @@
1
+ import { createHash } from "node:crypto";
2
+ import { homedir } from "node:os";
3
+ import { join, resolve } from "node:path";
4
+ import { env, platform } from "node:process";
5
+ export function defaultHome() {
6
+ if (env.STQL_HOME)
7
+ return resolve(env.STQL_HOME);
8
+ if (platform === "win32") {
9
+ return join(env.LOCALAPPDATA ?? join(homedir(), "AppData", "Local"), "stql");
10
+ }
11
+ return join(env.XDG_DATA_HOME ?? join(homedir(), ".local", "share"), "stql");
12
+ }
13
+ export function hash(value) {
14
+ return createHash("sha256").update(stableStringify(value)).digest("hex");
15
+ }
16
+ export function stableStringify(value) {
17
+ return JSON.stringify(sortValue(value));
18
+ }
19
+ function sortValue(value) {
20
+ if (Array.isArray(value))
21
+ return value.map(sortValue);
22
+ if (!value || typeof value !== "object")
23
+ return value;
24
+ return Object.fromEntries(Object.entries(value)
25
+ .sort(([left], [right]) => left.localeCompare(right))
26
+ .map(([key, item]) => [key, sortValue(item)]));
27
+ }
28
+ export function parseJson(value, fallback) {
29
+ try {
30
+ return JSON.parse(value);
31
+ }
32
+ catch {
33
+ return fallback;
34
+ }
35
+ }
36
+ export function redact(value) {
37
+ try {
38
+ const url = new URL(value);
39
+ if (url.password)
40
+ url.password = "***";
41
+ if (url.username)
42
+ url.username = "***";
43
+ for (const key of url.searchParams.keys()) {
44
+ if (/pass|token|secret|key/i.test(key))
45
+ url.searchParams.set(key, "***");
46
+ }
47
+ return url.toString();
48
+ }
49
+ catch {
50
+ return value.replace(/(password|token|secret|api[_-]?key)\s*=\s*([^\s;&]+)/gi, "$1=***");
51
+ }
52
+ }
53
+ export function compactRows(rows, maxCellCharacters) {
54
+ return rows.map((row) => Object.fromEntries(Object.entries(row).map(([key, value]) => [
55
+ key,
56
+ compactValue(value, maxCellCharacters),
57
+ ])));
58
+ }
59
+ function compactValue(value, max) {
60
+ if (typeof value === "bigint")
61
+ return value.toString();
62
+ if (Buffer.isBuffer(value)) {
63
+ return { type: "binary", length: value.length };
64
+ }
65
+ if (typeof value !== "string" || value.length <= max)
66
+ return value;
67
+ return {
68
+ type: "text",
69
+ length: value.length,
70
+ preview: value.slice(0, max),
71
+ };
72
+ }
73
+ export function toJsonSafe(value) {
74
+ return JSON.parse(JSON.stringify(value, (_key, item) => typeof item === "bigint" ? item.toString() : item));
75
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@fadhilp/stateql",
3
+ "version": "0.1.1",
4
+ "description": "Stateful, agent-oriented database CLI for safe result reuse",
5
+ "type": "module",
6
+ "bin": {
7
+ "stql": "dist/src/cli.js"
8
+ },
9
+ "main": "./dist/src/index.js",
10
+ "types": "./dist/src/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/src/index.d.ts",
14
+ "import": "./dist/src/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist/src",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc -p tsconfig.json",
24
+ "test": "npm run build && node --test dist/test/stateql.test.js",
25
+ "prepack": "npm test"
26
+ },
27
+ "keywords": [
28
+ "database",
29
+ "sqlite",
30
+ "postgresql",
31
+ "cli",
32
+ "agents",
33
+ "sql"
34
+ ],
35
+ "license": "MIT",
36
+ "engines": {
37
+ "node": ">=22.5"
38
+ },
39
+ "dependencies": {
40
+ "node-sql-parser": "^5.4.0",
41
+ "pg": "^8.16.3"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^24.0.0",
45
+ "@types/pg": "^8.15.5",
46
+ "typescript": "^7.0.0"
47
+ }
48
+ }