@saptools/cf-hana 0.1.2 → 0.1.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.4 - 2026-06-23
4
+
5
+ - Add automatic local CSV backups before CLI `query` runs an `UPDATE` or
6
+ `DELETE`.
7
+ - Derive the backup `SELECT` from the write target and top-level `WHERE`
8
+ clause, preserving only the WHERE parameters for `UPDATE` statements.
9
+ - Save each backup in its own non-expiring folder with `statement.sql` and
10
+ `backup.csv`, and add `--no-backup` for explicit CLI opt-out.
11
+
12
+ ## 0.1.3 - 2026-06-23
13
+
14
+ - Add local SQL history for successful direct `query` and `execute` calls under
15
+ `~/.saptools/cf-hana/histories/YYYY-MM-DD.jsonl`.
16
+ - Rotate SQL history with five-day retention and keep parameter values,
17
+ credentials, certificates, and result rows out of the history file.
18
+ - Keep helper-driven catalog SQL out of user SQL history and document the new
19
+ local state behavior.
20
+
3
21
  ## 0.1.2 - 2026-06-23
4
22
 
5
23
  - Harden connection pooling so queued callers continue after transient reconnect failures.
package/README.md CHANGED
@@ -22,6 +22,10 @@ login on the hot path) and connections are pooled and reused within a process.
22
22
  - **Query-builder shorthands** — `selectFrom`, `count`, `insertInto`, `update`,
23
23
  `deleteFrom` — query a table by name without writing SQL.
24
24
  - **Schema introspection** — list schemas, tables, and columns.
25
+ - **Local SQL history** — direct SQL calls are appended to dated JSONL files
26
+ under `~/.saptools/cf-hana/histories/` with five-day retention.
27
+ - **Write backups** — CLI `UPDATE` and `DELETE` statements create a local CSV
28
+ backup of matching rows before the write runs.
25
29
  - **Safety guard** — opt-in read-only mode and a destructive-statement guard
26
30
  (blocks `DROP`/`TRUNCATE`/`ALTER` and unscoped `UPDATE`/`DELETE`).
27
31
  - **Typed results** — `query<TRow>()` returns typed rows.
@@ -44,7 +48,7 @@ driver is bundled as a dependency — there is no native build step.
44
48
  import { connect, query } from "@saptools/cf-hana";
45
49
 
46
50
  // Open a reusable, pooled client for one CF app's HANA database.
47
- const db = await connect("eu10/acme/dev/orders-api");
51
+ const db = await connect("eu10/example-org/space-demo/app-demo");
48
52
 
49
53
  const open = await db.query("SELECT ID, STATUS FROM ORDERS WHERE STATUS = ?", ["OPEN"]);
50
54
  console.log(open.rows);
@@ -58,16 +62,16 @@ await db.transaction(async (tx) => {
58
62
  await db.close();
59
63
 
60
64
  // One-shot: connect, run one query, close.
61
- const rows = await query("orders-api", "SELECT COUNT(*) AS N FROM ORDERS");
65
+ const rows = await query("app-demo", "SELECT COUNT(*) AS N FROM ORDERS");
62
66
  ```
63
67
 
64
68
  ## The selector
65
69
 
66
70
  Every entry point takes a selector as its first argument:
67
71
 
68
- - **Explicit** — `region/org/space/app` (e.g. `eu10/acme/dev/orders-api`). Works
69
- without any cached topology.
70
- - **Bare app name** — `orders-api`. Resolved against the topology cached by
72
+ - **Explicit** — `region/org/space/app` (e.g.
73
+ `eu10/example-org/space-demo/app-demo`). Works without any cached topology.
74
+ - **Bare app name** — `app-demo`. Resolved against the topology cached by
71
75
  `cf-sync sync`; throws if the name is ambiguous across spaces.
72
76
 
73
77
  ## CLI
@@ -84,14 +88,17 @@ cf-hana info <selector> Print the resolved connection metada
84
88
  Common options: `--format <table|json|csv>`, `--refresh`, `--role <runtime|hdi>`,
85
89
  `--binding <name>` / `--binding-index <n>`, `--timeout <ms>`, `--read-only`,
86
90
  `--allow-destructive`, `--limit <n>`, `--no-auto-limit`. The `query` command also
87
- accepts `--param <value>` (repeatable) to bind `?` placeholders.
91
+ accepts `--param <value>` (repeatable) to bind `?` placeholders and
92
+ `--no-backup` to skip the default write backup.
88
93
 
89
94
  ```bash
90
- cf-hana query eu10/acme/dev/orders-api "SELECT ID, STATUS FROM ORDERS WHERE STATUS = ?" \
95
+ cf-hana query eu10/example-org/space-demo/app-demo "SELECT ID, STATUS FROM ORDERS WHERE STATUS = ?" \
91
96
  --param OPEN --format json
92
- cf-hana tables orders-api
93
- cf-hana columns orders-api ORDERS_APP.ORDERS
94
- cf-hana ping eu10/acme/dev/orders-api
97
+ cf-hana query app-demo "UPDATE ORDERS SET STATUS = ? WHERE ID = ?" \
98
+ --param DONE --param 42 --format json
99
+ cf-hana tables app-demo
100
+ cf-hana columns app-demo ORDERS_APP.ORDERS
101
+ cf-hana ping eu10/example-org/space-demo/app-demo
95
102
  ```
96
103
 
97
104
  ## Programmatic API
@@ -101,7 +108,7 @@ cf-hana ping eu10/acme/dev/orders-api
101
108
  | `connect(selector, options?)` | Open a reusable, pooled `HanaClient`. |
102
109
  | `query(selector, sql, params?, options?)` | One-shot: connect, query, close. |
103
110
  | `withConnection(selector, work, options?)` | Run `work` with a client that auto-closes. |
104
- | `HanaClient` | `query`, `execute`, `selectFrom`, `count`, `insertInto`, `update`, `deleteFrom`, `transaction`, `listSchemas`, `listTables`, `listColumns`, `explain`, `close`. |
111
+ | `HanaClient` | `query`, `execute`, `backupWriteStatement`, `selectFrom`, `count`, `insertInto`, `update`, `deleteFrom`, `transaction`, `listSchemas`, `listTables`, `listColumns`, `explain`, `close`. |
105
112
  | `createDriver`, `formatResult`, `build*` | Lower-level building blocks. |
106
113
 
107
114
  `ConnectOptions` highlights: `role` (`runtime` | `hdi`), `bindingName` /
@@ -117,11 +124,58 @@ Credentials are resolved **cache-first**:
117
124
  live from Cloud Foundry. The live fetch needs `SAP_EMAIL` and `SAP_PASSWORD`
118
125
  (or the `email` / `password` options) and never persists anything to disk.
119
126
 
120
- `cf-hana` itself writes nothing under `~/.saptools/` — it only reads what
127
+ Credential resolution writes nothing under `~/.saptools/` — it only reads what
121
128
  `cf-sync` cached. The connection pool is in-process and in-memory only, so it is
122
129
  safe to run many `cf-hana` processes in parallel and alongside any `cf-sync`
123
130
  command.
124
131
 
132
+ ## SQL history
133
+
134
+ Successful direct SQL calls are appended to daily JSONL files:
135
+
136
+ ```text
137
+ ~/.saptools/cf-hana/histories/YYYY-MM-DD.jsonl
138
+ ```
139
+
140
+ Each entry includes the timestamp, package version, selector, app name, schema,
141
+ role, operation (`query` or `execute`), statement kind, SQL text, parameter
142
+ count, row count, truncation flag, and elapsed time. Parameter values,
143
+ credentials, certificates, and result rows are not stored.
144
+
145
+ History retention runs opportunistically after each append and deletes dated
146
+ history files older than five days. Helper-driven catalog SQL such as `tables`
147
+ and `columns` is not recorded as user SQL history.
148
+
149
+ ## Write backups
150
+
151
+ When `cf-hana query` receives an `UPDATE` or `DELETE`, it first builds and runs a
152
+ matching `SELECT`:
153
+
154
+ - `UPDATE <target> SET ... WHERE ...` becomes
155
+ `SELECT * FROM <target> WHERE ...`.
156
+ - `DELETE FROM <target> WHERE ...` becomes
157
+ `SELECT * FROM <target> WHERE ...`.
158
+
159
+ The backup is saved before the write runs:
160
+
161
+ ```text
162
+ ~/.saptools/cf-hana/backups/<timestamp>-<operation>-<hash>/
163
+ statement.sql
164
+ backup.csv
165
+ ```
166
+
167
+ `statement.sql` contains the original write statement. `backup.csv` contains the
168
+ rows returned by the derived `SELECT`. Backup folders are not deleted by
169
+ `cf-hana`; clean them up manually when they are no longer needed. The backup path
170
+ is printed to stderr so JSON and CSV stdout remain parseable.
171
+
172
+ Use `--no-backup` when an external backup or transaction workflow already covers
173
+ the write:
174
+
175
+ ```bash
176
+ cf-hana query app-demo "DELETE FROM ORDERS WHERE ID = ?" --param 42 --no-backup
177
+ ```
178
+
125
179
  ## Safety
126
180
 
127
181
  - **Read-only mode** (`readOnly` / `--read-only`) rejects every DML and DDL statement.