@meistrari/vault-sdk 3.0.0 → 3.1.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 +57 -22
- package/dist/index.d.cts +15 -2
- package/dist/index.d.mts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.mjs +57 -23
- package/package.json +46 -46
package/dist/index.cjs
CHANGED
|
@@ -48,7 +48,7 @@ class FetchError extends Error {
|
|
|
48
48
|
this.name = "FetchError";
|
|
49
49
|
}
|
|
50
50
|
static async from(url, method, response) {
|
|
51
|
-
const text = await response.clone().json().then((json) => JSON.stringify(json, null, 2)).catch(() => response.clone().text());
|
|
51
|
+
const text = await response.clone().json().then((json) => JSON.stringify(json, null, 2)).catch(async () => await response.clone().text());
|
|
52
52
|
const error = new FetchError(`Failed to ${method} ${url}: ${response.status} ${response.statusText}:
|
|
53
53
|
${text}`, url, method, response);
|
|
54
54
|
return error;
|
|
@@ -237,7 +237,7 @@ function getFileName(content) {
|
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
const name = "@meistrari/vault-sdk";
|
|
240
|
-
const version = "3.
|
|
240
|
+
const version = "3.1.1";
|
|
241
241
|
const license = "UNLICENSED";
|
|
242
242
|
const repository = {
|
|
243
243
|
type: "git",
|
|
@@ -264,8 +264,8 @@ const scripts = {
|
|
|
264
264
|
check: "bun run lint && bun tsc --noEmit"
|
|
265
265
|
};
|
|
266
266
|
const dependencies = {
|
|
267
|
-
"@meistrari/file-type": "
|
|
268
|
-
"@meistrari/vault-shared": "0.0
|
|
267
|
+
"@meistrari/file-type": "22.0.0",
|
|
268
|
+
"@meistrari/vault-shared": "0.1.0",
|
|
269
269
|
"mime-types": "3.0.1",
|
|
270
270
|
ofetch: "1.4.1",
|
|
271
271
|
zod: "3.23.8"
|
|
@@ -309,6 +309,7 @@ var __publicField = (obj, key, value) => {
|
|
|
309
309
|
return value;
|
|
310
310
|
};
|
|
311
311
|
const compatibilityDate = "2025-05-19";
|
|
312
|
+
const bunStreamingUploadFixVersion = "1.3.10";
|
|
312
313
|
function detectMimeTypeFromFilename(filename) {
|
|
313
314
|
const extension = filename.split(".").pop()?.toLowerCase();
|
|
314
315
|
if (extension) {
|
|
@@ -319,6 +320,30 @@ function detectMimeTypeFromFilename(filename) {
|
|
|
319
320
|
}
|
|
320
321
|
return void 0;
|
|
321
322
|
}
|
|
323
|
+
function compareDottedVersions(left, right) {
|
|
324
|
+
const leftParts = left.split(".");
|
|
325
|
+
const rightParts = right.split(".");
|
|
326
|
+
const length = Math.max(leftParts.length, rightParts.length);
|
|
327
|
+
for (let index = 0; index < length; index++) {
|
|
328
|
+
const leftPart = Number.parseInt(leftParts[index] ?? "0", 10);
|
|
329
|
+
const rightPart = Number.parseInt(rightParts[index] ?? "0", 10);
|
|
330
|
+
const normalizedLeft = Number.isNaN(leftPart) ? 0 : leftPart;
|
|
331
|
+
const normalizedRight = Number.isNaN(rightPart) ? 0 : rightPart;
|
|
332
|
+
if (normalizedLeft !== normalizedRight) {
|
|
333
|
+
return normalizedLeft - normalizedRight;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return 0;
|
|
337
|
+
}
|
|
338
|
+
function shouldBufferStreamingUploadForBunVersion(bunVersion) {
|
|
339
|
+
return compareDottedVersions(bunVersion, bunStreamingUploadFixVersion) < 0;
|
|
340
|
+
}
|
|
341
|
+
function shouldBufferStreamingUploadOnBun() {
|
|
342
|
+
if (typeof Bun === "undefined") {
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
return shouldBufferStreamingUploadForBunVersion(Bun.version);
|
|
346
|
+
}
|
|
322
347
|
async function wrappedFetch(url, requestInit) {
|
|
323
348
|
const options = {
|
|
324
349
|
...requestInit,
|
|
@@ -426,7 +451,7 @@ class VaultFile {
|
|
|
426
451
|
async _createFile(metadata = {}, options) {
|
|
427
452
|
const response = await this._fetch({
|
|
428
453
|
method: "POST",
|
|
429
|
-
path:
|
|
454
|
+
path: "files",
|
|
430
455
|
body: JSON.stringify({
|
|
431
456
|
size: metadata.size,
|
|
432
457
|
mimeType: metadata.mimeType,
|
|
@@ -495,7 +520,7 @@ class VaultFile {
|
|
|
495
520
|
method: "GET",
|
|
496
521
|
headers: authStrategy.getHeaders(),
|
|
497
522
|
signal: options?.signal
|
|
498
|
-
}).then((response2) => response2.json()).then((data) => schemas.GetDownloadUrlResponse.safeParse(data));
|
|
523
|
+
}).then(async (response2) => await response2.json()).then((data) => schemas.GetDownloadUrlResponse.safeParse(data));
|
|
499
524
|
if (!response.success) {
|
|
500
525
|
throw new Error("Invalid response from vault service");
|
|
501
526
|
}
|
|
@@ -509,7 +534,7 @@ class VaultFile {
|
|
|
509
534
|
name: response.data.metadata?.originalFileName ?? void 0
|
|
510
535
|
};
|
|
511
536
|
if (download) {
|
|
512
|
-
await wrappedFetch(response.data.url, { method: "GET", signal: options?.signal }).then((response2) => response2.blob()).then((blob) => fileParams.content = blob);
|
|
537
|
+
await wrappedFetch(response.data.url, { method: "GET", signal: options?.signal }).then(async (response2) => await response2.blob()).then((blob) => fileParams.content = blob);
|
|
513
538
|
}
|
|
514
539
|
return new VaultFile(fileParams);
|
|
515
540
|
}
|
|
@@ -732,8 +757,8 @@ class VaultFile {
|
|
|
732
757
|
const file = new VaultFile({
|
|
733
758
|
config,
|
|
734
759
|
id: item.id,
|
|
735
|
-
name: item.metadata
|
|
736
|
-
content: preparedFiles[index]
|
|
760
|
+
name: item.metadata.originalFileName ?? preparedFiles[index]?.name,
|
|
761
|
+
content: preparedFiles[index]?.content,
|
|
737
762
|
metadata: item.metadata
|
|
738
763
|
});
|
|
739
764
|
file.lastUploadUrl = {
|
|
@@ -745,7 +770,7 @@ class VaultFile {
|
|
|
745
770
|
if (upload) {
|
|
746
771
|
await Promise.all(
|
|
747
772
|
vaultFiles.map(
|
|
748
|
-
(file) => file.upload(void 0, void 0, { signal: options?.signal })
|
|
773
|
+
async (file) => await file.upload(void 0, void 0, { signal: options?.signal })
|
|
749
774
|
)
|
|
750
775
|
);
|
|
751
776
|
}
|
|
@@ -812,7 +837,7 @@ class VaultFile {
|
|
|
812
837
|
const file = new VaultFile({
|
|
813
838
|
config,
|
|
814
839
|
id: item.id,
|
|
815
|
-
name: item.metadata?.originalFileName ?? preparedFiles[index]
|
|
840
|
+
name: item.metadata?.originalFileName ?? preparedFiles[index]?.name,
|
|
816
841
|
metadata: item.metadata
|
|
817
842
|
});
|
|
818
843
|
file.lastUploadUrl = {
|
|
@@ -867,6 +892,7 @@ class VaultFile {
|
|
|
867
892
|
} catch (error) {
|
|
868
893
|
console.error("Error fetching file metadata", error);
|
|
869
894
|
}
|
|
895
|
+
return void 0;
|
|
870
896
|
}
|
|
871
897
|
/**
|
|
872
898
|
* Returns the vault URI reference for this file.
|
|
@@ -1006,7 +1032,7 @@ class VaultFile {
|
|
|
1006
1032
|
path: `files/${this.id}`,
|
|
1007
1033
|
signal: options?.signal,
|
|
1008
1034
|
...options?.expiresIn ? { query: { expiresIn: options.expiresIn.toString() } } : {}
|
|
1009
|
-
}).then(schemas.GetUploadUrlResponseV2.safeParse);
|
|
1035
|
+
}).then((result) => schemas.GetUploadUrlResponseV2.safeParse(result));
|
|
1010
1036
|
if (!response.success) {
|
|
1011
1037
|
throw new Error(`Invalid response from vault service. ${JSON.stringify(response.error)}`);
|
|
1012
1038
|
}
|
|
@@ -1211,7 +1237,8 @@ class VaultFile {
|
|
|
1211
1237
|
*
|
|
1212
1238
|
* This method is ideal for uploading large files without loading the entire content into memory.
|
|
1213
1239
|
* The stream is sent directly to cloud storage, making it perfect for files larger than a few
|
|
1214
|
-
* megabytes. Note:
|
|
1240
|
+
* megabytes. Note: On Bun versions older than 1.3.10, the stream is buffered due to
|
|
1241
|
+
* implementation limitations.
|
|
1215
1242
|
*
|
|
1216
1243
|
* @param stream - A ReadableStream of Uint8Array chunks containing the file data
|
|
1217
1244
|
* @param options - Required options for the upload
|
|
@@ -1278,10 +1305,10 @@ class VaultFile {
|
|
|
1278
1305
|
headers.set("Content-Type", mimeType);
|
|
1279
1306
|
headers.set("Content-Length", contentLength.toString());
|
|
1280
1307
|
let content = stream;
|
|
1281
|
-
if (stream instanceof ReadableStream &&
|
|
1308
|
+
if (stream instanceof ReadableStream && shouldBufferStreamingUploadOnBun()) {
|
|
1282
1309
|
console.warn(
|
|
1283
|
-
|
|
1284
|
-
{ fileName: this.name, fileSize: contentLength }
|
|
1310
|
+
`[Vault SDK - WARNING] Buffering file upload on Bun ${Bun.version}. Streaming uploads are only buffered on Bun versions older than ${bunStreamingUploadFixVersion}. Large files may cause memory issues. Upgrade Bun or use Node.js for streaming uploads.`,
|
|
1311
|
+
{ fileName: this.name, fileSize: contentLength, bunVersion: Bun.version }
|
|
1285
1312
|
);
|
|
1286
1313
|
const chunks = [];
|
|
1287
1314
|
const reader = stream.getReader();
|
|
@@ -1412,7 +1439,7 @@ class VaultFile {
|
|
|
1412
1439
|
if (!this.metadata?.workspaceId) {
|
|
1413
1440
|
throw new Error("Workspace ID is not set. Call populateMetadata() to populate the metadata fields.");
|
|
1414
1441
|
}
|
|
1415
|
-
return Permalink.create(this.config, {
|
|
1442
|
+
return await Permalink.create(this.config, {
|
|
1416
1443
|
fileId: this.id,
|
|
1417
1444
|
workspaceId: this.metadata.workspaceId,
|
|
1418
1445
|
expiresIn: params.expiresIn
|
|
@@ -1685,7 +1712,7 @@ class VaultFile {
|
|
|
1685
1712
|
if (!this.id) {
|
|
1686
1713
|
throw new Error("Parent file ID is not set");
|
|
1687
1714
|
}
|
|
1688
|
-
return VaultFile.fromContent(
|
|
1715
|
+
return await VaultFile.fromContent(
|
|
1689
1716
|
{
|
|
1690
1717
|
...params,
|
|
1691
1718
|
config: this.config,
|
|
@@ -1734,7 +1761,7 @@ class VaultFile {
|
|
|
1734
1761
|
if (!this.id) {
|
|
1735
1762
|
throw new Error("Parent file ID is not set");
|
|
1736
1763
|
}
|
|
1737
|
-
return VaultFile.fromStream(
|
|
1764
|
+
return await VaultFile.fromStream(
|
|
1738
1765
|
{
|
|
1739
1766
|
...params,
|
|
1740
1767
|
config: this.config,
|
|
@@ -1809,8 +1836,8 @@ class VaultFile {
|
|
|
1809
1836
|
}
|
|
1810
1837
|
}
|
|
1811
1838
|
|
|
1812
|
-
const VAULT_REFERENCE_UUID_REGEX =
|
|
1813
|
-
const VAULT_REFERENCE_SHA256_REGEX =
|
|
1839
|
+
const VAULT_REFERENCE_UUID_REGEX = /vault:\/\/[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i;
|
|
1840
|
+
const VAULT_REFERENCE_SHA256_REGEX = /vault:\/\/[a-f0-9]{64}/i;
|
|
1814
1841
|
function isValidUuidV4(uuid) {
|
|
1815
1842
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(uuid);
|
|
1816
1843
|
}
|
|
@@ -1840,7 +1867,14 @@ function isS3UrlExpired(url) {
|
|
|
1840
1867
|
}
|
|
1841
1868
|
}
|
|
1842
1869
|
function isVaultReference(url) {
|
|
1843
|
-
return VAULT_REFERENCE_UUID_REGEX.test(url) || VAULT_REFERENCE_SHA256_REGEX.test(url);
|
|
1870
|
+
return new RegExp(`^${VAULT_REFERENCE_UUID_REGEX.source}$`, "i").test(url) || new RegExp(`^${VAULT_REFERENCE_SHA256_REGEX.source}$`, "i").test(url);
|
|
1871
|
+
}
|
|
1872
|
+
function extractVaultReferences(text) {
|
|
1873
|
+
const uuidRegex = new RegExp(VAULT_REFERENCE_UUID_REGEX.source, "gi");
|
|
1874
|
+
const sha256Regex = new RegExp(VAULT_REFERENCE_SHA256_REGEX.source, "gi");
|
|
1875
|
+
const uuidMatches = text.match(uuidRegex) || [];
|
|
1876
|
+
const sha256Matches = text.match(sha256Regex) || [];
|
|
1877
|
+
return [...uuidMatches, ...sha256Matches];
|
|
1844
1878
|
}
|
|
1845
1879
|
function isPresignedS3Url(url) {
|
|
1846
1880
|
try {
|
|
@@ -1985,6 +2019,7 @@ exports.FetchError = FetchError;
|
|
|
1985
2019
|
exports.VaultFile = VaultFile;
|
|
1986
2020
|
exports.convertS3UrlToVaultReference = convertS3UrlToVaultReference;
|
|
1987
2021
|
exports.extractVaultFileIdFromS3Url = extractVaultFileIdFromS3Url;
|
|
2022
|
+
exports.extractVaultReferences = extractVaultReferences;
|
|
1988
2023
|
exports.getVaultParamsFromS3Url = getVaultParamsFromS3Url;
|
|
1989
2024
|
exports.isS3UrlExpired = isS3UrlExpired;
|
|
1990
2025
|
exports.isTaggedVaultPresignedUrl = isTaggedVaultPresignedUrl;
|
package/dist/index.d.cts
CHANGED
|
@@ -786,7 +786,8 @@ declare class VaultFile {
|
|
|
786
786
|
*
|
|
787
787
|
* This method is ideal for uploading large files without loading the entire content into memory.
|
|
788
788
|
* The stream is sent directly to cloud storage, making it perfect for files larger than a few
|
|
789
|
-
* megabytes. Note:
|
|
789
|
+
* megabytes. Note: On Bun versions older than 1.3.10, the stream is buffered due to
|
|
790
|
+
* implementation limitations.
|
|
790
791
|
*
|
|
791
792
|
* @param stream - A ReadableStream of Uint8Array chunks containing the file data
|
|
792
793
|
* @param options - Required options for the upload
|
|
@@ -1271,6 +1272,18 @@ declare function isS3UrlExpired(url: string): boolean;
|
|
|
1271
1272
|
* @returns true if the URL is a valid vault reference, false otherwise
|
|
1272
1273
|
*/
|
|
1273
1274
|
declare function isVaultReference(url: string): boolean;
|
|
1275
|
+
/**
|
|
1276
|
+
* Extracts all vault references from a given text string.
|
|
1277
|
+
* Finds both UUID v4 and SHA-256 hash format vault references.
|
|
1278
|
+
*
|
|
1279
|
+
* @param text - The text to search for vault references
|
|
1280
|
+
* @returns An array of vault reference strings found in the text
|
|
1281
|
+
* @example
|
|
1282
|
+
* const text = 'Files: vault://2fce5740-83da-49fe-3f10-b32205893ec0 and vault://abc123...def'
|
|
1283
|
+
* const refs = extractVaultReferences(text)
|
|
1284
|
+
* // Returns: ['vault://2fce5740-83da-49fe-3f10-b32205893ec0', 'vault://abc123...def']
|
|
1285
|
+
*/
|
|
1286
|
+
declare function extractVaultReferences(text: string): string[];
|
|
1274
1287
|
/**
|
|
1275
1288
|
* Checks if a URL seems like a valid presigned S3 URL, with no additional checks.
|
|
1276
1289
|
*
|
|
@@ -1388,5 +1401,5 @@ declare function vaultClient(vaultConfig: VaultConfig): {
|
|
|
1388
1401
|
}) => Promise<VaultFile[]>;
|
|
1389
1402
|
};
|
|
1390
1403
|
|
|
1391
|
-
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, getVaultParamsFromS3Url, isS3UrlExpired, isTaggedVaultPresignedUrl, isPresignedS3Url as isVaultFileS3Url, isVaultReference, vaultClient };
|
|
1404
|
+
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, extractVaultReferences, getVaultParamsFromS3Url, isS3UrlExpired, isTaggedVaultPresignedUrl, isPresignedS3Url as isVaultFileS3Url, isVaultReference, vaultClient };
|
|
1392
1405
|
export type { AuthStrategy, VaultConfig };
|
package/dist/index.d.mts
CHANGED
|
@@ -786,7 +786,8 @@ declare class VaultFile {
|
|
|
786
786
|
*
|
|
787
787
|
* This method is ideal for uploading large files without loading the entire content into memory.
|
|
788
788
|
* The stream is sent directly to cloud storage, making it perfect for files larger than a few
|
|
789
|
-
* megabytes. Note:
|
|
789
|
+
* megabytes. Note: On Bun versions older than 1.3.10, the stream is buffered due to
|
|
790
|
+
* implementation limitations.
|
|
790
791
|
*
|
|
791
792
|
* @param stream - A ReadableStream of Uint8Array chunks containing the file data
|
|
792
793
|
* @param options - Required options for the upload
|
|
@@ -1271,6 +1272,18 @@ declare function isS3UrlExpired(url: string): boolean;
|
|
|
1271
1272
|
* @returns true if the URL is a valid vault reference, false otherwise
|
|
1272
1273
|
*/
|
|
1273
1274
|
declare function isVaultReference(url: string): boolean;
|
|
1275
|
+
/**
|
|
1276
|
+
* Extracts all vault references from a given text string.
|
|
1277
|
+
* Finds both UUID v4 and SHA-256 hash format vault references.
|
|
1278
|
+
*
|
|
1279
|
+
* @param text - The text to search for vault references
|
|
1280
|
+
* @returns An array of vault reference strings found in the text
|
|
1281
|
+
* @example
|
|
1282
|
+
* const text = 'Files: vault://2fce5740-83da-49fe-3f10-b32205893ec0 and vault://abc123...def'
|
|
1283
|
+
* const refs = extractVaultReferences(text)
|
|
1284
|
+
* // Returns: ['vault://2fce5740-83da-49fe-3f10-b32205893ec0', 'vault://abc123...def']
|
|
1285
|
+
*/
|
|
1286
|
+
declare function extractVaultReferences(text: string): string[];
|
|
1274
1287
|
/**
|
|
1275
1288
|
* Checks if a URL seems like a valid presigned S3 URL, with no additional checks.
|
|
1276
1289
|
*
|
|
@@ -1388,5 +1401,5 @@ declare function vaultClient(vaultConfig: VaultConfig): {
|
|
|
1388
1401
|
}) => Promise<VaultFile[]>;
|
|
1389
1402
|
};
|
|
1390
1403
|
|
|
1391
|
-
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, getVaultParamsFromS3Url, isS3UrlExpired, isTaggedVaultPresignedUrl, isPresignedS3Url as isVaultFileS3Url, isVaultReference, vaultClient };
|
|
1404
|
+
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, extractVaultReferences, getVaultParamsFromS3Url, isS3UrlExpired, isTaggedVaultPresignedUrl, isPresignedS3Url as isVaultFileS3Url, isVaultReference, vaultClient };
|
|
1392
1405
|
export type { AuthStrategy, VaultConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -786,7 +786,8 @@ declare class VaultFile {
|
|
|
786
786
|
*
|
|
787
787
|
* This method is ideal for uploading large files without loading the entire content into memory.
|
|
788
788
|
* The stream is sent directly to cloud storage, making it perfect for files larger than a few
|
|
789
|
-
* megabytes. Note:
|
|
789
|
+
* megabytes. Note: On Bun versions older than 1.3.10, the stream is buffered due to
|
|
790
|
+
* implementation limitations.
|
|
790
791
|
*
|
|
791
792
|
* @param stream - A ReadableStream of Uint8Array chunks containing the file data
|
|
792
793
|
* @param options - Required options for the upload
|
|
@@ -1271,6 +1272,18 @@ declare function isS3UrlExpired(url: string): boolean;
|
|
|
1271
1272
|
* @returns true if the URL is a valid vault reference, false otherwise
|
|
1272
1273
|
*/
|
|
1273
1274
|
declare function isVaultReference(url: string): boolean;
|
|
1275
|
+
/**
|
|
1276
|
+
* Extracts all vault references from a given text string.
|
|
1277
|
+
* Finds both UUID v4 and SHA-256 hash format vault references.
|
|
1278
|
+
*
|
|
1279
|
+
* @param text - The text to search for vault references
|
|
1280
|
+
* @returns An array of vault reference strings found in the text
|
|
1281
|
+
* @example
|
|
1282
|
+
* const text = 'Files: vault://2fce5740-83da-49fe-3f10-b32205893ec0 and vault://abc123...def'
|
|
1283
|
+
* const refs = extractVaultReferences(text)
|
|
1284
|
+
* // Returns: ['vault://2fce5740-83da-49fe-3f10-b32205893ec0', 'vault://abc123...def']
|
|
1285
|
+
*/
|
|
1286
|
+
declare function extractVaultReferences(text: string): string[];
|
|
1274
1287
|
/**
|
|
1275
1288
|
* Checks if a URL seems like a valid presigned S3 URL, with no additional checks.
|
|
1276
1289
|
*
|
|
@@ -1388,5 +1401,5 @@ declare function vaultClient(vaultConfig: VaultConfig): {
|
|
|
1388
1401
|
}) => Promise<VaultFile[]>;
|
|
1389
1402
|
};
|
|
1390
1403
|
|
|
1391
|
-
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, getVaultParamsFromS3Url, isS3UrlExpired, isTaggedVaultPresignedUrl, isPresignedS3Url as isVaultFileS3Url, isVaultReference, vaultClient };
|
|
1404
|
+
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, extractVaultReferences, getVaultParamsFromS3Url, isS3UrlExpired, isTaggedVaultPresignedUrl, isPresignedS3Url as isVaultFileS3Url, isVaultReference, vaultClient };
|
|
1392
1405
|
export type { AuthStrategy, VaultConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -42,7 +42,7 @@ class FetchError extends Error {
|
|
|
42
42
|
this.name = "FetchError";
|
|
43
43
|
}
|
|
44
44
|
static async from(url, method, response) {
|
|
45
|
-
const text = await response.clone().json().then((json) => JSON.stringify(json, null, 2)).catch(() => response.clone().text());
|
|
45
|
+
const text = await response.clone().json().then((json) => JSON.stringify(json, null, 2)).catch(async () => await response.clone().text());
|
|
46
46
|
const error = new FetchError(`Failed to ${method} ${url}: ${response.status} ${response.statusText}:
|
|
47
47
|
${text}`, url, method, response);
|
|
48
48
|
return error;
|
|
@@ -231,7 +231,7 @@ function getFileName(content) {
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
const name = "@meistrari/vault-sdk";
|
|
234
|
-
const version = "3.
|
|
234
|
+
const version = "3.1.1";
|
|
235
235
|
const license = "UNLICENSED";
|
|
236
236
|
const repository = {
|
|
237
237
|
type: "git",
|
|
@@ -258,8 +258,8 @@ const scripts = {
|
|
|
258
258
|
check: "bun run lint && bun tsc --noEmit"
|
|
259
259
|
};
|
|
260
260
|
const dependencies = {
|
|
261
|
-
"@meistrari/file-type": "
|
|
262
|
-
"@meistrari/vault-shared": "0.0
|
|
261
|
+
"@meistrari/file-type": "22.0.0",
|
|
262
|
+
"@meistrari/vault-shared": "0.1.0",
|
|
263
263
|
"mime-types": "3.0.1",
|
|
264
264
|
ofetch: "1.4.1",
|
|
265
265
|
zod: "3.23.8"
|
|
@@ -303,6 +303,7 @@ var __publicField = (obj, key, value) => {
|
|
|
303
303
|
return value;
|
|
304
304
|
};
|
|
305
305
|
const compatibilityDate = "2025-05-19";
|
|
306
|
+
const bunStreamingUploadFixVersion = "1.3.10";
|
|
306
307
|
function detectMimeTypeFromFilename(filename) {
|
|
307
308
|
const extension = filename.split(".").pop()?.toLowerCase();
|
|
308
309
|
if (extension) {
|
|
@@ -313,6 +314,30 @@ function detectMimeTypeFromFilename(filename) {
|
|
|
313
314
|
}
|
|
314
315
|
return void 0;
|
|
315
316
|
}
|
|
317
|
+
function compareDottedVersions(left, right) {
|
|
318
|
+
const leftParts = left.split(".");
|
|
319
|
+
const rightParts = right.split(".");
|
|
320
|
+
const length = Math.max(leftParts.length, rightParts.length);
|
|
321
|
+
for (let index = 0; index < length; index++) {
|
|
322
|
+
const leftPart = Number.parseInt(leftParts[index] ?? "0", 10);
|
|
323
|
+
const rightPart = Number.parseInt(rightParts[index] ?? "0", 10);
|
|
324
|
+
const normalizedLeft = Number.isNaN(leftPart) ? 0 : leftPart;
|
|
325
|
+
const normalizedRight = Number.isNaN(rightPart) ? 0 : rightPart;
|
|
326
|
+
if (normalizedLeft !== normalizedRight) {
|
|
327
|
+
return normalizedLeft - normalizedRight;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return 0;
|
|
331
|
+
}
|
|
332
|
+
function shouldBufferStreamingUploadForBunVersion(bunVersion) {
|
|
333
|
+
return compareDottedVersions(bunVersion, bunStreamingUploadFixVersion) < 0;
|
|
334
|
+
}
|
|
335
|
+
function shouldBufferStreamingUploadOnBun() {
|
|
336
|
+
if (typeof Bun === "undefined") {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
return shouldBufferStreamingUploadForBunVersion(Bun.version);
|
|
340
|
+
}
|
|
316
341
|
async function wrappedFetch(url, requestInit) {
|
|
317
342
|
const options = {
|
|
318
343
|
...requestInit,
|
|
@@ -420,7 +445,7 @@ class VaultFile {
|
|
|
420
445
|
async _createFile(metadata = {}, options) {
|
|
421
446
|
const response = await this._fetch({
|
|
422
447
|
method: "POST",
|
|
423
|
-
path:
|
|
448
|
+
path: "files",
|
|
424
449
|
body: JSON.stringify({
|
|
425
450
|
size: metadata.size,
|
|
426
451
|
mimeType: metadata.mimeType,
|
|
@@ -489,7 +514,7 @@ class VaultFile {
|
|
|
489
514
|
method: "GET",
|
|
490
515
|
headers: authStrategy.getHeaders(),
|
|
491
516
|
signal: options?.signal
|
|
492
|
-
}).then((response2) => response2.json()).then((data) => GetDownloadUrlResponse.safeParse(data));
|
|
517
|
+
}).then(async (response2) => await response2.json()).then((data) => GetDownloadUrlResponse.safeParse(data));
|
|
493
518
|
if (!response.success) {
|
|
494
519
|
throw new Error("Invalid response from vault service");
|
|
495
520
|
}
|
|
@@ -503,7 +528,7 @@ class VaultFile {
|
|
|
503
528
|
name: response.data.metadata?.originalFileName ?? void 0
|
|
504
529
|
};
|
|
505
530
|
if (download) {
|
|
506
|
-
await wrappedFetch(response.data.url, { method: "GET", signal: options?.signal }).then((response2) => response2.blob()).then((blob) => fileParams.content = blob);
|
|
531
|
+
await wrappedFetch(response.data.url, { method: "GET", signal: options?.signal }).then(async (response2) => await response2.blob()).then((blob) => fileParams.content = blob);
|
|
507
532
|
}
|
|
508
533
|
return new VaultFile(fileParams);
|
|
509
534
|
}
|
|
@@ -726,8 +751,8 @@ class VaultFile {
|
|
|
726
751
|
const file = new VaultFile({
|
|
727
752
|
config,
|
|
728
753
|
id: item.id,
|
|
729
|
-
name: item.metadata
|
|
730
|
-
content: preparedFiles[index]
|
|
754
|
+
name: item.metadata.originalFileName ?? preparedFiles[index]?.name,
|
|
755
|
+
content: preparedFiles[index]?.content,
|
|
731
756
|
metadata: item.metadata
|
|
732
757
|
});
|
|
733
758
|
file.lastUploadUrl = {
|
|
@@ -739,7 +764,7 @@ class VaultFile {
|
|
|
739
764
|
if (upload) {
|
|
740
765
|
await Promise.all(
|
|
741
766
|
vaultFiles.map(
|
|
742
|
-
(file) => file.upload(void 0, void 0, { signal: options?.signal })
|
|
767
|
+
async (file) => await file.upload(void 0, void 0, { signal: options?.signal })
|
|
743
768
|
)
|
|
744
769
|
);
|
|
745
770
|
}
|
|
@@ -806,7 +831,7 @@ class VaultFile {
|
|
|
806
831
|
const file = new VaultFile({
|
|
807
832
|
config,
|
|
808
833
|
id: item.id,
|
|
809
|
-
name: item.metadata?.originalFileName ?? preparedFiles[index]
|
|
834
|
+
name: item.metadata?.originalFileName ?? preparedFiles[index]?.name,
|
|
810
835
|
metadata: item.metadata
|
|
811
836
|
});
|
|
812
837
|
file.lastUploadUrl = {
|
|
@@ -861,6 +886,7 @@ class VaultFile {
|
|
|
861
886
|
} catch (error) {
|
|
862
887
|
console.error("Error fetching file metadata", error);
|
|
863
888
|
}
|
|
889
|
+
return void 0;
|
|
864
890
|
}
|
|
865
891
|
/**
|
|
866
892
|
* Returns the vault URI reference for this file.
|
|
@@ -1000,7 +1026,7 @@ class VaultFile {
|
|
|
1000
1026
|
path: `files/${this.id}`,
|
|
1001
1027
|
signal: options?.signal,
|
|
1002
1028
|
...options?.expiresIn ? { query: { expiresIn: options.expiresIn.toString() } } : {}
|
|
1003
|
-
}).then(GetUploadUrlResponseV2.safeParse);
|
|
1029
|
+
}).then((result) => GetUploadUrlResponseV2.safeParse(result));
|
|
1004
1030
|
if (!response.success) {
|
|
1005
1031
|
throw new Error(`Invalid response from vault service. ${JSON.stringify(response.error)}`);
|
|
1006
1032
|
}
|
|
@@ -1205,7 +1231,8 @@ class VaultFile {
|
|
|
1205
1231
|
*
|
|
1206
1232
|
* This method is ideal for uploading large files without loading the entire content into memory.
|
|
1207
1233
|
* The stream is sent directly to cloud storage, making it perfect for files larger than a few
|
|
1208
|
-
* megabytes. Note:
|
|
1234
|
+
* megabytes. Note: On Bun versions older than 1.3.10, the stream is buffered due to
|
|
1235
|
+
* implementation limitations.
|
|
1209
1236
|
*
|
|
1210
1237
|
* @param stream - A ReadableStream of Uint8Array chunks containing the file data
|
|
1211
1238
|
* @param options - Required options for the upload
|
|
@@ -1272,10 +1299,10 @@ class VaultFile {
|
|
|
1272
1299
|
headers.set("Content-Type", mimeType);
|
|
1273
1300
|
headers.set("Content-Length", contentLength.toString());
|
|
1274
1301
|
let content = stream;
|
|
1275
|
-
if (stream instanceof ReadableStream &&
|
|
1302
|
+
if (stream instanceof ReadableStream && shouldBufferStreamingUploadOnBun()) {
|
|
1276
1303
|
console.warn(
|
|
1277
|
-
|
|
1278
|
-
{ fileName: this.name, fileSize: contentLength }
|
|
1304
|
+
`[Vault SDK - WARNING] Buffering file upload on Bun ${Bun.version}. Streaming uploads are only buffered on Bun versions older than ${bunStreamingUploadFixVersion}. Large files may cause memory issues. Upgrade Bun or use Node.js for streaming uploads.`,
|
|
1305
|
+
{ fileName: this.name, fileSize: contentLength, bunVersion: Bun.version }
|
|
1279
1306
|
);
|
|
1280
1307
|
const chunks = [];
|
|
1281
1308
|
const reader = stream.getReader();
|
|
@@ -1406,7 +1433,7 @@ class VaultFile {
|
|
|
1406
1433
|
if (!this.metadata?.workspaceId) {
|
|
1407
1434
|
throw new Error("Workspace ID is not set. Call populateMetadata() to populate the metadata fields.");
|
|
1408
1435
|
}
|
|
1409
|
-
return Permalink.create(this.config, {
|
|
1436
|
+
return await Permalink.create(this.config, {
|
|
1410
1437
|
fileId: this.id,
|
|
1411
1438
|
workspaceId: this.metadata.workspaceId,
|
|
1412
1439
|
expiresIn: params.expiresIn
|
|
@@ -1679,7 +1706,7 @@ class VaultFile {
|
|
|
1679
1706
|
if (!this.id) {
|
|
1680
1707
|
throw new Error("Parent file ID is not set");
|
|
1681
1708
|
}
|
|
1682
|
-
return VaultFile.fromContent(
|
|
1709
|
+
return await VaultFile.fromContent(
|
|
1683
1710
|
{
|
|
1684
1711
|
...params,
|
|
1685
1712
|
config: this.config,
|
|
@@ -1728,7 +1755,7 @@ class VaultFile {
|
|
|
1728
1755
|
if (!this.id) {
|
|
1729
1756
|
throw new Error("Parent file ID is not set");
|
|
1730
1757
|
}
|
|
1731
|
-
return VaultFile.fromStream(
|
|
1758
|
+
return await VaultFile.fromStream(
|
|
1732
1759
|
{
|
|
1733
1760
|
...params,
|
|
1734
1761
|
config: this.config,
|
|
@@ -1803,8 +1830,8 @@ class VaultFile {
|
|
|
1803
1830
|
}
|
|
1804
1831
|
}
|
|
1805
1832
|
|
|
1806
|
-
const VAULT_REFERENCE_UUID_REGEX =
|
|
1807
|
-
const VAULT_REFERENCE_SHA256_REGEX =
|
|
1833
|
+
const VAULT_REFERENCE_UUID_REGEX = /vault:\/\/[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i;
|
|
1834
|
+
const VAULT_REFERENCE_SHA256_REGEX = /vault:\/\/[a-f0-9]{64}/i;
|
|
1808
1835
|
function isValidUuidV4(uuid) {
|
|
1809
1836
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(uuid);
|
|
1810
1837
|
}
|
|
@@ -1834,7 +1861,14 @@ function isS3UrlExpired(url) {
|
|
|
1834
1861
|
}
|
|
1835
1862
|
}
|
|
1836
1863
|
function isVaultReference(url) {
|
|
1837
|
-
return VAULT_REFERENCE_UUID_REGEX.test(url) || VAULT_REFERENCE_SHA256_REGEX.test(url);
|
|
1864
|
+
return new RegExp(`^${VAULT_REFERENCE_UUID_REGEX.source}$`, "i").test(url) || new RegExp(`^${VAULT_REFERENCE_SHA256_REGEX.source}$`, "i").test(url);
|
|
1865
|
+
}
|
|
1866
|
+
function extractVaultReferences(text) {
|
|
1867
|
+
const uuidRegex = new RegExp(VAULT_REFERENCE_UUID_REGEX.source, "gi");
|
|
1868
|
+
const sha256Regex = new RegExp(VAULT_REFERENCE_SHA256_REGEX.source, "gi");
|
|
1869
|
+
const uuidMatches = text.match(uuidRegex) || [];
|
|
1870
|
+
const sha256Matches = text.match(sha256Regex) || [];
|
|
1871
|
+
return [...uuidMatches, ...sha256Matches];
|
|
1838
1872
|
}
|
|
1839
1873
|
function isPresignedS3Url(url) {
|
|
1840
1874
|
try {
|
|
@@ -1973,4 +2007,4 @@ function vaultClient(vaultConfig) {
|
|
|
1973
2007
|
return { createFromContent, createFromReference, createFromStream, createFromContentBulk, createFromStreamBulk };
|
|
1974
2008
|
}
|
|
1975
2009
|
|
|
1976
|
-
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, getVaultParamsFromS3Url, isS3UrlExpired, isTaggedVaultPresignedUrl, isPresignedS3Url as isVaultFileS3Url, isVaultReference, vaultClient };
|
|
2010
|
+
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, extractVaultReferences, getVaultParamsFromS3Url, isS3UrlExpired, isTaggedVaultPresignedUrl, isPresignedS3Url as isVaultFileS3Url, isVaultReference, vaultClient };
|
package/package.json
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"main": "dist/index.mjs",
|
|
17
|
-
"types": "dist/index.d.ts",
|
|
18
|
-
"files": [
|
|
19
|
-
"dist"
|
|
20
|
-
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"test": "vitest --no-watch",
|
|
23
|
-
"test:watch": "vitest",
|
|
24
|
-
"build": "unbuild",
|
|
25
|
-
"lint": "eslint .",
|
|
26
|
-
"lint:fix": "eslint . --fix",
|
|
27
|
-
"check": "bun run lint && bun tsc --noEmit"
|
|
28
|
-
},
|
|
29
|
-
"dependencies": {
|
|
30
|
-
"@meistrari/file-type": "^22.0.0",
|
|
31
|
-
"@meistrari/vault-shared": "0.0.7",
|
|
32
|
-
"mime-types": "3.0.1",
|
|
33
|
-
"ofetch": "1.4.1",
|
|
34
|
-
"zod": "3.23.8"
|
|
35
|
-
},
|
|
36
|
-
"devDependencies": {
|
|
37
|
-
"@types/bun": "latest",
|
|
38
|
-
"@types/mime-types": "3.0.1",
|
|
39
|
-
"msw": "2.6.8",
|
|
40
|
-
"unbuild": "2.0.0",
|
|
41
|
-
"vitest": "2.1.9"
|
|
42
|
-
},
|
|
43
|
-
"peerDependencies": {
|
|
44
|
-
"typescript": "^5.0.0"
|
|
45
|
-
},
|
|
46
|
-
"publishConfig": {
|
|
47
|
-
"access": "public"
|
|
2
|
+
"name": "@meistrari/vault-sdk",
|
|
3
|
+
"version": "3.1.1",
|
|
4
|
+
"license": "UNLICENSED",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/meistrari/vault.git"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
48
14
|
}
|
|
15
|
+
},
|
|
16
|
+
"main": "dist/index.mjs",
|
|
17
|
+
"types": "dist/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "vitest --no-watch",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"build": "unbuild",
|
|
25
|
+
"lint": "eslint .",
|
|
26
|
+
"lint:fix": "eslint . --fix",
|
|
27
|
+
"check": "bun run lint && bun tsc --noEmit"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@meistrari/file-type": "22.0.0",
|
|
31
|
+
"@meistrari/vault-shared": "0.1.0",
|
|
32
|
+
"mime-types": "3.0.1",
|
|
33
|
+
"ofetch": "1.4.1",
|
|
34
|
+
"zod": "3.23.8"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/bun": "latest",
|
|
38
|
+
"@types/mime-types": "3.0.1",
|
|
39
|
+
"msw": "2.6.8",
|
|
40
|
+
"unbuild": "2.0.0",
|
|
41
|
+
"vitest": "2.1.9"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"typescript": "^5.0.0"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
}
|
|
49
49
|
}
|