@saptools/cf-hana 0.1.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/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +159 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1425 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +313 -0
- package/dist/index.js +1263 -0
- package/dist/index.js.map +1 -0
- package/package.json +71 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 - 2026-05-22
|
|
4
|
+
|
|
5
|
+
- Initial release: run SQL directly against SAP HANA Cloud databases bound to a Cloud Foundry app, addressed by a `region/org/space/app` selector (or a bare app name).
|
|
6
|
+
- Credentials are resolved cache-first via `@saptools/cf-sync`, with an on-demand live Cloud Foundry fetch fallback.
|
|
7
|
+
- Includes a `HanaClient` with pooled connections, parameterized queries, transactions, table introspection, query-builder shorthands, a read-only/destructive-statement safety guard, and a `cf-hana` CLI.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dongtran
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# @saptools/cf-hana
|
|
2
|
+
|
|
3
|
+
> Run SQL directly against SAP HANA Cloud databases bound to a Cloud Foundry app — addressed by a `region/org/space/app` selector.
|
|
4
|
+
|
|
5
|
+
`@saptools/cf-hana` closes the last gap in the `saptools` chain: `@saptools/cf-sync`
|
|
6
|
+
already discovers Cloud Foundry topology and HANA service bindings, but nothing
|
|
7
|
+
actually executes SQL. This package does. Pass a selector, get a connected,
|
|
8
|
+
pooled client, and run `SELECT` / `INSERT` / `UPDATE` / `DELETE` / DDL.
|
|
9
|
+
|
|
10
|
+
It is fast because credentials come from `cf-sync`'s on-disk cache (no 5–15s CF
|
|
11
|
+
login on the hot path) and connections are pooled and reused within a process.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Selector-based connect** — `region/org/space/app` or a bare app name.
|
|
16
|
+
- **Credentials, handled for you** — cache-first via `@saptools/cf-sync`, with an
|
|
17
|
+
on-demand live Cloud Foundry fetch as a fallback.
|
|
18
|
+
- **Parameterized queries** — values always travel as bound `?` parameters, never
|
|
19
|
+
string-concatenated.
|
|
20
|
+
- **Connection pooling** — pooled, reused connections; opt out with `pool: false`.
|
|
21
|
+
- **Transactions** — `transaction(work)` commits on success, rolls back on throw.
|
|
22
|
+
- **Query-builder shorthands** — `selectFrom`, `count`, `insertInto`, `update`,
|
|
23
|
+
`deleteFrom` — query a table by name without writing SQL.
|
|
24
|
+
- **Schema introspection** — list schemas, tables, and columns.
|
|
25
|
+
- **Safety guard** — opt-in read-only mode and a destructive-statement guard
|
|
26
|
+
(blocks `DROP`/`TRUNCATE`/`ALTER` and unscoped `UPDATE`/`DELETE`).
|
|
27
|
+
- **Typed results** — `query<TRow>()` returns typed rows.
|
|
28
|
+
- **CLI + API** — a `cf-hana` CLI and an ergonomic TypeScript API.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install @saptools/cf-hana
|
|
34
|
+
# or, for the CLI
|
|
35
|
+
npm install -g @saptools/cf-hana
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Requires Node.js >= 20. The pure-JavaScript [`hdb`](https://github.com/SAP/node-hdb)
|
|
39
|
+
driver is bundled as a dependency — there is no native build step.
|
|
40
|
+
|
|
41
|
+
## Quick start
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { connect, query } from "@saptools/cf-hana";
|
|
45
|
+
|
|
46
|
+
// Open a reusable, pooled client for one CF app's HANA database.
|
|
47
|
+
const db = await connect("eu10/acme/dev/orders-srv");
|
|
48
|
+
|
|
49
|
+
const open = await db.query("SELECT ID, STATUS FROM ORDERS WHERE STATUS = ?", ["OPEN"]);
|
|
50
|
+
console.log(open.rows);
|
|
51
|
+
|
|
52
|
+
const total = await db.count({ schema: "ORDERS_APP", table: "ORDERS", where: { STATUS: "OPEN" } });
|
|
53
|
+
|
|
54
|
+
await db.transaction(async (tx) => {
|
|
55
|
+
await tx.execute("UPDATE ORDERS SET STATUS = ? WHERE ID = ?", ["SHIPPED", 42]);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
await db.close();
|
|
59
|
+
|
|
60
|
+
// One-shot: connect, run one query, close.
|
|
61
|
+
const rows = await query("orders-srv", "SELECT COUNT(*) AS N FROM ORDERS");
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## The selector
|
|
65
|
+
|
|
66
|
+
Every entry point takes a selector as its first argument:
|
|
67
|
+
|
|
68
|
+
- **Explicit** — `region/org/space/app` (e.g. `eu10/acme/dev/orders-srv`). Works
|
|
69
|
+
without any cached topology.
|
|
70
|
+
- **Bare app name** — `orders-srv`. Resolved against the topology cached by
|
|
71
|
+
`cf-sync sync`; throws if the name is ambiguous across spaces.
|
|
72
|
+
|
|
73
|
+
## CLI
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
cf-hana query <selector> <sql> Run a single SQL statement
|
|
77
|
+
cf-hana tables <selector> [schema] List tables in a schema
|
|
78
|
+
cf-hana columns <selector> <schema.table> List the columns of a table
|
|
79
|
+
cf-hana count <selector> <schema.table> Count rows in a table
|
|
80
|
+
cf-hana ping <selector> Connect and measure round-trip latency
|
|
81
|
+
cf-hana info <selector> Print the resolved connection metadata
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Common options: `--format <table|json|csv>`, `--refresh`, `--role <runtime|hdi>`,
|
|
85
|
+
`--binding <name>` / `--binding-index <n>`, `--timeout <ms>`, `--read-only`,
|
|
86
|
+
`--allow-destructive`, `--limit <n>`, `--no-auto-limit`. The `query` command also
|
|
87
|
+
accepts `--param <value>` (repeatable) to bind `?` placeholders.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
cf-hana query eu10/acme/dev/orders-srv "SELECT ID, STATUS FROM ORDERS WHERE STATUS = ?" \
|
|
91
|
+
--param OPEN --format json
|
|
92
|
+
cf-hana tables orders-srv
|
|
93
|
+
cf-hana columns orders-srv ORDERS_APP.ORDERS
|
|
94
|
+
cf-hana ping eu10/acme/dev/orders-srv
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Programmatic API
|
|
98
|
+
|
|
99
|
+
| Export | Purpose |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| `connect(selector, options?)` | Open a reusable, pooled `HanaClient`. |
|
|
102
|
+
| `query(selector, sql, params?, options?)` | One-shot: connect, query, close. |
|
|
103
|
+
| `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`. |
|
|
105
|
+
| `createDriver`, `formatResult`, `build*` | Lower-level building blocks. |
|
|
106
|
+
|
|
107
|
+
`ConnectOptions` highlights: `role` (`runtime` | `hdi`), `bindingName` /
|
|
108
|
+
`bindingIndex`, `readOnly`, `allowDestructive`, `autoLimit`, `queryTimeoutMs`,
|
|
109
|
+
`connectTimeoutMs`, `refresh`, `pool`.
|
|
110
|
+
|
|
111
|
+
## Credentials
|
|
112
|
+
|
|
113
|
+
Credentials are resolved **cache-first**:
|
|
114
|
+
|
|
115
|
+
1. Read what `cf-sync db-sync` cached in `~/.saptools/cf-db-bindings.json`.
|
|
116
|
+
2. On a cache miss (or when `refresh: true` / `--refresh` is passed), fetch them
|
|
117
|
+
live from Cloud Foundry. The live fetch needs `SAP_EMAIL` and `SAP_PASSWORD`
|
|
118
|
+
(or the `email` / `password` options) and never persists anything to disk.
|
|
119
|
+
|
|
120
|
+
`cf-hana` itself writes nothing under `~/.saptools/` — it only reads what
|
|
121
|
+
`cf-sync` cached. The connection pool is in-process and in-memory only, so it is
|
|
122
|
+
safe to run many `cf-hana` processes in parallel and alongside any `cf-sync`
|
|
123
|
+
command.
|
|
124
|
+
|
|
125
|
+
## Safety
|
|
126
|
+
|
|
127
|
+
- **Read-only mode** (`readOnly` / `--read-only`) rejects every DML and DDL statement.
|
|
128
|
+
- **Destructive guard** blocks `DROP` / `TRUNCATE` / `ALTER` and `UPDATE` / `DELETE`
|
|
129
|
+
without a `WHERE` clause unless `allowDestructive` / `--allow-destructive` is set.
|
|
130
|
+
- **Auto-limit** appends a `LIMIT` to bare `SELECT` statements (default 1000);
|
|
131
|
+
`QueryResult.truncated` reports when it clipped the result. Disable with
|
|
132
|
+
`autoLimit: false` / `--no-auto-limit`.
|
|
133
|
+
|
|
134
|
+
The guard is a convenience, not a security control: always pass values as bound
|
|
135
|
+
parameters.
|
|
136
|
+
|
|
137
|
+
## Requirements
|
|
138
|
+
|
|
139
|
+
- Node.js >= 20.
|
|
140
|
+
- A HANA binding reachable from your network. Resolving a bare app name, or a
|
|
141
|
+
live credential fetch, additionally needs the Cloud Foundry CLI and
|
|
142
|
+
`SAP_EMAIL` / `SAP_PASSWORD`.
|
|
143
|
+
|
|
144
|
+
## Development
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
pnpm --filter @saptools/cf-hana build
|
|
148
|
+
pnpm --filter @saptools/cf-hana lint
|
|
149
|
+
pnpm --filter @saptools/cf-hana typecheck
|
|
150
|
+
pnpm --filter @saptools/cf-hana test:unit
|
|
151
|
+
pnpm --filter @saptools/cf-hana test:e2e:fake
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The live e2e suite (`test:e2e:live`) needs real `SAP_EMAIL` / `SAP_PASSWORD` and
|
|
155
|
+
a `CF_HANA_E2E_TARGET` selector pointing at a HANA-bound app.
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
MIT
|
package/dist/cli.d.ts
ADDED