@react-vault/core 0.1.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.
Files changed (119) hide show
  1. package/LICENSE +12 -0
  2. package/README.md +41 -0
  3. package/dist/audit/auditClient.d.ts +40 -0
  4. package/dist/audit/auditClient.d.ts.map +1 -0
  5. package/dist/audit/auditClient.js +180 -0
  6. package/dist/audit/auditClient.js.map +1 -0
  7. package/dist/audit/index.d.ts +9 -0
  8. package/dist/audit/index.d.ts.map +1 -0
  9. package/dist/audit/index.js +9 -0
  10. package/dist/audit/index.js.map +1 -0
  11. package/dist/audit/scrubber.d.ts +27 -0
  12. package/dist/audit/scrubber.d.ts.map +1 -0
  13. package/dist/audit/scrubber.js +111 -0
  14. package/dist/audit/scrubber.js.map +1 -0
  15. package/dist/audit/types.d.ts +42 -0
  16. package/dist/audit/types.d.ts.map +1 -0
  17. package/dist/audit/types.js +2 -0
  18. package/dist/audit/types.js.map +1 -0
  19. package/dist/auth/crossTabSync.d.ts +15 -0
  20. package/dist/auth/crossTabSync.d.ts.map +1 -0
  21. package/dist/auth/crossTabSync.js +30 -0
  22. package/dist/auth/crossTabSync.js.map +1 -0
  23. package/dist/auth/idleTimer.d.ts +34 -0
  24. package/dist/auth/idleTimer.d.ts.map +1 -0
  25. package/dist/auth/idleTimer.js +54 -0
  26. package/dist/auth/idleTimer.js.map +1 -0
  27. package/dist/auth/index.d.ts +8 -0
  28. package/dist/auth/index.d.ts.map +1 -0
  29. package/dist/auth/index.js +8 -0
  30. package/dist/auth/index.js.map +1 -0
  31. package/dist/auth/tokenManager.d.ts +47 -0
  32. package/dist/auth/tokenManager.d.ts.map +1 -0
  33. package/dist/auth/tokenManager.js +75 -0
  34. package/dist/auth/tokenManager.js.map +1 -0
  35. package/dist/compliance/csp.d.ts +20 -0
  36. package/dist/compliance/csp.d.ts.map +1 -0
  37. package/dist/compliance/csp.js +34 -0
  38. package/dist/compliance/csp.js.map +1 -0
  39. package/dist/compliance/index.d.ts +8 -0
  40. package/dist/compliance/index.d.ts.map +1 -0
  41. package/dist/compliance/index.js +8 -0
  42. package/dist/compliance/index.js.map +1 -0
  43. package/dist/compliance/safeError.d.ts +12 -0
  44. package/dist/compliance/safeError.d.ts.map +1 -0
  45. package/dist/compliance/safeError.js +39 -0
  46. package/dist/compliance/safeError.js.map +1 -0
  47. package/dist/encryption/aesgcm.d.ts +22 -0
  48. package/dist/encryption/aesgcm.d.ts.map +1 -0
  49. package/dist/encryption/aesgcm.js +67 -0
  50. package/dist/encryption/aesgcm.js.map +1 -0
  51. package/dist/encryption/envelope.d.ts +30 -0
  52. package/dist/encryption/envelope.d.ts.map +1 -0
  53. package/dist/encryption/envelope.js +46 -0
  54. package/dist/encryption/envelope.js.map +1 -0
  55. package/dist/encryption/index.d.ts +19 -0
  56. package/dist/encryption/index.d.ts.map +1 -0
  57. package/dist/encryption/index.js +19 -0
  58. package/dist/encryption/index.js.map +1 -0
  59. package/dist/encryption/pbkdf2.d.ts +21 -0
  60. package/dist/encryption/pbkdf2.d.ts.map +1 -0
  61. package/dist/encryption/pbkdf2.js +48 -0
  62. package/dist/encryption/pbkdf2.js.map +1 -0
  63. package/dist/encryption/rsaoaep.d.ts +21 -0
  64. package/dist/encryption/rsaoaep.d.ts.map +1 -0
  65. package/dist/encryption/rsaoaep.js +43 -0
  66. package/dist/encryption/rsaoaep.js.map +1 -0
  67. package/dist/encryption/util.d.ts +17 -0
  68. package/dist/encryption/util.d.ts.map +1 -0
  69. package/dist/encryption/util.js +47 -0
  70. package/dist/encryption/util.js.map +1 -0
  71. package/dist/http/createAxios.d.ts +39 -0
  72. package/dist/http/createAxios.d.ts.map +1 -0
  73. package/dist/http/createAxios.js +58 -0
  74. package/dist/http/createAxios.js.map +1 -0
  75. package/dist/http/errors.d.ts +28 -0
  76. package/dist/http/errors.d.ts.map +1 -0
  77. package/dist/http/errors.js +57 -0
  78. package/dist/http/errors.js.map +1 -0
  79. package/dist/http/index.d.ts +10 -0
  80. package/dist/http/index.d.ts.map +1 -0
  81. package/dist/http/index.js +10 -0
  82. package/dist/http/index.js.map +1 -0
  83. package/dist/http/interceptors.d.ts +30 -0
  84. package/dist/http/interceptors.d.ts.map +1 -0
  85. package/dist/http/interceptors.js +112 -0
  86. package/dist/http/interceptors.js.map +1 -0
  87. package/dist/index.d.ts +17 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +17 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/pii/index.d.ts +10 -0
  92. package/dist/pii/index.d.ts.map +1 -0
  93. package/dist/pii/index.js +10 -0
  94. package/dist/pii/index.js.map +1 -0
  95. package/dist/pii/maskers.d.ts +63 -0
  96. package/dist/pii/maskers.d.ts.map +1 -0
  97. package/dist/pii/maskers.js +186 -0
  98. package/dist/pii/maskers.js.map +1 -0
  99. package/dist/pii/patterns.d.ts +20 -0
  100. package/dist/pii/patterns.d.ts.map +1 -0
  101. package/dist/pii/patterns.js +19 -0
  102. package/dist/pii/patterns.js.map +1 -0
  103. package/dist/pii/validators.d.ts +10 -0
  104. package/dist/pii/validators.d.ts.map +1 -0
  105. package/dist/pii/validators.js +66 -0
  106. package/dist/pii/validators.js.map +1 -0
  107. package/dist/storage/index.d.ts +14 -0
  108. package/dist/storage/index.d.ts.map +1 -0
  109. package/dist/storage/index.js +14 -0
  110. package/dist/storage/index.js.map +1 -0
  111. package/dist/storage/secureStorage.d.ts +28 -0
  112. package/dist/storage/secureStorage.d.ts.map +1 -0
  113. package/dist/storage/secureStorage.js +140 -0
  114. package/dist/storage/secureStorage.js.map +1 -0
  115. package/dist/storage/types.d.ts +13 -0
  116. package/dist/storage/types.d.ts.map +1 -0
  117. package/dist/storage/types.js +2 -0
  118. package/dist/storage/types.js.map +1 -0
  119. package/package.json +95 -0
@@ -0,0 +1,48 @@
1
+ /**
2
+ * PBKDF2-SHA256 key derivation from passwords.
3
+ *
4
+ * Use for: deriving an encryption key from a user-supplied passphrase.
5
+ * Do NOT use for: server-side password storage (use bcrypt/argon2 on backend).
6
+ *
7
+ * Iteration count: 600,000 per OWASP 2025 recommendation for PBKDF2-SHA256.
8
+ */
9
+ import { toBytes } from './util.js';
10
+ const DEFAULT_ITERATIONS = 600_000;
11
+ /**
12
+ * Derive an AES-GCM key from a password and salt.
13
+ * Salt must be stored alongside the ciphertext (it's not secret, but it's per-record).
14
+ */
15
+ export async function deriveKey(password, salt, opts = {}) {
16
+ if (salt.length < 16) {
17
+ throw new Error(`salt must be >= 16 bytes, got ${salt.length}`);
18
+ }
19
+ const iterations = opts.iterations ?? DEFAULT_ITERATIONS;
20
+ const outputBits = opts.outputLengthBits ?? 256;
21
+ const algorithm = opts.algorithm ?? 'AES-GCM';
22
+ const passwordKey = await crypto.subtle.importKey('raw', toBytes(password), { name: 'PBKDF2' }, false, ['deriveKey']);
23
+ return crypto.subtle.deriveKey({
24
+ name: 'PBKDF2',
25
+ hash: 'SHA-256',
26
+ salt,
27
+ iterations,
28
+ }, passwordKey, { name: algorithm, length: outputBits }, true, algorithm === 'AES-GCM' ? ['encrypt', 'decrypt'] : ['sign', 'verify']);
29
+ }
30
+ /**
31
+ * Derive raw bytes (not a CryptoKey) — useful when you need to interoperate
32
+ * with code expecting a raw byte string.
33
+ */
34
+ export async function deriveBytes(password, salt, opts = {}) {
35
+ if (salt.length < 16) {
36
+ throw new Error(`salt must be >= 16 bytes, got ${salt.length}`);
37
+ }
38
+ const iterations = opts.iterations ?? DEFAULT_ITERATIONS;
39
+ const outputBits = opts.outputLengthBits ?? 256;
40
+ const passwordKey = await crypto.subtle.importKey('raw', toBytes(password), { name: 'PBKDF2' }, false, ['deriveBits']);
41
+ return new Uint8Array(await crypto.subtle.deriveBits({
42
+ name: 'PBKDF2',
43
+ hash: 'SHA-256',
44
+ salt,
45
+ iterations,
46
+ }, passwordKey, outputBits));
47
+ }
48
+ //# sourceMappingURL=pbkdf2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pbkdf2.js","sourceRoot":"","sources":["../../src/encryption/pbkdf2.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAUnC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAgB,EAChB,IAAgB,EAChB,OAAyB,EAAE;IAE3B,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,kBAAkB,CAAC;IACzD,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,IAAI,GAAG,CAAC;IAChD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC;IAE9C,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAC/C,KAAK,EACL,OAAO,CAAC,QAAQ,CAAC,EACjB,EAAE,IAAI,EAAE,QAAQ,EAAE,EAClB,KAAK,EACL,CAAC,WAAW,CAAC,CACd,CAAC;IAEF,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAC5B;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,SAAS;QACf,IAAI;QACJ,UAAU;KACX,EACD,WAAW,EACX,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,EACvC,IAAI,EACJ,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CACtE,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,QAAgB,EAChB,IAAgB,EAChB,OAA2D,EAAE;IAE7D,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,kBAAkB,CAAC;IACzD,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,IAAI,GAAG,CAAC;IAEhD,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAC/C,KAAK,EACL,OAAO,CAAC,QAAQ,CAAC,EACjB,EAAE,IAAI,EAAE,QAAQ,EAAE,EAClB,KAAK,EACL,CAAC,YAAY,CAAC,CACf,CAAC;IAEF,OAAO,IAAI,UAAU,CACnB,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,CAC5B;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,SAAS;QACf,IAAI;QACJ,UAAU;KACX,EACD,WAAW,EACX,UAAU,CACX,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ export type RsaPublicKey = CryptoKey;
2
+ export type RsaPrivateKey = CryptoKey;
3
+ export declare function generateKeyPair(modulusBits?: 2048 | 3072 | 4096): Promise<{
4
+ publicKey: RsaPublicKey;
5
+ privateKey: RsaPrivateKey;
6
+ }>;
7
+ /**
8
+ * Import a public key from SPKI (DER, base64) — common backend format.
9
+ */
10
+ export declare function importPublicKey(spkiBase64: string): Promise<RsaPublicKey>;
11
+ /**
12
+ * Import a public key from PEM format (`-----BEGIN PUBLIC KEY-----...`).
13
+ */
14
+ export declare function importPublicKeyPem(pem: string): Promise<RsaPublicKey>;
15
+ /**
16
+ * Encrypt a small payload (e.g. an AES key — 32 bytes). For 2048-bit RSA-OAEP-SHA256,
17
+ * max plaintext is 190 bytes. Don't try to bulk-encrypt with this.
18
+ */
19
+ export declare function encrypt(pub: RsaPublicKey, bytes: Uint8Array): Promise<string>;
20
+ export declare function decrypt(priv: RsaPrivateKey, blob: string): Promise<Uint8Array>;
21
+ //# sourceMappingURL=rsaoaep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rsaoaep.d.ts","sourceRoot":"","sources":["../../src/encryption/rsaoaep.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC;AACrC,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC;AAEtC,wBAAsB,eAAe,CAAC,WAAW,GAAE,IAAI,GAAG,IAAI,GAAG,IAAW,GAAG,OAAO,CAAC;IACrF,SAAS,EAAE,YAAY,CAAC;IACxB,UAAU,EAAE,aAAa,CAAC;CAC3B,CAAC,CAYD;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAE/E;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAM3E;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAGnF;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAEpF"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * RSA-OAEP encryption (for key-wrapping, not bulk data).
3
+ * Use AES-GCM for the data; RSA-OAEP for the key.
4
+ */
5
+ import { toBase64, fromBase64 } from './util.js';
6
+ const ALGO = { name: 'RSA-OAEP', hash: 'SHA-256' };
7
+ export async function generateKeyPair(modulusBits = 2048) {
8
+ const { publicKey, privateKey } = await crypto.subtle.generateKey({
9
+ name: 'RSA-OAEP',
10
+ modulusLength: modulusBits,
11
+ publicExponent: new Uint8Array([1, 0, 1]),
12
+ hash: 'SHA-256',
13
+ }, true, ['encrypt', 'decrypt']);
14
+ return { publicKey, privateKey };
15
+ }
16
+ /**
17
+ * Import a public key from SPKI (DER, base64) — common backend format.
18
+ */
19
+ export async function importPublicKey(spkiBase64) {
20
+ return crypto.subtle.importKey('spki', fromBase64(spkiBase64), ALGO, true, ['encrypt']);
21
+ }
22
+ /**
23
+ * Import a public key from PEM format (`-----BEGIN PUBLIC KEY-----...`).
24
+ */
25
+ export async function importPublicKeyPem(pem) {
26
+ const body = pem
27
+ .replace(/-----BEGIN [^-]+-----/g, '')
28
+ .replace(/-----END [^-]+-----/g, '')
29
+ .replace(/\s+/g, '');
30
+ return importPublicKey(body);
31
+ }
32
+ /**
33
+ * Encrypt a small payload (e.g. an AES key — 32 bytes). For 2048-bit RSA-OAEP-SHA256,
34
+ * max plaintext is 190 bytes. Don't try to bulk-encrypt with this.
35
+ */
36
+ export async function encrypt(pub, bytes) {
37
+ const ciphertext = new Uint8Array(await crypto.subtle.encrypt(ALGO, pub, bytes));
38
+ return toBase64(ciphertext);
39
+ }
40
+ export async function decrypt(priv, blob) {
41
+ return new Uint8Array(await crypto.subtle.decrypt(ALGO, priv, fromBase64(blob)));
42
+ }
43
+ //# sourceMappingURL=rsaoaep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rsaoaep.js","sourceRoot":"","sources":["../../src/encryption/rsaoaep.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEjD,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,UAAmB,EAAE,IAAI,EAAE,SAAkB,EAAE,CAAC;AAKrE,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,cAAkC,IAAI;IAI1E,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,WAAW,CAC/D;QACE,IAAI,EAAE,UAAU;QAChB,aAAa,EAAE,WAAW;QAC1B,cAAc,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACzC,IAAI,EAAE,SAAS;KAChB,EACD,IAAI,EACJ,CAAC,SAAS,EAAE,SAAS,CAAC,CACvB,CAAC;IACF,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAkB;IACtD,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;AAC1F,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAW;IAClD,MAAM,IAAI,GAAG,GAAG;SACb,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC;SACrC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC;SACnC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACvB,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAiB,EAAE,KAAiB;IAChE,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IACjF,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAmB,EAAE,IAAY;IAC7D,OAAO,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACnF,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Encoding utilities. All ciphertext is transported as base64 strings.
3
+ */
4
+ export declare function toBytes(text: string): Uint8Array;
5
+ export declare function fromBytes(bytes: Uint8Array): string;
6
+ export declare function toBase64(bytes: Uint8Array): string;
7
+ export declare function fromBase64(b64: string): Uint8Array;
8
+ /**
9
+ * Cryptographically secure random bytes.
10
+ * NEVER use Math.random() — see references/bfsi-encrypt-helper.
11
+ */
12
+ export declare function randomBytes(n: number): Uint8Array;
13
+ /**
14
+ * Concat byte arrays. Useful for IV-prefixed ciphertext.
15
+ */
16
+ export declare function concatBytes(...arrays: Uint8Array[]): Uint8Array;
17
+ //# sourceMappingURL=util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/encryption/util.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAEhD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEnD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAIlD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAKlD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,CAIjD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,UAAU,CAS/D"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Encoding utilities. All ciphertext is transported as base64 strings.
3
+ */
4
+ const enc = new TextEncoder();
5
+ const dec = new TextDecoder();
6
+ export function toBytes(text) {
7
+ return enc.encode(text);
8
+ }
9
+ export function fromBytes(bytes) {
10
+ return dec.decode(bytes);
11
+ }
12
+ export function toBase64(bytes) {
13
+ let binary = '';
14
+ for (const b of bytes)
15
+ binary += String.fromCharCode(b);
16
+ return btoa(binary);
17
+ }
18
+ export function fromBase64(b64) {
19
+ const binary = atob(b64);
20
+ const bytes = new Uint8Array(binary.length);
21
+ for (let i = 0; i < binary.length; i++)
22
+ bytes[i] = binary.charCodeAt(i);
23
+ return bytes;
24
+ }
25
+ /**
26
+ * Cryptographically secure random bytes.
27
+ * NEVER use Math.random() — see references/bfsi-encrypt-helper.
28
+ */
29
+ export function randomBytes(n) {
30
+ const buf = new Uint8Array(n);
31
+ crypto.getRandomValues(buf);
32
+ return buf;
33
+ }
34
+ /**
35
+ * Concat byte arrays. Useful for IV-prefixed ciphertext.
36
+ */
37
+ export function concatBytes(...arrays) {
38
+ const total = arrays.reduce((sum, a) => sum + a.length, 0);
39
+ const out = new Uint8Array(total);
40
+ let offset = 0;
41
+ for (const a of arrays) {
42
+ out.set(a, offset);
43
+ offset += a.length;
44
+ }
45
+ return out;
46
+ }
47
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/encryption/util.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;AAC9B,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;AAE9B,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAiB;IACzC,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAiB;IACxC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACxE,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAC9B,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAG,MAAoB;IACjD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACnB,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC;IACrB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Configurable axios factory. Apps create one (or more) instances by
3
+ * composing the interceptors they need.
4
+ *
5
+ * Auth model: tokens are set ONCE on the instance via {@link setAuthToken} at
6
+ * login time, not injected per-request. This is the rsense-react-org pattern
7
+ * — cheaper than reading from localStorage on every call. Call {@link clearAuthToken}
8
+ * on logout / 401.
9
+ */
10
+ import { type AxiosInstance } from 'axios';
11
+ export interface CreateAxiosOptions {
12
+ baseURL: string;
13
+ timeoutMs?: number;
14
+ /** Header name for the auth token. Default `Authorization` (sends `Bearer <token>`). */
15
+ authHeaderName?: string;
16
+ /** Callback for 401 responses (typically: clear auth + redirect to login). */
17
+ onUnauthorized?: () => void;
18
+ /**
19
+ * Whether backend uses snake_case. If true, response keys are converted to
20
+ * camelCase and request bodies converted to snake_case.
21
+ */
22
+ snakeCaseBackend?: boolean;
23
+ /** Disable auto idempotency-key + correlation-id headers if you handle them yourself. */
24
+ disableRequestIds?: boolean;
25
+ }
26
+ export declare function createAxios(opts: CreateAxiosOptions): AxiosInstance;
27
+ /**
28
+ * Set the auth token on an axios instance — call once at login.
29
+ *
30
+ * If the header name is `Authorization`, the value is automatically prefixed
31
+ * with `Bearer `. For any other header name (e.g. `X-Auth-Token`), the value
32
+ * is set verbatim.
33
+ */
34
+ export declare function setAuthToken(instance: AxiosInstance, token: string): void;
35
+ /**
36
+ * Remove the auth token from an axios instance — call on logout / 401.
37
+ */
38
+ export declare function clearAuthToken(instance: AxiosInstance): void;
39
+ //# sourceMappingURL=createAxios.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAxios.d.ts","sourceRoot":"","sources":["../../src/http/createAxios.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAc,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAQlD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,aAAa,CA+BnE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAKzE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAI5D"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Configurable axios factory. Apps create one (or more) instances by
3
+ * composing the interceptors they need.
4
+ *
5
+ * Auth model: tokens are set ONCE on the instance via {@link setAuthToken} at
6
+ * login time, not injected per-request. This is the rsense-react-org pattern
7
+ * — cheaper than reading from localStorage on every call. Call {@link clearAuthToken}
8
+ * on logout / 401.
9
+ */
10
+ import axios from 'axios';
11
+ import { attachCamelToSnake, attachErrorMapping, attachRequestIds, attachSnakeToCamel, } from './interceptors.js';
12
+ export function createAxios(opts) {
13
+ const instance = axios.create({
14
+ baseURL: opts.baseURL,
15
+ timeout: opts.timeoutMs ?? 30_000,
16
+ headers: {
17
+ 'Content-Type': 'application/json',
18
+ Accept: 'application/json',
19
+ },
20
+ });
21
+ // Stash the auth header name on the instance for set/clear helpers.
22
+ instance.__authHeaderName =
23
+ opts.authHeaderName ?? 'Authorization';
24
+ if (!opts.disableRequestIds) {
25
+ attachRequestIds(instance);
26
+ }
27
+ if (opts.snakeCaseBackend) {
28
+ attachSnakeToCamel(instance);
29
+ attachCamelToSnake(instance);
30
+ }
31
+ attachErrorMapping(instance, {
32
+ onUnauthorized: () => {
33
+ clearAuthToken(instance);
34
+ opts.onUnauthorized?.();
35
+ },
36
+ });
37
+ return instance;
38
+ }
39
+ /**
40
+ * Set the auth token on an axios instance — call once at login.
41
+ *
42
+ * If the header name is `Authorization`, the value is automatically prefixed
43
+ * with `Bearer `. For any other header name (e.g. `X-Auth-Token`), the value
44
+ * is set verbatim.
45
+ */
46
+ export function setAuthToken(instance, token) {
47
+ const headerName = instance.__authHeaderName ?? 'Authorization';
48
+ const value = headerName === 'Authorization' ? `Bearer ${token}` : token;
49
+ instance.defaults.headers.common[headerName] = value;
50
+ }
51
+ /**
52
+ * Remove the auth token from an axios instance — call on logout / 401.
53
+ */
54
+ export function clearAuthToken(instance) {
55
+ const headerName = instance.__authHeaderName ?? 'Authorization';
56
+ delete instance.defaults.headers.common[headerName];
57
+ }
58
+ //# sourceMappingURL=createAxios.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAxios.js","sourceRoot":"","sources":["../../src/http/createAxios.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAA6B,MAAM,OAAO,CAAC;AAClD,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAkB3B,MAAM,UAAU,WAAW,CAAC,IAAwB;IAClD,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,OAAO,EAAE,IAAI,CAAC,SAAS,IAAI,MAAM;QACjC,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,MAAM,EAAE,kBAAkB;SAC3B;KACF,CAAC,CAAC;IAEH,oEAAoE;IACnE,QAA0D,CAAC,gBAAgB;QAC1E,IAAI,CAAC,cAAc,IAAI,eAAe,CAAC;IAEzC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC5B,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC1B,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAC7B,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,kBAAkB,CAAC,QAAQ,EAAE;QAC3B,cAAc,EAAE,GAAG,EAAE;YACnB,cAAc,CAAC,QAAQ,CAAC,CAAC;YACzB,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QAC1B,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,QAAuB,EAAE,KAAa;IACjE,MAAM,UAAU,GACb,QAA0D,CAAC,gBAAgB,IAAI,eAAe,CAAC;IAClG,MAAM,KAAK,GAAG,UAAU,KAAK,eAAe,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IACzE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAuB;IACpD,MAAM,UAAU,GACb,QAA0D,CAAC,gBAAgB,IAAI,eAAe,CAAC;IAClG,OAAO,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Typed HTTP errors. Use these instead of raw `AxiosError` in app code.
3
+ */
4
+ export type ApiErrorKind = 'network' | 'timeout' | 'unauthorized' | 'forbidden' | 'not_found' | 'conflict' | 'validation' | 'rate_limited' | 'server_error' | 'cancelled' | 'unknown';
5
+ export interface ApiErrorOptions {
6
+ kind: ApiErrorKind;
7
+ /** HTTP status if available. */
8
+ status?: number;
9
+ /** Server-generated ref code or our own short ref for support. */
10
+ ref?: string;
11
+ /** Field-level errors from 422. Map of field path → message. */
12
+ fieldErrors?: Record<string, string>;
13
+ /** Original error (not exposed via toJSON). */
14
+ cause?: unknown;
15
+ }
16
+ export declare class ApiError extends Error {
17
+ readonly kind: ApiErrorKind;
18
+ readonly status?: number;
19
+ readonly ref?: string;
20
+ readonly fieldErrors?: Record<string, string>;
21
+ constructor(message: string, opts: ApiErrorOptions);
22
+ /**
23
+ * User-safe representation. Does NOT include `cause` (stack/PII risk).
24
+ */
25
+ toJSON(): Record<string, unknown>;
26
+ }
27
+ export declare function fromStatus(status: number): ApiErrorKind;
28
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,SAAS,GACT,cAAc,GACd,WAAW,GACX,WAAW,GACX,UAAU,GACV,YAAY,GACZ,cAAc,GACd,cAAc,GACd,WAAW,GACX,SAAS,CAAC;AAEd,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,gCAAgC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,+CAA+C;IAC/C,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAElC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe;IAYlD;;OAEG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CASlC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CASvD"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Typed HTTP errors. Use these instead of raw `AxiosError` in app code.
3
+ */
4
+ export class ApiError extends Error {
5
+ kind;
6
+ status;
7
+ ref;
8
+ fieldErrors;
9
+ constructor(message, opts) {
10
+ super(message);
11
+ this.name = 'ApiError';
12
+ this.kind = opts.kind;
13
+ this.status = opts.status;
14
+ this.ref = opts.ref;
15
+ this.fieldErrors = opts.fieldErrors;
16
+ if (opts.cause !== undefined) {
17
+ this.cause = opts.cause;
18
+ }
19
+ }
20
+ /**
21
+ * User-safe representation. Does NOT include `cause` (stack/PII risk).
22
+ */
23
+ toJSON() {
24
+ return {
25
+ name: this.name,
26
+ kind: this.kind,
27
+ status: this.status,
28
+ ref: this.ref,
29
+ fieldErrors: this.fieldErrors,
30
+ };
31
+ }
32
+ }
33
+ export function fromStatus(status) {
34
+ if (status === 401) {
35
+ return 'unauthorized';
36
+ }
37
+ if (status === 403) {
38
+ return 'forbidden';
39
+ }
40
+ if (status === 404) {
41
+ return 'not_found';
42
+ }
43
+ if (status === 409) {
44
+ return 'conflict';
45
+ }
46
+ if (status === 422) {
47
+ return 'validation';
48
+ }
49
+ if (status === 429) {
50
+ return 'rate_limited';
51
+ }
52
+ if (status >= 500 && status < 600) {
53
+ return 'server_error';
54
+ }
55
+ return 'unknown';
56
+ }
57
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AA2BH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,CAAe;IACnB,MAAM,CAAU;IAChB,GAAG,CAAU;IACb,WAAW,CAA0B;IAE9C,YAAY,OAAe,EAAE,IAAqB;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACpB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACpC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAc,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACrC,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC;IACJ,CAAC;CACF;AAED,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QAAA,OAAO,cAAc,CAAC;IAAA,CAAC;IAC5C,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QAAA,OAAO,WAAW,CAAC;IAAA,CAAC;IACzC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QAAA,OAAO,WAAW,CAAC;IAAA,CAAC;IACzC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QAAA,OAAO,UAAU,CAAC;IAAA,CAAC;IACxC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QAAA,OAAO,YAAY,CAAC;IAAA,CAAC;IAC1C,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QAAA,OAAO,cAAc,CAAC;IAAA,CAAC;IAC5C,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;QAAA,OAAO,cAAc,CAAC;IAAA,CAAC;IAC3D,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * HTTP — axios factory with composable BFSI-grade interceptors.
3
+ *
4
+ * Pattern: instead of one monolithic axios instance, expose composable
5
+ * interceptors. Each app composes the ones it needs.
6
+ */
7
+ export * from './createAxios.js';
8
+ export * from './interceptors.js';
9
+ export * from './errors.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * HTTP — axios factory with composable BFSI-grade interceptors.
3
+ *
4
+ * Pattern: instead of one monolithic axios instance, expose composable
5
+ * interceptors. Each app composes the ones it needs.
6
+ */
7
+ export * from './createAxios.js';
8
+ export * from './interceptors.js';
9
+ export * from './errors.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Composable axios interceptors. Each function takes an instance and attaches
3
+ * itself. App code chooses which to add.
4
+ *
5
+ * Note: auth-header injection is NOT here. Tokens are set once on the instance
6
+ * via setAuthToken() in createAxios.ts (rsense-style, set-at-login). Avoids
7
+ * reading from localStorage on every request.
8
+ */
9
+ import type { AxiosInstance } from 'axios';
10
+ /**
11
+ * Request interceptor: add a correlation ID and idempotency key.
12
+ * Idempotency key applied only to mutating methods.
13
+ */
14
+ export declare function attachRequestIds(instance: AxiosInstance): void;
15
+ /**
16
+ * Response transformer: convert snake_case keys to camelCase.
17
+ * Applied if your backend uses snake_case (e.g. Rails/Python).
18
+ */
19
+ export declare function attachSnakeToCamel(instance: AxiosInstance): void;
20
+ /**
21
+ * Request transformer: convert camelCase request bodies to snake_case.
22
+ */
23
+ export declare function attachCamelToSnake(instance: AxiosInstance): void;
24
+ /**
25
+ * Response interceptor: convert raw axios errors into typed `ApiError`.
26
+ */
27
+ export declare function attachErrorMapping(instance: AxiosInstance, opts?: {
28
+ onUnauthorized?: () => void;
29
+ }): void;
30
+ //# sourceMappingURL=interceptors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interceptors.d.ts","sourceRoot":"","sources":["../../src/http/interceptors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,aAAa,EAA8B,MAAM,OAAO,CAAC;AAIvE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAW9D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAKhE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAOhE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,aAAa,EACvB,IAAI,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;CAAO,GACzC,IAAI,CAWN"}
@@ -0,0 +1,112 @@
1
+ import { ApiError, fromStatus } from './errors.js';
2
+ import { generateEventId } from '../audit/auditClient.js';
3
+ /**
4
+ * Request interceptor: add a correlation ID and idempotency key.
5
+ * Idempotency key applied only to mutating methods.
6
+ */
7
+ export function attachRequestIds(instance) {
8
+ instance.interceptors.request.use((config) => {
9
+ config.headers.set('X-Request-Id', generateEventId());
10
+ const method = (config.method ?? 'get').toUpperCase();
11
+ if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
12
+ if (!config.headers.has('Idempotency-Key')) {
13
+ config.headers.set('Idempotency-Key', generateEventId());
14
+ }
15
+ }
16
+ return config;
17
+ });
18
+ }
19
+ /**
20
+ * Response transformer: convert snake_case keys to camelCase.
21
+ * Applied if your backend uses snake_case (e.g. Rails/Python).
22
+ */
23
+ export function attachSnakeToCamel(instance) {
24
+ instance.interceptors.response.use((response) => {
25
+ response.data = deepSnakeToCamel(response.data);
26
+ return response;
27
+ });
28
+ }
29
+ /**
30
+ * Request transformer: convert camelCase request bodies to snake_case.
31
+ */
32
+ export function attachCamelToSnake(instance) {
33
+ instance.interceptors.request.use((config) => {
34
+ if (config.data && typeof config.data === 'object' && !(config.data instanceof FormData)) {
35
+ config.data = deepCamelToSnake(config.data);
36
+ }
37
+ return config;
38
+ });
39
+ }
40
+ /**
41
+ * Response interceptor: convert raw axios errors into typed `ApiError`.
42
+ */
43
+ export function attachErrorMapping(instance, opts = {}) {
44
+ instance.interceptors.response.use((r) => r, (err) => {
45
+ const apiErr = mapError(err);
46
+ if (apiErr.kind === 'unauthorized') {
47
+ opts.onUnauthorized?.();
48
+ }
49
+ return Promise.reject(apiErr);
50
+ });
51
+ }
52
+ function mapError(err) {
53
+ if (err instanceof ApiError) {
54
+ return err;
55
+ }
56
+ // We don't import AxiosError type directly because we don't want a hard runtime dep
57
+ // on axios internals — duck-type instead.
58
+ const e = err;
59
+ if (e?.code === 'ECONNABORTED' || e?.code === 'ERR_CANCELED') {
60
+ return new ApiError('Request cancelled', { kind: 'cancelled', cause: err });
61
+ }
62
+ if (!e?.response) {
63
+ return new ApiError('Network error', { kind: 'network', cause: err });
64
+ }
65
+ const status = e.response.status ?? 0;
66
+ const kind = fromStatus(status);
67
+ const data = e.response.data;
68
+ return new ApiError(data?.message ?? `HTTP ${status}`, {
69
+ kind,
70
+ status,
71
+ ref: data?.ref,
72
+ fieldErrors: data?.field_errors ?? data?.errors,
73
+ cause: err,
74
+ });
75
+ }
76
+ // --- key transformation helpers ---
77
+ function camelToSnakeKey(key) {
78
+ return key.replace(/([A-Z])/g, '_$1').toLowerCase();
79
+ }
80
+ function snakeToCamelKey(key) {
81
+ return key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
82
+ }
83
+ function deepSnakeToCamel(value) {
84
+ if (Array.isArray(value)) {
85
+ return value.map(deepSnakeToCamel);
86
+ }
87
+ if (value && typeof value === 'object' && !(value instanceof Date)) {
88
+ const out = {};
89
+ for (const [k, v] of Object.entries(value)) {
90
+ out[snakeToCamelKey(k)] = deepSnakeToCamel(v);
91
+ }
92
+ return out;
93
+ }
94
+ return value;
95
+ }
96
+ function deepCamelToSnake(value) {
97
+ if (Array.isArray(value)) {
98
+ return value.map(deepCamelToSnake);
99
+ }
100
+ if (value &&
101
+ typeof value === 'object' &&
102
+ !(value instanceof Date) &&
103
+ !(value instanceof FormData)) {
104
+ const out = {};
105
+ for (const [k, v] of Object.entries(value)) {
106
+ out[camelToSnakeKey(k)] = deepCamelToSnake(v);
107
+ }
108
+ return out;
109
+ }
110
+ return value;
111
+ }
112
+ //# sourceMappingURL=interceptors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interceptors.js","sourceRoot":"","sources":["../../src/http/interceptors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @react-vault/core — barrel export.
3
+ *
4
+ * Prefer importing from sub-paths for tree-shaking:
5
+ * import { aesgcm } from '@react-vault/core/encryption';
6
+ * import { maskPan } from '@react-vault/core/pii';
7
+ *
8
+ * Only re-exports for convenience.
9
+ */
10
+ export * as encryption from './encryption/index.js';
11
+ export * as pii from './pii/index.js';
12
+ export * as audit from './audit/index.js';
13
+ export * as http from './http/index.js';
14
+ export * as auth from './auth/index.js';
15
+ export * as storage from './storage/index.js';
16
+ export * as compliance from './compliance/index.js';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,GAAG,MAAM,gBAAgB,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAC1C,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @react-vault/core — barrel export.
3
+ *
4
+ * Prefer importing from sub-paths for tree-shaking:
5
+ * import { aesgcm } from '@react-vault/core/encryption';
6
+ * import { maskPan } from '@react-vault/core/pii';
7
+ *
8
+ * Only re-exports for convenience.
9
+ */
10
+ export * as encryption from './encryption/index.js';
11
+ export * as pii from './pii/index.js';
12
+ export * as audit from './audit/index.js';
13
+ export * as http from './http/index.js';
14
+ export * as auth from './auth/index.js';
15
+ export * as storage from './storage/index.js';
16
+ export * as compliance from './compliance/index.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,GAAG,MAAM,gBAAgB,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAC1C,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAC"}