@netlify/blobs
Advanced tools
Comparing version
@@ -16,4 +16,11 @@ interface APICredentials { | ||
interface SetOptions { | ||
ttl?: Date | number; | ||
expiration?: Date | number; | ||
} | ||
interface SetFilesItem extends SetOptions { | ||
key: string; | ||
path: string; | ||
} | ||
interface SetFilesOptions { | ||
concurrency?: number; | ||
} | ||
type BlobInput = ReadableStream | string | ArrayBuffer | Blob; | ||
@@ -27,3 +34,3 @@ export declare class Blobs { | ||
private getFinalRequest; | ||
private static getTTLHeaders; | ||
private static getExpirationHeaders; | ||
private isConfigured; | ||
@@ -48,6 +55,7 @@ private makeStoreRequest; | ||
}): Promise<string>; | ||
set(key: string, data: BlobInput, { ttl }?: SetOptions): Promise<void>; | ||
setFile(key: string, path: string, { ttl }?: SetOptions): Promise<void>; | ||
setJSON(key: string, data: unknown, { ttl }?: SetOptions): Promise<void>; | ||
set(key: string, data: BlobInput, { expiration }?: SetOptions): Promise<void>; | ||
setFile(key: string, path: string, { expiration }?: SetOptions): Promise<void>; | ||
setFiles(files: SetFilesItem[], { concurrency }?: SetFilesOptions): Promise<void[]>; | ||
setJSON(key: string, data: unknown, { expiration }?: SetOptions): Promise<void>; | ||
} | ||
export {}; |
@@ -6,2 +6,128 @@ // src/main.ts | ||
// node_modules/p-map/index.js | ||
var AbortError = class extends Error { | ||
constructor(message) { | ||
super(); | ||
this.name = "AbortError"; | ||
this.message = message; | ||
} | ||
}; | ||
var getDOMException = (errorMessage) => globalThis.DOMException === void 0 ? new AbortError(errorMessage) : new DOMException(errorMessage); | ||
var getAbortedReason = (signal) => { | ||
const reason = signal.reason === void 0 ? getDOMException("This operation was aborted.") : signal.reason; | ||
return reason instanceof Error ? reason : getDOMException(reason); | ||
}; | ||
async function pMap(iterable, mapper, { | ||
concurrency = Number.POSITIVE_INFINITY, | ||
stopOnError = true, | ||
signal | ||
} = {}) { | ||
return new Promise((resolve, reject_) => { | ||
if (iterable[Symbol.iterator] === void 0 && iterable[Symbol.asyncIterator] === void 0) { | ||
throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`); | ||
} | ||
if (typeof mapper !== "function") { | ||
throw new TypeError("Mapper function is required"); | ||
} | ||
if (!((Number.isSafeInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency >= 1)) { | ||
throw new TypeError(`Expected \`concurrency\` to be an integer from 1 and up or \`Infinity\`, got \`${concurrency}\` (${typeof concurrency})`); | ||
} | ||
const result = []; | ||
const errors = []; | ||
const skippedIndexesMap = /* @__PURE__ */ new Map(); | ||
let isRejected = false; | ||
let isResolved = false; | ||
let isIterableDone = false; | ||
let resolvingCount = 0; | ||
let currentIndex = 0; | ||
const iterator = iterable[Symbol.iterator] === void 0 ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator](); | ||
const reject = (reason) => { | ||
isRejected = true; | ||
isResolved = true; | ||
reject_(reason); | ||
}; | ||
if (signal) { | ||
if (signal.aborted) { | ||
reject(getAbortedReason(signal)); | ||
} | ||
signal.addEventListener("abort", () => { | ||
reject(getAbortedReason(signal)); | ||
}); | ||
} | ||
const next = async () => { | ||
if (isResolved) { | ||
return; | ||
} | ||
const nextItem = await iterator.next(); | ||
const index = currentIndex; | ||
currentIndex++; | ||
if (nextItem.done) { | ||
isIterableDone = true; | ||
if (resolvingCount === 0 && !isResolved) { | ||
if (!stopOnError && errors.length > 0) { | ||
reject(new AggregateError(errors)); | ||
return; | ||
} | ||
isResolved = true; | ||
if (skippedIndexesMap.size === 0) { | ||
resolve(result); | ||
return; | ||
} | ||
const pureResult = []; | ||
for (const [index2, value] of result.entries()) { | ||
if (skippedIndexesMap.get(index2) === pMapSkip) { | ||
continue; | ||
} | ||
pureResult.push(value); | ||
} | ||
resolve(pureResult); | ||
} | ||
return; | ||
} | ||
resolvingCount++; | ||
(async () => { | ||
try { | ||
const element = await nextItem.value; | ||
if (isResolved) { | ||
return; | ||
} | ||
const value = await mapper(element, index); | ||
if (value === pMapSkip) { | ||
skippedIndexesMap.set(index, value); | ||
} | ||
result[index] = value; | ||
resolvingCount--; | ||
await next(); | ||
} catch (error) { | ||
if (stopOnError) { | ||
reject(error); | ||
} else { | ||
errors.push(error); | ||
resolvingCount--; | ||
try { | ||
await next(); | ||
} catch (error2) { | ||
reject(error2); | ||
} | ||
} | ||
} | ||
})(); | ||
}; | ||
(async () => { | ||
for (let index = 0; index < concurrency; index++) { | ||
try { | ||
await next(); | ||
} catch (error) { | ||
reject(error); | ||
break; | ||
} | ||
if (isIterableDone || isRejected) { | ||
break; | ||
} | ||
} | ||
})(); | ||
}); | ||
} | ||
var pMapSkip = Symbol("skip"); | ||
// src/retry.ts | ||
@@ -83,17 +209,17 @@ var DEFAULT_RETRY_DELAY = 5e3; | ||
} | ||
static getTTLHeaders(ttl) { | ||
if (typeof ttl === "number") { | ||
static getExpirationHeaders(expiration) { | ||
if (typeof expiration === "number") { | ||
return { | ||
[EXPIRY_HEADER]: (Date.now() + ttl).toString() | ||
[EXPIRY_HEADER]: (Date.now() + expiration).toString() | ||
}; | ||
} | ||
if (ttl instanceof Date) { | ||
if (expiration instanceof Date) { | ||
return { | ||
[EXPIRY_HEADER]: ttl.getTime().toString() | ||
[EXPIRY_HEADER]: expiration.getTime().toString() | ||
}; | ||
} | ||
if (ttl === void 0) { | ||
if (expiration === void 0) { | ||
return {}; | ||
} | ||
throw new TypeError(`'ttl' value must be a number or a Date, ${typeof ttl} found.`); | ||
throw new TypeError(`'expiration' value must be a number or a Date, ${typeof expiration} found.`); | ||
} | ||
@@ -138,6 +264,6 @@ isConfigured() { | ||
const res = await this.makeStoreRequest(key, "get" /* Get */); | ||
const expiry = res?.headers.get(EXPIRY_HEADER); | ||
if (typeof expiry === "string") { | ||
const expiryTS = Number.parseInt(expiry); | ||
if (!Number.isNaN(expiryTS) && expiryTS <= Date.now()) { | ||
const expiration = res?.headers.get(EXPIRY_HEADER); | ||
if (typeof expiration === "string") { | ||
const expirationTS = Number.parseInt(expiration); | ||
if (!Number.isNaN(expirationTS) && expirationTS <= Date.now()) { | ||
return null; | ||
@@ -166,11 +292,11 @@ } | ||
} | ||
async set(key, data, { ttl } = {}) { | ||
const headers = _Blobs.getTTLHeaders(ttl); | ||
async set(key, data, { expiration } = {}) { | ||
const headers = _Blobs.getExpirationHeaders(expiration); | ||
await this.makeStoreRequest(key, "put" /* Put */, headers, data); | ||
} | ||
async setFile(key, path, { ttl } = {}) { | ||
async setFile(key, path, { expiration } = {}) { | ||
const { size } = await stat(path); | ||
const file = Readable.toWeb(createReadStream(path)); | ||
const headers = { | ||
..._Blobs.getTTLHeaders(ttl), | ||
..._Blobs.getExpirationHeaders(expiration), | ||
"content-length": size.toString() | ||
@@ -180,6 +306,9 @@ }; | ||
} | ||
async setJSON(key, data, { ttl } = {}) { | ||
setFiles(files, { concurrency = 5 } = {}) { | ||
return pMap(files, ({ key, path, ...options }) => this.setFile(key, path, options), { concurrency }); | ||
} | ||
async setJSON(key, data, { expiration } = {}) { | ||
const payload = JSON.stringify(data); | ||
const headers = { | ||
..._Blobs.getTTLHeaders(ttl), | ||
..._Blobs.getExpirationHeaders(expiration), | ||
"content-type": "application/json" | ||
@@ -186,0 +315,0 @@ }; |
{ | ||
"name": "@netlify/blobs", | ||
"version": "1.5.0", | ||
"version": "1.6.0", | ||
"description": "A JavaScript client for the Netlify Blob Store", | ||
@@ -55,2 +55,3 @@ "type": "module", | ||
"c8": "^7.11.0", | ||
"esbuild": "^0.18.17", | ||
"husky": "^8.0.0", | ||
@@ -67,4 +68,4 @@ "node-fetch": "^3.3.1", | ||
"dependencies": { | ||
"esbuild": "0.18.16" | ||
"p-map": "^6.0.0" | ||
} | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
20663
27.71%372
57.63%0
-100%11
10%+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed