@shopify/cli-kit
Version:
A set of utilities, interfaces, and models that are common across all the platform features
158 lines • 6.08 kB
JavaScript
import { isUnitTest } from '../../public/node/context/local.js';
import { LocalStorage } from '../../public/node/local-storage.js';
import { outputContent, outputDebug } from '../../public/node/output.js';
let _instance;
/**
* CLIKIT Store.
*
* @returns CLIKitStore.
*/
function cliKitStore() {
if (!_instance) {
_instance = new LocalStorage({ projectName: `shopify-cli-kit${isUnitTest() ? '-test' : ''}` });
}
return _instance;
}
/**
* Get session.
*
* @returns Session.
*/
export function getSession(config = cliKitStore()) {
outputDebug(outputContent `Getting session store...`);
return config.get('sessionStore');
}
/**
* Set session.
*
* @param session - Session.
*/
export function setSession(session, config = cliKitStore()) {
outputDebug(outputContent `Setting session store...`);
config.set('sessionStore', session);
}
/**
* Remove session.
*/
export function removeSession(config = cliKitStore()) {
outputDebug(outputContent `Removing session store...`);
config.delete('sessionStore');
}
/**
* Fetch from cache, or run the provided function to get the value, and cache it
* before returning it.
* @param key - The key to use for the cache.
* @param fn - The function to run to get the value to cache, if a cache miss occurs.
* @param timeout - The maximum valid age of a cached value, in milliseconds.
* If the cached value is older than this, it will be refreshed.
* @returns The value from the cache or the result of the function.
*/
export async function cacheRetrieveOrRepopulate(key, fn, timeout, config = cliKitStore()) {
const cached = cacheRetrieve(key, config);
if (cached?.value !== undefined && (timeout === undefined || Date.now() - cached.timestamp < timeout)) {
return cached.value;
}
const value = await fn();
cacheStore(key, value, config);
return value;
}
export function cacheStore(key, value, config = cliKitStore()) {
const cache = config.get('cache') || {};
cache[key] = { value, timestamp: Date.now() };
config.set('cache', cache);
}
/**
* Fetch from cache if already populated, otherwise return undefined.
* @param key - The key to use for the cache.
* @returns The chache element.
*/
export function cacheRetrieve(key, config = cliKitStore()) {
const cache = config.get('cache') || {};
return cache[key];
}
export function cacheClear(config = cliKitStore()) {
config.delete('cache');
}
export function timeIntervalToMilliseconds({ days = 0, hours = 0, minutes = 0, seconds = 0 }) {
return (days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60 + seconds) * 1000;
}
/**
* Execute a task only if the most recent occurrence of the task is older than the specified timeout.
* @param key - The key to use for the cache.
* @param timeout - The maximum valid age of the most recent occurrence, expressed as an object with
* days, hours, minutes, and seconds properties.
* If the most recent occurrence is older than this, the task will be executed.
* @param task - The task to run if the most recent occurrence is older than the timeout.
* @returns true if the task was run, or false if the task was not run.
*/
export async function runAtMinimumInterval(key, timeout, task, config = cliKitStore()) {
const cache = config.get('cache') || {};
const cacheKey = `most-recent-occurrence-${key}`;
const cached = cache[cacheKey];
if (cached?.value !== undefined && Date.now() - cached.timestamp < timeIntervalToMilliseconds(timeout)) {
return false;
}
await task();
cache[cacheKey] = { value: true, timestamp: Date.now() };
config.set('cache', cache);
return true;
}
/**
* Execute a task with a time-based rate limit. The rate limit is enforced by
* checking how many times that task has been executed in a window of time ending
* at the current time. If the task has been executed more than the allowed number
* of times in that window, the task will not be executed.
*
* Note that this function has side effects, as it will also remove events prior
* to the window of time that is being checked.
* @param options - The options for the rate limiting.
* @returns true, or undefined if the task was not run.
*/
export async function runWithRateLimit(options, config = cliKitStore()) {
const { key, limit, timeout, task } = options;
const cache = config.get('cache') || {};
const cacheKey = `rate-limited-occurrences-${key}`;
const cached = cache[cacheKey];
const now = Date.now();
if (cached?.value) {
// First sweep through the cache and eliminate old events
const windowStart = now - timeIntervalToMilliseconds(timeout);
const occurrences = cached.value.filter((occurrence) => occurrence >= windowStart);
// Now check that the number of occurrences within the interval is below the limit
if (occurrences.length >= limit) {
// First remove the old occurrences from the cache
cache[cacheKey] = { value: occurrences, timestamp: Date.now() };
config.set('cache', cache);
return false;
}
await task();
cache[cacheKey] = { value: [...occurrences, now], timestamp: now };
}
else {
await task();
cache[cacheKey] = { value: [now], timestamp: now };
}
config.set('cache', cache);
return true;
}
export function getConfigStoreForPartnerStatus() {
return new LocalStorage({
projectName: 'shopify-cli-kit-partner-status',
});
}
export function getCachedPartnerAccountStatus(partnersToken) {
if (!partnersToken)
return null;
const store = getConfigStoreForPartnerStatus();
const hasPartnerAccount = store.get(partnersToken);
if (hasPartnerAccount) {
// this never needs to expire
return true;
}
return null;
}
export function setCachedPartnerAccountStatus(partnersToken) {
const store = getConfigStoreForPartnerStatus();
store.set(partnersToken, { status: true, checkedAt: new Date().toISOString() });
}
//# sourceMappingURL=conf-store.js.map