@aws-amplify/core
Version:
Core category of aws-amplify
78 lines (65 loc) • 2.46 kB
text/typescript
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { Framework } from './types';
import { detect } from './detection';
// We want to cache detection since the framework won't change
let frameworkCache: Framework | undefined;
export const frameworkChangeObservers: (() => void)[] = [];
// Setup the detection reset tracking / timeout delays
let resetTriggered = false;
const SSR_RESET_TIMEOUT = 10; // ms
const WEB_RESET_TIMEOUT = 10; // ms
const PRIME_FRAMEWORK_DELAY = 1_000; // ms
export const detectFramework = (): Framework => {
if (!frameworkCache) {
frameworkCache = detect();
if (resetTriggered) {
// The final run of detectFramework:
// Starting from this point, the `frameworkCache` becomes "final".
// So we don't need to notify the observers again so the observer
// can be removed after the final notice.
while (frameworkChangeObservers.length) {
frameworkChangeObservers.pop()?.();
}
} else {
// The first run of detectFramework:
// Every time we update the cache, call each observer function
frameworkChangeObservers.forEach(fcn => {
fcn();
});
}
// Retry once for either Unknown type after a delay (explained below)
resetTimeout(Framework.ServerSideUnknown, SSR_RESET_TIMEOUT);
resetTimeout(Framework.WebUnknown, WEB_RESET_TIMEOUT);
}
return frameworkCache;
};
/**
* @internal Setup observer callback that will be called everytime the framework changes
*/
export const observeFrameworkChanges = (fcn: () => void) => {
// When the `frameworkCache` won't be updated again, we ignore all incoming
// observers.
if (resetTriggered) {
return;
}
frameworkChangeObservers.push(fcn);
};
export function clearCache() {
frameworkCache = undefined;
}
// For a framework type and a delay amount, setup the event to re-detect
// During the runtime boot, it is possible that framework detection will
// be triggered before the framework has made modifications to the
// global/window/etc needed for detection. When no framework is detected
// we will reset and try again to ensure we don't use a cached
// non-framework detection result for all requests.
function resetTimeout(framework: Framework, delay: number) {
if (frameworkCache === framework && !resetTriggered) {
setTimeout(() => {
clearCache();
resetTriggered = true;
setTimeout(detectFramework, PRIME_FRAMEWORK_DELAY);
}, delay);
}
}