@meistrari/vault-sdk 1.4.3 → 1.6.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/dist/index.cjs +328 -11
- package/dist/index.d.cts +146 -6
- package/dist/index.d.mts +146 -6
- package/dist/index.d.ts +146 -6
- package/dist/index.mjs +325 -12
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -98,7 +98,7 @@ class Permalink {
|
|
|
98
98
|
/**
|
|
99
99
|
* Get a new permalink instance from its ID.
|
|
100
100
|
*
|
|
101
|
-
* @param
|
|
101
|
+
* @param vaultConfig - The vault config.
|
|
102
102
|
* @param id - The permalink ID.
|
|
103
103
|
* @returns The permalink.
|
|
104
104
|
*/
|
|
@@ -116,7 +116,7 @@ class Permalink {
|
|
|
116
116
|
/**
|
|
117
117
|
* Create a new permalink.
|
|
118
118
|
*
|
|
119
|
-
* @param
|
|
119
|
+
* @param vaultConfig - The vault config.
|
|
120
120
|
* @param params - The parameters for the permalink.
|
|
121
121
|
* @param params.expiresIn - Time, in seconds, the permalink will be valid for.
|
|
122
122
|
* @param params.fileId - The ID of the file to create a permalink for.
|
|
@@ -197,9 +197,92 @@ async function detectFileMimeType(blob) {
|
|
|
197
197
|
if (result?.mime) {
|
|
198
198
|
return result.mime;
|
|
199
199
|
}
|
|
200
|
+
const text = await blob.text();
|
|
201
|
+
const trimmedText = text.trim();
|
|
202
|
+
if (trimmedText.startsWith("{") && trimmedText.endsWith("}") || trimmedText.startsWith("[") && trimmedText.endsWith("]")) {
|
|
203
|
+
try {
|
|
204
|
+
JSON.parse(trimmedText);
|
|
205
|
+
return "application/json";
|
|
206
|
+
} catch {
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const lines = text.split("\n").slice(0, 5).filter((line) => line.trim() !== "");
|
|
210
|
+
if (lines.length > 1) {
|
|
211
|
+
const commaCounts = lines.map((line) => (line.match(/,/g) || []).length);
|
|
212
|
+
const allSame = commaCounts.every((count) => count === commaCounts[0]);
|
|
213
|
+
if (allSame && commaCounts[0] > 0) {
|
|
214
|
+
return "text/csv";
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (!text.includes("\0") && /^[\s\S]{1,1000}$/.test(text.slice(0, 1e3))) {
|
|
218
|
+
return "text/plain";
|
|
219
|
+
}
|
|
200
220
|
return void 0;
|
|
201
221
|
}
|
|
202
222
|
|
|
223
|
+
const name = "@meistrari/vault-sdk";
|
|
224
|
+
const version = "1.6.0";
|
|
225
|
+
const license = "UNLICENSED";
|
|
226
|
+
const repository = {
|
|
227
|
+
type: "git",
|
|
228
|
+
url: "https://github.com/meistrari/vault.git"
|
|
229
|
+
};
|
|
230
|
+
const exports$1 = {
|
|
231
|
+
".": {
|
|
232
|
+
types: "./dist/index.d.ts",
|
|
233
|
+
"import": "./dist/index.mjs",
|
|
234
|
+
require: "./dist/index.cjs"
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
const main = "dist/index.mjs";
|
|
238
|
+
const types = "dist/index.d.ts";
|
|
239
|
+
const files = [
|
|
240
|
+
"dist"
|
|
241
|
+
];
|
|
242
|
+
const scripts = {
|
|
243
|
+
test: "vitest --no-watch",
|
|
244
|
+
"test:watch": "vitest",
|
|
245
|
+
build: "unbuild",
|
|
246
|
+
lint: "eslint .",
|
|
247
|
+
"lint:fix": "eslint . --fix",
|
|
248
|
+
check: "bun run lint && bun tsc --noEmit"
|
|
249
|
+
};
|
|
250
|
+
const dependencies = {
|
|
251
|
+
"@meistrari/vault-shared": "workspace:*",
|
|
252
|
+
"file-type": "21.0.0",
|
|
253
|
+
"mime-types": "3.0.1",
|
|
254
|
+
ofetch: "1.4.1",
|
|
255
|
+
zod: "3.23.8"
|
|
256
|
+
};
|
|
257
|
+
const devDependencies = {
|
|
258
|
+
"@types/bun": "latest",
|
|
259
|
+
"@types/mime-types": "3.0.1",
|
|
260
|
+
msw: "2.6.8",
|
|
261
|
+
unbuild: "2.0.0",
|
|
262
|
+
vitest: "2.1.9"
|
|
263
|
+
};
|
|
264
|
+
const peerDependencies = {
|
|
265
|
+
typescript: "^5.0.0"
|
|
266
|
+
};
|
|
267
|
+
const publishConfig = {
|
|
268
|
+
access: "public"
|
|
269
|
+
};
|
|
270
|
+
const packageJson = {
|
|
271
|
+
name: name,
|
|
272
|
+
version: version,
|
|
273
|
+
license: license,
|
|
274
|
+
repository: repository,
|
|
275
|
+
exports: exports$1,
|
|
276
|
+
main: main,
|
|
277
|
+
types: types,
|
|
278
|
+
files: files,
|
|
279
|
+
scripts: scripts,
|
|
280
|
+
dependencies: dependencies,
|
|
281
|
+
devDependencies: devDependencies,
|
|
282
|
+
peerDependencies: peerDependencies,
|
|
283
|
+
publishConfig: publishConfig
|
|
284
|
+
};
|
|
285
|
+
|
|
203
286
|
var __defProp = Object.defineProperty;
|
|
204
287
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
205
288
|
var __publicField = (obj, key, value) => {
|
|
@@ -210,8 +293,23 @@ const compatibilityDate = "2025-05-19";
|
|
|
210
293
|
function removeVaultPrefix(url) {
|
|
211
294
|
return url.replace("vault://", "");
|
|
212
295
|
}
|
|
213
|
-
|
|
214
|
-
const
|
|
296
|
+
function detectMimeTypeFromFilename(filename) {
|
|
297
|
+
const extension = filename.split(".").pop()?.toLowerCase();
|
|
298
|
+
if (extension) {
|
|
299
|
+
const mimeType = mimeTypes.lookup(`.${extension}`);
|
|
300
|
+
if (mimeType) {
|
|
301
|
+
return mimeType;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return void 0;
|
|
305
|
+
}
|
|
306
|
+
async function wrappedFetch(url, requestInit) {
|
|
307
|
+
const options = {
|
|
308
|
+
...requestInit,
|
|
309
|
+
duplex: requestInit.body instanceof ReadableStream ? "half" : void 0
|
|
310
|
+
};
|
|
311
|
+
const request = new Request(url, options);
|
|
312
|
+
request.headers.set("User-Agent", `vault-js-sdk:${packageJson.version}`);
|
|
215
313
|
const response = await fetch(request);
|
|
216
314
|
if (!response.ok) {
|
|
217
315
|
throw await FetchError.from(request.url, request.method, response);
|
|
@@ -220,9 +318,11 @@ async function wrappedFetch(...params) {
|
|
|
220
318
|
}
|
|
221
319
|
class VaultFile {
|
|
222
320
|
/**
|
|
223
|
-
* Constructs a new VaultFile instance. Direct usage of the constructor is not recommended
|
|
224
|
-
*
|
|
225
|
-
*
|
|
321
|
+
* Constructs a new VaultFile instance. Direct usage of the constructor is not recommended.
|
|
322
|
+
*
|
|
323
|
+
* Use the static methods {@link VaultFile.fromVaultReference} when dealing with an existing file in the vault,
|
|
324
|
+
* {@link VaultFile.fromContent} when preparing a new file for upload,
|
|
325
|
+
* or {@link VaultFile.fromStream} when preparing a new file for streaming upload.
|
|
226
326
|
*
|
|
227
327
|
* @param params - The parameters for the VaultFile constructor
|
|
228
328
|
* @param params.config - The configuration for the VaultFile
|
|
@@ -253,7 +353,9 @@ class VaultFile {
|
|
|
253
353
|
* @returns The headers for the request
|
|
254
354
|
*/
|
|
255
355
|
get headers() {
|
|
256
|
-
|
|
356
|
+
const headers = this.config.authStrategy.getHeaders();
|
|
357
|
+
headers.set("User-Agent", `vault-js-sdk:${packageJson.version}`);
|
|
358
|
+
return headers;
|
|
257
359
|
}
|
|
258
360
|
/**
|
|
259
361
|
* Performs a request to the vault service and handles the response or errors.
|
|
@@ -276,12 +378,16 @@ class VaultFile {
|
|
|
276
378
|
url.searchParams.set(key, value);
|
|
277
379
|
});
|
|
278
380
|
}
|
|
279
|
-
const
|
|
381
|
+
const requestInit = {
|
|
280
382
|
method,
|
|
281
383
|
body,
|
|
282
384
|
headers,
|
|
283
385
|
signal
|
|
284
|
-
}
|
|
386
|
+
};
|
|
387
|
+
if (body && body instanceof ReadableStream) {
|
|
388
|
+
requestInit.duplex = "half";
|
|
389
|
+
}
|
|
390
|
+
const response = await wrappedFetch(url, requestInit);
|
|
285
391
|
if (response.status === 204 || response.headers.get("content-length") === "0") {
|
|
286
392
|
return null;
|
|
287
393
|
}
|
|
@@ -454,6 +560,48 @@ class VaultFile {
|
|
|
454
560
|
}
|
|
455
561
|
return file;
|
|
456
562
|
}
|
|
563
|
+
/**
|
|
564
|
+
* Creates a new VaultFile instance for streaming upload workflows.
|
|
565
|
+
* This method creates a VaultFile with placeholder content that's optimized for streaming uploads.
|
|
566
|
+
*
|
|
567
|
+
* @param params - The parameters for creating a VaultFile for streaming
|
|
568
|
+
* @param params.name - The name of the file
|
|
569
|
+
* @param params.contentLength - The size of the content in bytes
|
|
570
|
+
* @param params.config - The configuration for the VaultFile
|
|
571
|
+
* @param params.contentType - The MIME type of the content (optional)
|
|
572
|
+
* @param options - The options for the request
|
|
573
|
+
* @param options.signal - The signal to abort the request
|
|
574
|
+
*
|
|
575
|
+
* @returns A new VaultFile instance ready for streaming upload
|
|
576
|
+
*
|
|
577
|
+
* @example
|
|
578
|
+
* ```ts
|
|
579
|
+
* // Create VaultFile for streaming
|
|
580
|
+
* const vaultFile = await VaultFile.fromStream({
|
|
581
|
+
* name: 'large-video.mp4',
|
|
582
|
+
* contentLength: 100 * 1024 * 1024, // 100MB
|
|
583
|
+
* contentType: 'video/mp4',
|
|
584
|
+
* config: { vaultUrl, authStrategy }
|
|
585
|
+
* })
|
|
586
|
+
*
|
|
587
|
+
* // Upload using a stream
|
|
588
|
+
* const fileStream = file.stream()
|
|
589
|
+
* await vaultFile.uploadStream(fileStream, {
|
|
590
|
+
* contentLength: file.size,
|
|
591
|
+
* contentType: file.type
|
|
592
|
+
* })
|
|
593
|
+
* ```
|
|
594
|
+
*/
|
|
595
|
+
static async fromStream(params, options) {
|
|
596
|
+
const { name, contentLength, config: vaultConfig, contentType } = params;
|
|
597
|
+
const config = resolveConfig(vaultConfig);
|
|
598
|
+
const file = new VaultFile({ config, name });
|
|
599
|
+
await file._createFile({
|
|
600
|
+
size: contentLength,
|
|
601
|
+
mimeType: contentType || "application/octet-stream"
|
|
602
|
+
}, { signal: options?.signal });
|
|
603
|
+
return file;
|
|
604
|
+
}
|
|
457
605
|
/**
|
|
458
606
|
* Populates the metadata of the file instance.
|
|
459
607
|
* @param options - The options for the request
|
|
@@ -621,6 +769,90 @@ class VaultFile {
|
|
|
621
769
|
return blob;
|
|
622
770
|
return await blobToBase64(blob);
|
|
623
771
|
}
|
|
772
|
+
/**
|
|
773
|
+
* Downloads a file from the vault as a stream for memory-efficient processing.
|
|
774
|
+
*
|
|
775
|
+
* @param options - The options for the request
|
|
776
|
+
* @param options.signal - The signal to abort the request
|
|
777
|
+
*
|
|
778
|
+
* @returns A ReadableStream that yields chunks of the file data
|
|
779
|
+
*
|
|
780
|
+
* @example
|
|
781
|
+
* ```ts
|
|
782
|
+
* const vaultFile = await VaultFile.fromVaultReference('vault://1234567890', { vaultUrl, authStrategy })
|
|
783
|
+
* const stream = await vaultFile.downloadStream()
|
|
784
|
+
*
|
|
785
|
+
* // Process the stream chunk by chunk
|
|
786
|
+
* const reader = stream.getReader()
|
|
787
|
+
* try {
|
|
788
|
+
* while (true) {
|
|
789
|
+
* const { done, value } = await reader.read()
|
|
790
|
+
* if (done) break
|
|
791
|
+
* // Process the chunk (Uint8Array)
|
|
792
|
+
* console.log('Received chunk of size:', value.length)
|
|
793
|
+
* }
|
|
794
|
+
* } finally {
|
|
795
|
+
* reader.releaseLock()
|
|
796
|
+
* }
|
|
797
|
+
* ```
|
|
798
|
+
*/
|
|
799
|
+
async downloadStream(options) {
|
|
800
|
+
const downloadUrl = await this.getDownloadUrl({ signal: options?.signal });
|
|
801
|
+
const response = await wrappedFetch(downloadUrl, {
|
|
802
|
+
method: "GET",
|
|
803
|
+
signal: options?.signal
|
|
804
|
+
});
|
|
805
|
+
if (!response.body) {
|
|
806
|
+
throw new Error("Response body is not readable");
|
|
807
|
+
}
|
|
808
|
+
return response.body;
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* Uploads a file to the vault using a stream for memory-efficient processing.
|
|
812
|
+
*
|
|
813
|
+
* @param stream - The readable stream of file data to upload
|
|
814
|
+
* @param options - The options for the request
|
|
815
|
+
* @param options.signal - The signal to abort the request
|
|
816
|
+
* @param options.contentLength - The total size of the content (required for S3 uploads)
|
|
817
|
+
* @param options.contentType - The MIME type of the content (will be detected if not provided)
|
|
818
|
+
*
|
|
819
|
+
* @throws {Error} If contentLength is not provided
|
|
820
|
+
* @throws {FetchError} If the upload fails
|
|
821
|
+
* @returns Promise that resolves when upload is complete
|
|
822
|
+
*
|
|
823
|
+
* @example
|
|
824
|
+
* ```ts
|
|
825
|
+
* const file = new File(['content'], 'document.txt')
|
|
826
|
+
* const vaultFile = await VaultFile.fromStream('document.txt', file.size, {
|
|
827
|
+
* contentType: file.type,
|
|
828
|
+
* config: { vaultUrl, authStrategy }
|
|
829
|
+
* })
|
|
830
|
+
*
|
|
831
|
+
* // Upload using the stream directly
|
|
832
|
+
* const stream = file.stream()
|
|
833
|
+
* await vaultFile.uploadStream(stream, {
|
|
834
|
+
* contentLength: file.size,
|
|
835
|
+
* contentType: file.type
|
|
836
|
+
* })
|
|
837
|
+
* ```
|
|
838
|
+
*/
|
|
839
|
+
async uploadStream(stream, options) {
|
|
840
|
+
const { contentLength, contentType, signal } = options;
|
|
841
|
+
if (contentLength === void 0 || contentLength < 0) {
|
|
842
|
+
throw new Error("contentLength must be provided and non-negative for streaming uploads");
|
|
843
|
+
}
|
|
844
|
+
const uploadUrl = await this.getUploadUrl({ signal });
|
|
845
|
+
const mimeType = contentType ?? this.metadata?.mimeType ?? (this.name ? detectMimeTypeFromFilename(this.name) : void 0) ?? "application/octet-stream";
|
|
846
|
+
const headers = new Headers();
|
|
847
|
+
headers.set("Content-Type", mimeType);
|
|
848
|
+
headers.set("Content-Length", contentLength.toString());
|
|
849
|
+
await wrappedFetch(uploadUrl, {
|
|
850
|
+
method: "PUT",
|
|
851
|
+
body: stream,
|
|
852
|
+
headers,
|
|
853
|
+
signal
|
|
854
|
+
});
|
|
855
|
+
}
|
|
624
856
|
/**
|
|
625
857
|
* Deletes the file from the vault.
|
|
626
858
|
* @param options - The options for the request
|
|
@@ -679,6 +911,79 @@ class VaultFile {
|
|
|
679
911
|
}
|
|
680
912
|
}
|
|
681
913
|
|
|
914
|
+
function isS3UrlExpired(url) {
|
|
915
|
+
try {
|
|
916
|
+
const urlObj = new URL(url);
|
|
917
|
+
const amzDate = urlObj.searchParams.get("X-Amz-Date");
|
|
918
|
+
const amzExpires = urlObj.searchParams.get("X-Amz-Expires");
|
|
919
|
+
if (!amzDate || !amzExpires)
|
|
920
|
+
return false;
|
|
921
|
+
const year = Number.parseInt(amzDate.substring(0, 4));
|
|
922
|
+
const month = Number.parseInt(amzDate.substring(4, 6)) - 1;
|
|
923
|
+
const day = Number.parseInt(amzDate.substring(6, 8));
|
|
924
|
+
const hours = Number.parseInt(amzDate.substring(9, 11));
|
|
925
|
+
const minutes = Number.parseInt(amzDate.substring(11, 13));
|
|
926
|
+
const seconds = Number.parseInt(amzDate.substring(13, 15));
|
|
927
|
+
const signedDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
|
|
928
|
+
const expiresInSeconds = Number.parseInt(amzExpires);
|
|
929
|
+
const expirationTime = signedDate.getTime() + expiresInSeconds * 1e3;
|
|
930
|
+
const currentTime = Date.now();
|
|
931
|
+
return currentTime > expirationTime;
|
|
932
|
+
} catch {
|
|
933
|
+
return false;
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
function isVaultReference(url) {
|
|
937
|
+
return url.startsWith("vault://") && url.length === 10;
|
|
938
|
+
}
|
|
939
|
+
function isVaultFileS3Url(url) {
|
|
940
|
+
const urlObj = new URL(url);
|
|
941
|
+
const amzDate = urlObj.searchParams.get("X-Amz-Date");
|
|
942
|
+
const amzExpires = urlObj.searchParams.get("X-Amz-Expires");
|
|
943
|
+
return urlObj.hostname.includes("amazonaws.com") && Boolean(amzDate) && Boolean(amzExpires);
|
|
944
|
+
}
|
|
945
|
+
const URL_STRATEGIES = [
|
|
946
|
+
{
|
|
947
|
+
separator: "/",
|
|
948
|
+
extractSegments: ([workspaceId, vaultFileId]) => ({
|
|
949
|
+
workspaceId,
|
|
950
|
+
vaultFileId
|
|
951
|
+
})
|
|
952
|
+
},
|
|
953
|
+
{
|
|
954
|
+
separator: "_",
|
|
955
|
+
extractSegments: ([vaultFileId, workspaceId]) => ({
|
|
956
|
+
vaultFileId,
|
|
957
|
+
workspaceId
|
|
958
|
+
})
|
|
959
|
+
}
|
|
960
|
+
];
|
|
961
|
+
function extractVaultFileIdFromS3Url(url) {
|
|
962
|
+
if (isVaultReference(url))
|
|
963
|
+
return url.replace("vault://", "");
|
|
964
|
+
try {
|
|
965
|
+
if (!isVaultFileS3Url(url))
|
|
966
|
+
return null;
|
|
967
|
+
const urlObj = new URL(url);
|
|
968
|
+
const strategy = URL_STRATEGIES.find((strategy2) => urlObj.pathname.includes(strategy2.separator));
|
|
969
|
+
if (!strategy)
|
|
970
|
+
return null;
|
|
971
|
+
const segments = urlObj.pathname.split(strategy.separator).filter((segment) => segment.length > 0);
|
|
972
|
+
if (segments.length < 2)
|
|
973
|
+
return null;
|
|
974
|
+
const extractedIds = strategy.extractSegments(segments);
|
|
975
|
+
if (!extractedIds || !extractedIds.vaultFileId || !extractedIds.workspaceId || extractedIds.vaultFileId.length < 32)
|
|
976
|
+
return null;
|
|
977
|
+
return extractedIds.vaultFileId;
|
|
978
|
+
} catch {
|
|
979
|
+
return null;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
function convertS3UrlToVaultReference(url) {
|
|
983
|
+
const vaultFileId = extractVaultFileIdFromS3Url(url);
|
|
984
|
+
return vaultFileId ? `vault://${vaultFileId}` : null;
|
|
985
|
+
}
|
|
986
|
+
|
|
682
987
|
function vaultClient(vaultConfig) {
|
|
683
988
|
const config = resolveConfig(vaultConfig);
|
|
684
989
|
function createFromContent(name, content, options) {
|
|
@@ -694,11 +999,23 @@ function vaultClient(vaultConfig) {
|
|
|
694
999
|
config
|
|
695
1000
|
}, { signal: options?.signal });
|
|
696
1001
|
}
|
|
697
|
-
|
|
1002
|
+
async function createFromStream(name, contentLength, options) {
|
|
1003
|
+
return VaultFile.fromStream({
|
|
1004
|
+
name,
|
|
1005
|
+
contentLength,
|
|
1006
|
+
config,
|
|
1007
|
+
contentType: options?.contentType
|
|
1008
|
+
}, { signal: options?.signal });
|
|
1009
|
+
}
|
|
1010
|
+
return { createFromContent, createFromReference, createFromStream };
|
|
698
1011
|
}
|
|
699
1012
|
|
|
700
1013
|
exports.APIKeyAuthStrategy = APIKeyAuthStrategy;
|
|
701
1014
|
exports.DataTokenAuthStrategy = DataTokenAuthStrategy;
|
|
702
1015
|
exports.FetchError = FetchError;
|
|
703
1016
|
exports.VaultFile = VaultFile;
|
|
1017
|
+
exports.convertS3UrlToVaultReference = convertS3UrlToVaultReference;
|
|
1018
|
+
exports.extractVaultFileIdFromS3Url = extractVaultFileIdFromS3Url;
|
|
1019
|
+
exports.isS3UrlExpired = isS3UrlExpired;
|
|
1020
|
+
exports.isVaultFileS3Url = isVaultFileS3Url;
|
|
704
1021
|
exports.vaultClient = vaultClient;
|
package/dist/index.d.cts
CHANGED
|
@@ -45,7 +45,7 @@ declare class Permalink {
|
|
|
45
45
|
/**
|
|
46
46
|
* Get a new permalink instance from its ID.
|
|
47
47
|
*
|
|
48
|
-
* @param
|
|
48
|
+
* @param vaultConfig - The vault config.
|
|
49
49
|
* @param id - The permalink ID.
|
|
50
50
|
* @returns The permalink.
|
|
51
51
|
*/
|
|
@@ -53,7 +53,7 @@ declare class Permalink {
|
|
|
53
53
|
/**
|
|
54
54
|
* Create a new permalink.
|
|
55
55
|
*
|
|
56
|
-
* @param
|
|
56
|
+
* @param vaultConfig - The vault config.
|
|
57
57
|
* @param params - The parameters for the permalink.
|
|
58
58
|
* @param params.expiresIn - Time, in seconds, the permalink will be valid for.
|
|
59
59
|
* @param params.fileId - The ID of the file to create a permalink for.
|
|
@@ -114,9 +114,11 @@ declare class VaultFile {
|
|
|
114
114
|
} | undefined;
|
|
115
115
|
private readonly baseUrl;
|
|
116
116
|
/**
|
|
117
|
-
* Constructs a new VaultFile instance. Direct usage of the constructor is not recommended
|
|
118
|
-
*
|
|
119
|
-
*
|
|
117
|
+
* Constructs a new VaultFile instance. Direct usage of the constructor is not recommended.
|
|
118
|
+
*
|
|
119
|
+
* Use the static methods {@link VaultFile.fromVaultReference} when dealing with an existing file in the vault,
|
|
120
|
+
* {@link VaultFile.fromContent} when preparing a new file for upload,
|
|
121
|
+
* or {@link VaultFile.fromStream} when preparing a new file for streaming upload.
|
|
120
122
|
*
|
|
121
123
|
* @param params - The parameters for the VaultFile constructor
|
|
122
124
|
* @param params.config - The configuration for the VaultFile
|
|
@@ -254,6 +256,46 @@ declare class VaultFile {
|
|
|
254
256
|
}, options?: {
|
|
255
257
|
signal?: AbortSignal;
|
|
256
258
|
}): Promise<VaultFile>;
|
|
259
|
+
/**
|
|
260
|
+
* Creates a new VaultFile instance for streaming upload workflows.
|
|
261
|
+
* This method creates a VaultFile with placeholder content that's optimized for streaming uploads.
|
|
262
|
+
*
|
|
263
|
+
* @param params - The parameters for creating a VaultFile for streaming
|
|
264
|
+
* @param params.name - The name of the file
|
|
265
|
+
* @param params.contentLength - The size of the content in bytes
|
|
266
|
+
* @param params.config - The configuration for the VaultFile
|
|
267
|
+
* @param params.contentType - The MIME type of the content (optional)
|
|
268
|
+
* @param options - The options for the request
|
|
269
|
+
* @param options.signal - The signal to abort the request
|
|
270
|
+
*
|
|
271
|
+
* @returns A new VaultFile instance ready for streaming upload
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```ts
|
|
275
|
+
* // Create VaultFile for streaming
|
|
276
|
+
* const vaultFile = await VaultFile.fromStream({
|
|
277
|
+
* name: 'large-video.mp4',
|
|
278
|
+
* contentLength: 100 * 1024 * 1024, // 100MB
|
|
279
|
+
* contentType: 'video/mp4',
|
|
280
|
+
* config: { vaultUrl, authStrategy }
|
|
281
|
+
* })
|
|
282
|
+
*
|
|
283
|
+
* // Upload using a stream
|
|
284
|
+
* const fileStream = file.stream()
|
|
285
|
+
* await vaultFile.uploadStream(fileStream, {
|
|
286
|
+
* contentLength: file.size,
|
|
287
|
+
* contentType: file.type
|
|
288
|
+
* })
|
|
289
|
+
* ```
|
|
290
|
+
*/
|
|
291
|
+
static fromStream(params: {
|
|
292
|
+
name: string;
|
|
293
|
+
contentLength: number;
|
|
294
|
+
config: VaultConfig;
|
|
295
|
+
contentType?: string;
|
|
296
|
+
}, options?: {
|
|
297
|
+
signal?: AbortSignal;
|
|
298
|
+
}): Promise<VaultFile>;
|
|
257
299
|
/**
|
|
258
300
|
* Populates the metadata of the file instance.
|
|
259
301
|
* @param options - The options for the request
|
|
@@ -364,6 +406,70 @@ declare class VaultFile {
|
|
|
364
406
|
download(responseType: 'base64', options?: {
|
|
365
407
|
signal?: AbortSignal;
|
|
366
408
|
}): Promise<string>;
|
|
409
|
+
/**
|
|
410
|
+
* Downloads a file from the vault as a stream for memory-efficient processing.
|
|
411
|
+
*
|
|
412
|
+
* @param options - The options for the request
|
|
413
|
+
* @param options.signal - The signal to abort the request
|
|
414
|
+
*
|
|
415
|
+
* @returns A ReadableStream that yields chunks of the file data
|
|
416
|
+
*
|
|
417
|
+
* @example
|
|
418
|
+
* ```ts
|
|
419
|
+
* const vaultFile = await VaultFile.fromVaultReference('vault://1234567890', { vaultUrl, authStrategy })
|
|
420
|
+
* const stream = await vaultFile.downloadStream()
|
|
421
|
+
*
|
|
422
|
+
* // Process the stream chunk by chunk
|
|
423
|
+
* const reader = stream.getReader()
|
|
424
|
+
* try {
|
|
425
|
+
* while (true) {
|
|
426
|
+
* const { done, value } = await reader.read()
|
|
427
|
+
* if (done) break
|
|
428
|
+
* // Process the chunk (Uint8Array)
|
|
429
|
+
* console.log('Received chunk of size:', value.length)
|
|
430
|
+
* }
|
|
431
|
+
* } finally {
|
|
432
|
+
* reader.releaseLock()
|
|
433
|
+
* }
|
|
434
|
+
* ```
|
|
435
|
+
*/
|
|
436
|
+
downloadStream(options?: {
|
|
437
|
+
signal?: AbortSignal;
|
|
438
|
+
}): Promise<ReadableStream<Uint8Array>>;
|
|
439
|
+
/**
|
|
440
|
+
* Uploads a file to the vault using a stream for memory-efficient processing.
|
|
441
|
+
*
|
|
442
|
+
* @param stream - The readable stream of file data to upload
|
|
443
|
+
* @param options - The options for the request
|
|
444
|
+
* @param options.signal - The signal to abort the request
|
|
445
|
+
* @param options.contentLength - The total size of the content (required for S3 uploads)
|
|
446
|
+
* @param options.contentType - The MIME type of the content (will be detected if not provided)
|
|
447
|
+
*
|
|
448
|
+
* @throws {Error} If contentLength is not provided
|
|
449
|
+
* @throws {FetchError} If the upload fails
|
|
450
|
+
* @returns Promise that resolves when upload is complete
|
|
451
|
+
*
|
|
452
|
+
* @example
|
|
453
|
+
* ```ts
|
|
454
|
+
* const file = new File(['content'], 'document.txt')
|
|
455
|
+
* const vaultFile = await VaultFile.fromStream('document.txt', file.size, {
|
|
456
|
+
* contentType: file.type,
|
|
457
|
+
* config: { vaultUrl, authStrategy }
|
|
458
|
+
* })
|
|
459
|
+
*
|
|
460
|
+
* // Upload using the stream directly
|
|
461
|
+
* const stream = file.stream()
|
|
462
|
+
* await vaultFile.uploadStream(stream, {
|
|
463
|
+
* contentLength: file.size,
|
|
464
|
+
* contentType: file.type
|
|
465
|
+
* })
|
|
466
|
+
* ```
|
|
467
|
+
*/
|
|
468
|
+
uploadStream(stream: ReadableStream<Uint8Array>, options: {
|
|
469
|
+
signal?: AbortSignal;
|
|
470
|
+
contentLength: number;
|
|
471
|
+
contentType?: string;
|
|
472
|
+
}): Promise<void>;
|
|
367
473
|
/**
|
|
368
474
|
* Deletes the file from the vault.
|
|
369
475
|
* @param options - The options for the request
|
|
@@ -399,6 +505,36 @@ declare class VaultFile {
|
|
|
399
505
|
}): Promise<Permalink[]>;
|
|
400
506
|
}
|
|
401
507
|
|
|
508
|
+
/**
|
|
509
|
+
* Checks if an Amazon S3 signed URL has expired
|
|
510
|
+
* @param url - The S3 URL to check for expiration
|
|
511
|
+
* @returns true if the URL is expired, false if it's still valid or not an S3 signed URL
|
|
512
|
+
* @example
|
|
513
|
+
* const expired = isS3UrlExpired('https://vault-prod.s3.amazonaws.com/file?X-Amz-Date=20240101T000000Z&X-Amz-Expires=3600')
|
|
514
|
+
*/
|
|
515
|
+
declare function isS3UrlExpired(url: string): boolean;
|
|
516
|
+
/**
|
|
517
|
+
* Checks if a URL is a valid S3 vault URL
|
|
518
|
+
* @param url - The S3 URL to check
|
|
519
|
+
* @returns true if the URL is a valid S3 vault URL, false otherwise
|
|
520
|
+
*/
|
|
521
|
+
declare function isVaultFileS3Url(url: string): boolean;
|
|
522
|
+
/**
|
|
523
|
+
* Detects if a URL is an expired S3 vault URL and extracts the vault file ID
|
|
524
|
+
* Returns null if not a vault S3 URL, not expired, or extraction fails
|
|
525
|
+
*/
|
|
526
|
+
declare function extractVaultFileIdFromS3Url(url: string): string | null;
|
|
527
|
+
/**
|
|
528
|
+
* Converts an S3 vault URL to a vault reference format
|
|
529
|
+
* Extracts the vault file ID from the S3 URL path and formats it as vault://[fileId]
|
|
530
|
+
* @param url - The S3 vault URL to convert
|
|
531
|
+
* @returns A vault reference string (vault://[fileId]) if successful, null if the URL is not a valid vault S3 URL
|
|
532
|
+
* @example
|
|
533
|
+
* const ref = convertS3UrlToVaultReference('https://vault-prod.s3.amazonaws.com/workspace123/2fce574083da49fe3f10b32205893ec0bb024fe1c7673fa54927fdfe1d0db9d6?...')
|
|
534
|
+
* // Returns: 'vault://2fce574083da49fe3f10b32205893ec0bb024fe1c7673fa54927fdfe1d0db9d6'
|
|
535
|
+
*/
|
|
536
|
+
declare function convertS3UrlToVaultReference(url: string): string | null;
|
|
537
|
+
|
|
402
538
|
declare function vaultClient(vaultConfig: VaultConfig): {
|
|
403
539
|
createFromContent: (name: string, content: Blob | File, options?: {
|
|
404
540
|
signal?: AbortSignal;
|
|
@@ -406,7 +542,11 @@ declare function vaultClient(vaultConfig: VaultConfig): {
|
|
|
406
542
|
createFromReference: (reference: string, options?: {
|
|
407
543
|
signal?: AbortSignal;
|
|
408
544
|
}) => Promise<VaultFile>;
|
|
545
|
+
createFromStream: (name: string, contentLength: number, options?: {
|
|
546
|
+
contentType?: string;
|
|
547
|
+
signal?: AbortSignal;
|
|
548
|
+
}) => Promise<VaultFile>;
|
|
409
549
|
};
|
|
410
550
|
|
|
411
|
-
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, vaultClient };
|
|
551
|
+
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, isS3UrlExpired, isVaultFileS3Url, vaultClient };
|
|
412
552
|
export type { AuthStrategy, VaultConfig };
|