UNPKG

@shopify/create-app

Version:

A CLI tool to create a new Shopify app.

223 lines (218 loc) • 9.29 kB
import { external_exports, fetch, jsonOutputEnabled } from "./chunk-B7LXQVGX.js"; import { CLI_KIT_VERSION } from "./chunk-HHKEZAAX.js"; import { versionSatisfies } from "./chunk-ZPNNBR5Z.js"; import { cacheRetrieve, cacheStore } from "./chunk-5LLHAM5N.js"; import { exec, renderError, renderInfo, renderWarning } from "./chunk-TGZSJFOF.js"; import { AbortSilentError } from "./chunk-LEQAULOW.js"; import { outputDebug } from "./chunk-PK2M5CKS.js"; import { isTruthy } from "./chunk-HNIAZN6U.js"; import { init_cjs_shims } from "./chunk-3XNI6LP4.js"; // ../cli-kit/dist/public/node/notifications-system.js init_cjs_shims(); // ../cli-kit/dist/public/node/global-context.js init_cjs_shims(); var _globalContext; function getGlobalContext() { return _globalContext ??= { currentCommandId: "" }, _globalContext; } function getCurrentCommandId() { return getGlobalContext().currentCommandId; } function setCurrentCommandId(commandId) { getGlobalContext().currentCommandId = commandId; } // ../cli-kit/dist/public/node/notifications-system.js var URL = "https://cdn.shopify.com/static/cli/notifications.json", EMPTY_CACHE_MESSAGE = "Cache is empty", COMMANDS_TO_SKIP = [ "notifications:list", "notifications:generate", "init", "app:init", "theme:init", "hydrogen:init", "cache:clear", "send-analytics" ]; function url() { let envUrl = process.env.SHOPIFY_CLI_NOTIFICATIONS_URL; if (envUrl) try { if (new globalThis.URL(envUrl).protocol === "https:") return envUrl; outputDebug(`The notifications URL provided via SHOPIFY_CLI_NOTIFICATIONS_URL (${envUrl}) is not secure (https). Falling back to default.`); } catch { outputDebug(`The notifications URL provided via SHOPIFY_CLI_NOTIFICATIONS_URL (${envUrl}) is not a valid URL. Falling back to default.`); } return URL; } var NotificationSchema = external_exports.object({ id: external_exports.string(), message: external_exports.string(), type: external_exports.enum(["info", "warning", "error"]), frequency: external_exports.enum(["always", "once", "once_a_day", "once_a_week"]), ownerChannel: external_exports.string(), cta: external_exports.object({ label: external_exports.string(), url: external_exports.string().url() }).optional(), title: external_exports.string().optional(), minVersion: external_exports.string().optional(), maxVersion: external_exports.string().optional(), minDate: external_exports.string().optional(), maxDate: external_exports.string().optional(), commands: external_exports.array(external_exports.string()).optional(), surface: external_exports.string().optional() }), NotificationsSchema = external_exports.object({ notifications: external_exports.array(NotificationSchema) }); async function showNotificationsIfNeeded(currentSurfaces, environment = process.env) { try { let commandId = getCurrentCommandId(); if (skipNotifications(commandId, environment) || jsonOutputEnabled(environment)) return; let notifications = await getNotifications(), notificationsToShow = filterNotifications(notifications.notifications, commandId, currentSurfaces); outputDebug(`Notifications to show: ${notificationsToShow.length}`), await renderNotifications(notificationsToShow); } catch (error) { if (error.message === EMPTY_CACHE_MESSAGE) { outputDebug("Notifications to show: 0 (Cache is empty)"); return; } if (error.message === "abort") throw new AbortSilentError(); let errorMessage = `Error showing notifications: ${error.message}`; outputDebug(errorMessage); let { sendErrorToBugsnag } = await import("./error-handler-GGBOXL7F.js"); await sendErrorToBugsnag(errorMessage, "unexpected_error"); } } function skipNotifications(currentCommand, environment = process.env) { return isTruthy(environment.CI) || isTruthy(environment.SHOPIFY_UNIT_TEST) || COMMANDS_TO_SKIP.includes(currentCommand); } async function renderNotifications(notifications) { notifications.slice(0, 2).forEach((notification) => { let content = { headline: notification.title, body: notification.message.replace(/\\n/g, ` `), link: notification.cta }; switch (notification.type) { case "info": { renderInfo(content); break; } case "warning": { renderWarning(content); break; } case "error": throw renderError(content), new Error("abort"); } cacheStore(`notification-${notification.id}`, (/* @__PURE__ */ new Date()).getTime().toString()); }); } async function getNotifications() { let cacheKey = `notifications-${url()}`, rawNotifications = cacheRetrieve(cacheKey)?.value; if (!rawNotifications) throw new Error(EMPTY_CACHE_MESSAGE); let notifications = JSON.parse(rawNotifications); return NotificationsSchema.parse(notifications); } async function fetchNotifications() { outputDebug("Fetching notifications..."); let response = await fetch(url(), void 0, { useNetworkLevelRetry: !1, useAbortSignal: !0, timeoutMs: 3 * 1e3 }); if (response.status !== 200) throw new Error(`Failed to fetch notifications: ${response.statusText}`); let rawNotifications = await response.text(), notifications = JSON.parse(rawNotifications), result = NotificationsSchema.parse(notifications); return await cacheNotifications(rawNotifications), result; } async function cacheNotifications(notifications) { cacheStore(`notifications-${url()}`, notifications), outputDebug(`Notifications from ${url()} stored in the cache`); } function fetchNotificationsInBackground(currentCommand, argv = process.argv, environment = process.env) { if (skipNotifications(currentCommand, environment) || !argv[1]) return; let nodeBinary = process.execPath, args = [argv[1], "notifications", "list", "--ignore-errors"]; exec(nodeBinary, args, { background: !0, env: { ...process.env, SHOPIFY_CLI_NO_ANALYTICS: "1" }, externalErrorHandler: async (error) => { outputDebug(`Failed to fetch notifications in background: ${error.message}`); } }); } function filterNotifications(notifications, commandId, currentSurfaces, today = new Date((/* @__PURE__ */ new Date()).setUTCHours(0, 0, 0, 0)), currentVersion = CLI_KIT_VERSION) { return notifications.filter((notification) => filterByVersion(notification, currentVersion)).filter((notifications2) => filterByDate(notifications2, today)).filter((notification) => filterByCommand(notification, commandId)).filter((notification) => filterBySurface(notification, commandId, currentSurfaces)).filter((notification) => filterByFrequency(notification)); } function filterByVersion(notification, currentVersion) { let minVersion = !notification.minVersion || versionSatisfies(currentVersion, `>=${notification.minVersion}`), maxVersion = !notification.maxVersion || versionSatisfies(currentVersion, `<=${notification.maxVersion}`); return minVersion && maxVersion; } function filterByDate(notification, today) { let minDate = !notification.minDate || new Date(notification.minDate) <= today, maxDate = !notification.maxDate || new Date(notification.maxDate) >= today; return minDate && maxDate; } function filterByCommand(notification, commandId) { return commandId === "" ? !0 : !notification.commands || notification.commands.includes(commandId); } function filterBySurface(notification, commandId, surfacesFromContext) { let surfaceFromCommand = commandId.split(":")[0] ?? "all", notificationSurface = notification.surface ?? "all"; return surfacesFromContext ? surfacesFromContext.includes(notificationSurface) : notificationSurface === surfaceFromCommand || notificationSurface === "all"; } function filterByFrequency(notification) { if (!notification.frequency) return !0; let cacheKey = `notification-${notification.id}`, lastShown = cacheRetrieve(cacheKey)?.value; if (!lastShown) return !0; switch (notification.frequency) { case "always": return !0; case "once": return !1; case "once_a_day": return (/* @__PURE__ */ new Date()).getTime() - Number(lastShown) > 24 * 3600 * 1e3; case "once_a_week": return (/* @__PURE__ */ new Date()).getTime() - Number(lastShown) > 168 * 3600 * 1e3; } } function stringifyFilters(notification) { let filters = []; return notification.minDate && filters.push(`from ${notification.minDate}`), notification.maxDate && filters.push(`to ${notification.maxDate}`), notification.minVersion && filters.push(`from v${notification.minVersion}`), notification.maxVersion && filters.push(`to v${notification.maxVersion}`), notification.frequency === "once" && filters.push("show only once"), notification.frequency === "once_a_day" && filters.push("show once a day"), notification.frequency === "once_a_week" && filters.push("show once a week"), notification.surface && filters.push(`surface = ${notification.surface}`), notification.commands && filters.push(`commands = ${notification.commands.join(", ")}`), filters.join(` `); } export { setCurrentCommandId, showNotificationsIfNeeded, getNotifications, fetchNotifications, fetchNotificationsInBackground, filterNotifications, stringifyFilters }; //# sourceMappingURL=chunk-FU4STSWX.js.map