@hivedev/hivesdk 1.0.34 → 1.0.35

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 (2) hide show
  1. package/README.md +739 -1
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1 +1,739 @@
1
- Test
1
+ # @hivedev/hivesdk
2
+
3
+ Software development kit for microservices that integrate with the **Hive** system — a hub-and-spoke platform for educational institutions.
4
+
5
+ Every service in the Hive ecosystem (NoteHive, and any future service) is built around this SDK. It handles authentication, configuration management, service registration, database connectivity, push notifications, and client-side session management — so each service only has to implement its own domain logic.
6
+
7
+ ---
8
+
9
+ ## Table of Contents
10
+
11
+ - [Concepts](#concepts)
12
+ - [Installation](#installation)
13
+ - [Server SDK](#server-sdk)
14
+ - [1. Initialising the Server](#1-initialising-the-server)
15
+ - [2. Registering the Service](#2-registering-the-service)
16
+ - [3. Mounting the Middleware](#3-mounting-the-middleware)
17
+ - [4. Loading Configuration](#4-loading-configuration)
18
+ - [5. Connecting to the Database](#5-connecting-to-the-database)
19
+ - [6. Guarding Routes](#6-guarding-routes)
20
+ - [7. Sending Mail](#7-sending-mail)
21
+ - [8. Utility Functions](#8-utility-functions)
22
+ - [Full Server Bootstrap Example](#full-server-bootstrap-example)
23
+ - [Client SDK](#client-sdk)
24
+ - [1. Loading the Client Bundle](#1-loading-the-client-bundle)
25
+ - [2. Initialising the Client](#2-initialising-the-client)
26
+ - [3. Login](#3-login)
27
+ - [4. Checking Login State](#4-checking-login-state)
28
+ - [Full Client Bootstrap Example](#full-client-bootstrap-example)
29
+ - [Enumerations](#enumerations)
30
+ - [Environment Variables Reference](#environment-variables-reference)
31
+ - [How HivePortal Fits In](#how-hiveportal-fits-in)
32
+ - [Known Limitations](#known-limitations)
33
+
34
+ ---
35
+
36
+ ## Concepts
37
+
38
+ **HivePortal** is the central hub. It owns all user accounts, sessions, permissions, and service registry. Every microservice is a spoke — it delegates all authentication and configuration to HivePortal via this SDK.
39
+
40
+ **Service registration** is a two-step process:
41
+ 1. The service announces itself to HivePortal with its name and local/remote URLs.
42
+ 2. HivePortal administrators approve it. Once approved, HivePortal sends back an encrypted configuration payload containing database credentials, Firebase credentials, permissions, and SMTP credentials.
43
+
44
+ **Configuration** is stored encrypted on disk (AES-256-CBC, key derived via scrypt from `SERVER_PASSWORD`). It is decrypted at startup and cached in `process.env`. This means credentials never sit on disk in plaintext.
45
+
46
+ **Authentication** is always proxied. A service never validates a session token itself — it forwards the check to HivePortal and acts on the response.
47
+
48
+ ---
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ npm install @hivedev/hivesdk
54
+ ```
55
+
56
+ The SDK ships three pre-built files:
57
+ - `hive-server.js` — ESM bundle for Node.js backends
58
+ - `hive-server.cjs` — CommonJS bundle for Node.js backends
59
+ - `hive-client.js` — ESM bundle for browser frontends
60
+
61
+ Import paths:
62
+
63
+ ```js
64
+ // Server-side (ESM)
65
+ import { initServer, registerService } from "@hivedev/hivesdk/server";
66
+
67
+ // Client-side (browser, via a script tag or bundler)
68
+ import { initClient, login } from "@hivedev/hivesdk/client";
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Server SDK
74
+
75
+ ### 1. Initialising the Server
76
+
77
+ Call `initServer` once at the very start of your service, before anything else. It sets the service's identity and resolves the server password.
78
+
79
+ ```js
80
+ import { initServer } from "@hivedev/hivesdk/server";
81
+
82
+ await initServer({
83
+ serviceName: "NoteHive", // Must match the name registered in HivePortal
84
+ servicePort: 49161, // The port this service listens on
85
+ remoteUrl: "", // Public-facing URL if accessible from outside LAN, empty string if LAN-only
86
+ serverPassword: "" // Optional — see password resolution below
87
+ });
88
+ ```
89
+
90
+ **Password resolution order:**
91
+
92
+ 1. The `serverPassword` argument, if provided.
93
+ 2. The `SERVER_PASSWORD` environment variable, if set.
94
+ 3. An interactive terminal prompt, if neither of the above is available — it will ask the user to create a password on first run, or enter their existing password on subsequent runs.
95
+
96
+ The password is used as the encryption key for all `.dat` configuration files. Losing it means losing access to the stored configuration.
97
+
98
+ > **Important:** `initServer` must only be called once. Calling it a second time is a no-op with a console warning. In a clustered setup, call it only from the primary process.
99
+
100
+ ---
101
+
102
+ ### 2. Registering the Service
103
+
104
+ After `initServer`, call `registerService` to announce this service to HivePortal and receive configuration.
105
+
106
+ ```js
107
+ import { registerService } from "@hivedev/hivesdk/server";
108
+
109
+ await registerService();
110
+ ```
111
+
112
+ What this does internally:
113
+
114
+ 1. Sets the service's local URL (`http://<hostIp>:<servicePort>`) and remote URL in the internal registry.
115
+ 2. POSTs to HivePortal's `/RegisterService` endpoint.
116
+ 3. If HivePortal accepts the registration request, begins polling HivePortal's `/Configuration` endpoint every 2 seconds.
117
+ 4. Once a Hive administrator approves the service in HivePortal, the configuration payload is received, decrypted, and saved to disk via `saveConfiguration`.
118
+
119
+ **On first run**, the terminal will show:
120
+
121
+ ```
122
+ Registering service...
123
+ Service registration hasn't been approved yet. Please contact administrators!
124
+ Service registration hasn't been approved yet. Please contact administrators!
125
+ ...
126
+ Configuration received.
127
+ Saving configuration...
128
+ Service registered.
129
+ ```
130
+
131
+ Once registered and approved, subsequent startups will load configuration from disk directly via `loadConfiguration` and will not need to go through this polling process again, unless credentials change.
132
+
133
+ > In a clustered setup (e.g. Node.js `cluster` module), call `registerService` only from the primary process, after a short delay to allow workers to start up first.
134
+
135
+ ```js
136
+ import cluster from "cluster";
137
+ import os from "os";
138
+
139
+ if (cluster.isPrimary)
140
+ {
141
+ await initServer({ serviceName: "NoteHive", servicePort: 49161, remoteUrl: "" });
142
+
143
+ setTimeout(async () =>
144
+ {
145
+ await registerService();
146
+ }, 3000);
147
+
148
+ for (let i = 0; i < os.cpus().length; i++)
149
+ {
150
+ cluster.fork({ ...process.env });
151
+ }
152
+ }
153
+ else
154
+ {
155
+ // Start your HTTP server in workers
156
+ }
157
+ ```
158
+
159
+ ---
160
+
161
+ ### 3. Mounting the Middleware
162
+
163
+ `handleHiveRequests` is an Express-compatible middleware that intercepts all Hive-related routes. Mount it before your own route handlers.
164
+
165
+ ```js
166
+ import express from "express";
167
+ import { handleHiveRequests } from "@hivedev/hivesdk/server";
168
+
169
+ const app = express();
170
+
171
+ app.use(express.json());
172
+ app.use(cookieParser());
173
+ app.use(handleHiveRequests); // Must come before your own routes
174
+
175
+ // Your own routes go here
176
+ app.get("/my-route", (request, response) => { ... });
177
+ ```
178
+
179
+ **Routes handled automatically by this middleware:**
180
+
181
+ | Method | Route | What it does |
182
+ |--------|-------|--------------|
183
+ | `POST` | `/Login` | Proxies login credentials to HivePortal, sets session cookie and/or `x-session-token` header |
184
+ | `POST` | `/Logout` | Proxies logout to HivePortal, clears session |
185
+ | `GET` | `/ServiceUrls` | Returns local or remote URL for a named service |
186
+ | `POST` | `/IsLoggedIn` | Checks if the current session is valid with HivePortal |
187
+ | `POST` | `/IsLoggedInWithPermission` | Checks session validity and a specific permission |
188
+ | `POST` | `/SaveUserFilter` | Saves a user-defined data filter (requires `FILTER_OPERATIONS` permission) |
189
+ | `POST` | `/PushNotificationToken` | Registers a push notification token for the current device |
190
+ | `GET` | `/hive-client.js` | Serves the built client-side SDK bundle |
191
+
192
+ You do not need to implement any of these routes yourself. All of them are handled and proxied to HivePortal automatically.
193
+
194
+ ---
195
+
196
+ ### 4. Loading Configuration
197
+
198
+ On startup (after `initServer`), call `loadConfiguration` to decrypt and load credentials from disk into `process.env`.
199
+
200
+ ```js
201
+ import { loadConfiguration } from "@hivedev/hivesdk/server";
202
+
203
+ await loadConfiguration();
204
+ ```
205
+
206
+ This populates the following environment variables (only those with saved `.dat` files are loaded):
207
+
208
+ | Variable | Contents |
209
+ |----------|----------|
210
+ | `FIREBASE_ADMIN_CREDENTIALS` | JSON string of Firebase Admin SDK credentials |
211
+ | `DATABASE_CREDENTIALS` | JSON string of database credentials, keyed by service name |
212
+ | `PERMISSIONS` | JSON string of permission definitions |
213
+ | `SMTP_CREDENTIALS` | JSON string of SMTP credentials |
214
+ | `SMTP_PASSWORD` | Extracted SMTP password, ready for use in `nodemailer` |
215
+
216
+ It also calls `DatabaseConnector.setCredentials` internally using the credentials stored under your service's name, so the database is ready to connect after this call.
217
+
218
+ If a `.dat` file does not exist yet (e.g. first run before registration), that credential is simply skipped.
219
+
220
+ > You should call `loadConfiguration` before `registerService`. If no configuration files exist yet, it will silently skip them. Once `registerService` completes, the files will be written to disk, and `loadConfiguration` will populate everything on the next startup.
221
+
222
+ ---
223
+
224
+ ### 5. Connecting to the Database
225
+
226
+ The SDK includes a MongoDB connector. After `loadConfiguration`, call `DatabaseConnector.connect()` to establish the connection.
227
+
228
+ ```js
229
+ import DatabaseConnector from "@hivedev/hivesdk/server";
230
+
231
+ const connected = await DatabaseConnector.connect();
232
+
233
+ if (!connected)
234
+ {
235
+ console.error("Failed to connect to database.");
236
+ process.exit(1);
237
+ }
238
+
239
+ // DatabaseConnector.databaseObject is now a live Mongo db instance
240
+ const collection = DatabaseConnector.databaseObject.collection("my_collection");
241
+ ```
242
+
243
+ `DatabaseConnector` is not exported from `server.js` directly — you access it from its own path within the SDK. If you do not call `loadConfiguration` first, `DatabaseConnector.connect()` will attempt to call it automatically.
244
+
245
+ **Disconnecting:**
246
+
247
+ ```js
248
+ await DatabaseConnector.disconnect();
249
+ ```
250
+
251
+ ---
252
+
253
+ ### 6. Guarding Routes
254
+
255
+ Use `isLoggedIn` and `isLoggedInWithPermission` to protect your own route handlers. Both functions accept the request and response objects and a boolean `bSendResponse` flag.
256
+
257
+ When `bSendResponse` is `false`, the functions return a boolean and leave the response untouched — use this when you need to guard logic inside a handler.
258
+
259
+ When `bSendResponse` is `true`, the functions write the result directly to the response — this is used internally by `handleHiveRequests` for the `/IsLoggedIn` and `/IsLoggedInWithPermission` endpoints.
260
+
261
+ **Guarding a route with login check:**
262
+
263
+ ```js
264
+ import { isLoggedIn } from "@hivedev/hivesdk/server";
265
+
266
+ app.get("/my-protected-route", async (request, response) =>
267
+ {
268
+ const loggedIn = await isLoggedIn(request, response, false);
269
+
270
+ if (!loggedIn)
271
+ {
272
+ response.statusCode = 401;
273
+ response.end("Unauthorized");
274
+ return;
275
+ }
276
+
277
+ response.end("Here is your protected data.");
278
+ });
279
+ ```
280
+
281
+ **Guarding a route with a permission check:**
282
+
283
+ The permission name must be set on `request.body.permissionName` before calling `isLoggedInWithPermission`.
284
+
285
+ ```js
286
+ import { isLoggedInWithPermission } from "@hivedev/hivesdk/server";
287
+
288
+ app.post("/admin-action", async (request, response) =>
289
+ {
290
+ request.body.permissionName = "ADMIN_OPERATIONS";
291
+
292
+ const permitted = await isLoggedInWithPermission(request, response, false);
293
+
294
+ if (!permitted)
295
+ {
296
+ response.statusCode = 403;
297
+ response.end("Forbidden");
298
+ return;
299
+ }
300
+
301
+ response.end("Admin action performed.");
302
+ });
303
+ ```
304
+
305
+ Both functions handle **session refresh transparently** — if HivePortal signals that the session token should be refreshed, a new cookie and/or `x-session-token` header is set automatically before your handler continues.
306
+
307
+ ---
308
+
309
+ ### 7. Sending Mail
310
+
311
+ ```js
312
+ import { sendMail } from "@hivedev/hivesdk/server";
313
+
314
+ await sendMail(
315
+ "sender@yourdomain.com",
316
+ "recipient@example.com",
317
+ "Subject line here",
318
+ "<p>HTML body here</p>"
319
+ );
320
+ ```
321
+
322
+ Uses Gmail SMTP via nodemailer. The SMTP password is read from `process.env.SMTP_PASSWORD`, which is populated automatically by `loadConfiguration`. The sender Gmail address is currently hardcoded in `SendMail.js` — change it there if needed.
323
+
324
+ ---
325
+
326
+ ### 8. Utility Functions
327
+
328
+ All utilities are exported from `@hivedev/hivesdk/server`.
329
+
330
+ **`getAppDataDirectory()`**
331
+
332
+ Returns the platform-appropriate data directory for your service, creating it if it doesn't exist. On Windows this is `%APPDATA%\<ServiceName>`, on macOS `~/Library/Application Support/<ServiceName>`, on Linux `~/.config/<ServiceName>`.
333
+
334
+ ```js
335
+ import { getAppDataDirectory } from "@hivedev/hivesdk/server";
336
+
337
+ const dataDir = getAppDataDirectory();
338
+ // e.g. "/home/user/.config/NoteHive"
339
+ ```
340
+
341
+ **`getHostIp()`**
342
+
343
+ Returns the first non-loopback IPv4 address of the host machine. Used internally by `registerService` to build the local service URL.
344
+
345
+ ```js
346
+ import { getHostIp } from "@hivedev/hivesdk/server";
347
+
348
+ const ip = getHostIp(); // e.g. "192.168.1.42"
349
+ ```
350
+
351
+ **`findService(serviceName)`**
352
+
353
+ Discovers another Hive service on the LAN via UDP broadcast to port 49153. Returns an object with `{ name, urls: { local, remote } }` or `null` if not found.
354
+
355
+ ```js
356
+ import { findService } from "@hivedev/hivesdk/server";
357
+
358
+ const service = await findService("NoteHive");
359
+
360
+ if (service)
361
+ {
362
+ console.log(service.urls.local); // "http://192.168.1.42:49161"
363
+ }
364
+ ```
365
+
366
+ Requires `HIVE_PORTAL_LAN_IP` environment variable to be set. If not set, returns a default localhost URL.
367
+
368
+ **`extractConfigurationForService()`**
369
+
370
+ Parses `process.env` and returns the configuration as structured objects, extracting the correct database credentials for the current service name.
371
+
372
+ ```js
373
+ import { extractConfigurationForService } from "@hivedev/hivesdk/server";
374
+
375
+ const { firebaseAdminCredentials, databaseCredentials, permissions, smtpCredentials } = extractConfigurationForService();
376
+ ```
377
+
378
+ **`encryptAndStoreFile(data, fullPath, password)`**
379
+
380
+ Encrypts a string or Buffer with AES-256-CBC and writes it to disk.
381
+
382
+ ```js
383
+ import { encryptAndStoreFile } from "@hivedev/hivesdk/server";
384
+
385
+ await encryptAndStoreFile("my secret data", "/path/to/file.dat", process.env.SERVER_PASSWORD);
386
+ ```
387
+
388
+ **`decryptFileWithPassword(fullPath, password)`**
389
+
390
+ Reads and decrypts an encrypted `.dat` file. Returns the decrypted string, or `null` on failure.
391
+
392
+ ```js
393
+ import { decryptFileWithPassword } from "@hivedev/hivesdk/server";
394
+
395
+ const contents = await decryptFileWithPassword("/path/to/file.dat", process.env.SERVER_PASSWORD);
396
+ ```
397
+
398
+ **`saveConfiguration(configurationObject)` / `loadConfiguration()`**
399
+
400
+ Normally called automatically by `registerService` and during startup respectively. Available for manual use if needed.
401
+
402
+ ```js
403
+ import { saveConfiguration, loadConfiguration } from "@hivedev/hivesdk/server";
404
+
405
+ // Save a configuration object (any subset of keys is valid — only present keys are written)
406
+ await saveConfiguration({
407
+ databaseCredentials: { NoteHive: { host: "127.0.0.1", username: "admin", password: "pass", name: "notehive" } },
408
+ smtpCredentials: { password: "smtp-password" }
409
+ });
410
+
411
+ // Load configuration from disk into process.env
412
+ await loadConfiguration();
413
+ ```
414
+
415
+ ---
416
+
417
+ ### Full Server Bootstrap Example
418
+
419
+ This is the recommended startup sequence for any Hive microservice.
420
+
421
+ ```js
422
+ import express from "express";
423
+ import cookieParser from "cookie-parser";
424
+ import cluster from "cluster";
425
+ import os from "os";
426
+ import { handleHiveRequests, initServer, registerService, loadConfiguration } from "@hivedev/hivesdk/server";
427
+ import DatabaseConnector from "./node_modules/@hivedev/hivesdk/DatabaseConnector.js";
428
+
429
+ const SERVICE_NAME = "NoteHive";
430
+ const SERVICE_PORT = 49161;
431
+
432
+ const app = express();
433
+
434
+ app.use(express.json());
435
+ app.use(cookieParser());
436
+ app.use(handleHiveRequests);
437
+
438
+ // Your own routes
439
+ app.get("/", (request, response) => response.redirect("/Client/Pages/HomePage.html"));
440
+
441
+ if (cluster.isPrimary)
442
+ {
443
+ await initServer({
444
+ serviceName: SERVICE_NAME,
445
+ servicePort: SERVICE_PORT,
446
+ remoteUrl: process.env.REMOTE_URL || ""
447
+ });
448
+
449
+ await loadConfiguration();
450
+
451
+ // Delay slightly so workers are ready before registration begins
452
+ setTimeout(async () =>
453
+ {
454
+ await registerService();
455
+ }, 3000);
456
+
457
+ for (let i = 0; i < os.cpus().length; i++)
458
+ {
459
+ cluster.fork({ ...process.env });
460
+ }
461
+
462
+ cluster.on("exit", (worker) =>
463
+ {
464
+ console.log(`Worker ${worker.process.pid} died. Restarting...`);
465
+ cluster.fork();
466
+ });
467
+ }
468
+ else
469
+ {
470
+ await DatabaseConnector.connect();
471
+
472
+ app.listen(SERVICE_PORT, () =>
473
+ {
474
+ console.log(`Worker ${process.pid} listening on port ${SERVICE_PORT}`);
475
+ });
476
+ }
477
+ ```
478
+
479
+ ---
480
+
481
+ ## Client SDK
482
+
483
+ The client SDK is a browser bundle. It is automatically served at `/hive-client.js` by the `handleHiveRequests` middleware — you do not need to copy or host the file yourself.
484
+
485
+ ### 1. Loading the Client Bundle
486
+
487
+ Include the script in your HTML pages:
488
+
489
+ ```html
490
+ <script type="module">
491
+ import { initClient, login } from "/hive-client.js";
492
+ </script>
493
+ ```
494
+
495
+ Or via a module script tag:
496
+
497
+ ```html
498
+ <script type="module" src="/hive-client.js"></script>
499
+ ```
500
+
501
+ ---
502
+
503
+ ### 2. Initialising the Client
504
+
505
+ Call `initClient` once on page load. It sets up app detection, cookie signalling, and the periodic login state checker.
506
+
507
+ ```js
508
+ import { initClient } from "/hive-client.js";
509
+
510
+ await initClient({});
511
+ ```
512
+
513
+ `initClient` accepts one optional parameter:
514
+
515
+ | Parameter | Type | Default | Description |
516
+ |-----------|------|---------|-------------|
517
+ | `loginTokenStorageMethod` | `sessionStorageMethod` enum | `HTTP_ONLY_COOKIE` | How session tokens are stored on the client |
518
+
519
+ In practice, the SDK currently implements the `HTTP_ONLY_COOKIE` path fully. The token is stored in an `httpOnly` cookie set by the server. On native app clients (WebView), it is also sent via the `x-session-token` header since cookies may not be reliable across WebView boundaries.
520
+
521
+ ---
522
+
523
+ ### 3. Login
524
+
525
+ Call `login()` to open the HivePortal login popup. The SDK handles the entire flow — opening the window, receiving credentials via `postMessage`, posting to `/Login`, and redirecting on success.
526
+
527
+ ```js
528
+ import { login } from "/hive-client.js";
529
+
530
+ document.getElementById("login-button").addEventListener("click", async () =>
531
+ {
532
+ await login();
533
+ });
534
+ ```
535
+
536
+ When running inside the native mobile app (detected automatically via `isInApp()`), the login popup is rendered as an inline full-screen iframe overlay instead of a real popup window, since WebViews block `window.open`.
537
+
538
+ On success, the page redirects to `/`. On failure, the login page itself displays the error.
539
+
540
+ ---
541
+
542
+ ### 4. Checking Login State
543
+
544
+ `initClient` automatically starts a periodic login check (every 30 seconds by default, clamped between 10 and 60 seconds). Each check fires a `login-state-changed` custom event on the `window` object.
545
+
546
+ Listen for this event to reactively show or hide UI based on login state:
547
+
548
+ ```js
549
+ window.addEventListener("login-state-changed", (event) =>
550
+ {
551
+ const isLoggedIn = event.detail;
552
+
553
+ if (isLoggedIn)
554
+ {
555
+ document.getElementById("dashboard").style.display = "block";
556
+ document.getElementById("login-prompt").style.display = "none";
557
+ }
558
+ else
559
+ {
560
+ document.getElementById("dashboard").style.display = "none";
561
+ document.getElementById("login-prompt").style.display = "block";
562
+ }
563
+ });
564
+ ```
565
+
566
+ The current login state is also available synchronously at any time via `window.IS_LOGGED_IN`.
567
+
568
+ ```js
569
+ if (window.IS_LOGGED_IN)
570
+ {
571
+ // Safe to load user-specific content
572
+ }
573
+ ```
574
+
575
+ ---
576
+
577
+ ### Full Client Bootstrap Example
578
+
579
+ A typical HTML page in a Hive service would look like this:
580
+
581
+ ```html
582
+ <!DOCTYPE html>
583
+ <html lang="en">
584
+ <head>
585
+ <meta charset="UTF-8">
586
+ <title>NoteHive</title>
587
+ </head>
588
+ <body>
589
+
590
+ <div id="login-prompt">
591
+ <button id="login-button">Sign In</button>
592
+ </div>
593
+
594
+ <div id="dashboard" style="display: none;">
595
+ <h1>Welcome to NoteHive</h1>
596
+ </div>
597
+
598
+ <script type="module">
599
+ import { initClient, login } from "/hive-client.js";
600
+
601
+ // Initialise the SDK — sets up app detection, cookies, and login polling
602
+ await initClient({});
603
+
604
+ // React to login state changes
605
+ window.addEventListener("login-state-changed", (event) =>
606
+ {
607
+ const isLoggedIn = event.detail;
608
+ document.getElementById("login-prompt").style.display = isLoggedIn ? "none" : "block";
609
+ document.getElementById("dashboard").style.display = isLoggedIn ? "block" : "none";
610
+ });
611
+
612
+ // Wire up the login button
613
+ document.getElementById("login-button").addEventListener("click", async () =>
614
+ {
615
+ await login();
616
+ });
617
+ </script>
618
+
619
+ </body>
620
+ </html>
621
+ ```
622
+
623
+ ---
624
+
625
+ ## Enumerations
626
+
627
+ The SDK exports several enumerations from the client bundle. These are shared constants used throughout the Hive ecosystem.
628
+
629
+ **`userPrivileges`** — Numeric privilege levels assigned to users.
630
+
631
+ | Key | Value |
632
+ |-----|-------|
633
+ | `STUDENT` | 0 |
634
+ | `CLASS_REPRESENTATIVE` | 10 |
635
+ | `STUDENT_COORDINATOR` | 20 |
636
+ | `ASSISTANT` | 30 |
637
+ | `TEACHER` | 40 |
638
+ | `COURSE_COORDINATOR` | 50 |
639
+ | `HEAD_OF_DEPARTMENT` | 70 |
640
+ | `MANAGEMENT` | 80 |
641
+ | `SUPER_USER` | 100 |
642
+
643
+ **`sessionStorageMethod`** — How session tokens are stored on the client.
644
+
645
+ | Key | Value |
646
+ |-----|-------|
647
+ | `HTTP_ONLY_COOKIE` | 0 |
648
+ | `LOCAL_STORAGE` | 1 |
649
+ | `SESSION_STORAGE` | 2 |
650
+
651
+ **`clientConnectionTypeFlags`** — Bitmask flags describing how a client is connected.
652
+
653
+ | Key | Value |
654
+ |-----|-------|
655
+ | `LAN` | 1 |
656
+ | `REMOTE` | 2 |
657
+ | `SAME_SYSTEM` | 4 |
658
+ | `UNKNOWN` | 8 |
659
+
660
+ **`appWebViewInteractions`** — Message types exchanged between the web page and the native app WebView layer.
661
+
662
+ | Key | Value |
663
+ |-----|-------|
664
+ | `REQUEST_NOTIFICATION_TOKEN` | 0 |
665
+ | `BACK_PRESSED` | 1 |
666
+
667
+ **`approvalTypes`** — Types of approval requests sent to HivePortal administrators.
668
+
669
+ | Key | Value |
670
+ |-----|-------|
671
+ | `USER_REGISTERATION` | 0 |
672
+ | `SERVICE_REGISTERATION` | 1 |
673
+
674
+ **`filterTypes`**, **`filterOperators`**, **`userDataFetchFilterComparision`**, **`userFieldTypes`**, **`userFieldFormats`**, **`fileTreeNodeTypes`** — Domain-specific enumerations used for data querying, user field definitions, and file tree structures. Refer to their respective source files for values.
675
+
676
+ ---
677
+
678
+ ## Environment Variables Reference
679
+
680
+ These variables are either expected to be set externally or are populated by the SDK itself.
681
+
682
+ | Variable | Set by | Description |
683
+ |----------|--------|-------------|
684
+ | `SERVER_PASSWORD` | External / `setupPassword()` | Master password for encrypting/decrypting config files |
685
+ | `SERVICE_NAME` | `initServer` | Name of this service as registered with HivePortal |
686
+ | `SERVICE_PORT` | `initServer` | Port this service listens on |
687
+ | `REMOTE_URL` | `initServer` | Public-facing URL of this service (empty if LAN-only) |
688
+ | `HIVE_PORTAL_LAN_IP` | External | LAN IP address of HivePortal, used by `findService` for UDP discovery |
689
+ | `FIREBASE_ADMIN_CREDENTIALS` | `loadConfiguration` | JSON string of Firebase Admin credentials |
690
+ | `DATABASE_CREDENTIALS` | `loadConfiguration` | JSON string of database credentials keyed by service name |
691
+ | `PERMISSIONS` | `loadConfiguration` | JSON string of permission definitions |
692
+ | `SMTP_CREDENTIALS` | `loadConfiguration` | JSON string of SMTP credentials |
693
+ | `SMTP_PASSWORD` | `loadConfiguration` | Extracted SMTP password, ready for nodemailer |
694
+
695
+ ---
696
+
697
+ ## How HivePortal Fits In
698
+
699
+ ```
700
+ ┌─────────────────────┐
701
+ │ HivePortal │
702
+ │ (hub — port 49152) │
703
+ │ │
704
+ │ - User accounts │
705
+ │ - Sessions │
706
+ │ - Permissions │
707
+ │ - Service registry │
708
+ │ - Configuration │
709
+ └────────┬─────────────┘
710
+
711
+ ┌────────────────────┼────────────────────┐
712
+ │ │ │
713
+ ┌──────────▼──────────┐ │ ┌──────────▼──────────┐
714
+ │ NoteHive │ │ │ FutureService │
715
+ │ (port 49161) │ ... │ │ (port 49162) │
716
+ │ │ │ │ │
717
+ │ uses @hivedev/ │ │ │ uses @hivedev/ │
718
+ │ hivesdk │ │ │ hivesdk │
719
+ └──────────────────────┘ │ └─────────────────────┘
720
+
721
+ Each service:
722
+ 1. Calls initServer()
723
+ 2. Calls loadConfiguration()
724
+ 3. Calls registerService()
725
+ 4. Mounts handleHiveRequests
726
+ 5. Implements own domain logic
727
+ ```
728
+
729
+ Every authentication check a service performs is a proxied call to HivePortal. HivePortal is the single source of truth for all session and permission data. Services only store their own domain data (notes, files, etc.) — nothing related to users or sessions.
730
+
731
+ ---
732
+
733
+ ## Known Limitations
734
+
735
+ - **`ScheduleServiceUrlUpdate`** — This function is currently a stub and does nothing. It is intended for future use to periodically re-broadcast service URLs to HivePortal (e.g. if the host IP changes).
736
+ - **`loginTokenStorageMethod`** — The `LOCAL_STORAGE` and `SESSION_STORAGE` options in the `sessionStorageMethod` enum are defined but not yet implemented in the client SDK. Only `HTTP_ONLY_COOKIE` (with the `x-session-token` header fallback for app clients) is fully functional.
737
+ - **SMTP sender address** — The sender Gmail address in `SendMail.js` is hardcoded. If your service needs to send mail from a different address, edit `SendMail.js` in the SDK directly.
738
+ - **MongoDB only** — `DatabaseConnector` is built specifically for MongoDB. There is no support for other databases.
739
+ - **Port 27017 only** — The MongoDB port is hardcoded to 27017 in `DatabaseConnector`. Host is configurable via credentials but the port is not.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hivedev/hivesdk",
3
3
  "type": "module",
4
- "version": "1.0.34",
4
+ "version": "1.0.35",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
7
7
  "scripts": {