@meistrari/vault-sdk 1.4.2 → 1.5.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 +152 -6
- package/dist/index.d.cts +31 -1
- package/dist/index.d.mts +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/index.mjs +149 -7
- package/package.json +47 -47
package/dist/index.cjs
CHANGED
|
@@ -181,9 +181,8 @@ async function getFileHash(blob) {
|
|
|
181
181
|
return hashHex;
|
|
182
182
|
}
|
|
183
183
|
async function detectFileMimeType(blob) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
return result.mime;
|
|
184
|
+
if (blob instanceof Blob && blob.type) {
|
|
185
|
+
return blob.type;
|
|
187
186
|
}
|
|
188
187
|
if ("name" in blob && typeof blob.name === "string") {
|
|
189
188
|
const extension = blob.name.split(".").pop()?.toLowerCase();
|
|
@@ -194,12 +193,76 @@ async function detectFileMimeType(blob) {
|
|
|
194
193
|
}
|
|
195
194
|
}
|
|
196
195
|
}
|
|
197
|
-
|
|
198
|
-
|
|
196
|
+
const result = await fileType.fileTypeFromBlob(blob).catch(() => void 0);
|
|
197
|
+
if (result?.mime) {
|
|
198
|
+
return result.mime;
|
|
199
199
|
}
|
|
200
200
|
return void 0;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
+
const name = "@meistrari/vault-sdk";
|
|
204
|
+
const version = "1.5.0";
|
|
205
|
+
const license = "UNLICENSED";
|
|
206
|
+
const repository = {
|
|
207
|
+
type: "git",
|
|
208
|
+
url: "https://github.com/meistrari/vault.git"
|
|
209
|
+
};
|
|
210
|
+
const exports$1 = {
|
|
211
|
+
".": {
|
|
212
|
+
types: "./dist/index.d.ts",
|
|
213
|
+
"import": "./dist/index.mjs",
|
|
214
|
+
require: "./dist/index.cjs"
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
const main = "dist/index.mjs";
|
|
218
|
+
const types = "dist/index.d.ts";
|
|
219
|
+
const files = [
|
|
220
|
+
"dist"
|
|
221
|
+
];
|
|
222
|
+
const scripts = {
|
|
223
|
+
test: "vitest --no-watch",
|
|
224
|
+
"test:watch": "vitest",
|
|
225
|
+
build: "unbuild",
|
|
226
|
+
lint: "eslint .",
|
|
227
|
+
"lint:fix": "eslint . --fix",
|
|
228
|
+
check: "bun run lint && bun tsc --noEmit"
|
|
229
|
+
};
|
|
230
|
+
const dependencies = {
|
|
231
|
+
"@meistrari/vault-shared": "workspace:*",
|
|
232
|
+
"file-type": "21.0.0",
|
|
233
|
+
"mime-types": "3.0.1",
|
|
234
|
+
ofetch: "1.4.1",
|
|
235
|
+
zod: "3.23.8"
|
|
236
|
+
};
|
|
237
|
+
const devDependencies = {
|
|
238
|
+
"@types/bun": "latest",
|
|
239
|
+
"@types/mime-types": "3.0.1",
|
|
240
|
+
msw: "2.6.8",
|
|
241
|
+
unbuild: "2.0.0",
|
|
242
|
+
vitest: "2.1.9"
|
|
243
|
+
};
|
|
244
|
+
const peerDependencies = {
|
|
245
|
+
typescript: "^5.0.0"
|
|
246
|
+
};
|
|
247
|
+
const publishConfig = {
|
|
248
|
+
access: "public"
|
|
249
|
+
};
|
|
250
|
+
const packageJson = {
|
|
251
|
+
name: name,
|
|
252
|
+
version: version,
|
|
253
|
+
license: license,
|
|
254
|
+
repository: repository,
|
|
255
|
+
exports: exports$1,
|
|
256
|
+
main: main,
|
|
257
|
+
types: types,
|
|
258
|
+
files: files,
|
|
259
|
+
scripts: scripts,
|
|
260
|
+
dependencies: dependencies,
|
|
261
|
+
devDependencies: devDependencies,
|
|
262
|
+
peerDependencies: peerDependencies,
|
|
263
|
+
publishConfig: publishConfig
|
|
264
|
+
};
|
|
265
|
+
|
|
203
266
|
var __defProp = Object.defineProperty;
|
|
204
267
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
205
268
|
var __publicField = (obj, key, value) => {
|
|
@@ -212,6 +275,7 @@ function removeVaultPrefix(url) {
|
|
|
212
275
|
}
|
|
213
276
|
async function wrappedFetch(...params) {
|
|
214
277
|
const request = new Request(...params);
|
|
278
|
+
request.headers.set("User-Agent", `vault-js-sdk:${packageJson.version}`);
|
|
215
279
|
const response = await fetch(request);
|
|
216
280
|
if (!response.ok) {
|
|
217
281
|
throw await FetchError.from(request.url, request.method, response);
|
|
@@ -253,7 +317,9 @@ class VaultFile {
|
|
|
253
317
|
* @returns The headers for the request
|
|
254
318
|
*/
|
|
255
319
|
get headers() {
|
|
256
|
-
|
|
320
|
+
const headers = this.config.authStrategy.getHeaders();
|
|
321
|
+
headers.set("User-Agent", `vault-js-sdk:${packageJson.version}`);
|
|
322
|
+
return headers;
|
|
257
323
|
}
|
|
258
324
|
/**
|
|
259
325
|
* Performs a request to the vault service and handles the response or errors.
|
|
@@ -282,6 +348,9 @@ class VaultFile {
|
|
|
282
348
|
headers,
|
|
283
349
|
signal
|
|
284
350
|
});
|
|
351
|
+
if (response.status === 204 || response.headers.get("content-length") === "0") {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
285
354
|
const content = await response.json();
|
|
286
355
|
return content;
|
|
287
356
|
}
|
|
@@ -676,6 +745,79 @@ class VaultFile {
|
|
|
676
745
|
}
|
|
677
746
|
}
|
|
678
747
|
|
|
748
|
+
function isS3UrlExpired(url) {
|
|
749
|
+
try {
|
|
750
|
+
const urlObj = new URL(url);
|
|
751
|
+
const amzDate = urlObj.searchParams.get("X-Amz-Date");
|
|
752
|
+
const amzExpires = urlObj.searchParams.get("X-Amz-Expires");
|
|
753
|
+
if (!amzDate || !amzExpires)
|
|
754
|
+
return false;
|
|
755
|
+
const year = Number.parseInt(amzDate.substring(0, 4));
|
|
756
|
+
const month = Number.parseInt(amzDate.substring(4, 6)) - 1;
|
|
757
|
+
const day = Number.parseInt(amzDate.substring(6, 8));
|
|
758
|
+
const hours = Number.parseInt(amzDate.substring(9, 11));
|
|
759
|
+
const minutes = Number.parseInt(amzDate.substring(11, 13));
|
|
760
|
+
const seconds = Number.parseInt(amzDate.substring(13, 15));
|
|
761
|
+
const signedDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
|
|
762
|
+
const expiresInSeconds = Number.parseInt(amzExpires);
|
|
763
|
+
const expirationTime = signedDate.getTime() + expiresInSeconds * 1e3;
|
|
764
|
+
const currentTime = Date.now();
|
|
765
|
+
return currentTime > expirationTime;
|
|
766
|
+
} catch {
|
|
767
|
+
return false;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
function isVaultReference(url) {
|
|
771
|
+
return url.startsWith("vault://") && url.length === 10;
|
|
772
|
+
}
|
|
773
|
+
function isVaultFileS3Url(url) {
|
|
774
|
+
const urlObj = new URL(url);
|
|
775
|
+
const amzDate = urlObj.searchParams.get("X-Amz-Date");
|
|
776
|
+
const amzExpires = urlObj.searchParams.get("X-Amz-Expires");
|
|
777
|
+
return urlObj.hostname.includes("amazonaws.com") && Boolean(amzDate) && Boolean(amzExpires);
|
|
778
|
+
}
|
|
779
|
+
const URL_STRATEGIES = [
|
|
780
|
+
{
|
|
781
|
+
separator: "/",
|
|
782
|
+
extractSegments: ([workspaceId, vaultFileId]) => ({
|
|
783
|
+
workspaceId,
|
|
784
|
+
vaultFileId
|
|
785
|
+
})
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
separator: "_",
|
|
789
|
+
extractSegments: ([vaultFileId, workspaceId]) => ({
|
|
790
|
+
vaultFileId,
|
|
791
|
+
workspaceId
|
|
792
|
+
})
|
|
793
|
+
}
|
|
794
|
+
];
|
|
795
|
+
function extractVaultFileIdFromS3Url(url) {
|
|
796
|
+
if (isVaultReference(url))
|
|
797
|
+
return url.replace("vault://", "");
|
|
798
|
+
try {
|
|
799
|
+
if (!isVaultFileS3Url(url))
|
|
800
|
+
return null;
|
|
801
|
+
const urlObj = new URL(url);
|
|
802
|
+
const strategy = URL_STRATEGIES.find((strategy2) => urlObj.pathname.includes(strategy2.separator));
|
|
803
|
+
if (!strategy)
|
|
804
|
+
return null;
|
|
805
|
+
const segments = urlObj.pathname.split(strategy.separator).filter((segment) => segment.length > 0);
|
|
806
|
+
if (segments.length < 2)
|
|
807
|
+
return null;
|
|
808
|
+
const extractedIds = strategy.extractSegments(segments);
|
|
809
|
+
if (!extractedIds || !extractedIds.vaultFileId || !extractedIds.workspaceId || extractedIds.vaultFileId.length < 32)
|
|
810
|
+
return null;
|
|
811
|
+
return extractedIds.vaultFileId;
|
|
812
|
+
} catch {
|
|
813
|
+
return null;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
function convertS3UrlToVaultReference(url) {
|
|
817
|
+
const vaultFileId = extractVaultFileIdFromS3Url(url);
|
|
818
|
+
return vaultFileId ? `vault://${vaultFileId}` : null;
|
|
819
|
+
}
|
|
820
|
+
|
|
679
821
|
function vaultClient(vaultConfig) {
|
|
680
822
|
const config = resolveConfig(vaultConfig);
|
|
681
823
|
function createFromContent(name, content, options) {
|
|
@@ -698,4 +840,8 @@ exports.APIKeyAuthStrategy = APIKeyAuthStrategy;
|
|
|
698
840
|
exports.DataTokenAuthStrategy = DataTokenAuthStrategy;
|
|
699
841
|
exports.FetchError = FetchError;
|
|
700
842
|
exports.VaultFile = VaultFile;
|
|
843
|
+
exports.convertS3UrlToVaultReference = convertS3UrlToVaultReference;
|
|
844
|
+
exports.extractVaultFileIdFromS3Url = extractVaultFileIdFromS3Url;
|
|
845
|
+
exports.isS3UrlExpired = isS3UrlExpired;
|
|
846
|
+
exports.isVaultFileS3Url = isVaultFileS3Url;
|
|
701
847
|
exports.vaultClient = vaultClient;
|
package/dist/index.d.cts
CHANGED
|
@@ -399,6 +399,36 @@ declare class VaultFile {
|
|
|
399
399
|
}): Promise<Permalink[]>;
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Checks if an Amazon S3 signed URL has expired
|
|
404
|
+
* @param url - The S3 URL to check for expiration
|
|
405
|
+
* @returns true if the URL is expired, false if it's still valid or not an S3 signed URL
|
|
406
|
+
* @example
|
|
407
|
+
* const expired = isS3UrlExpired('https://vault-prod.s3.amazonaws.com/file?X-Amz-Date=20240101T000000Z&X-Amz-Expires=3600')
|
|
408
|
+
*/
|
|
409
|
+
declare function isS3UrlExpired(url: string): boolean;
|
|
410
|
+
/**
|
|
411
|
+
* Checks if a URL is a valid S3 vault URL
|
|
412
|
+
* @param url - The S3 URL to check
|
|
413
|
+
* @returns true if the URL is a valid S3 vault URL, false otherwise
|
|
414
|
+
*/
|
|
415
|
+
declare function isVaultFileS3Url(url: string): boolean;
|
|
416
|
+
/**
|
|
417
|
+
* Detects if a URL is an expired S3 vault URL and extracts the vault file ID
|
|
418
|
+
* Returns null if not a vault S3 URL, not expired, or extraction fails
|
|
419
|
+
*/
|
|
420
|
+
declare function extractVaultFileIdFromS3Url(url: string): string | null;
|
|
421
|
+
/**
|
|
422
|
+
* Converts an S3 vault URL to a vault reference format
|
|
423
|
+
* Extracts the vault file ID from the S3 URL path and formats it as vault://[fileId]
|
|
424
|
+
* @param url - The S3 vault URL to convert
|
|
425
|
+
* @returns A vault reference string (vault://[fileId]) if successful, null if the URL is not a valid vault S3 URL
|
|
426
|
+
* @example
|
|
427
|
+
* const ref = convertS3UrlToVaultReference('https://vault-prod.s3.amazonaws.com/workspace123/2fce574083da49fe3f10b32205893ec0bb024fe1c7673fa54927fdfe1d0db9d6?...')
|
|
428
|
+
* // Returns: 'vault://2fce574083da49fe3f10b32205893ec0bb024fe1c7673fa54927fdfe1d0db9d6'
|
|
429
|
+
*/
|
|
430
|
+
declare function convertS3UrlToVaultReference(url: string): string | null;
|
|
431
|
+
|
|
402
432
|
declare function vaultClient(vaultConfig: VaultConfig): {
|
|
403
433
|
createFromContent: (name: string, content: Blob | File, options?: {
|
|
404
434
|
signal?: AbortSignal;
|
|
@@ -408,5 +438,5 @@ declare function vaultClient(vaultConfig: VaultConfig): {
|
|
|
408
438
|
}) => Promise<VaultFile>;
|
|
409
439
|
};
|
|
410
440
|
|
|
411
|
-
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, vaultClient };
|
|
441
|
+
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, isS3UrlExpired, isVaultFileS3Url, vaultClient };
|
|
412
442
|
export type { AuthStrategy, VaultConfig };
|
package/dist/index.d.mts
CHANGED
|
@@ -399,6 +399,36 @@ declare class VaultFile {
|
|
|
399
399
|
}): Promise<Permalink[]>;
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Checks if an Amazon S3 signed URL has expired
|
|
404
|
+
* @param url - The S3 URL to check for expiration
|
|
405
|
+
* @returns true if the URL is expired, false if it's still valid or not an S3 signed URL
|
|
406
|
+
* @example
|
|
407
|
+
* const expired = isS3UrlExpired('https://vault-prod.s3.amazonaws.com/file?X-Amz-Date=20240101T000000Z&X-Amz-Expires=3600')
|
|
408
|
+
*/
|
|
409
|
+
declare function isS3UrlExpired(url: string): boolean;
|
|
410
|
+
/**
|
|
411
|
+
* Checks if a URL is a valid S3 vault URL
|
|
412
|
+
* @param url - The S3 URL to check
|
|
413
|
+
* @returns true if the URL is a valid S3 vault URL, false otherwise
|
|
414
|
+
*/
|
|
415
|
+
declare function isVaultFileS3Url(url: string): boolean;
|
|
416
|
+
/**
|
|
417
|
+
* Detects if a URL is an expired S3 vault URL and extracts the vault file ID
|
|
418
|
+
* Returns null if not a vault S3 URL, not expired, or extraction fails
|
|
419
|
+
*/
|
|
420
|
+
declare function extractVaultFileIdFromS3Url(url: string): string | null;
|
|
421
|
+
/**
|
|
422
|
+
* Converts an S3 vault URL to a vault reference format
|
|
423
|
+
* Extracts the vault file ID from the S3 URL path and formats it as vault://[fileId]
|
|
424
|
+
* @param url - The S3 vault URL to convert
|
|
425
|
+
* @returns A vault reference string (vault://[fileId]) if successful, null if the URL is not a valid vault S3 URL
|
|
426
|
+
* @example
|
|
427
|
+
* const ref = convertS3UrlToVaultReference('https://vault-prod.s3.amazonaws.com/workspace123/2fce574083da49fe3f10b32205893ec0bb024fe1c7673fa54927fdfe1d0db9d6?...')
|
|
428
|
+
* // Returns: 'vault://2fce574083da49fe3f10b32205893ec0bb024fe1c7673fa54927fdfe1d0db9d6'
|
|
429
|
+
*/
|
|
430
|
+
declare function convertS3UrlToVaultReference(url: string): string | null;
|
|
431
|
+
|
|
402
432
|
declare function vaultClient(vaultConfig: VaultConfig): {
|
|
403
433
|
createFromContent: (name: string, content: Blob | File, options?: {
|
|
404
434
|
signal?: AbortSignal;
|
|
@@ -408,5 +438,5 @@ declare function vaultClient(vaultConfig: VaultConfig): {
|
|
|
408
438
|
}) => Promise<VaultFile>;
|
|
409
439
|
};
|
|
410
440
|
|
|
411
|
-
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, vaultClient };
|
|
441
|
+
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, isS3UrlExpired, isVaultFileS3Url, vaultClient };
|
|
412
442
|
export type { AuthStrategy, VaultConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -399,6 +399,36 @@ declare class VaultFile {
|
|
|
399
399
|
}): Promise<Permalink[]>;
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Checks if an Amazon S3 signed URL has expired
|
|
404
|
+
* @param url - The S3 URL to check for expiration
|
|
405
|
+
* @returns true if the URL is expired, false if it's still valid or not an S3 signed URL
|
|
406
|
+
* @example
|
|
407
|
+
* const expired = isS3UrlExpired('https://vault-prod.s3.amazonaws.com/file?X-Amz-Date=20240101T000000Z&X-Amz-Expires=3600')
|
|
408
|
+
*/
|
|
409
|
+
declare function isS3UrlExpired(url: string): boolean;
|
|
410
|
+
/**
|
|
411
|
+
* Checks if a URL is a valid S3 vault URL
|
|
412
|
+
* @param url - The S3 URL to check
|
|
413
|
+
* @returns true if the URL is a valid S3 vault URL, false otherwise
|
|
414
|
+
*/
|
|
415
|
+
declare function isVaultFileS3Url(url: string): boolean;
|
|
416
|
+
/**
|
|
417
|
+
* Detects if a URL is an expired S3 vault URL and extracts the vault file ID
|
|
418
|
+
* Returns null if not a vault S3 URL, not expired, or extraction fails
|
|
419
|
+
*/
|
|
420
|
+
declare function extractVaultFileIdFromS3Url(url: string): string | null;
|
|
421
|
+
/**
|
|
422
|
+
* Converts an S3 vault URL to a vault reference format
|
|
423
|
+
* Extracts the vault file ID from the S3 URL path and formats it as vault://[fileId]
|
|
424
|
+
* @param url - The S3 vault URL to convert
|
|
425
|
+
* @returns A vault reference string (vault://[fileId]) if successful, null if the URL is not a valid vault S3 URL
|
|
426
|
+
* @example
|
|
427
|
+
* const ref = convertS3UrlToVaultReference('https://vault-prod.s3.amazonaws.com/workspace123/2fce574083da49fe3f10b32205893ec0bb024fe1c7673fa54927fdfe1d0db9d6?...')
|
|
428
|
+
* // Returns: 'vault://2fce574083da49fe3f10b32205893ec0bb024fe1c7673fa54927fdfe1d0db9d6'
|
|
429
|
+
*/
|
|
430
|
+
declare function convertS3UrlToVaultReference(url: string): string | null;
|
|
431
|
+
|
|
402
432
|
declare function vaultClient(vaultConfig: VaultConfig): {
|
|
403
433
|
createFromContent: (name: string, content: Blob | File, options?: {
|
|
404
434
|
signal?: AbortSignal;
|
|
@@ -408,5 +438,5 @@ declare function vaultClient(vaultConfig: VaultConfig): {
|
|
|
408
438
|
}) => Promise<VaultFile>;
|
|
409
439
|
};
|
|
410
440
|
|
|
411
|
-
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, vaultClient };
|
|
441
|
+
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, isS3UrlExpired, isVaultFileS3Url, vaultClient };
|
|
412
442
|
export type { AuthStrategy, VaultConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -179,9 +179,8 @@ async function getFileHash(blob) {
|
|
|
179
179
|
return hashHex;
|
|
180
180
|
}
|
|
181
181
|
async function detectFileMimeType(blob) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return result.mime;
|
|
182
|
+
if (blob instanceof Blob && blob.type) {
|
|
183
|
+
return blob.type;
|
|
185
184
|
}
|
|
186
185
|
if ("name" in blob && typeof blob.name === "string") {
|
|
187
186
|
const extension = blob.name.split(".").pop()?.toLowerCase();
|
|
@@ -192,12 +191,76 @@ async function detectFileMimeType(blob) {
|
|
|
192
191
|
}
|
|
193
192
|
}
|
|
194
193
|
}
|
|
195
|
-
|
|
196
|
-
|
|
194
|
+
const result = await fileTypeFromBlob(blob).catch(() => void 0);
|
|
195
|
+
if (result?.mime) {
|
|
196
|
+
return result.mime;
|
|
197
197
|
}
|
|
198
198
|
return void 0;
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
const name = "@meistrari/vault-sdk";
|
|
202
|
+
const version = "1.5.0";
|
|
203
|
+
const license = "UNLICENSED";
|
|
204
|
+
const repository = {
|
|
205
|
+
type: "git",
|
|
206
|
+
url: "https://github.com/meistrari/vault.git"
|
|
207
|
+
};
|
|
208
|
+
const exports = {
|
|
209
|
+
".": {
|
|
210
|
+
types: "./dist/index.d.ts",
|
|
211
|
+
"import": "./dist/index.mjs",
|
|
212
|
+
require: "./dist/index.cjs"
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
const main = "dist/index.mjs";
|
|
216
|
+
const types = "dist/index.d.ts";
|
|
217
|
+
const files = [
|
|
218
|
+
"dist"
|
|
219
|
+
];
|
|
220
|
+
const scripts = {
|
|
221
|
+
test: "vitest --no-watch",
|
|
222
|
+
"test:watch": "vitest",
|
|
223
|
+
build: "unbuild",
|
|
224
|
+
lint: "eslint .",
|
|
225
|
+
"lint:fix": "eslint . --fix",
|
|
226
|
+
check: "bun run lint && bun tsc --noEmit"
|
|
227
|
+
};
|
|
228
|
+
const dependencies = {
|
|
229
|
+
"@meistrari/vault-shared": "workspace:*",
|
|
230
|
+
"file-type": "21.0.0",
|
|
231
|
+
"mime-types": "3.0.1",
|
|
232
|
+
ofetch: "1.4.1",
|
|
233
|
+
zod: "3.23.8"
|
|
234
|
+
};
|
|
235
|
+
const devDependencies = {
|
|
236
|
+
"@types/bun": "latest",
|
|
237
|
+
"@types/mime-types": "3.0.1",
|
|
238
|
+
msw: "2.6.8",
|
|
239
|
+
unbuild: "2.0.0",
|
|
240
|
+
vitest: "2.1.9"
|
|
241
|
+
};
|
|
242
|
+
const peerDependencies = {
|
|
243
|
+
typescript: "^5.0.0"
|
|
244
|
+
};
|
|
245
|
+
const publishConfig = {
|
|
246
|
+
access: "public"
|
|
247
|
+
};
|
|
248
|
+
const packageJson = {
|
|
249
|
+
name: name,
|
|
250
|
+
version: version,
|
|
251
|
+
license: license,
|
|
252
|
+
repository: repository,
|
|
253
|
+
exports: exports,
|
|
254
|
+
main: main,
|
|
255
|
+
types: types,
|
|
256
|
+
files: files,
|
|
257
|
+
scripts: scripts,
|
|
258
|
+
dependencies: dependencies,
|
|
259
|
+
devDependencies: devDependencies,
|
|
260
|
+
peerDependencies: peerDependencies,
|
|
261
|
+
publishConfig: publishConfig
|
|
262
|
+
};
|
|
263
|
+
|
|
201
264
|
var __defProp = Object.defineProperty;
|
|
202
265
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
203
266
|
var __publicField = (obj, key, value) => {
|
|
@@ -210,6 +273,7 @@ function removeVaultPrefix(url) {
|
|
|
210
273
|
}
|
|
211
274
|
async function wrappedFetch(...params) {
|
|
212
275
|
const request = new Request(...params);
|
|
276
|
+
request.headers.set("User-Agent", `vault-js-sdk:${packageJson.version}`);
|
|
213
277
|
const response = await fetch(request);
|
|
214
278
|
if (!response.ok) {
|
|
215
279
|
throw await FetchError.from(request.url, request.method, response);
|
|
@@ -251,7 +315,9 @@ class VaultFile {
|
|
|
251
315
|
* @returns The headers for the request
|
|
252
316
|
*/
|
|
253
317
|
get headers() {
|
|
254
|
-
|
|
318
|
+
const headers = this.config.authStrategy.getHeaders();
|
|
319
|
+
headers.set("User-Agent", `vault-js-sdk:${packageJson.version}`);
|
|
320
|
+
return headers;
|
|
255
321
|
}
|
|
256
322
|
/**
|
|
257
323
|
* Performs a request to the vault service and handles the response or errors.
|
|
@@ -280,6 +346,9 @@ class VaultFile {
|
|
|
280
346
|
headers,
|
|
281
347
|
signal
|
|
282
348
|
});
|
|
349
|
+
if (response.status === 204 || response.headers.get("content-length") === "0") {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
283
352
|
const content = await response.json();
|
|
284
353
|
return content;
|
|
285
354
|
}
|
|
@@ -674,6 +743,79 @@ class VaultFile {
|
|
|
674
743
|
}
|
|
675
744
|
}
|
|
676
745
|
|
|
746
|
+
function isS3UrlExpired(url) {
|
|
747
|
+
try {
|
|
748
|
+
const urlObj = new URL(url);
|
|
749
|
+
const amzDate = urlObj.searchParams.get("X-Amz-Date");
|
|
750
|
+
const amzExpires = urlObj.searchParams.get("X-Amz-Expires");
|
|
751
|
+
if (!amzDate || !amzExpires)
|
|
752
|
+
return false;
|
|
753
|
+
const year = Number.parseInt(amzDate.substring(0, 4));
|
|
754
|
+
const month = Number.parseInt(amzDate.substring(4, 6)) - 1;
|
|
755
|
+
const day = Number.parseInt(amzDate.substring(6, 8));
|
|
756
|
+
const hours = Number.parseInt(amzDate.substring(9, 11));
|
|
757
|
+
const minutes = Number.parseInt(amzDate.substring(11, 13));
|
|
758
|
+
const seconds = Number.parseInt(amzDate.substring(13, 15));
|
|
759
|
+
const signedDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
|
|
760
|
+
const expiresInSeconds = Number.parseInt(amzExpires);
|
|
761
|
+
const expirationTime = signedDate.getTime() + expiresInSeconds * 1e3;
|
|
762
|
+
const currentTime = Date.now();
|
|
763
|
+
return currentTime > expirationTime;
|
|
764
|
+
} catch {
|
|
765
|
+
return false;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
function isVaultReference(url) {
|
|
769
|
+
return url.startsWith("vault://") && url.length === 10;
|
|
770
|
+
}
|
|
771
|
+
function isVaultFileS3Url(url) {
|
|
772
|
+
const urlObj = new URL(url);
|
|
773
|
+
const amzDate = urlObj.searchParams.get("X-Amz-Date");
|
|
774
|
+
const amzExpires = urlObj.searchParams.get("X-Amz-Expires");
|
|
775
|
+
return urlObj.hostname.includes("amazonaws.com") && Boolean(amzDate) && Boolean(amzExpires);
|
|
776
|
+
}
|
|
777
|
+
const URL_STRATEGIES = [
|
|
778
|
+
{
|
|
779
|
+
separator: "/",
|
|
780
|
+
extractSegments: ([workspaceId, vaultFileId]) => ({
|
|
781
|
+
workspaceId,
|
|
782
|
+
vaultFileId
|
|
783
|
+
})
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
separator: "_",
|
|
787
|
+
extractSegments: ([vaultFileId, workspaceId]) => ({
|
|
788
|
+
vaultFileId,
|
|
789
|
+
workspaceId
|
|
790
|
+
})
|
|
791
|
+
}
|
|
792
|
+
];
|
|
793
|
+
function extractVaultFileIdFromS3Url(url) {
|
|
794
|
+
if (isVaultReference(url))
|
|
795
|
+
return url.replace("vault://", "");
|
|
796
|
+
try {
|
|
797
|
+
if (!isVaultFileS3Url(url))
|
|
798
|
+
return null;
|
|
799
|
+
const urlObj = new URL(url);
|
|
800
|
+
const strategy = URL_STRATEGIES.find((strategy2) => urlObj.pathname.includes(strategy2.separator));
|
|
801
|
+
if (!strategy)
|
|
802
|
+
return null;
|
|
803
|
+
const segments = urlObj.pathname.split(strategy.separator).filter((segment) => segment.length > 0);
|
|
804
|
+
if (segments.length < 2)
|
|
805
|
+
return null;
|
|
806
|
+
const extractedIds = strategy.extractSegments(segments);
|
|
807
|
+
if (!extractedIds || !extractedIds.vaultFileId || !extractedIds.workspaceId || extractedIds.vaultFileId.length < 32)
|
|
808
|
+
return null;
|
|
809
|
+
return extractedIds.vaultFileId;
|
|
810
|
+
} catch {
|
|
811
|
+
return null;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
function convertS3UrlToVaultReference(url) {
|
|
815
|
+
const vaultFileId = extractVaultFileIdFromS3Url(url);
|
|
816
|
+
return vaultFileId ? `vault://${vaultFileId}` : null;
|
|
817
|
+
}
|
|
818
|
+
|
|
677
819
|
function vaultClient(vaultConfig) {
|
|
678
820
|
const config = resolveConfig(vaultConfig);
|
|
679
821
|
function createFromContent(name, content, options) {
|
|
@@ -692,4 +834,4 @@ function vaultClient(vaultConfig) {
|
|
|
692
834
|
return { createFromContent, createFromReference };
|
|
693
835
|
}
|
|
694
836
|
|
|
695
|
-
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, vaultClient };
|
|
837
|
+
export { APIKeyAuthStrategy, DataTokenAuthStrategy, FetchError, VaultFile, convertS3UrlToVaultReference, extractVaultFileIdFromS3Url, isS3UrlExpired, isVaultFileS3Url, vaultClient };
|
package/package.json
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
"name": "@meistrari/vault-sdk",
|
|
3
|
+
"version": "1.5.0",
|
|
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"
|
|
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/vault-shared": "0.0.5",
|
|
31
|
+
"file-type": "21.0.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"
|
|
14
48
|
}
|
|
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/vault-shared": "0.0.5",
|
|
31
|
-
"file-type": "21.0.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
|
+
}
|