kalam-link 0.2.0-alpha1
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 +17 -0
- package/README.md +423 -0
- package/dist/auth.d.ts +113 -0
- package/dist/auth.js +131 -0
- package/dist/index.d.ts +781 -0
- package/dist/index.js +683 -0
- package/dist/wasm/README.md +460 -0
- package/dist/wasm/kalam_link.d.ts +368 -0
- package/dist/wasm/kalam_link.js +1237 -0
- package/dist/wasm/kalam_link_bg.wasm +0 -0
- package/dist/wasm/kalam_link_bg.wasm.d.ts +45 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
Copyright 2025 KalamDB Team
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
you may not use this file except in compliance with the License.
|
|
9
|
+
You may obtain a copy of the License at
|
|
10
|
+
|
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
|
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
See the License for the specific language governing permissions and
|
|
17
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
# kalam-link
|
|
2
|
+
|
|
3
|
+
Official TypeScript/JavaScript client for KalamDB.
|
|
4
|
+
|
|
5
|
+
- Execute SQL over HTTP
|
|
6
|
+
- Subscribe to real-time changes over WebSocket
|
|
7
|
+
- Works in modern browsers and Node.js (>= 18)
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm i kalam-link
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { createClient, Auth, MessageType, ChangeType } from 'kalam-link';
|
|
19
|
+
|
|
20
|
+
const client = createClient({
|
|
21
|
+
url: 'http://localhost:8080',
|
|
22
|
+
auth: Auth.basic('admin', 'admin'),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
await client.connect();
|
|
26
|
+
|
|
27
|
+
// Query
|
|
28
|
+
const result = await client.query('SELECT 1 AS ok');
|
|
29
|
+
console.log(result.results[0]);
|
|
30
|
+
|
|
31
|
+
// Subscribe (returns an unsubscribe function)
|
|
32
|
+
const unsubscribe = await client.subscribe('app.messages', (event) => {
|
|
33
|
+
switch (event.type) {
|
|
34
|
+
case MessageType.Change:
|
|
35
|
+
if (event.change_type === ChangeType.Insert) {
|
|
36
|
+
console.log('New row:', event.rows);
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
case MessageType.InitialDataBatch:
|
|
40
|
+
console.log('Initial data:', event.rows);
|
|
41
|
+
break;
|
|
42
|
+
case MessageType.Error:
|
|
43
|
+
console.error('Subscription error:', event.message);
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Later
|
|
49
|
+
await unsubscribe();
|
|
50
|
+
await client.disconnect();
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Authentication
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { createClient, Auth } from 'kalam-link';
|
|
57
|
+
|
|
58
|
+
// Username/password
|
|
59
|
+
createClient({ url: 'http://localhost:8080', auth: Auth.basic('user', 'pass') });
|
|
60
|
+
|
|
61
|
+
// JWT token
|
|
62
|
+
createClient({ url: 'http://localhost:8080', auth: Auth.jwt('eyJhbGciOiJIUzI1NiIs...') });
|
|
63
|
+
|
|
64
|
+
// No auth (for local/dev setups that allow it)
|
|
65
|
+
createClient({ url: 'http://localhost:8080', auth: Auth.none() });
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## API Reference (Complete)
|
|
69
|
+
|
|
70
|
+
Everything below is exported from `kalam-link` unless noted otherwise.
|
|
71
|
+
|
|
72
|
+
### Imports
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import KalamDBClient, {
|
|
76
|
+
createClient,
|
|
77
|
+
Auth,
|
|
78
|
+
// Enums
|
|
79
|
+
MessageType,
|
|
80
|
+
ChangeType,
|
|
81
|
+
BatchStatus,
|
|
82
|
+
// Types
|
|
83
|
+
type AuthCredentials,
|
|
84
|
+
type BasicAuthCredentials,
|
|
85
|
+
type JwtAuthCredentials,
|
|
86
|
+
type NoAuthCredentials,
|
|
87
|
+
type ClientOptions,
|
|
88
|
+
type ClientOptionsWithAuth,
|
|
89
|
+
type ClientOptionsLegacy,
|
|
90
|
+
type ConnectionOptions,
|
|
91
|
+
type SubscriptionOptions,
|
|
92
|
+
type SubscribeOptions,
|
|
93
|
+
type QueryResponse,
|
|
94
|
+
type QueryResult,
|
|
95
|
+
type SchemaField,
|
|
96
|
+
type ErrorDetail,
|
|
97
|
+
type ServerMessage,
|
|
98
|
+
type BatchControl,
|
|
99
|
+
type SubscriptionCallback,
|
|
100
|
+
type SubscriptionInfo,
|
|
101
|
+
type Unsubscribe,
|
|
102
|
+
type WasmKalamClient,
|
|
103
|
+
// Helpers
|
|
104
|
+
buildAuthHeader,
|
|
105
|
+
encodeBasicAuth,
|
|
106
|
+
isAuthenticated,
|
|
107
|
+
isBasicAuth,
|
|
108
|
+
isJwtAuth,
|
|
109
|
+
isNoAuth,
|
|
110
|
+
} from 'kalam-link';
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Factory
|
|
114
|
+
|
|
115
|
+
#### `createClient(options: ClientOptions): KalamDBClient`
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
type ClientOptions = ClientOptionsWithAuth | ClientOptionsLegacy;
|
|
119
|
+
|
|
120
|
+
interface ClientOptionsWithAuth {
|
|
121
|
+
url: string;
|
|
122
|
+
auth: AuthCredentials;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
interface ClientOptionsLegacy {
|
|
126
|
+
url: string;
|
|
127
|
+
username: string;
|
|
128
|
+
password: string;
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Class: `KalamDBClient` (default export)
|
|
133
|
+
|
|
134
|
+
#### Constructors
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
new KalamDBClient(options: ClientOptionsWithAuth)
|
|
138
|
+
|
|
139
|
+
// Legacy (deprecated)
|
|
140
|
+
new KalamDBClient(url: string, username: string, password: string)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### Lifecycle
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
initialize(): Promise<void>
|
|
147
|
+
connect(): Promise<void>
|
|
148
|
+
disconnect(): Promise<void>
|
|
149
|
+
isConnected(): boolean
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### Authentication
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
getAuthType(): 'basic' | 'jwt' | 'none'
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
#### Queries
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
query(sql: string, params?: any[]): Promise<QueryResponse>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
#### Convenience DML
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
insert(tableName: string, data: Record<string, any>): Promise<QueryResponse>
|
|
168
|
+
delete(tableName: string, rowId: string | number): Promise<void>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### Subscriptions
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
subscribe(
|
|
175
|
+
tableName: string,
|
|
176
|
+
callback: SubscriptionCallback,
|
|
177
|
+
options?: SubscriptionOptions
|
|
178
|
+
): Promise<Unsubscribe>
|
|
179
|
+
|
|
180
|
+
subscribeWithSql(
|
|
181
|
+
sql: string,
|
|
182
|
+
callback: SubscriptionCallback,
|
|
183
|
+
options?: SubscriptionOptions
|
|
184
|
+
): Promise<Unsubscribe>
|
|
185
|
+
|
|
186
|
+
unsubscribe(subscriptionId: string): Promise<void>
|
|
187
|
+
unsubscribeAll(): Promise<void>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Subscription helpers:
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
getSubscriptionCount(): number
|
|
194
|
+
getSubscriptions(): SubscriptionInfo[]
|
|
195
|
+
isSubscribedTo(tableNameOrSql: string): boolean
|
|
196
|
+
getLastSeqId(subscriptionId: string): string | undefined
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### Reconnection controls
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
setAutoReconnect(enabled: boolean): void
|
|
203
|
+
setReconnectDelay(initialDelayMs: number, maxDelayMs: number): void
|
|
204
|
+
setMaxReconnectAttempts(maxAttempts: number): void
|
|
205
|
+
getReconnectAttempts(): number
|
|
206
|
+
isReconnecting(): boolean
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Auth API
|
|
210
|
+
|
|
211
|
+
#### Types
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
interface BasicAuthCredentials { type: 'basic'; username: string; password: string }
|
|
215
|
+
interface JwtAuthCredentials { type: 'jwt'; token: string }
|
|
216
|
+
interface NoAuthCredentials { type: 'none' }
|
|
217
|
+
|
|
218
|
+
type AuthCredentials =
|
|
219
|
+
| BasicAuthCredentials
|
|
220
|
+
| JwtAuthCredentials
|
|
221
|
+
| NoAuthCredentials;
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### Factories
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
Auth.basic(username: string, password: string): BasicAuthCredentials
|
|
228
|
+
Auth.jwt(token: string): JwtAuthCredentials
|
|
229
|
+
Auth.none(): NoAuthCredentials
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
#### Helpers
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
encodeBasicAuth(username: string, password: string): string
|
|
236
|
+
buildAuthHeader(auth: AuthCredentials): string | undefined
|
|
237
|
+
|
|
238
|
+
isBasicAuth(auth: AuthCredentials): auth is BasicAuthCredentials
|
|
239
|
+
isJwtAuth(auth: AuthCredentials): auth is JwtAuthCredentials
|
|
240
|
+
isNoAuth(auth: AuthCredentials): auth is NoAuthCredentials
|
|
241
|
+
isAuthenticated(auth: AuthCredentials): auth is BasicAuthCredentials | JwtAuthCredentials
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Query result types
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
interface SchemaField {
|
|
248
|
+
name: string;
|
|
249
|
+
data_type: string;
|
|
250
|
+
index: number;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
interface QueryResult {
|
|
254
|
+
schema: SchemaField[];
|
|
255
|
+
rows?: unknown[][];
|
|
256
|
+
row_count: number;
|
|
257
|
+
message?: string;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
interface QueryResponse {
|
|
261
|
+
status: 'success' | 'error';
|
|
262
|
+
results: QueryResult[];
|
|
263
|
+
took?: number;
|
|
264
|
+
error?: ErrorDetail;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
interface ErrorDetail {
|
|
268
|
+
code: string;
|
|
269
|
+
message: string;
|
|
270
|
+
details?: any;
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Enums
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
// Message type for WebSocket subscription events
|
|
278
|
+
enum MessageType {
|
|
279
|
+
SubscriptionAck = 'subscription_ack',
|
|
280
|
+
InitialDataBatch = 'initial_data_batch',
|
|
281
|
+
Change = 'change',
|
|
282
|
+
Error = 'error',
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Change type for live subscription change events
|
|
286
|
+
enum ChangeType {
|
|
287
|
+
Insert = 'insert',
|
|
288
|
+
Update = 'update',
|
|
289
|
+
Delete = 'delete',
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Batch loading status
|
|
293
|
+
enum BatchStatus {
|
|
294
|
+
Loading = 'loading',
|
|
295
|
+
LoadingBatch = 'loading_batch',
|
|
296
|
+
Ready = 'ready',
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Live subscription event types
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
type ServerMessage =
|
|
304
|
+
| {
|
|
305
|
+
type: MessageType.SubscriptionAck;
|
|
306
|
+
subscription_id: string;
|
|
307
|
+
total_rows: number;
|
|
308
|
+
batch_control: BatchControl;
|
|
309
|
+
schema: SchemaField[];
|
|
310
|
+
}
|
|
311
|
+
| {
|
|
312
|
+
type: MessageType.InitialDataBatch;
|
|
313
|
+
subscription_id: string;
|
|
314
|
+
rows: Record<string, any>[];
|
|
315
|
+
batch_control: BatchControl;
|
|
316
|
+
}
|
|
317
|
+
| {
|
|
318
|
+
type: MessageType.Change;
|
|
319
|
+
subscription_id: string;
|
|
320
|
+
change_type: ChangeType;
|
|
321
|
+
rows?: Record<string, any>[];
|
|
322
|
+
old_values?: Record<string, any>[];
|
|
323
|
+
}
|
|
324
|
+
| {
|
|
325
|
+
type: MessageType.Error;
|
|
326
|
+
subscription_id: string;
|
|
327
|
+
code: string;
|
|
328
|
+
message: string;
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
interface BatchControl {
|
|
332
|
+
batch_num: number;
|
|
333
|
+
has_more: boolean;
|
|
334
|
+
status: BatchStatus;
|
|
335
|
+
last_seq_id?: string;
|
|
336
|
+
snapshot_end_seq?: string;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
type SubscriptionCallback = (event: ServerMessage) => void;
|
|
340
|
+
type Unsubscribe = () => Promise<void>;
|
|
341
|
+
|
|
342
|
+
interface SubscriptionInfo {
|
|
343
|
+
id: string;
|
|
344
|
+
tableName: string;
|
|
345
|
+
createdAt: Date;
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Options
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
interface ConnectionOptions {
|
|
353
|
+
auto_reconnect?: boolean;
|
|
354
|
+
reconnect_delay_ms?: number;
|
|
355
|
+
max_reconnect_delay_ms?: number;
|
|
356
|
+
max_reconnect_attempts?: number;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
interface SubscriptionOptions {
|
|
360
|
+
batch_size?: number;
|
|
361
|
+
last_rows?: number;
|
|
362
|
+
from_seq_id?: string;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
type SubscribeOptions = SubscriptionOptions;
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Advanced: WASM entrypoint (`kalam-link/wasm`)
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
import init, {
|
|
372
|
+
KalamClient,
|
|
373
|
+
WasmTimestampFormatter,
|
|
374
|
+
parseIso8601,
|
|
375
|
+
timestampNow,
|
|
376
|
+
initSync,
|
|
377
|
+
} from 'kalam-link/wasm';
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Exports:
|
|
381
|
+
|
|
382
|
+
- `default init(moduleOrPath?) => Promise<InitOutput>`
|
|
383
|
+
- `initSync(moduleOrBytes) => InitOutput`
|
|
384
|
+
- `class KalamClient` (low-level WASM client)
|
|
385
|
+
- `class WasmTimestampFormatter`
|
|
386
|
+
- `parseIso8601(isoString: string): number`
|
|
387
|
+
- `timestampNow(): number`
|
|
388
|
+
|
|
389
|
+
## Notes (Browser/Node)
|
|
390
|
+
|
|
391
|
+
This package includes a small `.wasm` runtime under the hood.
|
|
392
|
+
|
|
393
|
+
- In browsers with bundlers (Vite/Webpack/Rollup), it should “just work”.
|
|
394
|
+
- If you see WASM loading errors, ensure your build serves/copies:
|
|
395
|
+
`node_modules/kalam-link/dist/wasm/kalam_link_bg.wasm`
|
|
396
|
+
|
|
397
|
+
## Links
|
|
398
|
+
|
|
399
|
+
- KalamDB repository: https://github.com/jamals86/KalamDB
|
|
400
|
+
- Issues: https://github.com/jamals86/KalamDB/issues
|
|
401
|
+
|
|
402
|
+
## Development (Build From This Repo)
|
|
403
|
+
|
|
404
|
+
Only needed if you are contributing to the SDK.
|
|
405
|
+
|
|
406
|
+
Prerequisites:
|
|
407
|
+
|
|
408
|
+
- Node.js `>=18`
|
|
409
|
+
- Rust toolchain + `wasm-pack`
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
cd link/sdks/typescript
|
|
413
|
+
npm install
|
|
414
|
+
npm run build
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## License
|
|
418
|
+
|
|
419
|
+
Apache-2.0 (see the repository root).
|
|
420
|
+
|
|
421
|
+
## Contributing
|
|
422
|
+
|
|
423
|
+
Issues/PRs are welcome: https://github.com/jamals86/KalamDB/issues
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication types and utilities for KalamDB client
|
|
3
|
+
*
|
|
4
|
+
* Provides a type-safe authentication API with support for:
|
|
5
|
+
* - Basic Auth (username/password)
|
|
6
|
+
* - JWT Token Auth
|
|
7
|
+
* - Anonymous (no auth - for localhost bypass)
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Basic authentication credentials (username/password)
|
|
11
|
+
*/
|
|
12
|
+
export interface BasicAuthCredentials {
|
|
13
|
+
type: 'basic';
|
|
14
|
+
username: string;
|
|
15
|
+
password: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* JWT token authentication credentials
|
|
19
|
+
*/
|
|
20
|
+
export interface JwtAuthCredentials {
|
|
21
|
+
type: 'jwt';
|
|
22
|
+
token: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* No authentication (anonymous access)
|
|
26
|
+
*/
|
|
27
|
+
export interface NoAuthCredentials {
|
|
28
|
+
type: 'none';
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Union type for all authentication credential types
|
|
32
|
+
*/
|
|
33
|
+
export type AuthCredentials = BasicAuthCredentials | JwtAuthCredentials | NoAuthCredentials;
|
|
34
|
+
/**
|
|
35
|
+
* Type guard to check if credentials are Basic Auth
|
|
36
|
+
*/
|
|
37
|
+
export declare function isBasicAuth(auth: AuthCredentials): auth is BasicAuthCredentials;
|
|
38
|
+
/**
|
|
39
|
+
* Type guard to check if credentials are JWT Auth
|
|
40
|
+
*/
|
|
41
|
+
export declare function isJwtAuth(auth: AuthCredentials): auth is JwtAuthCredentials;
|
|
42
|
+
/**
|
|
43
|
+
* Type guard to check if credentials are No Auth
|
|
44
|
+
*/
|
|
45
|
+
export declare function isNoAuth(auth: AuthCredentials): auth is NoAuthCredentials;
|
|
46
|
+
/**
|
|
47
|
+
* Type guard to check if any authentication is configured
|
|
48
|
+
*/
|
|
49
|
+
export declare function isAuthenticated(auth: AuthCredentials): auth is BasicAuthCredentials | JwtAuthCredentials;
|
|
50
|
+
/**
|
|
51
|
+
* Encode username and password for Basic Auth header
|
|
52
|
+
*
|
|
53
|
+
* @param username - Username
|
|
54
|
+
* @param password - Password
|
|
55
|
+
* @returns Base64 encoded credentials string
|
|
56
|
+
*/
|
|
57
|
+
export declare function encodeBasicAuth(username: string, password: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Build the Authorization header value for the given credentials
|
|
60
|
+
*
|
|
61
|
+
* @param auth - Authentication credentials
|
|
62
|
+
* @returns Authorization header value or undefined for no auth
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildAuthHeader(auth: AuthCredentials): string | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Auth factory for creating type-safe authentication credentials
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* import { createClient, Auth } from 'kalam-link';
|
|
71
|
+
*
|
|
72
|
+
* // Basic Auth
|
|
73
|
+
* const client = createClient({
|
|
74
|
+
* url: 'http://localhost:8080',
|
|
75
|
+
* auth: Auth.basic('admin', 'admin')
|
|
76
|
+
* });
|
|
77
|
+
*
|
|
78
|
+
* // JWT Token
|
|
79
|
+
* const jwtClient = createClient({
|
|
80
|
+
* url: 'http://localhost:8080',
|
|
81
|
+
* auth: Auth.jwt('eyJhbGciOiJIUzI1NiIs...')
|
|
82
|
+
* });
|
|
83
|
+
*
|
|
84
|
+
* // Anonymous (no auth)
|
|
85
|
+
* const anonClient = createClient({
|
|
86
|
+
* url: 'http://localhost:8080',
|
|
87
|
+
* auth: Auth.none()
|
|
88
|
+
* });
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare const Auth: {
|
|
92
|
+
/**
|
|
93
|
+
* Create Basic Auth credentials
|
|
94
|
+
*
|
|
95
|
+
* @param username - Username for authentication
|
|
96
|
+
* @param password - Password for authentication
|
|
97
|
+
* @returns BasicAuthCredentials object
|
|
98
|
+
*/
|
|
99
|
+
readonly basic: (username: string, password: string) => BasicAuthCredentials;
|
|
100
|
+
/**
|
|
101
|
+
* Create JWT Auth credentials
|
|
102
|
+
*
|
|
103
|
+
* @param token - JWT token string
|
|
104
|
+
* @returns JwtAuthCredentials object
|
|
105
|
+
*/
|
|
106
|
+
readonly jwt: (token: string) => JwtAuthCredentials;
|
|
107
|
+
/**
|
|
108
|
+
* Create No Auth credentials (anonymous access)
|
|
109
|
+
*
|
|
110
|
+
* @returns NoAuthCredentials object
|
|
111
|
+
*/
|
|
112
|
+
readonly none: () => NoAuthCredentials;
|
|
113
|
+
};
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication types and utilities for KalamDB client
|
|
3
|
+
*
|
|
4
|
+
* Provides a type-safe authentication API with support for:
|
|
5
|
+
* - Basic Auth (username/password)
|
|
6
|
+
* - JWT Token Auth
|
|
7
|
+
* - Anonymous (no auth - for localhost bypass)
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Type guard to check if credentials are Basic Auth
|
|
11
|
+
*/
|
|
12
|
+
export function isBasicAuth(auth) {
|
|
13
|
+
return auth.type === 'basic';
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Type guard to check if credentials are JWT Auth
|
|
17
|
+
*/
|
|
18
|
+
export function isJwtAuth(auth) {
|
|
19
|
+
return auth.type === 'jwt';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Type guard to check if credentials are No Auth
|
|
23
|
+
*/
|
|
24
|
+
export function isNoAuth(auth) {
|
|
25
|
+
return auth.type === 'none';
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Type guard to check if any authentication is configured
|
|
29
|
+
*/
|
|
30
|
+
export function isAuthenticated(auth) {
|
|
31
|
+
return auth.type !== 'none';
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Base64 encode a string (works in both Node.js and browser)
|
|
35
|
+
*/
|
|
36
|
+
function base64Encode(str) {
|
|
37
|
+
if (typeof btoa === 'function') {
|
|
38
|
+
// Browser environment
|
|
39
|
+
return btoa(str);
|
|
40
|
+
}
|
|
41
|
+
else if (typeof Buffer !== 'undefined') {
|
|
42
|
+
// Node.js environment
|
|
43
|
+
return Buffer.from(str).toString('base64');
|
|
44
|
+
}
|
|
45
|
+
throw new Error('No base64 encoding available');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Encode username and password for Basic Auth header
|
|
49
|
+
*
|
|
50
|
+
* @param username - Username
|
|
51
|
+
* @param password - Password
|
|
52
|
+
* @returns Base64 encoded credentials string
|
|
53
|
+
*/
|
|
54
|
+
export function encodeBasicAuth(username, password) {
|
|
55
|
+
return base64Encode(`${username}:${password}`);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Build the Authorization header value for the given credentials
|
|
59
|
+
*
|
|
60
|
+
* @param auth - Authentication credentials
|
|
61
|
+
* @returns Authorization header value or undefined for no auth
|
|
62
|
+
*/
|
|
63
|
+
export function buildAuthHeader(auth) {
|
|
64
|
+
switch (auth.type) {
|
|
65
|
+
case 'basic':
|
|
66
|
+
return `Basic ${encodeBasicAuth(auth.username, auth.password)}`;
|
|
67
|
+
case 'jwt':
|
|
68
|
+
return `Bearer ${auth.token}`;
|
|
69
|
+
case 'none':
|
|
70
|
+
return undefined;
|
|
71
|
+
default:
|
|
72
|
+
// Exhaustiveness check
|
|
73
|
+
const _exhaustive = auth;
|
|
74
|
+
throw new Error(`Unknown auth type: ${_exhaustive.type}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Auth factory for creating type-safe authentication credentials
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* import { createClient, Auth } from 'kalam-link';
|
|
83
|
+
*
|
|
84
|
+
* // Basic Auth
|
|
85
|
+
* const client = createClient({
|
|
86
|
+
* url: 'http://localhost:8080',
|
|
87
|
+
* auth: Auth.basic('admin', 'admin')
|
|
88
|
+
* });
|
|
89
|
+
*
|
|
90
|
+
* // JWT Token
|
|
91
|
+
* const jwtClient = createClient({
|
|
92
|
+
* url: 'http://localhost:8080',
|
|
93
|
+
* auth: Auth.jwt('eyJhbGciOiJIUzI1NiIs...')
|
|
94
|
+
* });
|
|
95
|
+
*
|
|
96
|
+
* // Anonymous (no auth)
|
|
97
|
+
* const anonClient = createClient({
|
|
98
|
+
* url: 'http://localhost:8080',
|
|
99
|
+
* auth: Auth.none()
|
|
100
|
+
* });
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export const Auth = {
|
|
104
|
+
/**
|
|
105
|
+
* Create Basic Auth credentials
|
|
106
|
+
*
|
|
107
|
+
* @param username - Username for authentication
|
|
108
|
+
* @param password - Password for authentication
|
|
109
|
+
* @returns BasicAuthCredentials object
|
|
110
|
+
*/
|
|
111
|
+
basic(username, password) {
|
|
112
|
+
return { type: 'basic', username, password };
|
|
113
|
+
},
|
|
114
|
+
/**
|
|
115
|
+
* Create JWT Auth credentials
|
|
116
|
+
*
|
|
117
|
+
* @param token - JWT token string
|
|
118
|
+
* @returns JwtAuthCredentials object
|
|
119
|
+
*/
|
|
120
|
+
jwt(token) {
|
|
121
|
+
return { type: 'jwt', token };
|
|
122
|
+
},
|
|
123
|
+
/**
|
|
124
|
+
* Create No Auth credentials (anonymous access)
|
|
125
|
+
*
|
|
126
|
+
* @returns NoAuthCredentials object
|
|
127
|
+
*/
|
|
128
|
+
none() {
|
|
129
|
+
return { type: 'none' };
|
|
130
|
+
}
|
|
131
|
+
};
|