@meistrari/vault-sdk 1.7.0 → 1.8.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/dist/index.cjs +733 -81
- package/dist/index.d.cts +677 -72
- package/dist/index.d.mts +677 -72
- package/dist/index.d.ts +677 -72
- package/dist/index.mjs +729 -81
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { GetUploadUrlResponseV2, GetDownloadUrlResponse } from '@meistrari/vault-shared/schemas';
|
|
2
2
|
import { fileTypeFromBlob } from '@meistrari/file-type';
|
|
3
3
|
import { lookup } from 'mime-types';
|
|
4
|
+
import vaultUtils from '@meistrari/vault-shared/utils';
|
|
4
5
|
|
|
5
6
|
var __defProp$2 = Object.defineProperty;
|
|
6
7
|
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -180,7 +181,7 @@ async function getFileHash(blob) {
|
|
|
180
181
|
}
|
|
181
182
|
async function detectFileMimeType(blob) {
|
|
182
183
|
if (blob instanceof Blob && blob.type) {
|
|
183
|
-
return blob.type;
|
|
184
|
+
return blob.type.split(";")[0].trim();
|
|
184
185
|
}
|
|
185
186
|
if ("name" in blob && typeof blob.name === "string") {
|
|
186
187
|
const extension = blob.name.split(".").pop()?.toLowerCase();
|
|
@@ -217,9 +218,20 @@ async function detectFileMimeType(blob) {
|
|
|
217
218
|
}
|
|
218
219
|
return void 0;
|
|
219
220
|
}
|
|
221
|
+
function basename(name, separator = "/") {
|
|
222
|
+
if (!name)
|
|
223
|
+
return void 0;
|
|
224
|
+
return name.substring(name.lastIndexOf(separator) + 1);
|
|
225
|
+
}
|
|
226
|
+
function getFileName(content) {
|
|
227
|
+
if ("name" in content && typeof content.name === "string") {
|
|
228
|
+
return basename(content.name);
|
|
229
|
+
}
|
|
230
|
+
return void 0;
|
|
231
|
+
}
|
|
220
232
|
|
|
221
233
|
const name = "@meistrari/vault-sdk";
|
|
222
|
-
const version = "1.
|
|
234
|
+
const version = "1.8.1";
|
|
223
235
|
const license = "UNLICENSED";
|
|
224
236
|
const repository = {
|
|
225
237
|
type: "git",
|
|
@@ -288,9 +300,6 @@ var __publicField = (obj, key, value) => {
|
|
|
288
300
|
return value;
|
|
289
301
|
};
|
|
290
302
|
const compatibilityDate = "2025-05-19";
|
|
291
|
-
function removeVaultPrefix(url) {
|
|
292
|
-
return url.replace("vault://", "");
|
|
293
|
-
}
|
|
294
303
|
function detectMimeTypeFromFilename(filename) {
|
|
295
304
|
const extension = filename.split(".").pop()?.toLowerCase();
|
|
296
305
|
if (extension) {
|
|
@@ -397,6 +406,7 @@ class VaultFile {
|
|
|
397
406
|
* @param metadata - The metadata for creating a file
|
|
398
407
|
* @param metadata.size - The size of the file
|
|
399
408
|
* @param metadata.mimeType - The mime type of the file
|
|
409
|
+
* @param metadata.parentId - The ID of the parent file for hierarchical file relationships
|
|
400
410
|
* @param options - The options for the request
|
|
401
411
|
* @param options.signal - The signal to abort the request
|
|
402
412
|
*
|
|
@@ -409,7 +419,9 @@ class VaultFile {
|
|
|
409
419
|
method: "POST",
|
|
410
420
|
path: `files`,
|
|
411
421
|
body: JSON.stringify({
|
|
412
|
-
|
|
422
|
+
size: metadata.size,
|
|
423
|
+
mimeType: metadata.mimeType,
|
|
424
|
+
parentId: metadata.parentId,
|
|
413
425
|
fileName: this.name,
|
|
414
426
|
sha256sum: this.id ?? this.metadata?.id ?? (this.content ? await getFileHash(this.content) : void 0)
|
|
415
427
|
}),
|
|
@@ -466,7 +478,7 @@ class VaultFile {
|
|
|
466
478
|
const { reference, config: vaultConfig, download = false } = params;
|
|
467
479
|
const config = resolveConfig(vaultConfig);
|
|
468
480
|
const { vaultUrl, authStrategy } = config;
|
|
469
|
-
const id =
|
|
481
|
+
const id = vaultUtils.file.getFileIdFromVaultReference(reference);
|
|
470
482
|
const url = new URL(`files/${id}`, config.vaultUrl);
|
|
471
483
|
const response = await wrappedFetch(url, {
|
|
472
484
|
method: "GET",
|
|
@@ -497,7 +509,9 @@ class VaultFile {
|
|
|
497
509
|
* @param params.name - The name of the file
|
|
498
510
|
* @param params.content - The content of the file
|
|
499
511
|
* @param params.config - The configuration for the VaultFile
|
|
512
|
+
* @param params.mimeType - The MIME type of the file (optional)
|
|
500
513
|
* @param params.upload - Whether to upload the file (default: false)
|
|
514
|
+
* @param params.parentId - The ID of the parent file for hierarchical file relationships
|
|
501
515
|
* @param options - The options for the request
|
|
502
516
|
* @param options.signal - The signal to abort the request
|
|
503
517
|
*
|
|
@@ -532,13 +546,30 @@ class VaultFile {
|
|
|
532
546
|
* upload: true
|
|
533
547
|
* })
|
|
534
548
|
* ```
|
|
549
|
+
*
|
|
550
|
+
* @example
|
|
551
|
+
* ```ts
|
|
552
|
+
* // Create a child file with a parent
|
|
553
|
+
* const file = new File(['content'], 'child.txt')
|
|
554
|
+
* const vaultFile = await VaultFile.fromContent({
|
|
555
|
+
* name: 'child.txt',
|
|
556
|
+
* content: file,
|
|
557
|
+
* parentId: 'parent-file-id',
|
|
558
|
+
* config: {
|
|
559
|
+
* vaultUrl,
|
|
560
|
+
* authStrategy,
|
|
561
|
+
* },
|
|
562
|
+
* upload: true
|
|
563
|
+
* })
|
|
564
|
+
* ```
|
|
535
565
|
*/
|
|
536
566
|
static async fromContent(params, options) {
|
|
537
|
-
const {
|
|
567
|
+
const { content, config: vaultConfig, upload = false, parentId } = params;
|
|
568
|
+
const name = basename(params.name) ?? getFileName(content);
|
|
538
569
|
const config = resolveConfig(vaultConfig);
|
|
539
570
|
const { vaultUrl, authStrategy } = config;
|
|
540
571
|
const sha256sum = await getFileHash(content);
|
|
541
|
-
const mimeType = await detectFileMimeType(content);
|
|
572
|
+
const mimeType = params.mimeType ?? await detectFileMimeType(content);
|
|
542
573
|
const size = content.size;
|
|
543
574
|
const file = new VaultFile({
|
|
544
575
|
content,
|
|
@@ -551,7 +582,8 @@ class VaultFile {
|
|
|
551
582
|
});
|
|
552
583
|
const createdFile = await file._createFile({
|
|
553
584
|
size,
|
|
554
|
-
mimeType
|
|
585
|
+
mimeType,
|
|
586
|
+
parentId
|
|
555
587
|
}, { signal: options?.signal });
|
|
556
588
|
if (upload) {
|
|
557
589
|
await file.upload(file.content, createdFile.uploadUrl, { signal: options?.signal });
|
|
@@ -567,6 +599,7 @@ class VaultFile {
|
|
|
567
599
|
* @param params.contentLength - The size of the content in bytes
|
|
568
600
|
* @param params.config - The configuration for the VaultFile
|
|
569
601
|
* @param params.contentType - The MIME type of the content (optional)
|
|
602
|
+
* @param params.parentId - The ID of the parent file for hierarchical file relationships
|
|
570
603
|
* @param options - The options for the request
|
|
571
604
|
* @param options.signal - The signal to abort the request
|
|
572
605
|
*
|
|
@@ -589,25 +622,66 @@ class VaultFile {
|
|
|
589
622
|
* contentType: file.type
|
|
590
623
|
* })
|
|
591
624
|
* ```
|
|
625
|
+
*
|
|
626
|
+
* @example
|
|
627
|
+
* ```ts
|
|
628
|
+
* // Create a child file with streaming
|
|
629
|
+
* const vaultFile = await VaultFile.fromStream({
|
|
630
|
+
* name: 'child-video.mp4',
|
|
631
|
+
* contentLength: 50 * 1024 * 1024,
|
|
632
|
+
* contentType: 'video/mp4',
|
|
633
|
+
* parentId: 'parent-file-id',
|
|
634
|
+
* config: { vaultUrl, authStrategy }
|
|
635
|
+
* })
|
|
636
|
+
* ```
|
|
592
637
|
*/
|
|
593
638
|
static async fromStream(params, options) {
|
|
594
|
-
const {
|
|
639
|
+
const { contentLength, config: vaultConfig, contentType, parentId } = params;
|
|
640
|
+
const name = basename(params.name);
|
|
595
641
|
const config = resolveConfig(vaultConfig);
|
|
596
642
|
const file = new VaultFile({ config, name });
|
|
597
643
|
await file._createFile({
|
|
598
644
|
size: contentLength,
|
|
599
|
-
mimeType: contentType || "application/octet-stream"
|
|
645
|
+
mimeType: contentType || "application/octet-stream",
|
|
646
|
+
parentId
|
|
600
647
|
}, { signal: options?.signal });
|
|
601
648
|
return file;
|
|
602
649
|
}
|
|
603
650
|
/**
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
*
|
|
651
|
+
* Fetches and populates the metadata fields for this VaultFile instance.
|
|
652
|
+
*
|
|
653
|
+
* This method retrieves the file's metadata from the vault server and updates the instance's
|
|
654
|
+
* metadata, name, and id properties. Useful when you have a VaultFile instance that was created
|
|
655
|
+
* without full metadata or when you need to refresh the metadata.
|
|
607
656
|
*
|
|
608
|
-
* @
|
|
657
|
+
* @param options - Additional options for the request
|
|
658
|
+
* @param options.signal - AbortSignal to cancel the request
|
|
659
|
+
*
|
|
660
|
+
* @returns The VaultFile instance with populated metadata (for method chaining)
|
|
609
661
|
* @throws {Error} If the file ID is not set
|
|
610
662
|
* @throws {FetchError} If the metadata fetch fails
|
|
663
|
+
*
|
|
664
|
+
* @example
|
|
665
|
+
* ```ts
|
|
666
|
+
* const vaultFile = await VaultFile.fromVaultReference({
|
|
667
|
+
* reference: 'vault://file-id',
|
|
668
|
+
* config: { vaultUrl, authStrategy }
|
|
669
|
+
* })
|
|
670
|
+
* await vaultFile.populateMetadata()
|
|
671
|
+
* console.log('File size:', vaultFile.metadata?.size)
|
|
672
|
+
* console.log('MIME type:', vaultFile.metadata?.mimeType)
|
|
673
|
+
* ```
|
|
674
|
+
*
|
|
675
|
+
* @example
|
|
676
|
+
* ```ts
|
|
677
|
+
* // Chain with other operations
|
|
678
|
+
* const file = await VaultFile.fromVaultReference({
|
|
679
|
+
* reference: 'vault://file-id',
|
|
680
|
+
* config: { vaultUrl, authStrategy }
|
|
681
|
+
* })
|
|
682
|
+
* await file.populateMetadata()
|
|
683
|
+
* const children = await file.getChildren()
|
|
684
|
+
* ```
|
|
611
685
|
*/
|
|
612
686
|
async populateMetadata(options) {
|
|
613
687
|
try {
|
|
@@ -620,10 +694,38 @@ class VaultFile {
|
|
|
620
694
|
}
|
|
621
695
|
}
|
|
622
696
|
/**
|
|
623
|
-
*
|
|
697
|
+
* Returns the vault URI reference for this file.
|
|
698
|
+
*
|
|
699
|
+
* The vault reference is a URI in the format `vault://{fileId}` that can be used to
|
|
700
|
+
* uniquely identify and retrieve this file from the vault. This reference can be stored
|
|
701
|
+
* in databases, passed to other services, or used with {@link VaultFile.fromVaultReference}
|
|
702
|
+
* to reconstruct a VaultFile instance.
|
|
624
703
|
*
|
|
625
|
-
* @returns The vault reference in the format `vault://{fileId}`
|
|
704
|
+
* @returns The vault reference string in the format `vault://{fileId}`
|
|
626
705
|
* @throws {Error} If the file ID is not set
|
|
706
|
+
*
|
|
707
|
+
* @example
|
|
708
|
+
* ```ts
|
|
709
|
+
* const file = await VaultFile.fromContent({
|
|
710
|
+
* name: 'document.txt',
|
|
711
|
+
* content: new Blob(['content']),
|
|
712
|
+
* config: { vaultUrl, authStrategy },
|
|
713
|
+
* upload: true
|
|
714
|
+
* })
|
|
715
|
+
* const reference = file.getVaultReference()
|
|
716
|
+
* // Returns: "vault://abc123..."
|
|
717
|
+
* // Store this reference in your database for later retrieval
|
|
718
|
+
* ```
|
|
719
|
+
*
|
|
720
|
+
* @example
|
|
721
|
+
* ```ts
|
|
722
|
+
* // Retrieve a file later using the reference
|
|
723
|
+
* const storedReference = database.get('file_reference')
|
|
724
|
+
* const file = await VaultFile.fromVaultReference({
|
|
725
|
+
* reference: storedReference,
|
|
726
|
+
* config: { vaultUrl, authStrategy }
|
|
727
|
+
* })
|
|
728
|
+
* ```
|
|
627
729
|
*/
|
|
628
730
|
getVaultReference() {
|
|
629
731
|
if (!this.id) {
|
|
@@ -632,13 +734,37 @@ class VaultFile {
|
|
|
632
734
|
return `vault://${this.id}`;
|
|
633
735
|
}
|
|
634
736
|
/**
|
|
635
|
-
* Fetches the metadata
|
|
636
|
-
* @param options - The options for the request
|
|
637
|
-
* @param options.signal - The signal to abort the request
|
|
737
|
+
* Fetches the complete metadata for this file from the vault server.
|
|
638
738
|
*
|
|
639
|
-
*
|
|
739
|
+
* Retrieves detailed information about the file including size, MIME type, creation date,
|
|
740
|
+
* workspace ID, and other metadata fields. Unlike {@link populateMetadata}, this method
|
|
741
|
+
* returns the metadata without modifying the VaultFile instance.
|
|
742
|
+
*
|
|
743
|
+
* @param options - Additional options for the request
|
|
744
|
+
* @param options.signal - AbortSignal to cancel the request
|
|
745
|
+
*
|
|
746
|
+
* @returns A Promise that resolves to the FileMetadata object
|
|
640
747
|
* @throws {Error} If the file ID is not set
|
|
641
748
|
* @throws {FetchError} If the metadata fetch fails
|
|
749
|
+
*
|
|
750
|
+
* @example
|
|
751
|
+
* ```ts
|
|
752
|
+
* const vaultFile = await VaultFile.fromVaultReference({
|
|
753
|
+
* reference: 'vault://file-id',
|
|
754
|
+
* config: { vaultUrl, authStrategy }
|
|
755
|
+
* })
|
|
756
|
+
* const metadata = await vaultFile.getFileMetadata()
|
|
757
|
+
* console.log('File size:', metadata.size)
|
|
758
|
+
* console.log('Created at:', metadata.createdAt)
|
|
759
|
+
* console.log('Workspace:', metadata.workspaceId)
|
|
760
|
+
* ```
|
|
761
|
+
*
|
|
762
|
+
* @example
|
|
763
|
+
* ```ts
|
|
764
|
+
* // Use with abort signal
|
|
765
|
+
* const controller = new AbortController()
|
|
766
|
+
* const metadata = await vaultFile.getFileMetadata({ signal: controller.signal })
|
|
767
|
+
* ```
|
|
642
768
|
*/
|
|
643
769
|
async getFileMetadata(options) {
|
|
644
770
|
if (!this.id) {
|
|
@@ -652,14 +778,41 @@ class VaultFile {
|
|
|
652
778
|
return response;
|
|
653
779
|
}
|
|
654
780
|
/**
|
|
655
|
-
*
|
|
656
|
-
*
|
|
657
|
-
*
|
|
658
|
-
*
|
|
781
|
+
* Retrieves a presigned upload URL for uploading file content to the vault.
|
|
782
|
+
*
|
|
783
|
+
* This method returns a temporary URL that can be used to upload the file content directly
|
|
784
|
+
* to cloud storage (e.g., S3). The URL is cached and reused if still valid. If the file
|
|
785
|
+
* doesn't exist yet, it will be created automatically.
|
|
659
786
|
*
|
|
660
|
-
* @
|
|
787
|
+
* @param options - Additional options for the request
|
|
788
|
+
* @param options.signal - AbortSignal to cancel the request
|
|
789
|
+
* @param options.expiresIn - Number of seconds the upload URL should be valid for (default: server-defined)
|
|
790
|
+
*
|
|
791
|
+
* @returns A Promise that resolves to a URL object for uploading the file
|
|
661
792
|
* @throws {Error} If the vault service returns an invalid response
|
|
662
793
|
* @throws {FetchError} If the upload URL fetch fails
|
|
794
|
+
*
|
|
795
|
+
* @example
|
|
796
|
+
* ```ts
|
|
797
|
+
* const vaultFile = await VaultFile.fromContent({
|
|
798
|
+
* name: 'document.txt',
|
|
799
|
+
* content: new Blob(['content']),
|
|
800
|
+
* config: { vaultUrl, authStrategy }
|
|
801
|
+
* })
|
|
802
|
+
* const uploadUrl = await vaultFile.getUploadUrl()
|
|
803
|
+
* // Use the URL for custom upload logic
|
|
804
|
+
* await fetch(uploadUrl, {
|
|
805
|
+
* method: 'PUT',
|
|
806
|
+
* body: file,
|
|
807
|
+
* headers: { 'Content-Type': 'text/plain' }
|
|
808
|
+
* })
|
|
809
|
+
* ```
|
|
810
|
+
*
|
|
811
|
+
* @example
|
|
812
|
+
* ```ts
|
|
813
|
+
* // Request a longer-lived upload URL
|
|
814
|
+
* const uploadUrl = await vaultFile.getUploadUrl({ expiresIn: 7200 }) // 2 hours
|
|
815
|
+
* ```
|
|
663
816
|
*/
|
|
664
817
|
async getUploadUrl(options) {
|
|
665
818
|
if (this.lastUploadUrl && this.lastUploadUrl.expiresAt > /* @__PURE__ */ new Date()) {
|
|
@@ -686,15 +839,38 @@ class VaultFile {
|
|
|
686
839
|
return this.lastUploadUrl.url;
|
|
687
840
|
}
|
|
688
841
|
/**
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
*
|
|
692
|
-
*
|
|
842
|
+
* Retrieves a presigned download URL for accessing the file content.
|
|
843
|
+
*
|
|
844
|
+
* This method returns a temporary URL that can be used to download the file content directly
|
|
845
|
+
* from cloud storage (e.g., S3). The URL is cached and reused if still valid. This is useful
|
|
846
|
+
* for generating shareable links or implementing custom download logic.
|
|
693
847
|
*
|
|
694
|
-
* @
|
|
848
|
+
* @param options - Additional options for the request
|
|
849
|
+
* @param options.signal - AbortSignal to cancel the request
|
|
850
|
+
* @param options.expiresIn - Number of seconds the download URL should be valid for (default: server-defined)
|
|
851
|
+
*
|
|
852
|
+
* @returns A Promise that resolves to a URL object for downloading the file
|
|
695
853
|
* @throws {Error} If the vault service returns an invalid response
|
|
696
|
-
* @throws {Error} If
|
|
854
|
+
* @throws {Error} If no file ID, name, or content is set
|
|
697
855
|
* @throws {FetchError} If the download URL fetch fails
|
|
856
|
+
*
|
|
857
|
+
* @example
|
|
858
|
+
* ```ts
|
|
859
|
+
* const vaultFile = await VaultFile.fromVaultReference({
|
|
860
|
+
* reference: 'vault://file-id',
|
|
861
|
+
* config: { vaultUrl, authStrategy }
|
|
862
|
+
* })
|
|
863
|
+
* const downloadUrl = await vaultFile.getDownloadUrl()
|
|
864
|
+
* // Use the URL to download the file
|
|
865
|
+
* window.location.href = downloadUrl.toString()
|
|
866
|
+
* ```
|
|
867
|
+
*
|
|
868
|
+
* @example
|
|
869
|
+
* ```ts
|
|
870
|
+
* // Request a longer-lived download URL
|
|
871
|
+
* const downloadUrl = await vaultFile.getDownloadUrl({ expiresIn: 3600 }) // 1 hour
|
|
872
|
+
* // Share this URL with others
|
|
873
|
+
* ```
|
|
698
874
|
*/
|
|
699
875
|
async getDownloadUrl(options) {
|
|
700
876
|
if (this.lastDownloadUrl && this.lastDownloadUrl.expiresAt > /* @__PURE__ */ new Date()) {
|
|
@@ -714,30 +890,51 @@ class VaultFile {
|
|
|
714
890
|
return this.lastDownloadUrl.url;
|
|
715
891
|
}
|
|
716
892
|
/**
|
|
717
|
-
* Uploads
|
|
893
|
+
* Uploads file content to the vault using a presigned URL.
|
|
894
|
+
*
|
|
895
|
+
* This method handles the actual file upload to cloud storage. If no file is provided,
|
|
896
|
+
* it uses the content from the VaultFile instance. If no upload URL is provided, one
|
|
897
|
+
* will be fetched automatically. The MIME type is detected automatically if not already set.
|
|
898
|
+
*
|
|
899
|
+
* @param file - The Blob or File to upload. If not provided, uses the instance's content property
|
|
900
|
+
* @param url - A presigned upload URL. If not provided, will be fetched via {@link getUploadUrl}
|
|
901
|
+
* @param options - Additional options for the request
|
|
902
|
+
* @param options.signal - AbortSignal to cancel the upload
|
|
903
|
+
*
|
|
904
|
+
* @throws {Error} If no file content is available (neither provided nor in the instance)
|
|
905
|
+
* @throws {FetchError} If the upload request fails
|
|
906
|
+
* @returns A Promise that resolves when the upload completes successfully
|
|
718
907
|
*
|
|
719
908
|
* @example
|
|
720
909
|
* ```ts
|
|
910
|
+
* // Simple upload using instance content
|
|
721
911
|
* const file = new File(['content'], 'document.txt')
|
|
722
912
|
* const vaultFile = await VaultFile.fromContent({
|
|
723
913
|
* name: 'document.txt',
|
|
724
914
|
* content: file,
|
|
725
|
-
* config: {
|
|
726
|
-
* vaultUrl,
|
|
727
|
-
* authStrategy,
|
|
728
|
-
* },
|
|
915
|
+
* config: { vaultUrl, authStrategy }
|
|
729
916
|
* })
|
|
730
|
-
* await vaultFile.upload(
|
|
917
|
+
* await vaultFile.upload()
|
|
731
918
|
* ```
|
|
732
919
|
*
|
|
733
|
-
* @
|
|
734
|
-
*
|
|
735
|
-
*
|
|
736
|
-
*
|
|
920
|
+
* @example
|
|
921
|
+
* ```ts
|
|
922
|
+
* // Upload different content than what's in the instance
|
|
923
|
+
* const vaultFile = await VaultFile.fromContent({
|
|
924
|
+
* name: 'document.txt',
|
|
925
|
+
* content: new Blob(['original']),
|
|
926
|
+
* config: { vaultUrl, authStrategy }
|
|
927
|
+
* })
|
|
928
|
+
* const newContent = new Blob(['updated content'])
|
|
929
|
+
* await vaultFile.upload(newContent)
|
|
930
|
+
* ```
|
|
737
931
|
*
|
|
738
|
-
* @
|
|
739
|
-
*
|
|
740
|
-
*
|
|
932
|
+
* @example
|
|
933
|
+
* ```ts
|
|
934
|
+
* // Upload with custom URL (advanced usage)
|
|
935
|
+
* const uploadUrl = await vaultFile.getUploadUrl({ expiresIn: 3600 })
|
|
936
|
+
* await vaultFile.upload(file, uploadUrl.toString())
|
|
937
|
+
* ```
|
|
741
938
|
*/
|
|
742
939
|
async upload(file, url, options) {
|
|
743
940
|
const content = file ?? this.content;
|
|
@@ -768,31 +965,60 @@ class VaultFile {
|
|
|
768
965
|
return await blobToBase64(blob);
|
|
769
966
|
}
|
|
770
967
|
/**
|
|
771
|
-
* Downloads
|
|
968
|
+
* Downloads the file as a ReadableStream for memory-efficient processing of large files.
|
|
772
969
|
*
|
|
773
|
-
*
|
|
774
|
-
*
|
|
970
|
+
* This method is ideal for handling large files without loading the entire content into memory.
|
|
971
|
+
* The stream can be processed chunk-by-chunk, piped to other streams, or saved incrementally.
|
|
972
|
+
* This is the recommended approach for files larger than a few megabytes.
|
|
775
973
|
*
|
|
776
|
-
* @
|
|
974
|
+
* @param options - Additional options for the request
|
|
975
|
+
* @param options.signal - AbortSignal to cancel the download
|
|
976
|
+
*
|
|
977
|
+
* @returns A Promise resolving to a ReadableStream that yields Uint8Array chunks
|
|
978
|
+
* @throws {Error} If the response body is not readable
|
|
979
|
+
* @throws {FetchError} If the download fails
|
|
777
980
|
*
|
|
778
981
|
* @example
|
|
779
982
|
* ```ts
|
|
780
|
-
*
|
|
983
|
+
* // Process large file chunk by chunk
|
|
984
|
+
* const vaultFile = await VaultFile.fromVaultReference({
|
|
985
|
+
* reference: 'vault://large-video-id',
|
|
986
|
+
* config: { vaultUrl, authStrategy }
|
|
987
|
+
* })
|
|
781
988
|
* const stream = await vaultFile.downloadStream()
|
|
782
989
|
*
|
|
783
|
-
* // Process the stream chunk by chunk
|
|
784
990
|
* const reader = stream.getReader()
|
|
991
|
+
* let bytesReceived = 0
|
|
785
992
|
* try {
|
|
786
993
|
* while (true) {
|
|
787
994
|
* const { done, value } = await reader.read()
|
|
788
995
|
* if (done) break
|
|
789
|
-
*
|
|
790
|
-
* console.log(
|
|
996
|
+
* bytesReceived += value.length
|
|
997
|
+
* console.log(`Downloaded ${bytesReceived} bytes...`)
|
|
998
|
+
* // Process chunk (value is Uint8Array)
|
|
791
999
|
* }
|
|
792
1000
|
* } finally {
|
|
793
1001
|
* reader.releaseLock()
|
|
794
1002
|
* }
|
|
795
1003
|
* ```
|
|
1004
|
+
*
|
|
1005
|
+
* @example
|
|
1006
|
+
* ```ts
|
|
1007
|
+
* // Pipe stream to a writable destination
|
|
1008
|
+
* const stream = await vaultFile.downloadStream()
|
|
1009
|
+
* const fileHandle = await navigator.storage.getDirectory()
|
|
1010
|
+
* .then(dir => dir.getFileHandle('output.dat', { create: true }))
|
|
1011
|
+
* const writable = await fileHandle.createWritable()
|
|
1012
|
+
* await stream.pipeTo(writable)
|
|
1013
|
+
* ```
|
|
1014
|
+
*
|
|
1015
|
+
* @example
|
|
1016
|
+
* ```ts
|
|
1017
|
+
* // Use with abort signal
|
|
1018
|
+
* const controller = new AbortController()
|
|
1019
|
+
* const stream = await vaultFile.downloadStream({ signal: controller.signal })
|
|
1020
|
+
* // Later: controller.abort()
|
|
1021
|
+
* ```
|
|
796
1022
|
*/
|
|
797
1023
|
async downloadStream(options) {
|
|
798
1024
|
const downloadUrl = await this.getDownloadUrl({ signal: options?.signal });
|
|
@@ -806,32 +1032,64 @@ class VaultFile {
|
|
|
806
1032
|
return response.body;
|
|
807
1033
|
}
|
|
808
1034
|
/**
|
|
809
|
-
* Uploads
|
|
1035
|
+
* Uploads file content using a ReadableStream for memory-efficient processing of large files.
|
|
810
1036
|
*
|
|
811
|
-
*
|
|
812
|
-
*
|
|
813
|
-
*
|
|
814
|
-
*
|
|
815
|
-
* @param
|
|
1037
|
+
* This method is ideal for uploading large files without loading the entire content into memory.
|
|
1038
|
+
* The stream is sent directly to cloud storage, making it perfect for files larger than a few
|
|
1039
|
+
* megabytes. Note: When using Bun, the stream is buffered due to implementation limitations.
|
|
1040
|
+
*
|
|
1041
|
+
* @param stream - A ReadableStream of Uint8Array chunks containing the file data
|
|
1042
|
+
* @param options - Required options for the upload
|
|
1043
|
+
* @param options.contentLength - The total size of the content in bytes (required for S3 uploads)
|
|
1044
|
+
* @param options.contentType - The MIME type of the content (auto-detected from filename if not provided)
|
|
1045
|
+
* @param options.signal - AbortSignal to cancel the upload
|
|
816
1046
|
*
|
|
817
|
-
* @throws {Error} If contentLength is not provided
|
|
1047
|
+
* @throws {Error} If contentLength is not provided or is negative
|
|
818
1048
|
* @throws {FetchError} If the upload fails
|
|
819
|
-
* @returns Promise that resolves when upload
|
|
1049
|
+
* @returns A Promise that resolves when the upload completes successfully
|
|
820
1050
|
*
|
|
821
1051
|
* @example
|
|
822
1052
|
* ```ts
|
|
823
|
-
*
|
|
824
|
-
* const
|
|
1053
|
+
* // Upload a large file using streaming
|
|
1054
|
+
* const file = new File(['large content'], 'video.mp4')
|
|
1055
|
+
* const vaultFile = await VaultFile.fromStream({
|
|
1056
|
+
* name: 'video.mp4',
|
|
1057
|
+
* contentLength: file.size,
|
|
825
1058
|
* contentType: file.type,
|
|
826
1059
|
* config: { vaultUrl, authStrategy }
|
|
827
1060
|
* })
|
|
828
1061
|
*
|
|
829
|
-
* // Upload using the stream directly
|
|
830
1062
|
* const stream = file.stream()
|
|
831
1063
|
* await vaultFile.uploadStream(stream, {
|
|
832
1064
|
* contentLength: file.size,
|
|
833
1065
|
* contentType: file.type
|
|
834
1066
|
* })
|
|
1067
|
+
* console.log('Upload complete!')
|
|
1068
|
+
* ```
|
|
1069
|
+
*
|
|
1070
|
+
* @example
|
|
1071
|
+
* ```ts
|
|
1072
|
+
* // Upload with progress tracking
|
|
1073
|
+
* const vaultFile = await VaultFile.fromStream({
|
|
1074
|
+
* name: 'document.pdf',
|
|
1075
|
+
* contentLength: fileSize,
|
|
1076
|
+
* config: { vaultUrl, authStrategy }
|
|
1077
|
+
* })
|
|
1078
|
+
*
|
|
1079
|
+
* // Create a transform stream to track progress
|
|
1080
|
+
* let uploaded = 0
|
|
1081
|
+
* const progressStream = new TransformStream({
|
|
1082
|
+
* transform(chunk, controller) {
|
|
1083
|
+
* uploaded += chunk.length
|
|
1084
|
+
* console.log(`Uploaded ${uploaded}/${fileSize} bytes`)
|
|
1085
|
+
* controller.enqueue(chunk)
|
|
1086
|
+
* }
|
|
1087
|
+
* })
|
|
1088
|
+
*
|
|
1089
|
+
* await vaultFile.uploadStream(
|
|
1090
|
+
* originalStream.pipeThrough(progressStream),
|
|
1091
|
+
* { contentLength: fileSize }
|
|
1092
|
+
* )
|
|
835
1093
|
* ```
|
|
836
1094
|
*/
|
|
837
1095
|
async uploadStream(stream, options) {
|
|
@@ -872,10 +1130,48 @@ class VaultFile {
|
|
|
872
1130
|
});
|
|
873
1131
|
}
|
|
874
1132
|
/**
|
|
875
|
-
*
|
|
876
|
-
*
|
|
877
|
-
*
|
|
1133
|
+
* Permanently deletes this file from the vault.
|
|
1134
|
+
*
|
|
1135
|
+
* This operation removes the file metadata and content from the vault. This action cannot be
|
|
1136
|
+
* undone. Any vault references or permalinks to this file will become invalid after deletion.
|
|
1137
|
+
* Note: This does not automatically delete child files in hierarchical relationships.
|
|
1138
|
+
*
|
|
1139
|
+
* @param options - Additional options for the request
|
|
1140
|
+
* @param options.signal - AbortSignal to cancel the request
|
|
1141
|
+
*
|
|
1142
|
+
* @throws {Error} If the file ID is not set
|
|
1143
|
+
* @throws {FetchError} If the deletion request fails
|
|
1144
|
+
* @returns A Promise that resolves when the deletion completes successfully
|
|
1145
|
+
*
|
|
1146
|
+
* @example
|
|
1147
|
+
* ```ts
|
|
1148
|
+
* // Delete a file
|
|
1149
|
+
* const vaultFile = await VaultFile.fromVaultReference({
|
|
1150
|
+
* reference: 'vault://file-id',
|
|
1151
|
+
* config: { vaultUrl, authStrategy }
|
|
1152
|
+
* })
|
|
1153
|
+
* await vaultFile.delete()
|
|
1154
|
+
* console.log('File deleted successfully')
|
|
1155
|
+
* ```
|
|
1156
|
+
*
|
|
1157
|
+
* @example
|
|
1158
|
+
* ```ts
|
|
1159
|
+
* // Delete with confirmation
|
|
1160
|
+
* const vaultFile = await VaultFile.fromVaultReference({
|
|
1161
|
+
* reference: 'vault://file-id',
|
|
1162
|
+
* config: { vaultUrl, authStrategy }
|
|
1163
|
+
* })
|
|
1164
|
+
* if (confirm('Are you sure you want to delete this file?')) {
|
|
1165
|
+
* await vaultFile.delete()
|
|
1166
|
+
* }
|
|
1167
|
+
* ```
|
|
878
1168
|
*
|
|
1169
|
+
* @example
|
|
1170
|
+
* ```ts
|
|
1171
|
+
* // Delete with abort signal
|
|
1172
|
+
* const controller = new AbortController()
|
|
1173
|
+
* await vaultFile.delete({ signal: controller.signal })
|
|
1174
|
+
* ```
|
|
879
1175
|
*/
|
|
880
1176
|
async delete(options) {
|
|
881
1177
|
if (!this.id) {
|
|
@@ -888,13 +1184,51 @@ class VaultFile {
|
|
|
888
1184
|
});
|
|
889
1185
|
}
|
|
890
1186
|
/**
|
|
891
|
-
* Creates a permalink for
|
|
892
|
-
*
|
|
893
|
-
*
|
|
894
|
-
*
|
|
895
|
-
*
|
|
1187
|
+
* Creates a new shareable permalink for this file.
|
|
1188
|
+
*
|
|
1189
|
+
* A permalink is a public URL that allows anyone with the link to access the file without
|
|
1190
|
+
* authentication. The permalink can optionally expire after a specified duration. This is
|
|
1191
|
+
* useful for sharing files with external users or embedding files in public content.
|
|
1192
|
+
*
|
|
1193
|
+
* @param params - Optional parameters for permalink creation
|
|
1194
|
+
* @param params.expiresIn - Number of seconds until the permalink expires (optional, defaults to server setting)
|
|
1195
|
+
* @param options - Additional options for the request
|
|
1196
|
+
* @param options.signal - AbortSignal to cancel the request
|
|
1197
|
+
*
|
|
1198
|
+
* @throws {Error} If the file ID is not set
|
|
1199
|
+
* @throws {Error} If the workspace ID is not available (call {@link populateMetadata} first)
|
|
1200
|
+
* @throws {FetchError} If the permalink creation fails
|
|
1201
|
+
* @returns A Promise that resolves to a Permalink instance
|
|
1202
|
+
*
|
|
1203
|
+
* @example
|
|
1204
|
+
* ```ts
|
|
1205
|
+
* // Create a permanent permalink
|
|
1206
|
+
* const vaultFile = await VaultFile.fromVaultReference({
|
|
1207
|
+
* reference: 'vault://file-id',
|
|
1208
|
+
* config: { vaultUrl, authStrategy }
|
|
1209
|
+
* })
|
|
1210
|
+
* await vaultFile.populateMetadata() // Required to get workspace ID
|
|
1211
|
+
* const permalink = await vaultFile.createPermalink()
|
|
1212
|
+
* console.log('Share this link:', permalink.url)
|
|
1213
|
+
* ```
|
|
1214
|
+
*
|
|
1215
|
+
* @example
|
|
1216
|
+
* ```ts
|
|
1217
|
+
* // Create a permalink that expires in 24 hours
|
|
1218
|
+
* await vaultFile.populateMetadata()
|
|
1219
|
+
* const permalink = await vaultFile.createPermalink({
|
|
1220
|
+
* expiresIn: 24 * 60 * 60 // 24 hours in seconds
|
|
1221
|
+
* })
|
|
1222
|
+
* console.log('Link expires at:', permalink.expiresAt)
|
|
1223
|
+
* ```
|
|
896
1224
|
*
|
|
897
|
-
* @
|
|
1225
|
+
* @example
|
|
1226
|
+
* ```ts
|
|
1227
|
+
* // Create a short-lived sharing link (1 hour)
|
|
1228
|
+
* await vaultFile.populateMetadata()
|
|
1229
|
+
* const permalink = await vaultFile.createPermalink({ expiresIn: 3600 })
|
|
1230
|
+
* // Send permalink.url to user
|
|
1231
|
+
* ```
|
|
898
1232
|
*/
|
|
899
1233
|
async createPermalink(params = {}, options) {
|
|
900
1234
|
if (!this.id) {
|
|
@@ -910,11 +1244,51 @@ class VaultFile {
|
|
|
910
1244
|
}, options);
|
|
911
1245
|
}
|
|
912
1246
|
/**
|
|
913
|
-
*
|
|
1247
|
+
* Retrieves all active permalinks associated with this file.
|
|
1248
|
+
*
|
|
1249
|
+
* This method fetches all permalinks that have been created for this file and are still
|
|
1250
|
+
* valid (not expired or deleted). Each permalink is returned as a Permalink instance
|
|
1251
|
+
* with full details including URL, expiration date, and other metadata.
|
|
1252
|
+
*
|
|
914
1253
|
* @param options - Additional options for the request
|
|
915
|
-
* @param options.signal -
|
|
1254
|
+
* @param options.signal - AbortSignal to cancel the request
|
|
1255
|
+
*
|
|
1256
|
+
* @throws {Error} If the file ID is not set
|
|
1257
|
+
* @throws {FetchError} If the request to fetch permalinks fails
|
|
1258
|
+
* @returns A Promise that resolves to an array of Permalink instances
|
|
916
1259
|
*
|
|
917
|
-
* @
|
|
1260
|
+
* @example
|
|
1261
|
+
* ```ts
|
|
1262
|
+
* // List all permalinks for a file
|
|
1263
|
+
* const vaultFile = await VaultFile.fromVaultReference({
|
|
1264
|
+
* reference: 'vault://file-id',
|
|
1265
|
+
* config: { vaultUrl, authStrategy }
|
|
1266
|
+
* })
|
|
1267
|
+
* const permalinks = await vaultFile.getPermalinks()
|
|
1268
|
+
* permalinks.forEach(permalink => {
|
|
1269
|
+
* console.log('URL:', permalink.url)
|
|
1270
|
+
* console.log('Expires:', permalink.expiresAt || 'Never')
|
|
1271
|
+
* })
|
|
1272
|
+
* ```
|
|
1273
|
+
*
|
|
1274
|
+
* @example
|
|
1275
|
+
* ```ts
|
|
1276
|
+
* // Check if any permalinks exist
|
|
1277
|
+
* const permalinks = await vaultFile.getPermalinks()
|
|
1278
|
+
* if (permalinks.length > 0) {
|
|
1279
|
+
* console.log(`This file has ${permalinks.length} active permalink(s)`)
|
|
1280
|
+
* } else {
|
|
1281
|
+
* console.log('No active permalinks')
|
|
1282
|
+
* }
|
|
1283
|
+
* ```
|
|
1284
|
+
*
|
|
1285
|
+
* @example
|
|
1286
|
+
* ```ts
|
|
1287
|
+
* // Find non-expiring permalinks
|
|
1288
|
+
* const permalinks = await vaultFile.getPermalinks()
|
|
1289
|
+
* const permanent = permalinks.filter(p => !p.expiresAt)
|
|
1290
|
+
* console.log(`Found ${permanent.length} permanent links`)
|
|
1291
|
+
* ```
|
|
918
1292
|
*/
|
|
919
1293
|
async getPermalinks(options) {
|
|
920
1294
|
if (!this.id) {
|
|
@@ -927,6 +1301,273 @@ class VaultFile {
|
|
|
927
1301
|
});
|
|
928
1302
|
return permalinks.map((data) => new Permalink(this.config, data));
|
|
929
1303
|
}
|
|
1304
|
+
/**
|
|
1305
|
+
* Retrieves all child files in the hierarchical file relationship.
|
|
1306
|
+
*
|
|
1307
|
+
* This method queries files that have this file set as their parent (via parentId).
|
|
1308
|
+
* Returns an empty array if the file has no children or if the file doesn't exist.
|
|
1309
|
+
* The returned children are VaultFile instances with populated metadata but no content.
|
|
1310
|
+
*
|
|
1311
|
+
* @param params - Optional parameters for filtering and request control
|
|
1312
|
+
* @param params.mimeType - Filter children by MIME type (e.g., 'image/png', 'application/pdf')
|
|
1313
|
+
* @param params.includeDeleted - Whether to include deleted child files (default: false)
|
|
1314
|
+
* @param params.limit - Maximum number of children to return (default: 100)
|
|
1315
|
+
* @param params.offset - Number of children to skip (default: 0)
|
|
1316
|
+
* @param options - Additional options for the request
|
|
1317
|
+
* @param options.signal - AbortSignal to cancel the request
|
|
1318
|
+
*
|
|
1319
|
+
* @returns An array of VaultFile instances representing the child files
|
|
1320
|
+
* @throws {Error} If the file ID is not set
|
|
1321
|
+
* @throws {FetchError} If the request to fetch children fails
|
|
1322
|
+
*
|
|
1323
|
+
* @example
|
|
1324
|
+
* ```ts
|
|
1325
|
+
* // Get all children of a file
|
|
1326
|
+
* const parent = await VaultFile.fromVaultReference({
|
|
1327
|
+
* reference: 'vault://parent-id',
|
|
1328
|
+
* config: { vaultUrl, authStrategy }
|
|
1329
|
+
* })
|
|
1330
|
+
* const children = await parent.getChildren()
|
|
1331
|
+
* console.log(`Found ${children.length} child files`)
|
|
1332
|
+
* ```
|
|
1333
|
+
*
|
|
1334
|
+
* @example
|
|
1335
|
+
* ```ts
|
|
1336
|
+
* // Get only image children
|
|
1337
|
+
* const parent = await VaultFile.fromVaultReference({
|
|
1338
|
+
* reference: 'vault://parent-id',
|
|
1339
|
+
* config: { vaultUrl, authStrategy }
|
|
1340
|
+
* })
|
|
1341
|
+
* const imageChildren = await parent.getChildren({ mimeType: 'image/png' })
|
|
1342
|
+
* ```
|
|
1343
|
+
*
|
|
1344
|
+
* @example
|
|
1345
|
+
* ```ts
|
|
1346
|
+
* // Get children with pagination
|
|
1347
|
+
* const parent = await VaultFile.fromVaultReference({
|
|
1348
|
+
* reference: 'vault://parent-id',
|
|
1349
|
+
* config: { vaultUrl, authStrategy }
|
|
1350
|
+
* })
|
|
1351
|
+
* const firstPage = await parent.getChildren({ limit: 10, offset: 0 })
|
|
1352
|
+
* const secondPage = await parent.getChildren({ limit: 10, offset: 10 })
|
|
1353
|
+
* ```
|
|
1354
|
+
*
|
|
1355
|
+
* @example
|
|
1356
|
+
* ```ts
|
|
1357
|
+
* // Use with abort signal for cancellable requests
|
|
1358
|
+
* const controller = new AbortController()
|
|
1359
|
+
* const children = await parent.getChildren({}, { signal: controller.signal })
|
|
1360
|
+
* // Later: controller.abort()
|
|
1361
|
+
* ```
|
|
1362
|
+
*/
|
|
1363
|
+
async getChildren(params = {}, options) {
|
|
1364
|
+
if (!this.id) {
|
|
1365
|
+
throw new Error("File ID is not set");
|
|
1366
|
+
}
|
|
1367
|
+
const query = {};
|
|
1368
|
+
if (params.mimeType) {
|
|
1369
|
+
query.mimeType = params.mimeType;
|
|
1370
|
+
}
|
|
1371
|
+
if (params.includeDeleted) {
|
|
1372
|
+
query.includeDeleted = params.includeDeleted ? "true" : "false";
|
|
1373
|
+
}
|
|
1374
|
+
if (params.limit !== void 0) {
|
|
1375
|
+
query.limit = params.limit.toString();
|
|
1376
|
+
}
|
|
1377
|
+
if (params.offset !== void 0) {
|
|
1378
|
+
query.offset = params.offset.toString();
|
|
1379
|
+
}
|
|
1380
|
+
const response = await this._fetch({
|
|
1381
|
+
method: "GET",
|
|
1382
|
+
path: `files/${this.id}/children`,
|
|
1383
|
+
signal: options?.signal,
|
|
1384
|
+
query
|
|
1385
|
+
});
|
|
1386
|
+
return response.files.map((data) => new VaultFile({
|
|
1387
|
+
config: this.config,
|
|
1388
|
+
id: data.id,
|
|
1389
|
+
name: data.originalFileName ?? void 0,
|
|
1390
|
+
metadata: data
|
|
1391
|
+
}));
|
|
1392
|
+
}
|
|
1393
|
+
/**
|
|
1394
|
+
* Iterates through all child files with automatic pagination.
|
|
1395
|
+
*
|
|
1396
|
+
* This method returns an async iterator that automatically fetches pages of children
|
|
1397
|
+
* as you iterate through them. This is useful when you have a large number of children
|
|
1398
|
+
* and want to process them without loading all of them into memory at once.
|
|
1399
|
+
*
|
|
1400
|
+
* @param params - Optional parameters for filtering and pagination
|
|
1401
|
+
* @param params.pageSize - Number of children to fetch per page (default: 100)
|
|
1402
|
+
* @param params.mimeType - Filter children by MIME type (e.g., 'image/png', 'application/pdf')
|
|
1403
|
+
* @param params.includeDeleted - Whether to include deleted child files (default: false)
|
|
1404
|
+
* @param options - Additional options for the request
|
|
1405
|
+
* @param options.signal - AbortSignal to cancel the iteration
|
|
1406
|
+
*
|
|
1407
|
+
* @returns An async iterator that yields VaultFile instances
|
|
1408
|
+
* @throws {Error} If the file ID is not set
|
|
1409
|
+
* @throws {FetchError} If the request to fetch children fails
|
|
1410
|
+
*
|
|
1411
|
+
* @example
|
|
1412
|
+
* ```ts
|
|
1413
|
+
* // Iterate through all children
|
|
1414
|
+
* const parent = await VaultFile.fromVaultReference({
|
|
1415
|
+
* reference: 'vault://parent-id',
|
|
1416
|
+
* config: { vaultUrl, authStrategy }
|
|
1417
|
+
* })
|
|
1418
|
+
*
|
|
1419
|
+
* for await (const child of parent.iterateChildren()) {
|
|
1420
|
+
* console.log(`Processing child: ${child.name}`)
|
|
1421
|
+
* }
|
|
1422
|
+
* ```
|
|
1423
|
+
*
|
|
1424
|
+
* @example
|
|
1425
|
+
* ```ts
|
|
1426
|
+
* // Iterate with filters and custom page size
|
|
1427
|
+
* for await (const child of parent.iterateChildren({
|
|
1428
|
+
* pageSize: 50,
|
|
1429
|
+
* mimeType: 'image/png'
|
|
1430
|
+
* })) {
|
|
1431
|
+
* console.log(`Processing image: ${child.name}`)
|
|
1432
|
+
* }
|
|
1433
|
+
* ```
|
|
1434
|
+
*
|
|
1435
|
+
* @example
|
|
1436
|
+
* ```ts
|
|
1437
|
+
* // Use with abort signal
|
|
1438
|
+
* const controller = new AbortController()
|
|
1439
|
+
* try {
|
|
1440
|
+
* for await (const child of parent.iterateChildren({}, { signal: controller.signal })) {
|
|
1441
|
+
* console.log(child.name)
|
|
1442
|
+
* // Can abort iteration at any time
|
|
1443
|
+
* if (someCondition) {
|
|
1444
|
+
* controller.abort()
|
|
1445
|
+
* }
|
|
1446
|
+
* }
|
|
1447
|
+
* } catch (error) {
|
|
1448
|
+
* if (error.name === 'AbortError') {
|
|
1449
|
+
* console.log('Iteration cancelled')
|
|
1450
|
+
* }
|
|
1451
|
+
* }
|
|
1452
|
+
* ```
|
|
1453
|
+
*/
|
|
1454
|
+
async *iterateChildren(params = {}, options) {
|
|
1455
|
+
if (!this.id) {
|
|
1456
|
+
throw new Error("File ID is not set");
|
|
1457
|
+
}
|
|
1458
|
+
const pageSize = params.pageSize ?? 100;
|
|
1459
|
+
let offset = 0;
|
|
1460
|
+
let hasMore = true;
|
|
1461
|
+
while (hasMore) {
|
|
1462
|
+
const children = await this.getChildren({
|
|
1463
|
+
limit: pageSize,
|
|
1464
|
+
offset,
|
|
1465
|
+
mimeType: params.mimeType,
|
|
1466
|
+
includeDeleted: params.includeDeleted
|
|
1467
|
+
}, options);
|
|
1468
|
+
for (const child of children) {
|
|
1469
|
+
yield child;
|
|
1470
|
+
}
|
|
1471
|
+
hasMore = children.length === pageSize;
|
|
1472
|
+
offset += children.length;
|
|
1473
|
+
if (children.length === 0) {
|
|
1474
|
+
hasMore = false;
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* Creates a child file from content with this file as the parent.
|
|
1480
|
+
*
|
|
1481
|
+
* This is a convenience method that wraps {@link VaultFile.fromContent} and automatically
|
|
1482
|
+
* sets the current file as the parent. All parameters and behavior are identical to
|
|
1483
|
+
* {@link VaultFile.fromContent}, except parentId is automatically provided.
|
|
1484
|
+
*
|
|
1485
|
+
* @param params - Parameters for creating the child file (same as fromContent, minus parentId)
|
|
1486
|
+
* @param options - Additional options for the request
|
|
1487
|
+
*
|
|
1488
|
+
* @returns A new VaultFile instance representing the child file
|
|
1489
|
+
* @throws {Error} If the parent file ID is not set
|
|
1490
|
+
* @throws {FetchError} If the child file creation fails
|
|
1491
|
+
*
|
|
1492
|
+
* @example
|
|
1493
|
+
* ```ts
|
|
1494
|
+
* // Create a child file
|
|
1495
|
+
* const parent = await VaultFile.fromContent({
|
|
1496
|
+
* name: 'parent.txt',
|
|
1497
|
+
* content: new Blob(['parent content']),
|
|
1498
|
+
* config: { vaultUrl, authStrategy },
|
|
1499
|
+
* upload: true
|
|
1500
|
+
* })
|
|
1501
|
+
* const child = await parent.createChildFromContent({
|
|
1502
|
+
* name: 'child.txt',
|
|
1503
|
+
* content: new Blob(['child content']),
|
|
1504
|
+
* upload: true
|
|
1505
|
+
* })
|
|
1506
|
+
* console.log('Child created with parent:', child.metadata?.parentId)
|
|
1507
|
+
* ```
|
|
1508
|
+
*/
|
|
1509
|
+
async createChildFromContent(params, options) {
|
|
1510
|
+
if (!this.id) {
|
|
1511
|
+
throw new Error("Parent file ID is not set");
|
|
1512
|
+
}
|
|
1513
|
+
return VaultFile.fromContent(
|
|
1514
|
+
{
|
|
1515
|
+
...params,
|
|
1516
|
+
config: this.config,
|
|
1517
|
+
parentId: this.id
|
|
1518
|
+
},
|
|
1519
|
+
options
|
|
1520
|
+
);
|
|
1521
|
+
}
|
|
1522
|
+
/**
|
|
1523
|
+
* Creates a child file from a stream with this file as the parent.
|
|
1524
|
+
*
|
|
1525
|
+
* This is a convenience method that wraps {@link VaultFile.fromStream} and automatically
|
|
1526
|
+
* sets the current file as the parent. All parameters and behavior are identical to
|
|
1527
|
+
* {@link VaultFile.fromStream}, except parentId is automatically provided.
|
|
1528
|
+
*
|
|
1529
|
+
* @param params - Parameters for creating the child file (same as fromStream, minus parentId)
|
|
1530
|
+
* @param options - Additional options for the request
|
|
1531
|
+
*
|
|
1532
|
+
* @returns A new VaultFile instance ready for streaming upload as a child
|
|
1533
|
+
* @throws {Error} If the parent file ID is not set
|
|
1534
|
+
* @throws {FetchError} If the child file creation fails
|
|
1535
|
+
*
|
|
1536
|
+
* @example
|
|
1537
|
+
* ```ts
|
|
1538
|
+
* // Create a child file for streaming
|
|
1539
|
+
* const parent = await VaultFile.fromContent({
|
|
1540
|
+
* name: 'parent.txt',
|
|
1541
|
+
* content: new Blob(['parent']),
|
|
1542
|
+
* config: { vaultUrl, authStrategy },
|
|
1543
|
+
* upload: true
|
|
1544
|
+
* })
|
|
1545
|
+
* const child = await parent.createChildFromStream({
|
|
1546
|
+
* name: 'large-child.mp4',
|
|
1547
|
+
* contentLength: 100 * 1024 * 1024,
|
|
1548
|
+
* contentType: 'video/mp4'
|
|
1549
|
+
* })
|
|
1550
|
+
* // Upload the stream
|
|
1551
|
+
* const stream = file.stream()
|
|
1552
|
+
* await child.uploadStream(stream, {
|
|
1553
|
+
* contentLength: file.size,
|
|
1554
|
+
* contentType: file.type
|
|
1555
|
+
* })
|
|
1556
|
+
* ```
|
|
1557
|
+
*/
|
|
1558
|
+
async createChildFromStream(params, options) {
|
|
1559
|
+
if (!this.id) {
|
|
1560
|
+
throw new Error("Parent file ID is not set");
|
|
1561
|
+
}
|
|
1562
|
+
return VaultFile.fromStream(
|
|
1563
|
+
{
|
|
1564
|
+
...params,
|
|
1565
|
+
config: this.config,
|
|
1566
|
+
parentId: this.id
|
|
1567
|
+
},
|
|
1568
|
+
options
|
|
1569
|
+
);
|
|
1570
|
+
}
|
|
930
1571
|
}
|
|
931
1572
|
|
|
932
1573
|
function isS3UrlExpired(url) {
|
|
@@ -978,7 +1619,7 @@ const URL_STRATEGIES = [
|
|
|
978
1619
|
];
|
|
979
1620
|
function extractVaultFileIdFromS3Url(url) {
|
|
980
1621
|
if (isVaultReference(url))
|
|
981
|
-
return
|
|
1622
|
+
return vaultUtils.file.getFileIdFromVaultReference(url);
|
|
982
1623
|
try {
|
|
983
1624
|
if (!isVaultFileS3Url(url))
|
|
984
1625
|
return null;
|
|
@@ -1012,12 +1653,18 @@ function vaultClient(vaultConfig) {
|
|
|
1012
1653
|
const name2 = nameOrContent;
|
|
1013
1654
|
const content2 = contentOrNameOrOptions;
|
|
1014
1655
|
const signal2 = options?.signal;
|
|
1015
|
-
|
|
1656
|
+
const parentId2 = options?.parentId;
|
|
1657
|
+
const mimeType2 = options?.mimeType;
|
|
1658
|
+
const upload2 = options?.upload;
|
|
1659
|
+
return VaultFile.fromContent({ content: content2, name: name2, config, parentId: parentId2, mimeType: mimeType2, upload: upload2 }, { signal: signal2 });
|
|
1016
1660
|
}
|
|
1017
1661
|
const content = nameOrContent;
|
|
1018
1662
|
const name = typeof contentOrNameOrOptions === "string" ? contentOrNameOrOptions : void 0;
|
|
1019
1663
|
const signal = isOptionsObject(contentOrNameOrOptions) ? contentOrNameOrOptions.signal : options?.signal;
|
|
1020
|
-
|
|
1664
|
+
const parentId = isOptionsObject(contentOrNameOrOptions) ? contentOrNameOrOptions.parentId : options?.parentId;
|
|
1665
|
+
const mimeType = isOptionsObject(contentOrNameOrOptions) ? contentOrNameOrOptions.mimeType : options?.mimeType;
|
|
1666
|
+
const upload = isOptionsObject(contentOrNameOrOptions) ? contentOrNameOrOptions.upload : options?.upload;
|
|
1667
|
+
return VaultFile.fromContent({ content, name, config, parentId, mimeType, upload }, { signal });
|
|
1021
1668
|
}
|
|
1022
1669
|
function createFromReference(reference, options) {
|
|
1023
1670
|
return VaultFile.fromVaultReference({
|
|
@@ -1030,7 +1677,8 @@ function vaultClient(vaultConfig) {
|
|
|
1030
1677
|
name,
|
|
1031
1678
|
contentLength,
|
|
1032
1679
|
config,
|
|
1033
|
-
contentType: options?.contentType
|
|
1680
|
+
contentType: options?.contentType,
|
|
1681
|
+
parentId: options?.parentId
|
|
1034
1682
|
}, { signal: options?.signal });
|
|
1035
1683
|
}
|
|
1036
1684
|
return { createFromContent, createFromReference, createFromStream };
|