UNPKG

@shopify/cli-kit

Version:

A set of utilities, interfaces, and models that are common across all the platform features

158 lines 6.08 kB
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