vault-sdk-prod 1.0.0 → 2.2.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 +343 -87
- package/package.json +9 -6
- package/src/Vault.js +2357 -535
- package/src/utils/file.js +270 -0
- package/src/utils/sanitizeFileName.js +67 -0
- package/src/utils/validationError.js +85 -7
package/README.md
CHANGED
|
@@ -5,13 +5,13 @@ A lightweight Node.js SDK for the Vault service. Upload, organize, and manage fi
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install vault-sdk-
|
|
8
|
+
npm install vault-sdk-prod
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```javascript
|
|
14
|
-
import Vault from "vault-sdk-
|
|
14
|
+
import Vault from "vault-sdk-prod";
|
|
15
15
|
|
|
16
16
|
const vault = new Vault({
|
|
17
17
|
VAULT_ACCESS_KEY: "your-access-key",
|
|
@@ -22,81 +22,65 @@ const vault = new Vault({
|
|
|
22
22
|
});
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
Only the first four are required. The SDK will throw a clear error listing any missing ones.
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
### File Upload
|
|
27
|
+
`VAULT_BASE_URL` and `VAULT_WS_URL` must be `https://` / `wss://`. An unencrypted URL is refused with `INSECURE_TRANSPORT`, because it would send your keys, signatures and file contents in the clear. Local addresses (`localhost`, `127.0.0.1`) are exempt, and `VAULT_ALLOW_INSECURE: true` lifts the rule for a test server you control.
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Upload a single file to the vault. This method is a convenience wrapper for the full secure upload flow used by the SDK:
|
|
29
|
+
Your keys are held as non-enumerable properties, so `console.log(vault)` and `JSON.stringify(vault)` print `[redacted]` rather than the secret.
|
|
34
30
|
|
|
35
|
-
|
|
36
|
-
2. Call `getPresignedUrl(...)` to generate a temporary S3 upload URL.
|
|
37
|
-
3. Upload the file data directly to the presigned URL.
|
|
38
|
-
4. Call `registerUpload(...)` to register the file metadata in Vault.
|
|
31
|
+
These optional settings control uploads:
|
|
39
32
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
| Option | Default | What it does |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| `VAULT_ALLOW_INSECURE` | `false` | Allow `http://` / `ws://` to a non-local host |
|
|
36
|
+
| `VAULT_UPLOAD_ROOT` | the working directory | Paths passed to `uploadFile()` must resolve inside this directory |
|
|
37
|
+
| `VAULT_UPLOAD_HOSTS` | Filebase storage + your API host | Extra hosts the SDK may upload files to |
|
|
38
|
+
| `VAULT_TIMEOUT` | `30000` | Timeout in ms for API requests |
|
|
39
|
+
| `VAULT_UPLOAD_TIMEOUT` | scaled to the file size | Timeout in ms for one file upload |
|
|
40
|
+
| `VAULT_UPLOAD_CONCURRENCY` | `3` | How many files upload at once in the batch methods |
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
const fileHash = crypto.createHash("sha256").update(fileBuffer).digest("hex");
|
|
46
|
-
|
|
47
|
-
// Step 1 & 2: Request a presigned URL from the Vault API
|
|
48
|
-
const presigned = await vault.getPresignedUrl({
|
|
49
|
-
vaultId: "your-vault-id",
|
|
50
|
-
fileName: "photo.jpg",
|
|
51
|
-
fileType: "image/jpeg",
|
|
52
|
-
fileSize: fileBuffer.length,
|
|
53
|
-
contentHash: fileHash,
|
|
54
|
-
folderId: undefined, // optional
|
|
55
|
-
});
|
|
42
|
+
## API Reference
|
|
56
43
|
|
|
57
|
-
|
|
58
|
-
await axios.put(presigned.url, fileBuffer, {
|
|
59
|
-
headers: {
|
|
60
|
-
"Content-Type": presigned.contentType || "application/octet-stream",
|
|
61
|
-
},
|
|
62
|
-
});
|
|
44
|
+
### File Upload
|
|
63
45
|
|
|
64
|
-
|
|
65
|
-
const result = await vault.registerUpload({
|
|
66
|
-
vaultId: "your-vault-id",
|
|
67
|
-
fileName: "photo.jpg",
|
|
68
|
-
filebaseKey: presigned.key,
|
|
69
|
-
fileSize: fileBuffer.length,
|
|
70
|
-
contentHash: fileHash,
|
|
71
|
-
folderId: undefined,
|
|
72
|
-
});
|
|
46
|
+
#### `uploadFile(file, vaultId, parentId?)`
|
|
73
47
|
|
|
74
|
-
|
|
48
|
+
Upload a file to the vault. Hand over the file and nothing else — the SDK reads the bytes, sanitizes the name, resolves the MIME type, hashes the content, gets a presigned storage URL, uploads, and registers the file, all in this one call.
|
|
75
49
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"your-vault-id"
|
|
80
|
-
);
|
|
50
|
+
```javascript
|
|
51
|
+
// Straight from disk — name and type come from the file itself
|
|
52
|
+
const result = await vault.uploadFile("./photo.jpg", "your-vault-id");
|
|
81
53
|
|
|
82
54
|
// Upload into a specific folder
|
|
83
|
-
const
|
|
84
|
-
|
|
55
|
+
const inFolder = await vault.uploadFile(
|
|
56
|
+
"./report.pdf",
|
|
85
57
|
"your-vault-id",
|
|
86
58
|
"parent-folder-id"
|
|
87
59
|
);
|
|
88
60
|
```
|
|
89
61
|
|
|
62
|
+
`file` can be any of:
|
|
63
|
+
|
|
64
|
+
| Form | Example |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| Path on disk | `"./photo.jpg"` (must be inside `VAULT_UPLOAD_ROOT`) |
|
|
67
|
+
| Bytes + name | `{ buffer: fileBuffer, name: "report.pdf" }` |
|
|
68
|
+
| Path in an object | `{ path: "./photo.jpg" }` |
|
|
69
|
+
| `File` / `Blob` | `new File([bytes], "photo.jpg", { type: "image/jpeg" })` |
|
|
70
|
+
|
|
71
|
+
`type` (or `mimeType` / `contentType`) is optional — it's derived from the file extension when omitted. Names are sanitized to ASCII before upload, so `héllo wörld🤣.PNG` is stored as `hello world.PNG`.
|
|
72
|
+
|
|
73
|
+
The call throws a `VaultError` if the file can't be read, is empty, exceeds the 10 GB limit, or if any upload step fails — the `code` tells you which step (`FILE_READ_FAILED`, `INVALID_PARAMETER`, `FILE_TOO_LARGE`, `PATH_NOT_ALLOWED`, `PRESIGN_FAILED`, `UPLOAD_URL_REJECTED`, `STORAGE_UPLOAD_FAILED`, `REGISTER_FAILED`).
|
|
74
|
+
|
|
75
|
+
`PATH_NOT_ALLOWED` means the path resolved outside `VAULT_UPLOAD_ROOT`; `UPLOAD_URL_REJECTED` means the server handed back an upload URL that is not HTTPS or not on an allowed storage host, so nothing was sent.
|
|
76
|
+
|
|
90
77
|
#### `uploadFiles(files, vaultId, parentId?)`
|
|
91
78
|
|
|
92
|
-
Upload multiple files
|
|
79
|
+
Upload multiple files, a few at a time (`VAULT_UPLOAD_CONCURRENCY`, 3 by default). Each file is handled independently — one failure won't block the others. Every entry accepts the same forms as `uploadFile()`.
|
|
93
80
|
|
|
94
81
|
```javascript
|
|
95
82
|
const results = await vault.uploadFiles(
|
|
96
|
-
[
|
|
97
|
-
{ buffer: buf1, name: "file1.pdf", type: "application/pdf" },
|
|
98
|
-
{ buffer: buf2, name: "file2.jpg", type: "image/jpeg" },
|
|
99
|
-
],
|
|
83
|
+
["./file1.pdf", { buffer: buf2, name: "file2.jpg" }],
|
|
100
84
|
"your-vault-id"
|
|
101
85
|
);
|
|
102
86
|
|
|
@@ -105,6 +89,8 @@ const results = await vault.uploadFiles(
|
|
|
105
89
|
// { status: "failed", fileName: "file2.jpg", error: "...", code: "..." }
|
|
106
90
|
```
|
|
107
91
|
|
|
92
|
+
Partial failures are reported in the array. If **every** file fails, the call throws a `VaultError` with code `UPLOAD_FAILED` instead, carrying the same per-file results in `error.data.results`.
|
|
93
|
+
|
|
108
94
|
### File Retrieval
|
|
109
95
|
|
|
110
96
|
#### `getFiles(vaultId, query?)`
|
|
@@ -178,6 +164,273 @@ Delete a folder.
|
|
|
178
164
|
await vault.deleteFolder("your-vault-id", "folder-id");
|
|
179
165
|
```
|
|
180
166
|
|
|
167
|
+
### Bot Operations
|
|
168
|
+
|
|
169
|
+
#### `createBot(vaultId, bot)`
|
|
170
|
+
|
|
171
|
+
Create a bot for the vault. This uses the Vault SDK auth flow and creates the bot's dedicated folder automatically.
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
const bot = await vault.createBot("your-vault-id", {
|
|
175
|
+
name: "Support Bot",
|
|
176
|
+
description: "Answers customer questions clearly",
|
|
177
|
+
profession: "Customer Support",
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`bot` accepts:
|
|
182
|
+
|
|
183
|
+
| Field | Required | Description |
|
|
184
|
+
| --- | --- | --- |
|
|
185
|
+
| `name` | Yes | Bot display name |
|
|
186
|
+
| `description` | No | Bot personality / description |
|
|
187
|
+
| `profession` | No | Profession label for the bot |
|
|
188
|
+
|
|
189
|
+
#### `updateBot(vaultId, botId, updates)`
|
|
190
|
+
|
|
191
|
+
Update a bot through the Vault SDK. You can send any subset of the editable bot fields.
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
const updated = await vault.updateBot("your-vault-id", "bot-id", {
|
|
195
|
+
name: "Support Bot v2",
|
|
196
|
+
description: "Helpful and concise",
|
|
197
|
+
profession: "Customer Support",
|
|
198
|
+
useLLMFallback: true,
|
|
199
|
+
wordLimit: 200,
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
#### `getBotDetails(vaultId, botId?)`
|
|
204
|
+
|
|
205
|
+
Fetch one bot's full details, or all bots with their associated files and folders.
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
const oneBot = await vault.getBotDetails("your-vault-id", "bot-id");
|
|
209
|
+
const allBots = await vault.getBotDetails("your-vault-id");
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
#### `addDriveFilesToBot(vaultId, botId, fileIds)`
|
|
213
|
+
|
|
214
|
+
Attach one or more existing storage files to a bot without re-uploading them. Accepts either a
|
|
215
|
+
single file ID string or an array of file IDs.
|
|
216
|
+
|
|
217
|
+
```javascript
|
|
218
|
+
await vault.addDriveFilesToBot("your-vault-id", "bot-id", "file-id");
|
|
219
|
+
|
|
220
|
+
await vault.addDriveFilesToBot(
|
|
221
|
+
"your-vault-id",
|
|
222
|
+
"bot-id",
|
|
223
|
+
["file-a", "file-b"]
|
|
224
|
+
);
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### `addDriveFoldersToBot(vaultId, botId, folderIds)`
|
|
228
|
+
|
|
229
|
+
Attach one or more existing storage folders to a bot without moving them. Accepts either a
|
|
230
|
+
single folder ID string or an array of folder IDs.
|
|
231
|
+
|
|
232
|
+
```javascript
|
|
233
|
+
await vault.addDriveFoldersToBot("your-vault-id", "bot-id", "folder-id");
|
|
234
|
+
|
|
235
|
+
await vault.addDriveFoldersToBot(
|
|
236
|
+
"your-vault-id",
|
|
237
|
+
"bot-id",
|
|
238
|
+
["folder-a", "folder-b"]
|
|
239
|
+
);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### `uploadFilesToBot(files, vaultId, botId)`
|
|
243
|
+
|
|
244
|
+
Upload one or more files directly to a bot and start ingestion.
|
|
245
|
+
|
|
246
|
+
This method now uses the bot upload flow internally: it gets a presigned URL,
|
|
247
|
+
uploads each file straight to storage, and then registers it with the bot. The
|
|
248
|
+
same method works for both smaller and larger files.
|
|
249
|
+
|
|
250
|
+
```javascript
|
|
251
|
+
await vault.uploadFilesToBot("./faq.pdf", "your-vault-id", "bot-id");
|
|
252
|
+
|
|
253
|
+
await vault.uploadFilesToBot(
|
|
254
|
+
["./faq.pdf", { buffer: audioBuffer, name: "call.mp3" }],
|
|
255
|
+
"your-vault-id",
|
|
256
|
+
"bot-id"
|
|
257
|
+
);
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
#### `quoteTranscription(vaultId, botId, payload)`
|
|
261
|
+
|
|
262
|
+
Quote the Twin Points cost of transcribing media before uploading files or linking folders.
|
|
263
|
+
|
|
264
|
+
```javascript
|
|
265
|
+
const quote = await vault.quoteTranscription("your-vault-id", "bot-id", {
|
|
266
|
+
files: [{ name: "call.mp3", size: 1048576 }],
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const folderQuote = await vault.quoteTranscription("your-vault-id", "bot-id", {
|
|
270
|
+
folderIds: ["folder-a", "folder-b"],
|
|
271
|
+
});
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### `deleteBot(botId, vaultId)`
|
|
275
|
+
|
|
276
|
+
Delete a bot using the same backend behavior as Twin Vault's `DELETE /bots/:botId`.
|
|
277
|
+
|
|
278
|
+
```javascript
|
|
279
|
+
const result = await vault.deleteBot("bot-id", "your-vault-id");
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### `getBotFileText(vaultId, botId, fileId)`
|
|
283
|
+
|
|
284
|
+
Fetch the extracted text content for a bot file through the SDK route.
|
|
285
|
+
|
|
286
|
+
```javascript
|
|
287
|
+
const text = await vault.getBotFileText("your-vault-id", "bot-id", "file-id");
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
#### `cancelBotFile(vaultId, botId, fileId)`
|
|
291
|
+
|
|
292
|
+
Cancel a processing bot file through the SDK route.
|
|
293
|
+
|
|
294
|
+
```javascript
|
|
295
|
+
const result = await vault.cancelBotFile("your-vault-id", "bot-id", "file-id");
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### `retryBotFile(vaultId, botId, fileId)`
|
|
299
|
+
|
|
300
|
+
Retry a failed bot file through the SDK route.
|
|
301
|
+
|
|
302
|
+
```javascript
|
|
303
|
+
const result = await vault.retryBotFile("your-vault-id", "bot-id", "file-id");
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
#### `deleteBotSessions(vaultId, botId, sessionIds)`
|
|
307
|
+
|
|
308
|
+
Delete one or more bot chat sessions through the bulk-delete route.
|
|
309
|
+
|
|
310
|
+
```javascript
|
|
311
|
+
await vault.deleteBotSessions("your-vault-id", "bot-id", "session-id");
|
|
312
|
+
await vault.deleteBotSessions("your-vault-id", "bot-id", ["session-a", "session-b"]);
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
#### `exportBotSessions(vaultId, botId, sessionIds, saveOption, targetBotId?)`
|
|
316
|
+
|
|
317
|
+
Export one or more bot chat sessions through the bulk-export route.
|
|
318
|
+
|
|
319
|
+
```javascript
|
|
320
|
+
await vault.exportBotSessions("your-vault-id", "bot-id", "session-id", "drive");
|
|
321
|
+
await vault.exportBotSessions(
|
|
322
|
+
"your-vault-id",
|
|
323
|
+
"bot-id",
|
|
324
|
+
["session-a", "session-b"],
|
|
325
|
+
"brain",
|
|
326
|
+
"target-bot-id"
|
|
327
|
+
);
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
#### `removeBotAsset(vaultId, botId, assetType, assetId)`
|
|
331
|
+
|
|
332
|
+
Remove either a bot file or a linked storage folder from a bot.
|
|
333
|
+
|
|
334
|
+
```javascript
|
|
335
|
+
await vault.removeBotAsset("your-vault-id", "bot-id", "file", "file-id", {
|
|
336
|
+
permanent: true,
|
|
337
|
+
keepTranscript: false,
|
|
338
|
+
});
|
|
339
|
+
await vault.removeBotAsset("your-vault-id", "bot-id", "folder", "folder-id");
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### `getBotSessions(vaultId, botId, sessionId?)`
|
|
343
|
+
|
|
344
|
+
Fetch all chat sessions for a bot, or fetch all messages for one session.
|
|
345
|
+
|
|
346
|
+
```javascript
|
|
347
|
+
const sessions = await vault.getBotSessions("your-vault-id", "bot-id");
|
|
348
|
+
const messages = await vault.getBotSessions("your-vault-id", "bot-id", "session-id");
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
#### `createVaultLaunchToken(vaultId, options?)`
|
|
352
|
+
|
|
353
|
+
Create a short-lived launch token for the vault user linked to your SDK credentials. This is mainly useful when you want to hand the auth off elsewhere.
|
|
354
|
+
|
|
355
|
+
```javascript
|
|
356
|
+
const launch = await vault.createVaultLaunchToken("your-vault-id");
|
|
357
|
+
const launchToken = launch.data.launchToken;
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
#### `redeemVaultLaunchToken(launchToken)`
|
|
361
|
+
|
|
362
|
+
Exchange a launch token for a normal vault access token.
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
const redeemed = await vault.redeemVaultLaunchToken(launchToken);
|
|
366
|
+
const accessToken = redeemed.data.user.accessToken;
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
#### `connectToBotChat(vaultId, options?)`
|
|
370
|
+
|
|
371
|
+
Open the live bot chat WebSocket. If you do not pass `options.token`, the SDK will create and redeem a launch token automatically, then connect the socket for you.
|
|
372
|
+
|
|
373
|
+
```javascript
|
|
374
|
+
await vault.connectToBotChat("your-vault-id", {
|
|
375
|
+
botId: "bot-id",
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
vault.on("bot_chat_chat_history", (payload) => {
|
|
379
|
+
console.log("history", payload.history);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
let streamed = "";
|
|
383
|
+
vault.on("bot_chat_token", ({ token }) => {
|
|
384
|
+
streamed += token;
|
|
385
|
+
process.stdout.write(token);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
vault.on("bot_chat_message_complete", ({ content, sessionId }) => {
|
|
389
|
+
console.log("\ncomplete", sessionId, content);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
vault.sendBotChatMessage("Hello bot");
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
Bot chat connects through `/ws/bot-chat`, which is intended to stay separate from
|
|
396
|
+
legacy twin chat websocket traffic on `/ws/chat`.
|
|
397
|
+
|
|
398
|
+
You can also pass an existing token:
|
|
399
|
+
|
|
400
|
+
```javascript
|
|
401
|
+
await vault.connectToBotChat("your-vault-id", {
|
|
402
|
+
token: "vault-jwt",
|
|
403
|
+
botId: "bot-id",
|
|
404
|
+
sessionId: "existing-session-id",
|
|
405
|
+
});
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Available helpers:
|
|
409
|
+
|
|
410
|
+
| Method | Purpose |
|
|
411
|
+
| --- | --- |
|
|
412
|
+
| `joinBotChat(botId, sessionId?)` | Join or resume a bot chat |
|
|
413
|
+
| `sendBotChatMessage(message)` | Send a message to the joined bot. The server rebuilds the conversation from the stored session, so a `history` argument is accepted but ignored |
|
|
414
|
+
| `sendBotChatTyping()` | Emit typing state |
|
|
415
|
+
| `disconnectBotChat()` | Close the bot chat socket |
|
|
416
|
+
|
|
417
|
+
Useful emitted events:
|
|
418
|
+
|
|
419
|
+
| Event | Payload |
|
|
420
|
+
| --- | --- |
|
|
421
|
+
| `bot_chat_open` | none |
|
|
422
|
+
| `bot_chat_message` | Raw parsed socket message |
|
|
423
|
+
| `bot_chat_connected` | Server connected payload |
|
|
424
|
+
| `bot_chat_chat_history` | Bot/session/history payload |
|
|
425
|
+
| `bot_chat_session_info` | Session ID payload |
|
|
426
|
+
| `bot_chat_token` | Stream token payload |
|
|
427
|
+
| `bot_chat_message_complete` | Final assistant response payload |
|
|
428
|
+
| `bot_chat_points_update` | Updated points payload |
|
|
429
|
+
| `bot_chat_typing` | Typing payload |
|
|
430
|
+
| `bot_chat_error` | Server-side error payload |
|
|
431
|
+
| `bot_chat_close` | Native close event |
|
|
432
|
+
| `bot_chat_stream_error` | SDK parse/transport error |
|
|
433
|
+
|
|
181
434
|
### Storage & Plans
|
|
182
435
|
|
|
183
436
|
#### `getStorageDetails(vaultId)`
|
|
@@ -236,60 +489,58 @@ Get active subscriptions.
|
|
|
236
489
|
const subs = await vault.getSubscriptions("your-vault-id");
|
|
237
490
|
```
|
|
238
491
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
#### `createPlatformUser(email, platformId?)`
|
|
492
|
+
#### `getWalletInfo(vaultId)`
|
|
242
493
|
|
|
243
|
-
|
|
494
|
+
Get the wallet summary for the authenticated vault user.
|
|
244
495
|
|
|
245
496
|
```javascript
|
|
246
|
-
const
|
|
247
|
-
const sdkUser = await vault.createPlatformUser("user@example.com");
|
|
497
|
+
const wallet = await vault.getWalletInfo("your-vault-id");
|
|
248
498
|
```
|
|
249
499
|
|
|
250
|
-
#### `
|
|
500
|
+
#### `getTransactionHistory(vaultId, query?)`
|
|
251
501
|
|
|
252
|
-
|
|
502
|
+
Get paginated wallet transaction history. You can optionally filter by page, limit, and category.
|
|
503
|
+
|
|
504
|
+
`page` and `limit` must be numbers; anything else is rejected with `INVALID_PARAMETER`. Both are rounded down to whole numbers, `page` starts at 1, and `limit` is clamped to 1-100.
|
|
253
505
|
|
|
254
506
|
```javascript
|
|
255
|
-
const
|
|
256
|
-
|
|
507
|
+
const history = await vault.getTransactionHistory("your-vault-id");
|
|
508
|
+
|
|
509
|
+
const filtered = await vault.getTransactionHistory("your-vault-id", {
|
|
510
|
+
page: 2,
|
|
511
|
+
limit: 10,
|
|
512
|
+
category: "credit",
|
|
513
|
+
});
|
|
257
514
|
```
|
|
258
515
|
|
|
259
|
-
###
|
|
516
|
+
### Vault Operations
|
|
260
517
|
|
|
261
|
-
#### `
|
|
518
|
+
#### `createVault(email, platformId?)`
|
|
262
519
|
|
|
263
|
-
|
|
520
|
+
Create a new SDK user link. `platformId` is optional.
|
|
264
521
|
|
|
265
522
|
```javascript
|
|
266
|
-
const
|
|
523
|
+
const user = await vault.createVault("user@example.com", "platform-id");
|
|
524
|
+
const sdkUser = await vault.createVault("user@example.com");
|
|
267
525
|
```
|
|
268
526
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
#### `connectToWebsocket()`
|
|
527
|
+
#### `importVault(vaultId, platformId?)`
|
|
272
528
|
|
|
273
|
-
|
|
529
|
+
Import an existing vault. When `platformId` is omitted, SDK access is enabled and the client is linked directly to the user.
|
|
274
530
|
|
|
275
531
|
```javascript
|
|
276
|
-
await vault.
|
|
277
|
-
|
|
278
|
-
vault.on("message", (data) => {
|
|
279
|
-
console.log("Received:", data);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
vault.on("stream_error", (error) => {
|
|
283
|
-
console.error("WebSocket error:", error);
|
|
284
|
-
});
|
|
532
|
+
const result = await vault.importVault("vault-id", "platform-id");
|
|
533
|
+
const resultWithoutPlatform = await vault.importVault("vault-id");
|
|
285
534
|
```
|
|
286
535
|
|
|
287
536
|
## Error Handling
|
|
288
537
|
|
|
289
538
|
The SDK provides specific, actionable error messages. All errors include a `code` for programmatic handling.
|
|
290
539
|
|
|
540
|
+
A `VaultError` from the server also carries a `requestId`. Server errors deliberately carry only a message, a code and that id — quote the id when you contact support, and the full detail is in the server's own logs.
|
|
541
|
+
|
|
291
542
|
```javascript
|
|
292
|
-
import Vault, { VaultError, ValidationError } from "vault-sdk-
|
|
543
|
+
import Vault, { VaultError, ValidationError } from "vault-sdk-prod";
|
|
293
544
|
|
|
294
545
|
try {
|
|
295
546
|
await vault.uploadFile(file, vaultId);
|
|
@@ -301,9 +552,10 @@ try {
|
|
|
301
552
|
console.error(error.param); // "vaultId"
|
|
302
553
|
} else if (error instanceof VaultError) {
|
|
303
554
|
// API or network error
|
|
304
|
-
console.error(error.message);
|
|
305
|
-
console.error(error.code);
|
|
306
|
-
console.error(error.status);
|
|
555
|
+
console.error(error.message); // "[Vault SDK] 'uploadFile': Authentication failed..."
|
|
556
|
+
console.error(error.code); // "UNAUTHORIZED"
|
|
557
|
+
console.error(error.status); // 401
|
|
558
|
+
console.error(error.requestId); // "9f1c…" — quote this to support
|
|
307
559
|
}
|
|
308
560
|
}
|
|
309
561
|
```
|
|
@@ -323,6 +575,10 @@ try {
|
|
|
323
575
|
| `RATE_LIMITED` | Too many requests — slow down (429) |
|
|
324
576
|
| `SERVER_ERROR` | Server-side error (500) |
|
|
325
577
|
| `NETWORK_ERROR` | No response — check network/URL |
|
|
578
|
+
| `REQUEST_TIMEOUT` | No reply within `VAULT_TIMEOUT` |
|
|
579
|
+
| `INSECURE_TRANSPORT` | Base or WebSocket URL is not https/wss |
|
|
580
|
+
| `PATH_NOT_ALLOWED` | File path resolved outside `VAULT_UPLOAD_ROOT` |
|
|
581
|
+
| `UPLOAD_URL_REJECTED` | Presign returned an unexpected or unencrypted upload host |
|
|
326
582
|
| `WEBSOCKET_ERROR` | WebSocket connection failed |
|
|
327
583
|
| `STORAGE_UPLOAD_FAILED` | File failed to upload to storage |
|
|
328
584
|
| `PRESIGN_FAILED` | Could not get upload URL |
|
package/package.json
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vault-sdk-prod",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Vault SDK — File storage client for uploading, managing, and organizing files in your vault",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"files": [
|
|
8
|
+
"index.js",
|
|
9
|
+
"src",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
7
12
|
"scripts": {
|
|
8
13
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
14
|
},
|
|
10
15
|
"author": "vDoIT Technologies Ltd, Sector 66, Gurugram, Haryana 122011, India",
|
|
11
16
|
"contributors": [
|
|
12
|
-
"Shreyash Gupta <shreyashgupta125@gmail.com>"
|
|
17
|
+
"Shreyash Gupta <shreyashgupta125@gmail.com>",
|
|
18
|
+
"Pinki Mondal <pinki2021.vdoit@gmail.com>"
|
|
13
19
|
],
|
|
14
20
|
"license": "ISC",
|
|
15
21
|
"dependencies": {
|
|
16
|
-
"axios": "^1.
|
|
22
|
+
"axios": "^1.6.0",
|
|
17
23
|
"ws": "^8.18.0"
|
|
18
24
|
},
|
|
19
|
-
"peerDependencies": {
|
|
20
|
-
"axios": "^1.6.0"
|
|
21
|
-
},
|
|
22
25
|
"keywords": [
|
|
23
26
|
"vault",
|
|
24
27
|
"storage",
|