Next.js website for Rocky Mountain Vending company featuring: - Product catalog with Stripe integration - Service areas and parts pages - Admin dashboard with Clerk authentication - SEO optimized pages with JSON-LD structured data Co-authored-by: Cursor <cursoragent@cursor.com>
54 lines
1.6 KiB
Text
54 lines
1.6 KiB
Text
export function memoizeChain(providers, treatAsExpired) {
|
|
const chain = internalCreateChain(providers);
|
|
let activeLock;
|
|
let passiveLock;
|
|
let credentials;
|
|
const provider = async (options) => {
|
|
if (options?.forceRefresh) {
|
|
return await chain(options);
|
|
}
|
|
if (credentials?.expiration) {
|
|
if (credentials?.expiration?.getTime() < Date.now()) {
|
|
credentials = undefined;
|
|
}
|
|
}
|
|
if (activeLock) {
|
|
await activeLock;
|
|
}
|
|
else if (!credentials || treatAsExpired?.(credentials)) {
|
|
if (credentials) {
|
|
if (!passiveLock) {
|
|
passiveLock = chain(options).then((c) => {
|
|
credentials = c;
|
|
passiveLock = undefined;
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
activeLock = chain(options).then((c) => {
|
|
credentials = c;
|
|
activeLock = undefined;
|
|
});
|
|
return provider(options);
|
|
}
|
|
}
|
|
return credentials;
|
|
};
|
|
return provider;
|
|
}
|
|
export const internalCreateChain = (providers) => async (awsIdentityProperties) => {
|
|
let lastProviderError;
|
|
for (const provider of providers) {
|
|
try {
|
|
return await provider(awsIdentityProperties);
|
|
}
|
|
catch (err) {
|
|
lastProviderError = err;
|
|
if (err?.tryNextLink) {
|
|
continue;
|
|
}
|
|
throw err;
|
|
}
|
|
}
|
|
throw lastProviderError;
|
|
};
|