@shopify/cli
Version:
A CLI tool to build for the Shopify platform
204 lines (199 loc) • 8.39 kB
JavaScript
import {
fetch,
jsonOutputEnabled,
z
} from "./chunk-Q76H7OUL.js";
import {
CLI_KIT_VERSION
} from "./chunk-Z2AIGIVT.js";
import {
cacheRetrieve,
cacheStore,
versionSatisfies
} from "./chunk-KDFL67TE.js";
import {
AbortSilentError,
exec,
isTruthy,
outputDebug,
renderError,
renderInfo,
renderWarning
} from "./chunk-4NC2NVYY.js";
import {
init_cjs_shims
} from "./chunk-PKR7KJ6P.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 || (_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"
];
function url() {
return process.env.SHOPIFY_CLI_NOTIFICATIONS_URL ?? URL;
}
var NotificationSchema = z.object({
id: z.string(),
message: z.string(),
type: z.enum(["info", "warning", "error"]),
frequency: z.enum(["always", "once", "once_a_day", "once_a_week"]),
ownerChannel: z.string(),
cta: z.object({
label: z.string(),
url: z.string().url()
}).optional(),
title: z.string().optional(),
minVersion: z.string().optional(),
maxVersion: z.string().optional(),
minDate: z.string().optional(),
maxDate: z.string().optional(),
commands: z.array(z.string()).optional(),
surface: z.string().optional()
}), NotificationsSchema = z.object({ notifications: z.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-WBLMZ6OH.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.replaceAll("\\n", `
`),
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[0] || !argv[1])
return;
let nodeBinary = argv[0], 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) > 7 * 24 * 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,
stringifyFilters
};
//# sourceMappingURL=chunk-JLITATNF.js.map