@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 +18 -0
- package/README.md +66 -12
- package/dist/cli.js +422 -107
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.js +418 -105
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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/
|
|
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("
|
|
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.
|
|
69
|
-
without any cached topology.
|
|
70
|
-
- **Bare app name** — `
|
|
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/
|
|
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
|
|
93
|
-
|
|
94
|
-
cf-hana
|
|
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
|
-
|
|
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.
|