dominus-sdk-nodejs-dev 1.2.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.
Files changed (75) hide show
  1. package/LLM-GUIDE.md +537 -0
  2. package/README.md +585 -0
  3. package/dist/index.d.ts +191 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +224 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/lib/cache.d.ts +112 -0
  8. package/dist/lib/cache.d.ts.map +1 -0
  9. package/dist/lib/cache.js +237 -0
  10. package/dist/lib/cache.js.map +1 -0
  11. package/dist/lib/client.d.ts +38 -0
  12. package/dist/lib/client.d.ts.map +1 -0
  13. package/dist/lib/client.js +425 -0
  14. package/dist/lib/client.js.map +1 -0
  15. package/dist/lib/config.d.ts +20 -0
  16. package/dist/lib/config.d.ts.map +1 -0
  17. package/dist/lib/config.js +32 -0
  18. package/dist/lib/config.js.map +1 -0
  19. package/dist/lib/crypto.d.ts +70 -0
  20. package/dist/lib/crypto.d.ts.map +1 -0
  21. package/dist/lib/crypto.js +95 -0
  22. package/dist/lib/crypto.js.map +1 -0
  23. package/dist/lib/errors.d.ts +77 -0
  24. package/dist/lib/errors.d.ts.map +1 -0
  25. package/dist/lib/errors.js +134 -0
  26. package/dist/lib/errors.js.map +1 -0
  27. package/dist/namespaces/auth.d.ts +237 -0
  28. package/dist/namespaces/auth.d.ts.map +1 -0
  29. package/dist/namespaces/auth.js +785 -0
  30. package/dist/namespaces/auth.js.map +1 -0
  31. package/dist/namespaces/courier.d.ts +67 -0
  32. package/dist/namespaces/courier.d.ts.map +1 -0
  33. package/dist/namespaces/courier.js +90 -0
  34. package/dist/namespaces/courier.js.map +1 -0
  35. package/dist/namespaces/db.d.ts +117 -0
  36. package/dist/namespaces/db.d.ts.map +1 -0
  37. package/dist/namespaces/db.js +149 -0
  38. package/dist/namespaces/db.js.map +1 -0
  39. package/dist/namespaces/ddl.d.ts +84 -0
  40. package/dist/namespaces/ddl.d.ts.map +1 -0
  41. package/dist/namespaces/ddl.js +211 -0
  42. package/dist/namespaces/ddl.js.map +1 -0
  43. package/dist/namespaces/files.d.ts +107 -0
  44. package/dist/namespaces/files.d.ts.map +1 -0
  45. package/dist/namespaces/files.js +161 -0
  46. package/dist/namespaces/files.js.map +1 -0
  47. package/dist/namespaces/health.d.ts +30 -0
  48. package/dist/namespaces/health.d.ts.map +1 -0
  49. package/dist/namespaces/health.js +66 -0
  50. package/dist/namespaces/health.js.map +1 -0
  51. package/dist/namespaces/logs.d.ts +97 -0
  52. package/dist/namespaces/logs.d.ts.map +1 -0
  53. package/dist/namespaces/logs.js +194 -0
  54. package/dist/namespaces/logs.js.map +1 -0
  55. package/dist/namespaces/open.d.ts +27 -0
  56. package/dist/namespaces/open.d.ts.map +1 -0
  57. package/dist/namespaces/open.js +46 -0
  58. package/dist/namespaces/open.js.map +1 -0
  59. package/dist/namespaces/portal.d.ts +172 -0
  60. package/dist/namespaces/portal.d.ts.map +1 -0
  61. package/dist/namespaces/portal.js +332 -0
  62. package/dist/namespaces/portal.js.map +1 -0
  63. package/dist/namespaces/redis.d.ts +144 -0
  64. package/dist/namespaces/redis.d.ts.map +1 -0
  65. package/dist/namespaces/redis.js +218 -0
  66. package/dist/namespaces/redis.js.map +1 -0
  67. package/dist/namespaces/secrets.d.ts +50 -0
  68. package/dist/namespaces/secrets.d.ts.map +1 -0
  69. package/dist/namespaces/secrets.js +93 -0
  70. package/dist/namespaces/secrets.js.map +1 -0
  71. package/dist/namespaces/secure.d.ts +102 -0
  72. package/dist/namespaces/secure.d.ts.map +1 -0
  73. package/dist/namespaces/secure.js +151 -0
  74. package/dist/namespaces/secure.js.map +1 -0
  75. package/package.json +45 -0
package/README.md ADDED
@@ -0,0 +1,585 @@
1
+ # CB Dominus SDK for Node.js
2
+
3
+ **TypeScript SDK for the Dominus Orchestrator Platform**
4
+
5
+ A unified, async-first TypeScript SDK providing seamless access to all Dominus backend services including secrets management, database operations, caching, file storage, authentication, schema management, and structured logging.
6
+
7
+ ## Features
8
+
9
+ - **Namespace-based API** - Intuitive access via `dominus.db`, `dominus.redis`, `dominus.files`, etc.
10
+ - **Async/Await** - Built for modern async TypeScript/JavaScript applications
11
+ - **Automatic JWT Management** - Token minting, caching, and refresh handled transparently
12
+ - **Resilience Built-in** - Circuit breaker, exponential backoff with jitter, retry logic
13
+ - **Cold Start Handling** - Special retry logic for orchestrator cold starts
14
+ - **Typed Errors** - 9 specific error classes for different failure modes
15
+ - **Secure by Default** - Client-side password hashing, audit trail support
16
+ - **Server-Side Only** - Designed for Next.js API routes, Express, and Node.js backends
17
+
18
+ ## Quick Start
19
+
20
+ ```typescript
21
+ import { dominus } from 'dominus-sdk-nodejs';
22
+
23
+ // Set your token (or use DOMINUS_TOKEN environment variable)
24
+ process.env.DOMINUS_TOKEN = "your-psk-token";
25
+
26
+ // Secrets
27
+ const dbUrl = await dominus.secrets.get("DATABASE_URL");
28
+
29
+ // Database queries
30
+ const users = await dominus.db.query("users", { filters: { status: "active" } });
31
+
32
+ // Redis caching
33
+ await dominus.redis.set("session:123", { user: "john" }, { ttl: 3600 });
34
+
35
+ // File storage
36
+ const result = await dominus.files.upload(buffer, "report.pdf", { category: "reports" });
37
+
38
+ // Structured logging
39
+ await dominus.logs.info("User logged in", { user_id: "123" });
40
+ ```
41
+
42
+ ## Installation
43
+
44
+ ```bash
45
+ npm install dominus-sdk-nodejs
46
+ ```
47
+
48
+ Or add directly from GitHub:
49
+
50
+ ```bash
51
+ npm install github:carebridgesystems/cb-dominus-sdk-nodejs
52
+ ```
53
+
54
+ ## Requirements
55
+
56
+ - Node.js 18+ (uses native fetch)
57
+ - TypeScript 5.0+ (optional, but recommended)
58
+
59
+ ## Namespaces
60
+
61
+ | Namespace | Service | Purpose |
62
+ |-----------|---------|---------|
63
+ | `dominus.secrets` | Warden | Secrets management |
64
+ | `dominus.db` | Scribe | Database CRUD operations |
65
+ | `dominus.secure` | Scribe | Secure table access with audit logging |
66
+ | `dominus.redis` | Whisperer | Redis caching & distributed locks |
67
+ | `dominus.files` | Archivist | Object storage (Backblaze B2) |
68
+ | `dominus.auth` | Guardian | Users, roles, scopes, tenants, pages, navigation |
69
+ | `dominus.ddl` | Smith | Schema DDL & migrations |
70
+ | `dominus.logs` | Herald | Structured logging (BetterStack) |
71
+ | `dominus.portal` | Portal | User auth, sessions, profiles, navigation |
72
+ | `dominus.courier` | Courier | Email delivery (Postmark) |
73
+ | `dominus.open` | Scribe | Direct database access |
74
+ | `dominus.health` | Health | Service health checks |
75
+
76
+ ## Usage Examples
77
+
78
+ ### Secrets Management
79
+
80
+ ```typescript
81
+ // Get a secret
82
+ const value = await dominus.secrets.get("API_KEY");
83
+
84
+ // Create or update
85
+ await dominus.secrets.upsert("API_KEY", "new-value", "Updated API key");
86
+
87
+ // List secrets with prefix
88
+ const secrets = await dominus.secrets.list("DB_");
89
+
90
+ // Delete
91
+ await dominus.secrets.delete("OLD_KEY");
92
+
93
+ // Root-level shortcuts
94
+ const dbUrl = await dominus.get("DATABASE_URL");
95
+ await dominus.upsert("KEY", "value");
96
+ ```
97
+
98
+ ### Database Operations
99
+
100
+ ```typescript
101
+ // List tables
102
+ const tables = await dominus.db.tables();
103
+ const tenantTables = await dominus.db.tables("tenant_acme");
104
+
105
+ // Query with filters and pagination
106
+ const users = await dominus.db.query("users", {
107
+ filters: { status: "active", role: ["admin", "manager"] },
108
+ sortBy: "created_at",
109
+ sortOrder: "DESC",
110
+ limit: 50,
111
+ offset: 0
112
+ });
113
+
114
+ // Insert
115
+ const user = await dominus.db.insert("users", {
116
+ email: "john@example.com",
117
+ name: "John Doe"
118
+ });
119
+
120
+ // Update
121
+ await dominus.db.update("users", { status: "inactive" }, { id: userId });
122
+
123
+ // Delete
124
+ await dominus.db.delete("users", { id: userId });
125
+
126
+ // Bulk insert
127
+ await dominus.db.bulkInsert("events", [
128
+ { type: "login", user_id: "123" },
129
+ { type: "login", user_id: "456" }
130
+ ]);
131
+
132
+ // Secure table access (requires audit reason)
133
+ const patients = await dominus.db.query("patients", {
134
+ schema: "tenant_acme",
135
+ reason: "Reviewing records for appointment #123",
136
+ actor: "dr.smith"
137
+ });
138
+ ```
139
+
140
+ ### Redis Caching
141
+
142
+ ```typescript
143
+ // Key-value operations
144
+ await dominus.redis.set("user:123", { name: "John" }, { ttl: 3600 });
145
+ const value = await dominus.redis.get("user:123");
146
+
147
+ // Distributed locks
148
+ const acquired = await dominus.redis.setnx("lock:job", "worker-1", { ttl: 60 });
149
+ if (acquired) {
150
+ try {
151
+ // Do exclusive work
152
+ } finally {
153
+ await dominus.redis.delete("lock:job");
154
+ }
155
+ }
156
+
157
+ // Counters
158
+ await dominus.redis.incr("page:views", 1);
159
+
160
+ // Hash operations
161
+ await dominus.redis.hset("user:123", "email", "john@example.com", { ttl: 3600 });
162
+ const email = await dominus.redis.hget("user:123", "email");
163
+ const allFields = await dominus.redis.hgetall("user:123");
164
+ ```
165
+
166
+ ### File Storage
167
+
168
+ ```typescript
169
+ import { readFileSync } from 'fs';
170
+
171
+ // Upload file
172
+ const data = readFileSync("report.pdf");
173
+ const result = await dominus.files.upload(data, "report.pdf", {
174
+ category: "reports",
175
+ contentType: "application/pdf"
176
+ });
177
+
178
+ // Get download URL
179
+ const download = await dominus.files.download({ id: result.id });
180
+ console.log(download.download_url);
181
+
182
+ // Fetch file from URL and store
183
+ const fetched = await dominus.files.fetch("https://example.com/doc.pdf", {
184
+ filename: "external-doc.pdf",
185
+ category: "imports"
186
+ });
187
+
188
+ // List files
189
+ const files = await dominus.files.list({ category: "reports", prefix: "2025/" });
190
+
191
+ // Delete file
192
+ await dominus.files.delete({ id: result.id });
193
+ ```
194
+
195
+ ### Structured Logging
196
+
197
+ ```typescript
198
+ // Simple logging (auto-captures file and function)
199
+ await dominus.logs.info("User logged in", { user_id: "123" });
200
+ await dominus.logs.error("Payment failed", { order_id: "456" });
201
+
202
+ // All log levels
203
+ await dominus.logs.debug("Debug message", { data: "..." });
204
+ await dominus.logs.notice("Important notice", {});
205
+ await dominus.logs.warn("Warning message", {});
206
+ await dominus.logs.critical("Critical error", {});
207
+
208
+ // With category
209
+ await dominus.logs.info("Cache hit", { key: "user:123" }, "cache");
210
+
211
+ // With exception
212
+ try {
213
+ riskyOperation();
214
+ } catch (error) {
215
+ await dominus.logs.error("Operation failed", {}, { exception: error as Error });
216
+ }
217
+
218
+ // Batch logging
219
+ await dominus.logs.batch([
220
+ { level: "info", message: "Step 1 complete", data: {} },
221
+ { level: "info", message: "Step 2 complete", data: {} }
222
+ ]);
223
+
224
+ // Query logs
225
+ const errors = await dominus.logs.query({ level: "error", limit: 100 });
226
+ ```
227
+
228
+ ### Authentication & Authorization (Guardian)
229
+
230
+ ```typescript
231
+ // User management
232
+ const users = await dominus.auth.listUsers();
233
+ const user = await dominus.auth.getUser("user-uuid");
234
+
235
+ const newUser = await dominus.auth.addUser({
236
+ username: "john",
237
+ password: "secure-password",
238
+ email: "john@example.com"
239
+ });
240
+
241
+ await dominus.auth.updateUser("user-uuid", { status: "active" });
242
+ await dominus.auth.deleteUser("user-uuid");
243
+
244
+ // Role management
245
+ const roles = await dominus.auth.listRoles();
246
+ const role = await dominus.auth.addRole({
247
+ name: "Editor",
248
+ scopeSlugs: ["read", "write", "publish"]
249
+ });
250
+
251
+ // Scope management
252
+ const scopes = await dominus.auth.listScopes();
253
+ await dominus.auth.addScope({ name: "publish", slug: "publish" });
254
+
255
+ // Tenant management
256
+ const tenants = await dominus.auth.listTenants();
257
+ const categories = await dominus.auth.listTenantCategories();
258
+
259
+ // Page and navigation
260
+ const pages = await dominus.auth.listPages();
261
+ const navItems = await dominus.auth.listNavigation();
262
+
263
+ // Secure tables registry
264
+ const secureTables = await dominus.auth.listSecureTables();
265
+ await dominus.auth.addSecureTable("patients", "tenant_acme");
266
+ ```
267
+
268
+ ### Schema Management (DDL)
269
+
270
+ ```typescript
271
+ // Create table
272
+ await dominus.ddl.createTable("orders", [
273
+ { name: "id", type: "UUID", constraints: ["PRIMARY KEY"] },
274
+ { name: "user_id", type: "UUID", constraints: ["NOT NULL"] },
275
+ { name: "total", type: "DECIMAL(10,2)" },
276
+ { name: "created_at", type: "TIMESTAMPTZ", default: "NOW()" }
277
+ ]);
278
+
279
+ // Add column
280
+ await dominus.ddl.addColumn("orders", {
281
+ name: "status",
282
+ type: "VARCHAR(50)",
283
+ default: "'pending'"
284
+ });
285
+
286
+ // Alter column
287
+ await dominus.ddl.alterColumn("orders", "status", { type: "VARCHAR(100)" });
288
+
289
+ // Create index
290
+ await dominus.ddl.createIndex("orders", "idx_orders_user", ["user_id"]);
291
+
292
+ // Migrations
293
+ const migrations = await dominus.ddl.listMigrations();
294
+ await dominus.ddl.applyMigration("20250101_add_orders");
295
+
296
+ // Provision tenant schema from category template
297
+ await dominus.ddl.provisionTenantFromCategory("customer_acme", "healthcare");
298
+ ```
299
+
300
+ ### User Authentication (Portal)
301
+
302
+ ```typescript
303
+ // User login (tenant_id is optional)
304
+ const session = await dominus.portal.login(
305
+ "john@example.com",
306
+ "secret123",
307
+ "tenant-uuid" // optional
308
+ );
309
+
310
+ // Client login with PSK (for service-to-service)
311
+ const clientSession = await dominus.portal.loginClient("psk-token");
312
+
313
+ // Get current user
314
+ const me = await dominus.portal.me();
315
+
316
+ // Get navigation (access-filtered for current user)
317
+ const nav = await dominus.portal.getNavigation();
318
+
319
+ // Check page access
320
+ const hasAccess = await dominus.portal.checkPageAccess("/dashboard/admin/users");
321
+
322
+ // Switch tenant
323
+ await dominus.portal.switchTenant("other-tenant-uuid");
324
+
325
+ // Profile & preferences
326
+ const profile = await dominus.portal.getProfile();
327
+ await dominus.portal.updateProfile({ displayName: "John Doe" });
328
+
329
+ const prefs = await dominus.portal.getPreferences();
330
+ await dominus.portal.updatePreferences({
331
+ theme: "dark",
332
+ timezone: "America/New_York"
333
+ });
334
+
335
+ // Password management
336
+ await dominus.portal.changePassword("old-password", "new-password");
337
+ await dominus.portal.requestPasswordReset("john@example.com");
338
+ await dominus.portal.confirmPasswordReset("reset-token", "new-password");
339
+
340
+ // Session management
341
+ const sessions = await dominus.portal.listSessions();
342
+ await dominus.portal.revokeSession("session-id");
343
+ await dominus.portal.revokeAllSessions();
344
+
345
+ // Registration & email verification
346
+ await dominus.portal.register("newuser", "new@example.com", "password", "tenant-id");
347
+ await dominus.portal.verifyEmail("verification-token");
348
+ await dominus.portal.resendVerification("new@example.com");
349
+
350
+ // Logout
351
+ await dominus.portal.logout();
352
+ ```
353
+
354
+ ### Email Delivery (Courier)
355
+
356
+ ```typescript
357
+ // Send email via Postmark template
358
+ const result = await dominus.courier.send(
359
+ "welcome",
360
+ "user@example.com",
361
+ "noreply@myapp.com",
362
+ { name: "John", product_name: "My App" }
363
+ );
364
+
365
+ // Convenience methods
366
+ await dominus.courier.sendWelcome(
367
+ "user@example.com",
368
+ "noreply@myapp.com",
369
+ { name: "John", actionUrl: "https://myapp.com/start", productName: "My App" }
370
+ );
371
+
372
+ await dominus.courier.sendPasswordReset(
373
+ "user@example.com",
374
+ "noreply@myapp.com",
375
+ { name: "John", resetUrl: "https://myapp.com/reset?token=abc", productName: "My App" }
376
+ );
377
+
378
+ await dominus.courier.sendEmailVerification(
379
+ "user@example.com",
380
+ "noreply@myapp.com",
381
+ { name: "John", verifyUrl: "https://myapp.com/verify?token=xyz", productName: "My App" }
382
+ );
383
+
384
+ await dominus.courier.sendInvitation(
385
+ "invited@example.com",
386
+ "noreply@myapp.com",
387
+ {
388
+ name: "Invited User",
389
+ inviteUrl: "https://myapp.com/invite?token=abc",
390
+ inviterName: "John",
391
+ productName: "My App"
392
+ }
393
+ );
394
+ ```
395
+
396
+ ### Health Checks
397
+
398
+ ```typescript
399
+ // Basic health check
400
+ const status = await dominus.health.check();
401
+
402
+ // Ping (lightweight)
403
+ await dominus.health.ping();
404
+
405
+ // Warmup (for cold start tolerance)
406
+ await dominus.health.warmup();
407
+ ```
408
+
409
+ ## Error Handling
410
+
411
+ ```typescript
412
+ import {
413
+ dominus,
414
+ DominusError,
415
+ AuthenticationError,
416
+ AuthorizationError,
417
+ NotFoundError,
418
+ ValidationError,
419
+ ConflictError,
420
+ ServiceError,
421
+ SecureTableError,
422
+ ConnectionError,
423
+ TimeoutError,
424
+ } from 'dominus-sdk-nodejs';
425
+
426
+ try {
427
+ const user = await dominus.auth.getUser("invalid-id");
428
+ } catch (error) {
429
+ if (error instanceof NotFoundError) {
430
+ console.log(`User not found: ${error.message}`);
431
+ } else if (error instanceof SecureTableError) {
432
+ console.log("Secure table requires 'reason' and 'actor' parameters");
433
+ } else if (error instanceof AuthenticationError) {
434
+ console.log("Invalid or expired token");
435
+ } else if (error instanceof AuthorizationError) {
436
+ console.log("Insufficient permissions");
437
+ } else if (error instanceof ValidationError) {
438
+ console.log(`Invalid request: ${error.message}`);
439
+ } else if (error instanceof TimeoutError) {
440
+ console.log("Request timed out");
441
+ } else if (error instanceof DominusError) {
442
+ console.log(`Error ${error.statusCode}: ${error.message}`);
443
+ if (error.details) {
444
+ console.log(`Details: ${JSON.stringify(error.details)}`);
445
+ }
446
+ }
447
+ }
448
+ ```
449
+
450
+ ### Error Types
451
+
452
+ | Error | Status | Description |
453
+ |-------|--------|-------------|
454
+ | `AuthenticationError` | 401 | Invalid or missing token |
455
+ | `AuthorizationError` | 403 | Insufficient permissions |
456
+ | `NotFoundError` | 404 | Resource not found |
457
+ | `ValidationError` | 400 | Invalid request data |
458
+ | `ConflictError` | 409 | Duplicate or version conflict |
459
+ | `ServiceError` | 5xx | Backend service error |
460
+ | `SecureTableError` | 403 | Missing reason for secure table |
461
+ | `ConnectionError` | - | Network connection failed |
462
+ | `TimeoutError` | 504 | Request timed out |
463
+
464
+ ## Configuration
465
+
466
+ ### Environment Variables
467
+
468
+ ```bash
469
+ # Required: PSK token for authentication
470
+ export DOMINUS_TOKEN="your-psk-token"
471
+ ```
472
+
473
+ ### Resilience Configuration
474
+
475
+ The SDK includes built-in resilience features:
476
+
477
+ | Feature | Configuration |
478
+ |---------|---------------|
479
+ | Request Timeout | 30 seconds |
480
+ | Max Retries | 3 with exponential backoff |
481
+ | Circuit Breaker | Opens after 5 failures, resets after 30s |
482
+ | JWT Cache TTL | Refreshes when <60 seconds remain |
483
+ | JWT Mint Retries | 3 with backoff (handles cold starts) |
484
+ | Backoff Delays | Base 1s, max 15s with jitter |
485
+
486
+ ## Architecture
487
+
488
+ ```
489
+ ┌─────────────────┐
490
+ │ Your App │
491
+ │ (Next.js API) │
492
+ └────────┬────────┘
493
+ │ await dominus.db.query(...)
494
+
495
+ ┌─────────────────┐
496
+ │ Dominus SDK │ ← JWT caching, circuit breaker, retries
497
+ │ (this package) │
498
+ └────────┬────────┘
499
+ │ HTTPS (base64-encoded JSON)
500
+
501
+ ┌─────────────────────────────────┐
502
+ │ Dominus Orchestrator │
503
+ │ (Cloud Run FastAPI backend) │
504
+ │ │
505
+ │ ┌─────────┬─────────┬────────┐ │
506
+ │ │ Warden │Guardian │Archivist│ │
507
+ │ │ Scribe │ Smith │Whisperer│ │
508
+ │ │ Herald │ Portal │ Courier │ │
509
+ │ └─────────┴─────────┴────────┘ │
510
+ └─────────────────────────────────┘
511
+ ```
512
+
513
+ ## Next.js Integration
514
+
515
+ ```typescript
516
+ // app/api/users/route.ts
517
+ import { dominus, NotFoundError } from 'dominus-sdk-nodejs';
518
+ import { NextRequest, NextResponse } from 'next/server';
519
+
520
+ export async function GET(request: NextRequest) {
521
+ try {
522
+ const users = await dominus.db.query("users", {
523
+ filters: { status: "active" },
524
+ limit: 50
525
+ });
526
+ return NextResponse.json(users);
527
+ } catch (error) {
528
+ if (error instanceof NotFoundError) {
529
+ return NextResponse.json({ error: "Not found" }, { status: 404 });
530
+ }
531
+ return NextResponse.json({ error: "Failed to fetch users" }, { status: 500 });
532
+ }
533
+ }
534
+ ```
535
+
536
+ ## Crypto Helpers
537
+
538
+ The SDK exports utility functions for password and token handling:
539
+
540
+ ```typescript
541
+ import {
542
+ hashPassword,
543
+ verifyPasswordLocal,
544
+ hashPsk,
545
+ verifyPskLocal,
546
+ generatePskLocal,
547
+ hashToken,
548
+ generateToken
549
+ } from 'dominus-sdk-nodejs';
550
+
551
+ // Password hashing (bcrypt)
552
+ const hash = await hashPassword("user-password");
553
+ const isValid = await verifyPasswordLocal("user-password", hash);
554
+
555
+ // PSK generation and verification
556
+ const psk = generatePskLocal();
557
+ const pskHash = await hashPsk(psk);
558
+ const pskValid = await verifyPskLocal(psk, pskHash);
559
+
560
+ // Token generation
561
+ const token = generateToken(32); // 32-byte random token
562
+ const tokenHash = hashToken(token); // SHA-256 hash
563
+ ```
564
+
565
+ ## Dependencies
566
+
567
+ - `bcryptjs` - Password hashing
568
+
569
+ ## Version
570
+
571
+ **v1.2.2** - Latest release with navigation routes fix and page scope methods
572
+
573
+ ### Changelog
574
+
575
+ - **v1.2.2** - Fix `checkPageAccess` to send correct parameter
576
+ - **v1.2.0** - Add navigation routes and page scope methods
577
+ - **v1.1.6** - Add user token support for user-authenticated requests
578
+ - **v1.1.5** - Make `tenant_id` optional in login methods
579
+ - **v1.1.3** - Add retry with backoff for JWT mint (cold start handling)
580
+ - **v1.1.0** - Fix SDK routes and improve error messaging
581
+ - **v1.0.0** - Initial release with full namespace API
582
+
583
+ ## License
584
+
585
+ Proprietary - CareBridge Systems