@vicaniddouglas/js_aide 1.8.0 → 1.10.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/README.md CHANGED
@@ -52,6 +52,10 @@ Utilities for number formatting, currency (including UGX defaults), and percenta
52
52
 
53
53
  A robust manager for dynamically loading CDN-based libraries (like SheetJS or jsPDF) with retry logic and dependency tracking.
54
54
 
55
+ ### `WebSocketClient`
56
+
57
+ A professional-grade WebSocket client featuring automatic reconnection, heartbeat/health monitoring, and a built-in instance registry to prevent duplicate connections. Supports namespaces, rooms, and message acknowledgements.
58
+
55
59
  ## Installation
56
60
 
57
61
  Install the package via npm:
@@ -149,6 +153,171 @@ if (productDetailView) {
149
153
  router.navigate("/products/123?utm_source=email#overview");
150
154
  ```
151
155
 
156
+ ### Example: Using the WebSocket Client
157
+
158
+ The `WebSocketClient` is designed to be "Zero-Touch," handling connection lifecycles and resource management automatically.
159
+
160
+ ```javascript
161
+ import { WebSocketClient, ConnectionEvent } from "@vicaniddouglas/js_aide";
162
+
163
+ // The constructor automatically reuses instances for the same URL (Registry Pattern)
164
+ const ws = new WebSocketClient("ws://localhost:8000");
165
+
166
+ // Listen for connection events
167
+ ws.on("open", () => {
168
+ console.log("Connected to server!");
169
+ });
170
+
171
+ // Register a handler for a specific event
172
+ ws.onMessage("user_update", (data) => {
173
+ console.log("Profile updated:", data);
174
+ });
175
+
176
+ ws.connect();
177
+ ```
178
+
179
+ #### `ws.send(event, data)` vs `ws.sendWithAck(event, data)`
180
+
181
+ 1. **`ws.send()`**: A "fire and forget" method. It sends the data and returns immediately. Use this for non-critical updates like typing indicators.
182
+ 2. **`ws.sendWithAck()`**: Returns a **Promise** that resolves when the server confirms receipt. Use this for critical actions like saving a profile or processing a payment.
183
+
184
+ ```javascript
185
+ // Critical action with Acknowledgement
186
+ try {
187
+ const response = await ws.sendWithAck("save_profile", { bio: "Hello world" });
188
+ console.log("Profile saved successfully:", response);
189
+ } catch (error) {
190
+ console.error("Failed to save profile (timed out):", error.message);
191
+ }
192
+ ```
193
+
194
+ #### The Backend Contract (Implementing Acknowledgements)
195
+
196
+ To support `sendWithAck()`, your backend (e.g., Python/FastAPI, Node.js, Go) must follow the `@vicaniddouglas` framework standard:
197
+
198
+ 1. The client sends a message containing an `id` and `ack: true`.
199
+ 2. The server **must** respond with a message containing:
200
+ * `event: "ack"`
201
+ * `id`: The *exact* same ID sent by the client.
202
+ * `success`: `true` or `false`.
203
+ * `data` (optional): Any response data to return to the client.
204
+
205
+ **Example Server Response (JSON):**
206
+ ```json
207
+ {
208
+ "event": "ack",
209
+ "id": "1712065432123-0",
210
+ "success": true,
211
+ "data": { "status": "saved" }
212
+ }
213
+ ```
214
+
215
+ ### Example: Using the Requests Module
216
+
217
+ The `sendRequest` function is a proactive HTTP client that standardizes all responses into a single dictionary format. It automatically handles error popups and callbacks, eliminating the need for `try-catch` blocks.
218
+
219
+ #### Standardized Response
220
+ Every call returns a Promise that always resolves to this structure:
221
+ ```javascript
222
+ {
223
+ status: boolean, // true if Success, false if Error (Network or Business)
224
+ log: string, // Error message on failure, or "" on success
225
+ data: any, // The actual payload from the server
226
+ httpCode: number // The raw HTTP status code
227
+ }
228
+ ```
229
+
230
+ #### New Proactive Options
231
+ | Option | Type | Default | Description |
232
+ | :--- | :--- | :--- | :--- |
233
+ | `onSuccess` | `Function` | `null` | Runs automatically if `status` is `true`. |
234
+ | `onError` | `Function` | `null` | Runs automatically if `status` is `false`. |
235
+ | `silent` | `Boolean` | `false` | If `true`, disables the automatic Red Popup on error. |
236
+
237
+ #### Usage Patterns
238
+
239
+ **1. The "Fire and Forget" (Proactive Success)**
240
+ No need to check status if you only care about success. If it fails, the user gets a popup automatically.
241
+ ```javascript
242
+ import { sendRequest } from "@vicaniddouglas/js_aide";
243
+
244
+ sendRequest({
245
+ endpoint: '/api/settings',
246
+ onSuccess: (data) => console.log("Profile updated!", data)
247
+ });
248
+ ```
249
+
250
+ **2. The "Sequential Chain" (Linear Await)**
251
+ Since the promise **never rejects**, you can write linear logic without `try-catch`.
252
+ ```javascript
253
+ const res = await sendRequest({ endpoint: '/profile' });
254
+
255
+ if (res.status) {
256
+ // Since status is true, we know data is safe to use
257
+ const stats = await sendRequest({ endpoint: `/stats/${res.data.id}` });
258
+ if (stats.status) render(stats.data);
259
+ }
260
+ ```
261
+
262
+ **3. Silent Background Tasks**
263
+ Use `silent: true` for background checks where a popup would be annoying.
264
+ ```javascript
265
+ sendRequest({
266
+ endpoint: '/api/poll-notifications',
267
+ silent: true,
268
+ onSuccess: (count) => updateBadge(count)
269
+ });
270
+ ```
271
+
272
+ ### Example: Using the Popup System
273
+
274
+ The `popup` module provides a Promise-based modal system for showing professional alerts. It is fully accessible (supports the `Escape` key) and highly customizable.
275
+
276
+ ```javascript
277
+ import { popup, icons } from "@vicaniddouglas/js_aide";
278
+
279
+ // Basic success alert (auto-closes in 2.5s)
280
+ await popup.success("Profile saved!");
281
+ ```
282
+
283
+ #### Configuration Reference
284
+ Every popup method (`.success()`, `.error()`, `.info()`) accepts an optional **`options`** object as the second argument.
285
+
286
+ | Option | Type | Default | Description |
287
+ | :--- | :--- | :--- | :--- |
288
+ | `duration` | `Number` | `2500ms - 4000ms` | Time before the modal closes automatically. |
289
+ | `persistent`| `Boolean`| `false` | If `true`, the modal will stay on screen until manually closed. |
290
+ | `closable` | `Boolean`| `true` | If `false`, hides the close button and disables `Esc`/backdrop clicks. |
291
+ | `icon` | `String` | Theme default | A custom SVG string to override the default icon. |
292
+ | `color` | `String` | Theme default | A custom hex or CSS color for the icon and background tint. |
293
+
294
+ #### Common Usage Patterns
295
+
296
+ **1. Sticky Info (Requires Acknowledgment)**
297
+ ```javascript
298
+ await popup.info("Maintenance scheduled for midnight.", { persistent: true });
299
+ ```
300
+
301
+ **2. Process Lock (Interaction Block)**
302
+ Use this to prevent users from navigating away during critical operations.
303
+ ```javascript
304
+ // Shows a modal with no close buttons
305
+ popup.info("Deleting account data...", { persistent: true, closable: false });
306
+
307
+ await api.deleteAccount();
308
+ popup.close(); // Programmatically remove the modal
309
+ await popup.success("Account deleted.");
310
+ ```
311
+
312
+ **3. Custom Branding**
313
+ Override the icon and color to match specific visual needs.
314
+ ```javascript
315
+ popup.success("Photo Uploaded!", {
316
+ icon: icons.cameraIcon(),
317
+ color: "#3b82f6"
318
+ });
319
+ ```
320
+
152
321
  ## Development
153
322
 
154
323
  ### Running Tests