@meistrari/vault-sdk 3.2.0 → 3.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,6 +1,8 @@
1
1
  # Vault SDK
2
2
 
3
- TypeScript SDK for interacting with the Vault file storage service. Provides file upload, download, streaming, hierarchy management, permalinks, and vault reference utilities.
3
+ TypeScript SDK for interacting with the Vault file storage service. It supports file upload, download, streaming uploads, file hierarchies, public assets, permalinks, and vault reference utilities.
4
+
5
+ Use the SDK when an application needs to store private files in Vault, publish stable public asset URLs such as avatars or logos, or keep durable `vault://` references instead of temporary presigned URLs.
4
6
 
5
7
  ## Installation
6
8
 
@@ -8,502 +10,30 @@ TypeScript SDK for interacting with the Vault file storage service. Provides fil
8
10
  bun add @meistrari/vault-sdk
9
11
  ```
10
12
 
11
- ## Table of Contents
12
-
13
- - [Core Concepts](#core-concepts)
14
- - [Quick Start](#quick-start)
15
- - [Authentication Strategies](#authentication-strategies)
16
- - [API Reference](#api-reference)
17
- - [VaultFile](#vaultfile)
18
- - [Vault Client](#vault-client)
19
- - [Permalinks](#permalinks)
20
- - [File Hierarchies](#file-hierarchies)
21
- - [Vault Reference Utilities](#vault-reference-utilities)
22
- - [Advanced Usage](#advanced-usage)
23
-
24
- ## Core Concepts
25
-
26
- The SDK revolves around two main components:
27
-
28
- 1. **VaultFile** - The primary class for interacting with files in the vault
29
- 2. **Vault Client** - A helper function (`vaultClient`) that simplifies creating VaultFile instances with shared configuration
30
-
31
- Files in the vault are identified by vault references in the format `vault://{fileId}`.
32
-
33
13
  ## Quick Start
34
14
 
35
- ```ts
36
- import { VaultFile, DataTokenAuthStrategy } from '@meistrari/vault-sdk'
37
-
38
- const config = {
39
- vaultUrl: 'https://vault.tela.com',
40
- authStrategy: new DataTokenAuthStrategy('[your-data-token]')
41
- }
42
-
43
- // Upload a new file
44
- const file = new File(['Hello World'], 'hello.txt')
45
- const vaultFile = await VaultFile.fromContent({
46
- name: 'hello.txt',
47
- content: file,
48
- config,
49
- upload: true
50
- })
51
-
52
- // Get the vault reference to store in your database
53
- const reference = vaultFile.getVaultReference() // 'vault://abc123...'
54
-
55
- // Later, retrieve and download the file
56
- const retrieved = await VaultFile.fromVaultReference({
57
- reference,
58
- config
59
- })
60
- const content = await retrieved.download() // Returns a Blob
61
- ```
62
-
63
- ## Authentication Strategies
64
-
65
- The SDK provides two authentication strategies:
66
-
67
- ### DataTokenAuthStrategy
68
-
69
- Used for internal calls to the vault service. Passes the data token as the `x-data-token` header.
70
-
71
- ```ts
72
- import { DataTokenAuthStrategy } from '@meistrari/vault-sdk'
73
-
74
- const authStrategy = new DataTokenAuthStrategy('[your-data-token]')
75
- ```
76
-
77
- ### APIKeyAuthStrategy
78
-
79
- Used for external calls **through the API Gateway**. Passes the API key as the `Authorization` header.
80
-
81
- > [!WARNING]
82
- > The vault service itself does not support API Keys directly. When using this strategy, requests **must** go through the API Gateway.
83
- >
84
- > ✅ Use: `https://staging.api.tela.com/_services/vault`
85
- > ❌ Not: `https://staging.vault.tela.com`
86
-
87
- ```ts
88
- import { APIKeyAuthStrategy } from '@meistrari/vault-sdk'
89
-
90
- const authStrategy = new APIKeyAuthStrategy('[your-api-key]')
91
- ```
92
-
93
- ## API Reference
94
-
95
- ### VaultFile
96
-
97
- The main class for interacting with vault files.
98
-
99
- #### Static Methods
100
-
101
- ##### `VaultFile.fromContent(params, options?)`
102
-
103
- Creates a new VaultFile from content (File or Blob).
104
-
105
- ```ts
106
- const vaultFile = await VaultFile.fromContent({
107
- name: 'document.txt',
108
- content: new File(['content'], 'document.txt'),
109
- config: {
110
- vaultUrl,
111
- authStrategy
112
- },
113
- upload: false // Set to true to upload immediately
114
- }, { signal: abortSignal }) // Optional abort signal
115
- ```
116
-
117
- ##### `VaultFile.fromVaultReference(params, options?)`
118
-
119
- Creates a VaultFile instance from an existing vault reference.
120
-
121
- ```ts
122
- const vaultFile = await VaultFile.fromVaultReference({
123
- reference: 'vault://abc123...',
124
- config: {
125
- vaultUrl,
126
- authStrategy
127
- },
128
- download: false // Set to true to download immediately
129
- }, { signal: abortSignal }) // Optional abort signal
130
- ```
131
-
132
- ##### `VaultFile.fromStream(params, options?)`
133
-
134
- Creates a VaultFile for streaming upload workflows. Useful for large files to avoid loading the entire file into memory.
135
-
136
- ```ts
137
- const vaultFile = await VaultFile.fromStream({
138
- name: 'large-video.mp4',
139
- contentLength: 100 * 1024 * 1024, // 100MB
140
- contentType: 'video/mp4',
141
- config: { vaultUrl, authStrategy }
142
- }, { signal: abortSignal })
143
-
144
- // Upload using a stream
145
- const stream = file.stream()
146
- await vaultFile.uploadStream(stream, {
147
- contentLength: file.size,
148
- contentType: file.type
149
- })
150
- ```
151
-
152
- #### Instance Methods
153
-
154
- ##### `upload(file?, url?, options?)`
155
-
156
- Uploads the file to the vault. If no file is provided, uses the content from the VaultFile instance.
157
-
158
- ```ts
159
- await vaultFile.upload() // Uses vaultFile.content
160
- // or
161
- await vaultFile.upload(someBlob) // Upload specific blob
162
- ```
163
-
164
- ##### `uploadStream(stream, options)`
165
-
166
- Uploads a file using a ReadableStream for memory-efficient processing of large files.
167
-
168
- ```ts
169
- const stream = file.stream()
170
- await vaultFile.uploadStream(stream, {
171
- contentLength: file.size,
172
- contentType: 'video/mp4'
173
- })
174
- ```
175
-
176
- ##### `download(responseType?, options?)`
177
-
178
- Downloads the file content from the vault.
179
-
180
- ```ts
181
- const blob = await vaultFile.download() // Returns Blob
182
- const base64 = await vaultFile.download('base64') // Returns base64 string
183
- ```
184
-
185
- ##### `downloadStream(options?)`
186
-
187
- Downloads the file as a ReadableStream for memory-efficient processing.
188
-
189
- ```ts
190
- const stream = await vaultFile.downloadStream()
191
- const reader = stream.getReader()
192
-
193
- while (true) {
194
- const { done, value } = await reader.read()
195
- if (done)
196
- break
197
- console.log('Chunk size:', value.length)
198
- }
199
- ```
200
-
201
- ##### `getVaultReference()`
202
-
203
- Returns the vault reference string for this file.
204
-
205
- ```ts
206
- const reference = vaultFile.getVaultReference() // 'vault://abc123...'
207
- ```
208
-
209
- ##### `getFileMetadata(options?)`
210
-
211
- Fetches the file's metadata from the vault.
212
-
213
- ```ts
214
- const metadata = await vaultFile.getFileMetadata()
215
- // Returns FileMetadata with properties like originalFileName, mimeType, size, etc.
216
- ```
217
-
218
- ##### `populateMetadata(options?)`
219
-
220
- Populates the file instance's metadata by fetching it from the vault.
221
-
222
- ```ts
223
- await vaultFile.populateMetadata()
224
- console.log(vaultFile.metadata)
225
- ```
226
-
227
- ##### `getUploadUrl(options?)`
228
-
229
- Gets a pre-signed upload URL for the file.
230
-
231
- ```ts
232
- const uploadUrl = await vaultFile.getUploadUrl({ expiresIn: 3600 }) // 1 hour
233
- ```
234
-
235
- ##### `getDownloadUrl(options?)`
236
-
237
- Gets a pre-signed download URL for the file.
238
-
239
- ```ts
240
- const downloadUrl = await vaultFile.getDownloadUrl({ expiresIn: 3600 }) // 1 hour
241
- ```
242
-
243
- ##### `delete(options?)`
244
-
245
- Deletes the file from the vault.
246
-
247
- ```ts
248
- await vaultFile.delete()
249
- ```
250
-
251
- ##### `createPermalink(params?, options?)`
252
-
253
- Creates a permalink for the file. Requires workspace ID to be set in metadata.
254
-
255
- ```ts
256
- await vaultFile.populateMetadata() // Ensure metadata is loaded
257
- const permalink = await vaultFile.createPermalink({ expiresIn: 86400 }) // 24 hours
258
- console.log(permalink.url) // Public URL
259
- ```
260
-
261
- ##### `getPermalinks(options?)`
262
-
263
- Gets all valid permalinks for the file.
264
-
265
- ```ts
266
- const permalinks = await vaultFile.getPermalinks()
267
- for (const permalink of permalinks) {
268
- console.log(permalink.url, permalink.expiresAt)
269
- }
270
- ```
271
-
272
- ### Vault Client
273
-
274
- The `vaultClient` helper simplifies working with multiple files using shared configuration.
275
-
276
15
  ```ts
277
16
  import { vaultClient, DataTokenAuthStrategy } from '@meistrari/vault-sdk'
278
17
 
279
18
  const client = vaultClient({
280
19
  vaultUrl: 'https://vault.tela.com',
281
- authStrategy: new DataTokenAuthStrategy('[your-data-token]')
20
+ authStrategy: new DataTokenAuthStrategy('[your-data-token]'),
282
21
  })
283
22
 
284
- // Create from content
285
23
  const vaultFile = await client.createFromContent(
286
- 'document.txt',
287
- new File(['content'], 'document.txt')
24
+ new File(['Hello World'], 'hello.txt'),
25
+ { upload: true },
288
26
  )
289
27
 
290
- // Create from reference
291
- const retrieved = await client.createFromReference('vault://abc123...')
292
-
293
- // Create from stream
294
- const streamFile = await client.createFromStream(
295
- 'video.mp4',
296
- 100 * 1024 * 1024, // 100MB
297
- { contentType: 'video/mp4' }
298
- )
28
+ console.log(vaultFile.getVaultReference())
299
29
  ```
300
30
 
301
- ### Permalinks
302
-
303
- Permalinks are public, optionally time-limited URLs for files.
304
-
305
- #### `Permalink.create(config, params, options?)`
306
-
307
- Creates a new permalink.
308
-
309
- ```ts
310
- import { Permalink } from '@meistrari/vault-sdk'
311
-
312
- const permalink = await Permalink.create(config, {
313
- fileId: 'abc123...',
314
- workspaceId: 'workspace-id',
315
- expiresIn: 86400 // 24 hours (optional)
316
- })
317
-
318
- console.log(permalink.url)
319
- ```
320
-
321
- #### `Permalink.fromId(config, id)`
322
-
323
- Retrieves a permalink by its ID.
324
-
325
- ```ts
326
- const permalink = await Permalink.fromId(config, 'permalink-id')
327
- ```
328
-
329
- #### `permalink.delete(options?)`
330
-
331
- Deletes the permalink.
332
-
333
- ```ts
334
- await permalink.delete()
335
- ```
336
-
337
- ## File Hierarchies
338
-
339
- Files can be organized into parent-child relationships. See the [File Hierarchy Guide](docs/guides/file-hierarchy.md) for full details, patterns, and best practices.
340
-
341
- ```ts
342
- // Create a child file
343
- const child = await parentFile.createChildFromContent({
344
- name: 'page-1.png',
345
- content: imageBlob,
346
- })
347
-
348
- // List children
349
- const children = await parentFile.getChildren()
350
-
351
- // Iterate children with auto-pagination
352
- for await (const child of parentFile.iterateChildren()) {
353
- console.log(child.name)
354
- }
355
- ```
31
+ For a more detailed usage guide, see the [SDK guides](docs/guides/README.md).
356
32
 
357
- Options for handling edge cases:
33
+ ## Guides
358
34
 
359
- - `onMissingParent`: `'error'` (default) or `'create-as-root'`
360
- - `onParentConflict`: `'error'` (default), `'update-parent-id'`, or `'ignore'`
35
+ - [SDK Guides](docs/guides/README.md)
361
36
 
362
- ## Vault Reference Utilities
37
+ ## Main Exports
363
38
 
364
- Utilities for working with `vault://` URIs and S3 presigned URLs.
365
-
366
- ```ts
367
- import {
368
- isVaultReference,
369
- extractVaultReferences,
370
- isS3UrlExpired,
371
- convertS3UrlToVaultReference,
372
- extractVaultFileIdFromS3Url,
373
- } from '@meistrari/vault-sdk'
374
-
375
- isVaultReference('vault://abc-123') // true
376
- extractVaultReferences('See vault://a and vault://b') // ['vault://a', 'vault://b']
377
- isS3UrlExpired(presignedUrl) // boolean
378
- convertS3UrlToVaultReference(s3Url) // 'vault://...'
379
- ```
380
-
381
- ## Advanced Usage
382
-
383
- ### Complete Workflow Example
384
-
385
- ```ts
386
- import { VaultFile, DataTokenAuthStrategy } from '@meistrari/vault-sdk'
387
-
388
- const config = {
389
- vaultUrl: 'https://vault.tela.com',
390
- authStrategy: new DataTokenAuthStrategy('[your-data-token]')
391
- }
392
-
393
- // 1. Create and upload a file
394
- const file = new File(['content'], 'document.txt')
395
- const vaultFile = await VaultFile.fromContent({
396
- name: 'document.txt',
397
- content: file,
398
- config,
399
- upload: true
400
- })
401
-
402
- // 2. Store the reference in your database
403
- const reference = vaultFile.getVaultReference()
404
- await db.saveDocument({ vaultReference: reference })
405
-
406
- // 3. Later, retrieve the file
407
- const doc = await db.getDocument()
408
- const retrieved = await VaultFile.fromVaultReference({
409
- reference: doc.vaultReference,
410
- config,
411
- download: true
412
- })
413
-
414
- // 4. Use the content
415
- const blob = retrieved.content // Already downloaded
416
- console.log('File size:', blob.size)
417
- ```
418
-
419
- ### Streaming Large Files
420
-
421
- ```ts
422
- // Upload a large file efficiently
423
- const vaultFile = await VaultFile.fromStream({
424
- name: 'large-file.bin',
425
- contentLength: largeFile.size,
426
- contentType: largeFile.type,
427
- config
428
- })
429
-
430
- await vaultFile.uploadStream(largeFile.stream(), {
431
- contentLength: largeFile.size,
432
- contentType: largeFile.type
433
- })
434
-
435
- // Download a large file efficiently
436
- const stream = await vaultFile.downloadStream()
437
- // Process stream in chunks without loading entire file
438
- ```
439
-
440
- ### Abort Requests
441
-
442
- All methods that make network requests support AbortSignal for request cancellation:
443
-
444
- ```ts
445
- const controller = new AbortController()
446
-
447
- // Cancel after 5 seconds
448
- setTimeout(() => controller.abort(), 5000)
449
-
450
- try {
451
- const vaultFile = await VaultFile.fromContent({
452
- name: 'document.txt',
453
- content: file,
454
- config
455
- }, { signal: controller.signal })
456
-
457
- // Upload with abort signal
458
- await vaultFile.upload(undefined, undefined, { signal: controller.signal })
459
-
460
- console.log('Upload successful')
461
- }
462
- catch (error) {
463
- if (error.name === 'AbortError') {
464
- console.log('Upload was cancelled')
465
- }
466
- else {
467
- throw error
468
- }
469
- }
470
- ```
471
-
472
- You can also cancel downloads and other operations:
473
-
474
- ```ts
475
- const controller = new AbortController()
476
-
477
- // Start download
478
- const downloadPromise = vaultFile.download('blob', { signal: controller.signal })
479
-
480
- // Cancel if user clicks a button
481
- cancelButton.addEventListener('click', () => controller.abort())
482
-
483
- try {
484
- const blob = await downloadPromise
485
- console.log('Download complete:', blob.size)
486
- }
487
- catch (error) {
488
- if (error.name === 'AbortError') {
489
- console.log('Download cancelled by user')
490
- }
491
- }
492
- ```
493
-
494
- ### Working with Metadata
495
-
496
- ```ts
497
- const vaultFile = await VaultFile.fromVaultReference({
498
- reference: 'vault://abc123...',
499
- config
500
- })
501
-
502
- // Load metadata
503
- await vaultFile.populateMetadata()
504
-
505
- console.log(vaultFile.metadata.originalFileName)
506
- console.log(vaultFile.metadata.mimeType)
507
- console.log(vaultFile.metadata.size)
508
- console.log(vaultFile.metadata.workspaceId)
509
- ```
39
+ The package exports `vaultClient`, `VaultFile`, `VaultAsset`, `Permalink`, `DataTokenAuthStrategy`, `APIKeyAuthStrategy`, and vault reference utility functions.