@vicaniddouglas/js_aide 1.9.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 +169 -0
- package/dist/js_aide.cjs.js +1162 -1145
- package/dist/js_aide.cjs.js.map +4 -4
- package/dist/js_aide.esm.js +1144 -1127
- package/dist/js_aide.esm.js.map +4 -4
- package/dist/js_aide.min.js +1162 -1145
- package/dist/js_aide.min.js.map +4 -4
- package/package.json +1 -1
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
|