@vicaniddouglas/js_aide 1.15.4 → 1.17.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
@@ -5,6 +5,7 @@
5
5
  **JS Aide** is a high-performance, modular utility collection designed for modern web applications. Whether you're building a native SPA or an enterprise-grade MPA, JS Aide provides the orchestrated power you need.
6
6
 
7
7
  ## 🕹️ Live Playground
8
+
8
9
  Explore all library features—including the new Asynchronous Handshaking system—directly in our **[Interactive Sandbox](https://vicaniddouglas.gitlab.io/js_aide)**.
9
10
 
10
11
  ### `Router`
@@ -71,11 +72,11 @@ You can import specific modules or all of them:
71
72
 
72
73
  ```javascript
73
74
  // Import specific modules for best tree-shaking
74
- import {
75
- Router,
76
- sendRequest,
77
- validatePhoneNumber,
78
- humanizeDate
75
+ import {
76
+ Router,
77
+ sendRequest,
78
+ validatePhoneNumber,
79
+ humanizeDate,
79
80
  } from "@vicaniddouglas/js_aide";
80
81
  ```
81
82
 
@@ -158,12 +159,12 @@ const ws = new WebSocketClient("ws://localhost:8000");
158
159
 
159
160
  // Listen for connection events
160
161
  ws.on("open", () => {
161
- console.log("Connected to server!");
162
+ console.log("Connected to server!");
162
163
  });
163
164
 
164
165
  // Register a handler for a specific event
165
166
  ws.onMessage("user_update", (data) => {
166
- console.log("Profile updated:", data);
167
+ console.log("Profile updated:", data);
167
168
  });
168
169
 
169
170
  ws.connect();
@@ -177,10 +178,10 @@ ws.connect();
177
178
  ```javascript
178
179
  // Critical action with Acknowledgement
179
180
  try {
180
- const response = await ws.sendWithAck("save_profile", { bio: "Hello world" });
181
- console.log("Profile saved successfully:", response);
181
+ const response = await ws.sendWithAck("save_profile", { bio: "Hello world" });
182
+ console.log("Profile saved successfully:", response);
182
183
  } catch (error) {
183
- console.error("Failed to save profile (timed out):", error.message);
184
+ console.error("Failed to save profile (timed out):", error.message);
184
185
  }
185
186
  ```
186
187
 
@@ -190,12 +191,13 @@ To support `sendWithAck()`, your backend (e.g., Python/FastAPI, Node.js, Go) mus
190
191
 
191
192
  1. The client sends a message containing an `id` and `ack: true`.
192
193
  2. The server **must** respond with a message containing:
193
- * `event: "ack"`
194
- * `id`: The *exact* same ID sent by the client.
195
- * `success`: `true` or `false`.
196
- * `data` (optional): Any response data to return to the client.
194
+ - `event: "ack"`
195
+ - `id`: The _exact_ same ID sent by the client.
196
+ - `success`: `true` or `false`.
197
+ - `data` (optional): Any response data to return to the client.
197
198
 
198
199
  **Example Server Response (JSON):**
200
+
199
201
  ```json
200
202
  {
201
203
  "event": "ack",
@@ -210,7 +212,9 @@ To support `sendWithAck()`, your backend (e.g., Python/FastAPI, Node.js, Go) mus
210
212
  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.
211
213
 
212
214
  #### Standardized Response
215
+
213
216
  Every call returns a Promise that always resolves to this structure:
217
+
214
218
  ```javascript
215
219
  {
216
220
  status: boolean, // true if Success, false if Error (Network or Business)
@@ -221,63 +225,68 @@ Every call returns a Promise that always resolves to this structure:
221
225
  ```
222
226
 
223
227
  #### New Proactive Options
224
- | Option | Type | Default | Description |
225
- | :--- | :--- | :--- | :--- |
226
- | `onSuccess` | `Function` | `null` | Runs automatically if `status` is `true`. **Strictly awaited.** |
227
- | `onError` | `Function` | `null` | Runs automatically if `status` is `false`. **Strictly awaited.** |
228
- | `showLoading` | `Function` | `null` | Called with `true`/`false`. **Strictly awaited.** |
229
- | `silent` | `Boolean` | `false` | If `true`, disables the automatic Red Popup on error. |
228
+
229
+ | Option | Type | Default | Description |
230
+ | :------------ | :--------- | :------ | :--------------------------------------------------------------- |
231
+ | `onSuccess` | `Function` | `null` | Runs automatically if `status` is `true`. **Strictly awaited.** |
232
+ | `onError` | `Function` | `null` | Runs automatically if `status` is `false`. **Strictly awaited.** |
233
+ | `showLoading` | `Function` | `null` | Called with `true`/`false`. **Strictly awaited.** |
234
+ | `silent` | `Boolean` | `false` | If `true`, disables the automatic Red Popup on error. |
230
235
 
231
236
  #### Usage Patterns
232
237
 
233
238
  **1. The "Sequential Async Flow" (Awaiting Callbacks)**
234
239
  Because `sendRequest` **strictly awaits** your callbacks, you can safely use `async/await` inside them without worrying about race conditions or premature page reloads.
240
+
235
241
  ```javascript
236
242
  import { sendRequest, popup } from "@vicaniddouglas/js_aide";
237
243
 
238
244
  await sendRequest({
239
- endpoint: '/api/save',
245
+ endpoint: "/api/save",
240
246
  onSuccess: async (data) => {
241
247
  // This popup is BEAUTIFUL and BLOCKING.
242
248
  // sendRequest will NOT finish until the user clicks OK.
243
- await popup.success("Settings Saved!");
244
- }
249
+ await popup.success("Settings Saved!");
250
+ },
245
251
  });
246
252
 
247
253
  // This reload is GUARANTEED to happen only after the popup is closed.
248
- window.location.reload();
254
+ window.location.reload();
249
255
  ```
250
256
 
251
257
  **2. The "Fire and Forget" (Proactive Success)**
252
258
  No need to check status if you only care about success. If it fails, the user gets a popup automatically.
259
+
253
260
  ```javascript
254
261
  import { sendRequest } from "@vicaniddouglas/js_aide";
255
262
 
256
263
  sendRequest({
257
- endpoint: '/api/settings',
258
- onSuccess: (data) => console.log("Profile updated!", data)
264
+ endpoint: "/api/settings",
265
+ onSuccess: (data) => console.log("Profile updated!", data),
259
266
  });
260
267
  ```
261
268
 
262
269
  **2. The "Sequential Chain" (Linear Await)**
263
270
  Since the promise **never rejects**, you can write linear logic without `try-catch`.
271
+
264
272
  ```javascript
265
- const res = await sendRequest({ endpoint: '/profile' });
273
+ const res = await sendRequest({ endpoint: "/profile" });
266
274
 
267
275
  if (res.status) {
268
- // Since status is true, we know data is safe to use
269
- const stats = await sendRequest({ endpoint: `/stats/${res.data.id}` });
270
- if (stats.status) render(stats.data);
276
+ // Since status is true, we know data is safe to use
277
+ const stats = await sendRequest({ endpoint: `/stats/${res.data.id}` });
278
+ if (stats.status) render(stats.data);
271
279
  }
272
280
  ```
273
281
 
274
282
  **3. Silent Background Tasks**
275
283
  Use `silent: true` for background checks where a popup would be annoying.
284
+
276
285
  ```javascript
277
286
  sendRequest({
278
- endpoint: '/api/poll-notifications',
287
+ endpoint: "/api/poll-notifications",
279
288
  silent: true,
280
- onSuccess: (count) => updateBadge(count)
289
+ onSuccess: (count) => updateBadge(count),
281
290
  });
282
291
  ```
283
292
 
@@ -286,6 +295,7 @@ sendRequest({
286
295
  The `FileUploader` module provides standardized utilities for validating and uploading files. It supports both traditional binary (`Multipart/Form-Data`) and JSON-based Base64 uploads.
287
296
 
288
297
  #### Base64 File Conversions (For Previews)
298
+
289
299
  The `toBase64` utility converts a raw `File` object into a Base64 string. It follows the "Always Resolve" pattern.
290
300
 
291
301
  ```javascript
@@ -294,42 +304,44 @@ import { toBase64 } from "@vicaniddouglas/js_aide";
294
304
  const res = await toBase64(myFile);
295
305
 
296
306
  if (res.status) {
297
- // res.data is the full data URL (e.g. data:image/png;base64,...)
298
- myImagePreview.src = res.data;
307
+ // res.data is the full data URL (e.g. data:image/png;base64,...)
308
+ myImagePreview.src = res.data;
299
309
  } else {
300
- console.error("Conversion failed:", res.log);
310
+ console.error("Conversion failed:", res.log);
301
311
  }
302
312
  ```
303
313
 
304
314
  #### Standard Binary Upload
315
+
305
316
  By default, `uploadFile` sends files as a binary `Multipart/Form-Data` stream.
306
317
 
307
318
  ```javascript
308
319
  import { uploadFile, popup } from "@vicaniddouglas/js_aide";
309
320
 
310
321
  await uploadFile({
311
- files: document.getElementById('myFileInput').files[0],
312
- endpoint: '/api/upload-avatar',
313
- fieldName: 'avatar',
314
- onSuccess: () => popup.success("Avatar uploaded!")
322
+ files: document.getElementById("myFileInput").files[0],
323
+ endpoint: "/api/upload-avatar",
324
+ fieldName: "avatar",
325
+ onSuccess: () => popup.success("Avatar uploaded!"),
315
326
  });
316
327
  ```
317
328
 
318
329
  #### Base64 JSON Upload
330
+
319
331
  For APIs that require images to be embedded in a JSON payload, simply toggle the `asBase64` flag.
320
332
 
321
333
  ```javascript
322
334
  import { uploadFile } from "@vicaniddouglas/js_aide";
323
335
 
324
336
  await uploadFile({
325
- files: selectedFiles,
326
- endpoint: '/api/upload-as-json',
327
- asBase64: true, // Automically converts to Base64 strings
328
- stripPrefix: true, // Only send the raw Base64 data (no "data:image/..." prefix)
329
- payload: {
330
- userId: 123,
331
- description: "Holiday photo"
332
- }
337
+ files: selectedFiles,
338
+ endpoint: "/api/upload-as-json",
339
+ asBase64: true, // Automically converts to Base64 strings
340
+ stripPrefix: true, // Only send the raw Base64 data (no "data:image/..." prefix)
341
+ payload: {
342
+ userId: 123,
343
+ description: "Holiday photo",
344
+ },
333
345
  });
334
346
  ```
335
347
 
@@ -345,25 +357,28 @@ await popup.success("Profile saved!");
345
357
  ```
346
358
 
347
359
  #### Configuration Reference
360
+
348
361
  Every popup method (`.success()`, `.error()`, `.info()`) accepts an optional **`options`** object as the second argument.
349
362
 
350
- | Option | Type | Default | Description |
351
- | :--- | :--- | :--- | :--- |
352
- | `duration` | `Number` | `2500ms - 4000ms` | Time before the modal closes automatically. |
353
- | `persistent`| `Boolean`| `false` | If `true`, the modal will stay on screen until manually closed. |
354
- | `closable` | `Boolean`| `true` | If `false`, hides the close button and disables `Esc`/backdrop clicks. |
355
- | `icon` | `String` | Theme default | A custom SVG string to override the default icon. |
356
- | `color` | `String` | Theme default | A custom hex or CSS color for the icon and background tint. |
363
+ | Option | Type | Default | Description |
364
+ | :----------- | :-------- | :---------------- | :--------------------------------------------------------------------- |
365
+ | `duration` | `Number` | `2500ms - 4000ms` | Time before the modal closes automatically. |
366
+ | `persistent` | `Boolean` | `false` | If `true`, the modal will stay on screen until manually closed. |
367
+ | `closable` | `Boolean` | `true` | If `false`, hides the close button and disables `Esc`/backdrop clicks. |
368
+ | `icon` | `String` | Theme default | A custom SVG string to override the default icon. |
369
+ | `color` | `String` | Theme default | A custom hex or CSS color for the icon and background tint. |
357
370
 
358
371
  #### Common Usage Patterns
359
372
 
360
373
  **1. Sticky Info (Requires Acknowledgment)**
374
+
361
375
  ```javascript
362
376
  await popup.info("Maintenance scheduled for midnight.", { persistent: true });
363
377
  ```
364
378
 
365
379
  **2. Process Lock (Interaction Block)**
366
380
  Use this to prevent users from navigating away during critical operations.
381
+
367
382
  ```javascript
368
383
  // Shows a modal with no close buttons
369
384
  popup.info("Deleting account data...", { persistent: true, closable: false });
@@ -375,18 +390,21 @@ await popup.success("Account deleted.");
375
390
 
376
391
  **3. Custom Branding**
377
392
  Override the icon and color to match specific visual needs.
393
+
378
394
  ```javascript
379
- popup.success("Photo Uploaded!", {
395
+ popup.success("Photo Uploaded!", {
380
396
  icon: icons.cameraIcon(),
381
- color: "#3b82f6"
397
+ color: "#3b82f6",
382
398
  });
383
399
  ```
384
400
 
385
401
  #### 4. Asynchronous Handshaking (Zero-Alert)
402
+
386
403
  The popup system provides replacements for native `confirm()` and `prompt()` that are fully asynchronous, themeable, and non-blocking in the developer's logic (via `await`).
387
404
 
388
405
  **Confirmation Dialogs**
389
406
  Returns `true` on confirm, `false` on cancel/close.
407
+
390
408
  ```javascript
391
409
  const confirmed = await popup.confirm("Are you sure you want to delete this?");
392
410
 
@@ -398,10 +416,11 @@ if (confirmed) {
398
416
 
399
417
  **Data-Entry Prompts**
400
418
  Returns the input value as a **string** on submit, or `null` if cancelled.
419
+
401
420
  ```javascript
402
421
  const name = await popup.prompt("Enter your display name:", {
403
422
  placeholder: "e.g., Douglas",
404
- inputType: "text" // Options: text, number, currency, password
423
+ inputType: "text", // Options: text, number, currency, password
405
424
  });
406
425
 
407
426
  if (name) {
@@ -409,12 +428,12 @@ if (name) {
409
428
  }
410
429
  ```
411
430
 
412
- | Prompt Option | Description |
413
- | :--- | :--- |
414
- | `inputType` | Controls input behavior (`text`, `number`, `currency`, `password`). |
415
- | `defaultValue`| Initial text inside the input. |
416
- | `submitText` | Text for the action button (default: "Submit"). |
417
- | `cancelText` | Text for the dismiss button (default: "Cancel"). |
431
+ | Prompt Option | Description |
432
+ | :------------- | :------------------------------------------------------------------ |
433
+ | `inputType` | Controls input behavior (`text`, `number`, `currency`, `password`). |
434
+ | `defaultValue` | Initial text inside the input. |
435
+ | `submitText` | Text for the action button (default: "Submit"). |
436
+ | `cancelText` | Text for the dismiss button (default: "Cancel"). |
418
437
 
419
438
  ## Development
420
439
 
package/declarations.d.ts CHANGED
@@ -305,14 +305,21 @@ declare module "@vicaniddouglas/js_aide" {
305
305
  interface RequestOptions {
306
306
  method?: string;
307
307
  endpoint: string;
308
+ params?: object | URLSearchParams | null;
308
309
  payload?: object | FormData | null;
309
310
  headers?: { [key: string]: string };
311
+ auth?: {
312
+ type: "bearer" | "basic" | "none";
313
+ token?: string;
314
+ username?: string;
315
+ password?: string;
316
+ } | null;
310
317
  timeout?: number;
311
318
  maxRetries?: number;
312
319
  retryStrategy?: "exponential" | "linear" | "fibonacci";
313
320
  useQueue?: boolean;
314
321
  priority?: number;
315
- responseType?: "json" | "text";
322
+ responseType?: "json" | "text" | "blob" | "arraybuffer";
316
323
  showLoading?: (isLoading: boolean) => void | Promise<void>;
317
324
  onSuccess?: (data: any) => void | Promise<void>;
318
325
  onError?: (log: string) => void | Promise<void>;
@@ -323,10 +330,14 @@ declare module "@vicaniddouglas/js_aide" {
323
330
  config: RequestOptions,
324
331
  ) => RequestOptions | Promise<RequestOptions>;
325
332
  type ResponseInterceptor = (response: {
333
+ status: boolean;
334
+ log: string;
326
335
  data: any;
327
- status: number;
336
+ httpCode: number;
337
+ headers: { [key: string]: string };
328
338
  url: string;
329
- }) => any | Promise<any>;
339
+ method: string;
340
+ }) => StandardizedResponse | Promise<StandardizedResponse> | any | Promise<any>;
330
341
  type ErrorInterceptor = (error: XMLHttpRequest) => void;
331
342
 
332
343
  interface InterceptorMethods {
@@ -345,6 +356,7 @@ declare module "@vicaniddouglas/js_aide" {
345
356
  log: string;
346
357
  data: any;
347
358
  httpCode: number;
359
+ headers: { [key: string]: string };
348
360
  }
349
361
 
350
362
  export const sendRequest: (
@@ -547,7 +559,9 @@ declare module "@vicaniddouglas/js_aide" {
547
559
  options?: toBase64Options,
548
560
  ): Promise<Base64Result>;
549
561
 
550
- export function uploadFile(options: UploadOptions): Promise<StandardizedResponse>;
562
+ export function uploadFile(
563
+ options: UploadOptions,
564
+ ): Promise<StandardizedResponse>;
551
565
 
552
566
  export function uploadDataUrl(
553
567
  dataUrl: string,