@vicaniddouglas/js_aide 1.15.3 → 1.16.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 +82 -63
- package/declarations.d.ts +3 -1
- package/dist/js_aide.cjs.js +223 -222
- package/dist/js_aide.cjs.js.map +4 -4
- package/dist/js_aide.esm.js +224 -223
- package/dist/js_aide.esm.js.map +4 -4
- package/dist/js_aide.min.js +223 -222
- package/dist/js_aide.min.js.map +4 -4
- package/package.json +1 -1
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
181
|
-
|
|
181
|
+
const response = await ws.sendWithAck("save_profile", { bio: "Hello world" });
|
|
182
|
+
console.log("Profile saved successfully:", response);
|
|
182
183
|
} catch (error) {
|
|
183
|
-
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
|
|
225
|
-
|
|
|
226
|
-
|
|
|
227
|
-
| `
|
|
228
|
-
| `
|
|
229
|
-
| `
|
|
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:
|
|
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:
|
|
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:
|
|
273
|
+
const res = await sendRequest({ endpoint: "/profile" });
|
|
266
274
|
|
|
267
275
|
if (res.status) {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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:
|
|
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
|
-
|
|
298
|
-
|
|
307
|
+
// res.data is the full data URL (e.g. data:image/png;base64,...)
|
|
308
|
+
myImagePreview.src = res.data;
|
|
299
309
|
} else {
|
|
300
|
-
|
|
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
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
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
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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
|
|
351
|
-
|
|
|
352
|
-
| `duration`
|
|
353
|
-
| `persistent
|
|
354
|
-
| `closable`
|
|
355
|
-
| `icon`
|
|
356
|
-
| `color`
|
|
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
|
|
413
|
-
|
|
|
414
|
-
| `inputType`
|
|
415
|
-
| `defaultValue
|
|
416
|
-
| `submitText`
|
|
417
|
-
| `cancelText`
|
|
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
|
@@ -547,7 +547,9 @@ declare module "@vicaniddouglas/js_aide" {
|
|
|
547
547
|
options?: toBase64Options,
|
|
548
548
|
): Promise<Base64Result>;
|
|
549
549
|
|
|
550
|
-
export function uploadFile(
|
|
550
|
+
export function uploadFile(
|
|
551
|
+
options: UploadOptions,
|
|
552
|
+
): Promise<StandardizedResponse>;
|
|
551
553
|
|
|
552
554
|
export function uploadDataUrl(
|
|
553
555
|
dataUrl: string,
|