@centia-io/sdk 0.0.26 → 0.0.28

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 MapCentia ApS
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,288 @@
1
+ # @centia-io/sdk
2
+
3
+ TypeScript/JavaScript client SDK for Centia GC2. It provides:
4
+
5
+ - Authentication helpers:
6
+ - CodeFlow (OAuth 2.0 Authorization Code + PKCE) for browser apps
7
+ - PasswordFlow for trusted/CLI/server environments
8
+ - Data access:
9
+ - Sql: Execute parameterized SQL
10
+ - Rpc: Call JSON-RPC methods
11
+ - createApi: A tiny type-safe helper that maps TypeScript interfaces to JSON‑RPC calls
12
+
13
+ This README focuses on CodeFlow, PasswordFlow, Sql, Rpc and Api.ts (createApi).
14
+
15
+ ## Installation
16
+
17
+ - npm: `npm install @centia-io/sdk`
18
+ - pnpm: `pnpm add @centia-io/sdk`
19
+ - yarn: `yarn add @centia-io/sdk`
20
+
21
+ Requirements:
22
+ - Browser or Node.js 18+ (for global `fetch`).
23
+ - An accessible GC2 host URL and client credentials.
24
+
25
+ ESM import:
26
+ ```ts
27
+ import { CodeFlow, PasswordFlow, Sql, Rpc, createApi } from "@centia-io/sdk";
28
+ import type { RpcRequest, RpcResponse, PgTypes } from "@centia-io/sdk";
29
+ ```
30
+
31
+ ---
32
+
33
+ ## Authentication
34
+
35
+ The SDK handles token storage and refresh for you.
36
+ - Tokens and minimal options are saved to `localStorage` in browsers. In non‑browser environments, an in‑memory store is used for the lifetime of the process.
37
+ - Authorization headers are added automatically for Sql/Rpc requests.
38
+
39
+ ### CodeFlow (Browser, OAuth 2.0 Authorization Code + PKCE)
40
+
41
+ Use this flow in browser applications where you can redirect the user to the GC2 login page.
42
+
43
+ Required options:
44
+ - `host`: Base URL of your GC2 instance, e.g. `https://your.gc2.host`
45
+ - `clientId`: OAuth client id configured in GC2
46
+ - `redirectUri`: The URL in your app that handles the redirect back from GC2 (must be whitelisted)
47
+ - `scope` (optional): space‑separated scopes, e.g. `"openid profile"`
48
+
49
+ Example (vanilla JS/TS + SPA):
50
+ ```ts
51
+ import { CodeFlow } from "@centia-io/sdk";
52
+
53
+ const codeFlow = new CodeFlow({
54
+ host: "https://your.gc2.host",
55
+ clientId: "your-client-id",
56
+ redirectUri: window.location.origin + "/auth/callback",
57
+ scope: "openid"
58
+ });
59
+
60
+ // On app startup, call redirectHandle() once to complete a login redirect (if any)
61
+ codeFlow.redirectHandle().then((signedIn) => {
62
+ if (signedIn) {
63
+ console.log("User signed in");
64
+ }
65
+ });
66
+
67
+ // Start sign-in when user clicks Login
68
+ function onLoginClick() {
69
+ codeFlow.signIn(); // Redirects to GC2 auth page
70
+ }
71
+
72
+ // Sign out (clears tokens/options and redirects to signout endpoint)
73
+ function onLogoutClick() {
74
+ codeFlow.signOut();
75
+ }
76
+ ```
77
+
78
+ Notes:
79
+ - `redirectHandle()` detects errors from the auth server, validates `state` (CSRF protection), exchanges the `code` for tokens, stores tokens and cleans up the URL.
80
+ - `signOut()` clears local tokens/options and redirects to the sign-out URL. If you only need to clear local state without redirect, call `codeFlow.clear()`.
81
+
82
+ ### PasswordFlow (Trusted environments, CLI/Server)
83
+
84
+ Use only in trusted environments. The user’s database credentials are exchanged directly for tokens.
85
+
86
+ Required options:
87
+ - `host`
88
+ - `clientId`
89
+ - `username`
90
+ - `password`
91
+ - `database`
92
+
93
+ Example (Node.js):
94
+ ```ts
95
+ import { PasswordFlow } from "@centia-io/sdk";
96
+
97
+ const flow = new PasswordFlow({
98
+ host: "http://localhost:8080",
99
+ clientId: "gc2-cli",
100
+ username: "mydb",
101
+ password: "secret",
102
+ database: "mydb"
103
+ });
104
+
105
+ await flow.signIn();
106
+ // Tokens are now stored; subsequent Sql/Rpc calls will include Authorization header.
107
+
108
+ // ... your code ...
109
+
110
+ flow.signOut(); // Clears tokens/options in local storage (no redirect)
111
+ ```
112
+
113
+ ---
114
+
115
+ ## SQL
116
+
117
+ Execute parameterized SQL against GC2.
118
+
119
+ - Class: `new Sql()`
120
+ - Method: `exec(request: SqlRequest): Promise<SQLResponse>`
121
+ - Endpoint: `POST {host}/api/v4/sql`
122
+
123
+ Types (simplified):
124
+ - `SqlRequest` has:
125
+ - `q`: SQL string, you can use named placeholders like `:a` (server-side feature)
126
+ - `params?`: object with values for placeholders
127
+ - `type_hints?`: optional explicit type hints
128
+ - `type_formats?`: optional per-column format strings
129
+ - `SQLResponse` has:
130
+ - `schema`: a map of column name -> `{ type: string, array: boolean }`
131
+ - `data`: an array of rows (records)
132
+
133
+ Example:
134
+ ```ts
135
+ import { Sql } from "@centia-io/sdk";
136
+
137
+ const sql = new Sql();
138
+
139
+ const payload = {
140
+ a: 1,
141
+ b: "hello",
142
+ c: "3.14", // numeric/decimal values are strings
143
+ d: ["x", "y"], // arrays are supported
144
+ e: { nested: [1,2] } // JSON
145
+ };
146
+
147
+ const res = await sql.exec({
148
+ q: "select :a::int as a, :b::varchar as b, :c::numeric as c, :d::varchar[] as d, :e::jsonb as e",
149
+ params: payload
150
+ });
151
+
152
+ console.log(res.schema); // { a: {type: 'int4', array: false}, ... }
153
+ console.log(res.data); // [{ a: 1, b: 'hello', c: '3.14', d: ['x','y'], e: {nested:[1,2]} }]
154
+ ```
155
+
156
+ Typing the rows:
157
+ ```ts
158
+ import type { PgTypes } from "@centia-io/sdk";
159
+
160
+ interface Row extends PgTypes.DataRow {
161
+ a: number;
162
+ b: string;
163
+ c: PgTypes.NumericString;
164
+ d: PgTypes.PgArray<string>;
165
+ e: PgTypes.JsonValue;
166
+ }
167
+
168
+ // res: PgTypes.SQLResponse<Row>
169
+ const res = await sql.exec({ q: "...", params: payload }) as PgTypes.SQLResponse<Row>;
170
+ ```
171
+
172
+ ---
173
+
174
+ ## RPC
175
+
176
+ Call JSON‑RPC methods exposed by GC2.
177
+
178
+ - Class: `new Rpc()`
179
+ - Method: `call(request: RpcRequest): Promise<RpcResponse>`
180
+ - Endpoint: `POST {host}/api/v4/call`
181
+
182
+ Types (simplified):
183
+ - `RpcRequest` has `jsonrpc: "2.0"`, `method`, optional `params`, optional `id`
184
+ - `RpcResponse` has `jsonrpc: "2.0"`, `id`, and `result` with `{ schema, data }`
185
+
186
+ Example:
187
+ ```ts
188
+ import { Rpc } from "@centia-io/sdk";
189
+
190
+ const rpc = new Rpc();
191
+
192
+ const payload = { a: 1, b: "hello" };
193
+
194
+ const res = await rpc.call({
195
+ jsonrpc: "2.0",
196
+ method: "typeTest",
197
+ params: payload,
198
+ id: 1
199
+ });
200
+
201
+ console.log(res.result.schema);
202
+ console.log(res.result.data); // array of rows
203
+ ```
204
+
205
+ Typing the rows:
206
+ ```ts
207
+ import type { PgTypes } from "@centia-io/sdk";
208
+
209
+ interface Row extends PgTypes.DataRow {
210
+ a: number;
211
+ b: string;
212
+ }
213
+
214
+ const res = await rpc.call({ jsonrpc: "2.0", method: "typeTest", params: payload }) as PgTypes.RpcResponse<Row>;
215
+ ```
216
+
217
+ ---
218
+
219
+ ## createApi (Api.ts)
220
+
221
+ A tiny helper that builds a Proxy around `Rpc` so you can call `api.someMethod(params)` directly, with TypeScript autocompletion and type‑checking based on your own interface.
222
+
223
+ Under the hood, each property access becomes a JSON‑RPC call with the property name as the method. The helper returns `result.data` (array of rows) from the RPC response.
224
+
225
+ Example with typing:
226
+ ```ts
227
+ import { createApi } from "@centia-io/sdk";
228
+ import type { PgTypes } from "@centia-io/sdk";
229
+
230
+ // Define the shape of your RPC methods and return types
231
+ interface MyApi {
232
+ typeTest(params: {
233
+ a: number;
234
+ b: string;
235
+ c: PgTypes.NumericString;
236
+ d: PgTypes.PgArray<string>;
237
+ e: PgTypes.JsonValue;
238
+ }): Promise<Array<{
239
+ a: number;
240
+ b: string;
241
+ c: PgTypes.NumericString;
242
+ d: PgTypes.PgArray<string>;
243
+ e: PgTypes.JsonValue;
244
+ }>>;
245
+ }
246
+
247
+ const api = createApi<MyApi>();
248
+
249
+ const rows = await api.typeTest({
250
+ a: 1,
251
+ b: "hej",
252
+ c: "3.4",
253
+ d: ["ds", "sdsd"],
254
+ e: { zdsd: [2,3,4,5,6,7,8,9,10] }
255
+ });
256
+
257
+ console.log(rows); // typed row array
258
+ ```
259
+
260
+ Notes:
261
+ - `createApi<T>()` relies on naming conventions: the property name is the JSON‑RPC `method` name.
262
+ - Each call returns `result.data` from the RPC response (array of rows).
263
+
264
+ ---
265
+
266
+ ## Error handling
267
+
268
+ - Network/HTTP errors: thrown as `Error` with the status/body text when available.
269
+ - Auth errors: the SDK auto‑refreshes access tokens when possible. If the refresh token is expired or missing, you’ll get an error and should re‑authenticate.
270
+
271
+ ---
272
+
273
+ ## Environment details
274
+
275
+ - Storage: tokens/options stored in `localStorage` when available; otherwise a global in‑memory store is used (`globalThis.__gc2_memory_storage`).
276
+ - Fetch: Node.js 18+ recommended (includes native `fetch`). For older Node versions, add a Fetch polyfill.
277
+
278
+ ---
279
+
280
+ ## Examples
281
+
282
+ See the `examples/` folder for runnable snippets showing PasswordFlow + Sql/Rpc and browser CodeFlow usage.
283
+
284
+ ---
285
+
286
+ ## License
287
+
288
+ AGPL-3.0