@vicaniddouglas/js_aide 1.19.0 → 1.20.1

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
@@ -44,6 +44,23 @@ Specialized formatting for financial data. Includes native support for **UGX** (
44
44
 
45
45
  A smart loader for external libraries (like SheetJS or jsPDF). Manages CDN fallbacks, retry logic, and ensures libraries are only loaded when needed.
46
46
 
47
+ ### `Response (ok / error)`
48
+
49
+ A standardized response helper mirroring the Python `py_aide.response.Response` pattern. Every operation returns `{ status, data, log }`.
50
+
51
+ - `ok(data)` — creates a success response (truthy via `valueOf()`)
52
+ - `error(message)` — creates an error response (falsy via `valueOf()`)
53
+ - The `Response` class has a **guarded constructor** — only `ok()` and `error()` can instantiate it; direct `new Response(...)` throws.
54
+
55
+ ### `FieldTokenizer`
56
+
57
+ A cryptographic token engine compatible with the Python `FieldTokenizer`. Produces v3 tokens (URL-safe base64) that are byte-for-byte interchangeable between JS and Python.
58
+
59
+ - **Non-deterministic** — same value produces a different token each time (random XOR seed)
60
+ - **Integrity** — HMAC-SHA256 verification detects tampering
61
+ - **TTL support** — tokens can expire; expiry is checked on `detokenize()`
62
+ - **Isolated secrets** — different keys produce incompatible tokens
63
+
47
64
  ### `WebSocket Client`
48
65
 
49
66
  A professional-grade WebSocket implementation with automatic reconnection, heartbeat monitoring, and a registry to prevent duplicate connections.
package/declarations.d.ts CHANGED
@@ -1614,4 +1614,89 @@ declare module "@vicaniddouglas/js_aide" {
1614
1614
  * @returns Object with element, callback, and pool counts
1615
1615
  */
1616
1616
  export function getWatcherStats(): WatcherStats;
1617
+
1618
+ // =========================================================
1619
+ // Response (from response.js)
1620
+ // =========================================================
1621
+ /**
1622
+ * Standardized response object with { status, data, log } shape.
1623
+ * Cannot be instantiated directly — use ok() or error() instead.
1624
+ */
1625
+ export class Response {
1626
+ /** true on success, false on error */
1627
+ status: boolean;
1628
+ /** Error message on failure, "" on success */
1629
+ log: string;
1630
+ /** The payload on success, null on error */
1631
+ data: any;
1632
+
1633
+ /** @throws Error — use ok() / error() instead */
1634
+ private constructor();
1635
+
1636
+ /** Truthy on success, falsy on error */
1637
+ valueOf(): boolean;
1638
+ }
1639
+
1640
+ /**
1641
+ * Create a success Response.
1642
+ * @param data Optional payload (defaults to undefined)
1643
+ */
1644
+ export function ok(data?: any): Response;
1645
+
1646
+ /**
1647
+ * Create an error Response.
1648
+ * @param message Error description
1649
+ */
1650
+ export function error(message: string): Response;
1651
+
1652
+ // =========================================================
1653
+ // Tokenizer (from tokens/tokenizer.js)
1654
+ // =========================================================
1655
+ interface TokenizeOptions {
1656
+ /** Time-to-live in seconds */
1657
+ ttl?: number;
1658
+ /** Explicit timestamp (Unix seconds) for testing */
1659
+ timestamp?: number;
1660
+ }
1661
+
1662
+ interface DetokenizeOptions {
1663
+ /** Skip TTL expiry check (default: true) */
1664
+ verify_ttl?: boolean;
1665
+ }
1666
+
1667
+ /**
1668
+ * Cryptographic token engine compatible with Python FieldTokenizer.
1669
+ * Produces v3 tokens with HMAC-SHA256 integrity and optional TTL.
1670
+ */
1671
+ export class FieldTokenizer {
1672
+ /**
1673
+ * @param secret HMAC key — required, no default.
1674
+ */
1675
+ constructor(secret: string);
1676
+
1677
+ /**
1678
+ * Transform a value into a non-deterministic, integrity-checked v3 token.
1679
+ * @returns Response with .data = base64url token string on success
1680
+ */
1681
+ tokenize(value: any, options?: TokenizeOptions): Response;
1682
+
1683
+ /**
1684
+ * Recover the original value from a token, verifying integrity.
1685
+ * Handles v1, v2, and v3 tokens transparently.
1686
+ * @returns Response with .data = original value on success
1687
+ */
1688
+ detokenize(token: string, options?: DetokenizeOptions): Response;
1689
+ }
1690
+
1691
+ /**
1692
+ * Quick token creation — one call, cached secret.
1693
+ * Pass opts.secret on first call to set the secret.
1694
+ */
1695
+ export function tokenize(value: any, options?: TokenizeOptions & { secret?: string }): Response;
1696
+
1697
+ /**
1698
+ * Quick token verification — one call, cached secret.
1699
+ * Pass opts.secret on first call to set the secret.
1700
+ */
1701
+ export function detokenize(token: string, options?: DetokenizeOptions & { secret?: string }): Response;
1617
1702
  }
@@ -1114,8 +1114,8 @@ var PA=Object.defineProperty;var D2=Object.getOwnPropertyDescriptor;var s2=Objec
1114
1114
  <div class="point point3" style="display: none;"></div>
1115
1115
  <div class="point point4" style="display: none;"></div>
1116
1116
  <div class="crop-controls">
1117
- <button class="cancel-crop" style="background-color: #f44336;">\u2715</button>
1118
- <button class="accept-crop" style="background-color: #4CAF50;">\u2713</button>
1117
+ <button class="cancel-crop">\u2715</button>
1118
+ <button class="accept-crop">\u2713</button>
1119
1119
  </div>
1120
1120
  </div>
1121
1121
  <div class="modal-footer">
@@ -1176,7 +1176,7 @@ var PA=Object.defineProperty;var D2=Object.getOwnPropertyDescriptor;var s2=Objec
1176
1176
  color: #000;
1177
1177
  }
1178
1178
 
1179
- h2 {
1179
+ .camera-modal h2 {
1180
1180
  text-align: center;
1181
1181
  color: #333;
1182
1182
  margin-top: 0;
@@ -1192,17 +1192,12 @@ var PA=Object.defineProperty;var D2=Object.getOwnPropertyDescriptor;var s2=Objec
1192
1192
 
1193
1193
  .switch-camera-btn {
1194
1194
  padding: 10px 15px;
1195
- background-color: #3498db; /* Blue color */
1195
+ background-color: #627181;
1196
1196
  color: white;
1197
1197
  border: none;
1198
1198
  border-radius: 6px;
1199
1199
  cursor: pointer;
1200
1200
  font-size: 15px;
1201
- transition: background-color 0.3s ease;
1202
- }
1203
-
1204
- .switch-camera-btn:hover {
1205
- background-color: #2980b9;
1206
1201
  }
1207
1202
 
1208
1203
  .camera-preview {
@@ -1258,11 +1253,16 @@ var PA=Object.defineProperty;var D2=Object.getOwnPropertyDescriptor;var s2=Objec
1258
1253
  justify-content: center;
1259
1254
  align-items: center;
1260
1255
  box-shadow: 0 2px 5px rgba(0,0,0,0.2);
1261
- transition: transform 0.2s ease;
1262
1256
  }
1263
1257
 
1264
- .crop-controls button:hover {
1265
- transform: translateY(-2px);
1258
+ .cancel-crop {
1259
+ background-color: #627181;
1260
+ color: white;
1261
+ }
1262
+
1263
+ .accept-crop {
1264
+ background-color: #627181;
1265
+ color: white;
1266
1266
  }
1267
1267
 
1268
1268
  .point {
@@ -1303,26 +1303,19 @@ var PA=Object.defineProperty;var D2=Object.getOwnPropertyDescriptor;var s2=Objec
1303
1303
  z-index: 20;
1304
1304
  }
1305
1305
 
1306
- button {
1306
+ .camera-modal button {
1307
1307
  padding: 12px 20px; /* More padding for buttons */
1308
- background-color: #2ecc71; /* Green color */
1308
+ background-color: #627181;
1309
1309
  color: white;
1310
1310
  border: none;
1311
1311
  border-radius: 6px; /* Rounded buttons */
1312
1312
  cursor: pointer;
1313
1313
  font-size: 16px;
1314
1314
  margin: 0 5px;
1315
- transition: background-color 0.3s ease, transform 0.2s ease;
1316
1315
  box-shadow: 0 2px 5px rgba(0,0,0,0.2);
1317
1316
  }
1318
1317
 
1319
- button:hover {
1320
- background-color: #27ae60;
1321
- transform: translateY(-2px);
1322
- }
1323
-
1324
- button:active {
1325
- transform: translateY(0);
1318
+ .camera-modal button:active {
1326
1319
  box-shadow: none;
1327
1320
  }
1328
1321
 
@@ -1360,7 +1353,7 @@ var PA=Object.defineProperty;var D2=Object.getOwnPropertyDescriptor;var s2=Objec
1360
1353
  padding: 15px;
1361
1354
  }
1362
1355
 
1363
- button {
1356
+ .camera-modal button {
1364
1357
  padding: 10px 15px;
1365
1358
  font-size: 14px;
1366
1359
  }