wolfronix-sdk 1.2.0 → 1.3.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
@@ -1,19 +1,17 @@
1
- # @wolfronix/sdk
1
+ # wolfronix-sdk
2
2
 
3
3
  Official JavaScript/TypeScript SDK for Wolfronix - Zero-knowledge encryption made simple.
4
4
 
5
- [![npm version](https://badge.fury.io/js/@wolfronix%2Fsdk.svg)](https://www.npmjs.com/package/@wolfronix/sdk)
5
+ [![npm version](https://badge.fury.io/js/wolfronix-sdk.svg)](https://www.npmjs.com/package/wolfronix-sdk)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
8
  ## Features
9
9
 
10
10
  - 🔐 **Zero-Knowledge Encryption** - Keys generated client-side, never leave your device
11
11
  - 🏢 **Enterprise Ready** - Seamless integration with your existing storage
12
-
13
12
  - 🚀 **Simple API** - Encrypt files in 2 lines of code
14
13
  - 📦 **TypeScript Native** - Full type definitions included
15
- - 🌐 **Universal** - Works in Node.js and browsers
16
- - ⚡ **Streaming** - Handle large files with progress tracking
14
+ - 🌐 **Universal** - Works in Node.js 16+ and modern browsers
17
15
  - 🔄 **Auto Retry** - Built-in retry logic with exponential backoff
18
16
 
19
17
  ## Backend Integration (Enterprise Mode)
@@ -30,17 +28,17 @@ Wolfronix handles all encryption/decryption keys and logic; you only handle the
30
28
  ## Installation
31
29
 
32
30
  ```bash
33
- npm install @wolfronix/sdk
31
+ npm install wolfronix-sdk
34
32
  # or
35
- yarn add @wolfronix/sdk
33
+ yarn add wolfronix-sdk
36
34
  # or
37
- pnpm add @wolfronix/sdk
35
+ pnpm add wolfronix-sdk
38
36
  ```
39
37
 
40
38
  ## Quick Start
41
39
 
42
40
  ```typescript
43
- import Wolfronix from '@wolfronix/sdk';
41
+ import Wolfronix from 'wolfronix-sdk';
44
42
 
45
43
  // Initialize client
46
44
  const wfx = new Wolfronix({
@@ -67,7 +65,7 @@ const decrypted = await wfx.decrypt(result.file_id);
67
65
  ### Browser (React, Vue, Angular, etc.)
68
66
 
69
67
  ```typescript
70
- import Wolfronix from '@wolfronix/sdk';
68
+ import Wolfronix from 'wolfronix-sdk';
71
69
 
72
70
  const wfx = new Wolfronix('https://wolfronix-server:5002');
73
71
 
@@ -77,7 +75,6 @@ const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
77
75
  if (!file) return;
78
76
 
79
77
  try {
80
- // Keys are automatically handled by the SDK
81
78
  const { file_id } = await wfx.encrypt(file);
82
79
  console.log('File encrypted with your private key:', file_id);
83
80
  } catch (error) {
@@ -102,7 +99,7 @@ const handleDownload = async (fileId: string, filename: string) => {
102
99
  ### Node.js
103
100
 
104
101
  ```typescript
105
- import Wolfronix from '@wolfronix/sdk';
102
+ import Wolfronix from 'wolfronix-sdk';
106
103
  import * as fs from 'fs';
107
104
 
108
105
  const wfx = new Wolfronix({
@@ -132,23 +129,6 @@ async function main() {
132
129
  main();
133
130
  ```
134
131
 
135
- ### Large File Streaming with Progress
136
-
137
- ```typescript
138
- const wfx = new Wolfronix('https://wolfronix-server:5002');
139
-
140
- // Encrypt with progress
141
- const result = await wfx.encryptStream(largeFile, (percent) => {
142
- console.log(`Uploading: ${percent}%`);
143
- progressBar.value = percent;
144
- });
145
-
146
- // Decrypt with progress
147
- const blob = await wfx.decryptStream(fileId, (percent) => {
148
- console.log(`Downloading: ${percent}%`);
149
- });
150
- ```
151
-
152
132
  ## API Reference
153
133
 
154
134
  ### Constructor
@@ -181,10 +161,8 @@ new Wolfronix(config: WolfronixConfig | string)
181
161
  | Method | Description |
182
162
  |--------|-------------|
183
163
  | `encrypt(file, filename?)` | Encrypt and store file |
184
- | `encryptStream(file, onProgress?)` | Encrypt large file with progress |
185
164
  | `decrypt(fileId)` | Decrypt file (returns Blob) |
186
165
  | `decryptToBuffer(fileId)` | Decrypt file (returns ArrayBuffer) |
187
- | `decryptStream(fileId, onProgress?)` | Decrypt large file with progress |
188
166
  | `listFiles()` | List user's encrypted files |
189
167
  | `deleteFile(fileId)` | Delete encrypted file |
190
168
 
@@ -207,7 +185,7 @@ import Wolfronix, {
207
185
  PermissionDeniedError,
208
186
  NetworkError,
209
187
  ValidationError
210
- } from '@wolfronix/sdk';
188
+ } from 'wolfronix-sdk';
211
189
 
212
190
  try {
213
191
  await wfx.encrypt(file);
@@ -246,7 +224,7 @@ import Wolfronix, {
246
224
  FileInfo,
247
225
  ListFilesResponse,
248
226
  MetricsResponse
249
- } from '@wolfronix/sdk';
227
+ } from 'wolfronix-sdk';
250
228
 
251
229
  // All methods are fully typed
252
230
  const config: WolfronixConfig = {
@@ -263,7 +241,7 @@ const response: EncryptResponse = await wfx.encrypt(file);
263
241
  ```typescript
264
242
  // useWolfronix.ts
265
243
  import { useState, useCallback, useMemo } from 'react';
266
- import Wolfronix, { FileInfo as WolfronixFile } from '@wolfronix/sdk';
244
+ import Wolfronix, { FileInfo as WolfronixFile } from 'wolfronix-sdk';
267
245
 
268
246
  export function useWolfronix(baseUrl: string, clientId?: string) {
269
247
  const [isLoading, setIsLoading] = useState(false);
@@ -351,10 +329,25 @@ function FileManager() {
351
329
  }
352
330
  ```
353
331
 
332
+ ## Real-World Use Cases
333
+
334
+ Wolfronix can be integrated into **any application** that handles sensitive data:
335
+
336
+ | Industry | Application | How Wolfronix Helps |
337
+ |----------|------------|---------------------|
338
+ | 🏥 **Healthcare** | Patient records, lab reports | HIPAA-compliant encryption at rest |
339
+ | 🏦 **Finance** | Invoices, tax docs, receipts | End-to-end encrypted banking documents |
340
+ | ⚖️ **Legal** | Contracts, case files | Zero-knowledge confidential storage |
341
+ | ☁️ **Cloud Storage** | Drive/Dropbox alternatives | Encrypted file vault with user-owned keys |
342
+ | 🏢 **Enterprise** | HR records, internal docs | Per-employee encryption isolation |
343
+ | 🎓 **Education** | Exam papers, student data | Tamper-proof academic records |
344
+ | 💬 **Messaging** | File attachments | Encrypted file sharing in chat apps |
345
+ | 🛒 **E-commerce** | Order docs, payment receipts | PCI-compliant document storage |
346
+
354
347
  ## Requirements
355
348
 
356
349
  - Node.js 16+ (for Node.js usage)
357
- - Modern browser with Fetch API support
350
+ - Modern browser with Web Crypto API support
358
351
 
359
352
  ## License
360
353
 
package/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@
3
3
  * Zero-knowledge encryption made simple
4
4
  *
5
5
  * @package @wolfronix/sdk
6
- * @version 1.2.0
6
+ * @version 1.3.0
7
7
  */
8
8
  interface WolfronixConfig {
9
9
  /** Wolfronix server base URL */
@@ -25,7 +25,7 @@ interface AuthResponse {
25
25
  }
26
26
  interface EncryptResponse {
27
27
  status: string;
28
- file_id: number;
28
+ file_id: string;
29
29
  file_size: number;
30
30
  enc_time_ms: number;
31
31
  }
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * Zero-knowledge encryption made simple
4
4
  *
5
5
  * @package @wolfronix/sdk
6
- * @version 1.2.0
6
+ * @version 1.3.0
7
7
  */
8
8
  interface WolfronixConfig {
9
9
  /** Wolfronix server base URL */
@@ -25,7 +25,7 @@ interface AuthResponse {
25
25
  }
26
26
  interface EncryptResponse {
27
27
  status: string;
28
- file_id: number;
28
+ file_id: string;
29
29
  file_size: number;
30
30
  enc_time_ms: number;
31
31
  }
package/dist/index.js CHANGED
@@ -33,6 +33,14 @@ __export(index_exports, {
33
33
  module.exports = __toCommonJS(index_exports);
34
34
 
35
35
  // src/crypto.ts
36
+ var getCrypto = () => {
37
+ if (typeof globalThis.crypto !== "undefined") {
38
+ return globalThis.crypto;
39
+ }
40
+ throw new Error(
41
+ "Web Crypto API not available. Requires a modern browser or Node.js 16+."
42
+ );
43
+ };
36
44
  var RSA_ALG = {
37
45
  name: "RSA-OAEP",
38
46
  modulusLength: 2048,
@@ -42,7 +50,7 @@ var RSA_ALG = {
42
50
  var WRAP_ALG = "AES-GCM";
43
51
  var PBKDF2_ITERATIONS = 1e5;
44
52
  async function generateKeyPair() {
45
- return await window.crypto.subtle.generateKey(
53
+ return await getCrypto().subtle.generateKey(
46
54
  RSA_ALG,
47
55
  true,
48
56
  // extractable
@@ -51,7 +59,7 @@ async function generateKeyPair() {
51
59
  }
52
60
  async function exportKeyToPEM(key, type) {
53
61
  const format = type === "public" ? "spki" : "pkcs8";
54
- const exported = await window.crypto.subtle.exportKey(format, key);
62
+ const exported = await getCrypto().subtle.exportKey(format, key);
55
63
  const exportedAsBase64 = arrayBufferToBase64(exported);
56
64
  const pemHeader = type === "public" ? "-----BEGIN PUBLIC KEY-----" : "-----BEGIN PRIVATE KEY-----";
57
65
  const pemFooter = type === "public" ? "-----END PUBLIC KEY-----" : "-----END PRIVATE KEY-----";
@@ -66,7 +74,7 @@ async function importKeyFromPEM(pem, type) {
66
74
  const binaryDer = base64ToArrayBuffer(pemContents);
67
75
  const format = type === "public" ? "spki" : "pkcs8";
68
76
  const usage = type === "public" ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"];
69
- return await window.crypto.subtle.importKey(
77
+ return await getCrypto().subtle.importKey(
70
78
  format,
71
79
  binaryDer,
72
80
  RSA_ALG,
@@ -76,7 +84,7 @@ async function importKeyFromPEM(pem, type) {
76
84
  }
77
85
  async function deriveWrappingKey(password, saltHex) {
78
86
  const enc = new TextEncoder();
79
- const passwordKey = await window.crypto.subtle.importKey(
87
+ const passwordKey = await getCrypto().subtle.importKey(
80
88
  "raw",
81
89
  enc.encode(password),
82
90
  "PBKDF2",
@@ -84,7 +92,7 @@ async function deriveWrappingKey(password, saltHex) {
84
92
  ["deriveKey"]
85
93
  );
86
94
  const salt = hexToArrayBuffer(saltHex);
87
- return await window.crypto.subtle.deriveKey(
95
+ return await getCrypto().subtle.deriveKey(
88
96
  {
89
97
  name: "PBKDF2",
90
98
  salt,
@@ -98,12 +106,13 @@ async function deriveWrappingKey(password, saltHex) {
98
106
  );
99
107
  }
100
108
  async function wrapPrivateKey(privateKey, password) {
101
- const salt = window.crypto.getRandomValues(new Uint8Array(16));
109
+ const crypto = getCrypto();
110
+ const salt = crypto.getRandomValues(new Uint8Array(16));
102
111
  const saltHex = arrayBufferToHex(salt.buffer);
103
112
  const wrappingKey = await deriveWrappingKey(password, saltHex);
104
- const exportedKey = await window.crypto.subtle.exportKey("pkcs8", privateKey);
105
- const iv = window.crypto.getRandomValues(new Uint8Array(12));
106
- const encryptedContent = await window.crypto.subtle.encrypt(
113
+ const exportedKey = await crypto.subtle.exportKey("pkcs8", privateKey);
114
+ const iv = crypto.getRandomValues(new Uint8Array(12));
115
+ const encryptedContent = await crypto.subtle.encrypt(
107
116
  {
108
117
  name: WRAP_ALG,
109
118
  iv
@@ -125,7 +134,7 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
125
134
  const iv = combinedArray.slice(0, 12);
126
135
  const data = combinedArray.slice(12);
127
136
  const wrappingKey = await deriveWrappingKey(password, saltHex);
128
- const decryptedKeyData = await window.crypto.subtle.decrypt(
137
+ const decryptedKeyData = await getCrypto().subtle.decrypt(
129
138
  {
130
139
  name: WRAP_ALG,
131
140
  iv
@@ -133,7 +142,7 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
133
142
  wrappingKey,
134
143
  data
135
144
  );
136
- return await window.crypto.subtle.importKey(
145
+ return await getCrypto().subtle.importKey(
137
146
  "pkcs8",
138
147
  decryptedKeyData,
139
148
  RSA_ALG,
@@ -142,16 +151,23 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
142
151
  );
143
152
  }
144
153
  function arrayBufferToBase64(buffer) {
145
- let binary = "";
146
154
  const bytes = new Uint8Array(buffer);
155
+ if (typeof Buffer !== "undefined") {
156
+ return Buffer.from(bytes).toString("base64");
157
+ }
158
+ let binary = "";
147
159
  const len = bytes.byteLength;
148
160
  for (let i = 0; i < len; i++) {
149
161
  binary += String.fromCharCode(bytes[i]);
150
162
  }
151
- return window.btoa(binary);
163
+ return btoa(binary);
152
164
  }
153
165
  function base64ToArrayBuffer(base64) {
154
- const binary_string = window.atob(base64);
166
+ if (typeof Buffer !== "undefined") {
167
+ const buf = Buffer.from(base64, "base64");
168
+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
169
+ }
170
+ const binary_string = atob(base64);
155
171
  const len = binary_string.length;
156
172
  const bytes = new Uint8Array(len);
157
173
  for (let i = 0; i < len; i++) {
@@ -492,9 +508,15 @@ var Wolfronix = class {
492
508
  throw new Error("Public key not available. Is user logged in?");
493
509
  }
494
510
  formData.append("client_public_key", this.publicKeyPEM);
495
- return this.request("POST", "/api/v1/encrypt", {
511
+ const response = await this.request("POST", "/api/v1/encrypt", {
496
512
  formData
497
513
  });
514
+ return {
515
+ status: response.status,
516
+ file_id: String(response.file_id),
517
+ file_size: response.file_size,
518
+ enc_time_ms: response.enc_time_ms
519
+ };
498
520
  }
499
521
  /**
500
522
  * Decrypt and retrieve a file
package/dist/index.mjs CHANGED
@@ -1,4 +1,12 @@
1
1
  // src/crypto.ts
2
+ var getCrypto = () => {
3
+ if (typeof globalThis.crypto !== "undefined") {
4
+ return globalThis.crypto;
5
+ }
6
+ throw new Error(
7
+ "Web Crypto API not available. Requires a modern browser or Node.js 16+."
8
+ );
9
+ };
2
10
  var RSA_ALG = {
3
11
  name: "RSA-OAEP",
4
12
  modulusLength: 2048,
@@ -8,7 +16,7 @@ var RSA_ALG = {
8
16
  var WRAP_ALG = "AES-GCM";
9
17
  var PBKDF2_ITERATIONS = 1e5;
10
18
  async function generateKeyPair() {
11
- return await window.crypto.subtle.generateKey(
19
+ return await getCrypto().subtle.generateKey(
12
20
  RSA_ALG,
13
21
  true,
14
22
  // extractable
@@ -17,7 +25,7 @@ async function generateKeyPair() {
17
25
  }
18
26
  async function exportKeyToPEM(key, type) {
19
27
  const format = type === "public" ? "spki" : "pkcs8";
20
- const exported = await window.crypto.subtle.exportKey(format, key);
28
+ const exported = await getCrypto().subtle.exportKey(format, key);
21
29
  const exportedAsBase64 = arrayBufferToBase64(exported);
22
30
  const pemHeader = type === "public" ? "-----BEGIN PUBLIC KEY-----" : "-----BEGIN PRIVATE KEY-----";
23
31
  const pemFooter = type === "public" ? "-----END PUBLIC KEY-----" : "-----END PRIVATE KEY-----";
@@ -32,7 +40,7 @@ async function importKeyFromPEM(pem, type) {
32
40
  const binaryDer = base64ToArrayBuffer(pemContents);
33
41
  const format = type === "public" ? "spki" : "pkcs8";
34
42
  const usage = type === "public" ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"];
35
- return await window.crypto.subtle.importKey(
43
+ return await getCrypto().subtle.importKey(
36
44
  format,
37
45
  binaryDer,
38
46
  RSA_ALG,
@@ -42,7 +50,7 @@ async function importKeyFromPEM(pem, type) {
42
50
  }
43
51
  async function deriveWrappingKey(password, saltHex) {
44
52
  const enc = new TextEncoder();
45
- const passwordKey = await window.crypto.subtle.importKey(
53
+ const passwordKey = await getCrypto().subtle.importKey(
46
54
  "raw",
47
55
  enc.encode(password),
48
56
  "PBKDF2",
@@ -50,7 +58,7 @@ async function deriveWrappingKey(password, saltHex) {
50
58
  ["deriveKey"]
51
59
  );
52
60
  const salt = hexToArrayBuffer(saltHex);
53
- return await window.crypto.subtle.deriveKey(
61
+ return await getCrypto().subtle.deriveKey(
54
62
  {
55
63
  name: "PBKDF2",
56
64
  salt,
@@ -64,12 +72,13 @@ async function deriveWrappingKey(password, saltHex) {
64
72
  );
65
73
  }
66
74
  async function wrapPrivateKey(privateKey, password) {
67
- const salt = window.crypto.getRandomValues(new Uint8Array(16));
75
+ const crypto = getCrypto();
76
+ const salt = crypto.getRandomValues(new Uint8Array(16));
68
77
  const saltHex = arrayBufferToHex(salt.buffer);
69
78
  const wrappingKey = await deriveWrappingKey(password, saltHex);
70
- const exportedKey = await window.crypto.subtle.exportKey("pkcs8", privateKey);
71
- const iv = window.crypto.getRandomValues(new Uint8Array(12));
72
- const encryptedContent = await window.crypto.subtle.encrypt(
79
+ const exportedKey = await crypto.subtle.exportKey("pkcs8", privateKey);
80
+ const iv = crypto.getRandomValues(new Uint8Array(12));
81
+ const encryptedContent = await crypto.subtle.encrypt(
73
82
  {
74
83
  name: WRAP_ALG,
75
84
  iv
@@ -91,7 +100,7 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
91
100
  const iv = combinedArray.slice(0, 12);
92
101
  const data = combinedArray.slice(12);
93
102
  const wrappingKey = await deriveWrappingKey(password, saltHex);
94
- const decryptedKeyData = await window.crypto.subtle.decrypt(
103
+ const decryptedKeyData = await getCrypto().subtle.decrypt(
95
104
  {
96
105
  name: WRAP_ALG,
97
106
  iv
@@ -99,7 +108,7 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
99
108
  wrappingKey,
100
109
  data
101
110
  );
102
- return await window.crypto.subtle.importKey(
111
+ return await getCrypto().subtle.importKey(
103
112
  "pkcs8",
104
113
  decryptedKeyData,
105
114
  RSA_ALG,
@@ -108,16 +117,23 @@ async function unwrapPrivateKey(encryptedKeyBase64, password, saltHex) {
108
117
  );
109
118
  }
110
119
  function arrayBufferToBase64(buffer) {
111
- let binary = "";
112
120
  const bytes = new Uint8Array(buffer);
121
+ if (typeof Buffer !== "undefined") {
122
+ return Buffer.from(bytes).toString("base64");
123
+ }
124
+ let binary = "";
113
125
  const len = bytes.byteLength;
114
126
  for (let i = 0; i < len; i++) {
115
127
  binary += String.fromCharCode(bytes[i]);
116
128
  }
117
- return window.btoa(binary);
129
+ return btoa(binary);
118
130
  }
119
131
  function base64ToArrayBuffer(base64) {
120
- const binary_string = window.atob(base64);
132
+ if (typeof Buffer !== "undefined") {
133
+ const buf = Buffer.from(base64, "base64");
134
+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
135
+ }
136
+ const binary_string = atob(base64);
121
137
  const len = binary_string.length;
122
138
  const bytes = new Uint8Array(len);
123
139
  for (let i = 0; i < len; i++) {
@@ -458,9 +474,15 @@ var Wolfronix = class {
458
474
  throw new Error("Public key not available. Is user logged in?");
459
475
  }
460
476
  formData.append("client_public_key", this.publicKeyPEM);
461
- return this.request("POST", "/api/v1/encrypt", {
477
+ const response = await this.request("POST", "/api/v1/encrypt", {
462
478
  formData
463
479
  });
480
+ return {
481
+ status: response.status,
482
+ file_id: String(response.file_id),
483
+ file_size: response.file_size,
484
+ enc_time_ms: response.enc_time_ms
485
+ };
464
486
  }
465
487
  /**
466
488
  * Decrypt and retrieve a file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wolfronix-sdk",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Official Wolfronix SDK for JavaScript/TypeScript - Zero-knowledge encryption made simple",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",