118 lines
3.3 KiB
JavaScript
118 lines
3.3 KiB
JavaScript
'use strict';
|
|
|
|
class ProviderError extends Error {
|
|
name = "ProviderError";
|
|
tryNextLink;
|
|
constructor(message, options = true) {
|
|
let logger;
|
|
let tryNextLink = true;
|
|
if (typeof options === "boolean") {
|
|
logger = undefined;
|
|
tryNextLink = options;
|
|
}
|
|
else if (options != null && typeof options === "object") {
|
|
logger = options.logger;
|
|
tryNextLink = options.tryNextLink ?? true;
|
|
}
|
|
super(message);
|
|
this.tryNextLink = tryNextLink;
|
|
Object.setPrototypeOf(this, ProviderError.prototype);
|
|
logger?.debug?.(`@smithy/property-provider ${tryNextLink ? "->" : "(!)"} ${message}`);
|
|
}
|
|
static from(error, options = true) {
|
|
return Object.assign(new this(error.message, options), error);
|
|
}
|
|
}
|
|
|
|
class CredentialsProviderError extends ProviderError {
|
|
name = "CredentialsProviderError";
|
|
constructor(message, options = true) {
|
|
super(message, options);
|
|
Object.setPrototypeOf(this, CredentialsProviderError.prototype);
|
|
}
|
|
}
|
|
|
|
class TokenProviderError extends ProviderError {
|
|
name = "TokenProviderError";
|
|
constructor(message, options = true) {
|
|
super(message, options);
|
|
Object.setPrototypeOf(this, TokenProviderError.prototype);
|
|
}
|
|
}
|
|
|
|
const chain = (...providers) => async () => {
|
|
if (providers.length === 0) {
|
|
throw new ProviderError("No providers in chain");
|
|
}
|
|
let lastProviderError;
|
|
for (const provider of providers) {
|
|
try {
|
|
const credentials = await provider();
|
|
return credentials;
|
|
}
|
|
catch (err) {
|
|
lastProviderError = err;
|
|
if (err?.tryNextLink) {
|
|
continue;
|
|
}
|
|
throw err;
|
|
}
|
|
}
|
|
throw lastProviderError;
|
|
};
|
|
|
|
const fromStatic = (staticValue) => () => Promise.resolve(staticValue);
|
|
|
|
const memoize = (provider, isExpired, requiresRefresh) => {
|
|
let resolved;
|
|
let pending;
|
|
let hasResult;
|
|
let isConstant = false;
|
|
const coalesceProvider = async () => {
|
|
if (!pending) {
|
|
pending = provider();
|
|
}
|
|
try {
|
|
resolved = await pending;
|
|
hasResult = true;
|
|
isConstant = false;
|
|
}
|
|
finally {
|
|
pending = undefined;
|
|
}
|
|
return resolved;
|
|
};
|
|
if (isExpired === undefined) {
|
|
return async (options) => {
|
|
if (!hasResult || options?.forceRefresh) {
|
|
resolved = await coalesceProvider();
|
|
}
|
|
return resolved;
|
|
};
|
|
}
|
|
return async (options) => {
|
|
if (!hasResult || options?.forceRefresh) {
|
|
resolved = await coalesceProvider();
|
|
}
|
|
if (isConstant) {
|
|
return resolved;
|
|
}
|
|
if (requiresRefresh && !requiresRefresh(resolved)) {
|
|
isConstant = true;
|
|
return resolved;
|
|
}
|
|
if (isExpired(resolved)) {
|
|
await coalesceProvider();
|
|
return resolved;
|
|
}
|
|
return resolved;
|
|
};
|
|
};
|
|
|
|
exports.CredentialsProviderError = CredentialsProviderError;
|
|
exports.ProviderError = ProviderError;
|
|
exports.TokenProviderError = TokenProviderError;
|
|
exports.chain = chain;
|
|
exports.fromStatic = fromStatic;
|
|
exports.memoize = memoize;
|