@shopify/cli-kit 3.76.2 → 3.77.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/private/node/api.d.ts +27 -4
- package/dist/private/node/api.js +64 -8
- package/dist/private/node/api.js.map +1 -1
- package/dist/private/node/constants.d.ts +2 -0
- package/dist/private/node/constants.js +2 -0
- package/dist/private/node/constants.js.map +1 -1
- package/dist/private/node/session/device-authorization.js +3 -3
- package/dist/private/node/session/device-authorization.js.map +1 -1
- package/dist/private/node/session/schema.d.ts +40 -40
- package/dist/private/node/sleep-with-backoff.d.ts +16 -0
- package/dist/private/node/sleep-with-backoff.js +64 -0
- package/dist/private/node/sleep-with-backoff.js.map +1 -0
- package/dist/public/common/version.d.ts +1 -1
- package/dist/public/common/version.js +1 -1
- package/dist/public/common/version.js.map +1 -1
- package/dist/public/node/api/admin.js +2 -2
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/api/graphql.js +6 -1
- package/dist/public/node/api/graphql.js.map +1 -1
- package/dist/public/node/context/fqdn.js +1 -1
- package/dist/public/node/context/fqdn.js.map +1 -1
- package/dist/public/node/environment.d.ts +20 -0
- package/dist/public/node/environment.js +29 -0
- package/dist/public/node/environment.js.map +1 -1
- package/dist/public/node/github.d.ts +1 -0
- package/dist/public/node/github.js +31 -2
- package/dist/public/node/github.js.map +1 -1
- package/dist/public/node/http.d.ts +48 -3
- package/dist/public/node/http.js +134 -24
- package/dist/public/node/http.js.map +1 -1
- package/dist/public/node/monorail.js +1 -1
- package/dist/public/node/monorail.js.map +1 -1
- package/dist/public/node/notifications-system.d.ts +22 -22
- package/dist/public/node/notifications-system.js +6 -2
- package/dist/public/node/notifications-system.js.map +1 -1
- package/dist/public/node/system.d.ts +6 -0
- package/dist/public/node/system.js +8 -0
- package/dist/public/node/system.js.map +1 -1
- package/dist/public/node/testing/test-with-temp-dir.d.ts +9 -0
- package/dist/public/node/testing/test-with-temp-dir.js +14 -0
- package/dist/public/node/testing/test-with-temp-dir.js.map +1 -0
- package/dist/public/node/themes/types.d.ts +3 -2
- package/dist/public/node/themes/types.js.map +1 -1
- package/dist/public/node/vendor/dev_server/dev-server-2016.d.ts +9 -0
- package/dist/public/node/vendor/dev_server/dev-server-2016.js +38 -0
- package/dist/public/node/vendor/dev_server/dev-server-2016.js.map +1 -0
- package/dist/public/node/vendor/dev_server/dev-server-2024.d.ts +9 -0
- package/dist/public/node/vendor/dev_server/dev-server-2024.js +68 -0
- package/dist/public/node/vendor/dev_server/dev-server-2024.js.map +1 -0
- package/dist/public/node/vendor/dev_server/dev-server-spin.d.ts +5 -0
- package/dist/public/node/vendor/dev_server/dev-server-spin.js +28 -0
- package/dist/public/node/vendor/dev_server/dev-server-spin.js.map +1 -0
- package/dist/public/node/vendor/dev_server/dev-server.d.ts +15 -0
- package/dist/public/node/vendor/dev_server/dev-server.js +59 -0
- package/dist/public/node/vendor/dev_server/dev-server.js.map +1 -0
- package/dist/public/node/vendor/dev_server/env.d.ts +2 -0
- package/dist/public/node/vendor/dev_server/env.js +7 -0
- package/dist/public/node/vendor/dev_server/env.js.map +1 -0
- package/dist/public/node/vendor/dev_server/index.d.ts +2 -0
- package/dist/public/node/vendor/dev_server/index.js +3 -0
- package/dist/public/node/vendor/dev_server/index.js.map +1 -0
- package/dist/public/node/vendor/dev_server/network/host.d.ts +2 -0
- package/dist/public/node/vendor/dev_server/network/host.js +45 -0
- package/dist/public/node/vendor/dev_server/network/host.js.map +1 -0
- package/dist/public/node/vendor/dev_server/network/index.d.ts +9 -0
- package/dist/public/node/vendor/dev_server/network/index.js +36 -0
- package/dist/public/node/vendor/dev_server/network/index.js.map +1 -0
- package/dist/public/node/vendor/dev_server/types.d.ts +11 -0
- package/dist/public/node/vendor/dev_server/types.js +2 -0
- package/dist/public/node/vendor/dev_server/types.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -1
- package/dist/public/node/vendor/dev_server/DevServer.d.ts +0 -19
- package/dist/public/node/vendor/dev_server/DevServer.js +0 -170
- package/dist/public/node/vendor/dev_server/DevServer.js.map +0 -1
|
@@ -9,11 +9,11 @@ declare const NotificationSchema: zod.ZodObject<{
|
|
|
9
9
|
label: zod.ZodString;
|
|
10
10
|
url: zod.ZodString;
|
|
11
11
|
}, "strip", zod.ZodTypeAny, {
|
|
12
|
-
label: string;
|
|
13
12
|
url: string;
|
|
14
|
-
}, {
|
|
15
13
|
label: string;
|
|
14
|
+
}, {
|
|
16
15
|
url: string;
|
|
16
|
+
label: string;
|
|
17
17
|
}>>;
|
|
18
18
|
title: zod.ZodOptional<zod.ZodString>;
|
|
19
19
|
minVersion: zod.ZodOptional<zod.ZodString>;
|
|
@@ -24,15 +24,15 @@ declare const NotificationSchema: zod.ZodObject<{
|
|
|
24
24
|
surface: zod.ZodOptional<zod.ZodString>;
|
|
25
25
|
}, "strip", zod.ZodTypeAny, {
|
|
26
26
|
id: string;
|
|
27
|
+
type: "error" | "info" | "warning";
|
|
27
28
|
message: string;
|
|
28
|
-
type: "info" | "warning" | "error";
|
|
29
29
|
frequency: "always" | "once" | "once_a_day" | "once_a_week";
|
|
30
30
|
ownerChannel: string;
|
|
31
|
+
title?: string | undefined;
|
|
31
32
|
cta?: {
|
|
32
|
-
label: string;
|
|
33
33
|
url: string;
|
|
34
|
+
label: string;
|
|
34
35
|
} | undefined;
|
|
35
|
-
title?: string | undefined;
|
|
36
36
|
minVersion?: string | undefined;
|
|
37
37
|
maxVersion?: string | undefined;
|
|
38
38
|
minDate?: string | undefined;
|
|
@@ -41,15 +41,15 @@ declare const NotificationSchema: zod.ZodObject<{
|
|
|
41
41
|
surface?: string | undefined;
|
|
42
42
|
}, {
|
|
43
43
|
id: string;
|
|
44
|
+
type: "error" | "info" | "warning";
|
|
44
45
|
message: string;
|
|
45
|
-
type: "info" | "warning" | "error";
|
|
46
46
|
frequency: "always" | "once" | "once_a_day" | "once_a_week";
|
|
47
47
|
ownerChannel: string;
|
|
48
|
+
title?: string | undefined;
|
|
48
49
|
cta?: {
|
|
49
|
-
label: string;
|
|
50
50
|
url: string;
|
|
51
|
+
label: string;
|
|
51
52
|
} | undefined;
|
|
52
|
-
title?: string | undefined;
|
|
53
53
|
minVersion?: string | undefined;
|
|
54
54
|
maxVersion?: string | undefined;
|
|
55
55
|
minDate?: string | undefined;
|
|
@@ -69,11 +69,11 @@ declare const NotificationsSchema: zod.ZodObject<{
|
|
|
69
69
|
label: zod.ZodString;
|
|
70
70
|
url: zod.ZodString;
|
|
71
71
|
}, "strip", zod.ZodTypeAny, {
|
|
72
|
-
label: string;
|
|
73
72
|
url: string;
|
|
74
|
-
}, {
|
|
75
73
|
label: string;
|
|
74
|
+
}, {
|
|
76
75
|
url: string;
|
|
76
|
+
label: string;
|
|
77
77
|
}>>;
|
|
78
78
|
title: zod.ZodOptional<zod.ZodString>;
|
|
79
79
|
minVersion: zod.ZodOptional<zod.ZodString>;
|
|
@@ -84,15 +84,15 @@ declare const NotificationsSchema: zod.ZodObject<{
|
|
|
84
84
|
surface: zod.ZodOptional<zod.ZodString>;
|
|
85
85
|
}, "strip", zod.ZodTypeAny, {
|
|
86
86
|
id: string;
|
|
87
|
+
type: "error" | "info" | "warning";
|
|
87
88
|
message: string;
|
|
88
|
-
type: "info" | "warning" | "error";
|
|
89
89
|
frequency: "always" | "once" | "once_a_day" | "once_a_week";
|
|
90
90
|
ownerChannel: string;
|
|
91
|
+
title?: string | undefined;
|
|
91
92
|
cta?: {
|
|
92
|
-
label: string;
|
|
93
93
|
url: string;
|
|
94
|
+
label: string;
|
|
94
95
|
} | undefined;
|
|
95
|
-
title?: string | undefined;
|
|
96
96
|
minVersion?: string | undefined;
|
|
97
97
|
maxVersion?: string | undefined;
|
|
98
98
|
minDate?: string | undefined;
|
|
@@ -101,15 +101,15 @@ declare const NotificationsSchema: zod.ZodObject<{
|
|
|
101
101
|
surface?: string | undefined;
|
|
102
102
|
}, {
|
|
103
103
|
id: string;
|
|
104
|
+
type: "error" | "info" | "warning";
|
|
104
105
|
message: string;
|
|
105
|
-
type: "info" | "warning" | "error";
|
|
106
106
|
frequency: "always" | "once" | "once_a_day" | "once_a_week";
|
|
107
107
|
ownerChannel: string;
|
|
108
|
+
title?: string | undefined;
|
|
108
109
|
cta?: {
|
|
109
|
-
label: string;
|
|
110
110
|
url: string;
|
|
111
|
+
label: string;
|
|
111
112
|
} | undefined;
|
|
112
|
-
title?: string | undefined;
|
|
113
113
|
minVersion?: string | undefined;
|
|
114
114
|
maxVersion?: string | undefined;
|
|
115
115
|
minDate?: string | undefined;
|
|
@@ -120,15 +120,15 @@ declare const NotificationsSchema: zod.ZodObject<{
|
|
|
120
120
|
}, "strip", zod.ZodTypeAny, {
|
|
121
121
|
notifications: {
|
|
122
122
|
id: string;
|
|
123
|
+
type: "error" | "info" | "warning";
|
|
123
124
|
message: string;
|
|
124
|
-
type: "info" | "warning" | "error";
|
|
125
125
|
frequency: "always" | "once" | "once_a_day" | "once_a_week";
|
|
126
126
|
ownerChannel: string;
|
|
127
|
+
title?: string | undefined;
|
|
127
128
|
cta?: {
|
|
128
|
-
label: string;
|
|
129
129
|
url: string;
|
|
130
|
+
label: string;
|
|
130
131
|
} | undefined;
|
|
131
|
-
title?: string | undefined;
|
|
132
132
|
minVersion?: string | undefined;
|
|
133
133
|
maxVersion?: string | undefined;
|
|
134
134
|
minDate?: string | undefined;
|
|
@@ -139,15 +139,15 @@ declare const NotificationsSchema: zod.ZodObject<{
|
|
|
139
139
|
}, {
|
|
140
140
|
notifications: {
|
|
141
141
|
id: string;
|
|
142
|
+
type: "error" | "info" | "warning";
|
|
142
143
|
message: string;
|
|
143
|
-
type: "info" | "warning" | "error";
|
|
144
144
|
frequency: "always" | "once" | "once_a_day" | "once_a_week";
|
|
145
145
|
ownerChannel: string;
|
|
146
|
+
title?: string | undefined;
|
|
146
147
|
cta?: {
|
|
147
|
-
label: string;
|
|
148
148
|
url: string;
|
|
149
|
+
label: string;
|
|
149
150
|
} | undefined;
|
|
150
|
-
title?: string | undefined;
|
|
151
151
|
minVersion?: string | undefined;
|
|
152
152
|
maxVersion?: string | undefined;
|
|
153
153
|
minDate?: string | undefined;
|
|
@@ -128,8 +128,12 @@ export async function getNotifications() {
|
|
|
128
128
|
* @returns A string with the notifications.
|
|
129
129
|
*/
|
|
130
130
|
export async function fetchNotifications() {
|
|
131
|
-
outputDebug(`Fetching
|
|
132
|
-
const response = await fetch(url(), {
|
|
131
|
+
outputDebug(`Fetching notifications...`);
|
|
132
|
+
const response = await fetch(url(), undefined, {
|
|
133
|
+
useNetworkLevelRetry: false,
|
|
134
|
+
useAbortSignal: true,
|
|
135
|
+
timeoutMs: 3 * 1000,
|
|
136
|
+
});
|
|
133
137
|
if (response.status !== 200)
|
|
134
138
|
throw new Error(`Failed to fetch notifications: ${response.statusText}`);
|
|
135
139
|
const rawNotifications = await response.text();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications-system.js","sourceRoot":"","sources":["../../../src/public/node/notifications-system.ts"],"names":[],"mappings":"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","sourcesContent":["import {versionSatisfies} from './node-package-manager.js'\nimport {renderError, renderInfo, renderWarning} from './ui.js'\nimport {getCurrentCommandId} from './global-context.js'\nimport {outputDebug} from './output.js'\nimport {zod} from './schema.js'\nimport {AbortSilentError} from './error.js'\nimport {isTruthy} from './context/utilities.js'\nimport {exec} from './system.js'\nimport {jsonOutputEnabled} from './environment.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {NotificationKey, NotificationsKey, cacheRetrieve, cacheStore} from '../../private/node/conf-store.js'\nimport {fetch} from '@shopify/cli-kit/node/http'\n\nconst URL = 'https://cdn.shopify.com/static/cli/notifications.json'\nconst EMPTY_CACHE_MESSAGE = 'Cache is empty'\nconst COMMANDS_TO_SKIP = [\n 'notifications:list',\n 'notifications:generate',\n 'init',\n 'app:init',\n 'theme:init',\n 'hydrogen:init',\n 'cache:clear',\n]\n\nfunction url(): string {\n return process.env.SHOPIFY_CLI_NOTIFICATIONS_URL ?? URL\n}\n\nconst NotificationSchema = zod.object({\n id: zod.string(),\n message: zod.string(),\n type: zod.enum(['info', 'warning', 'error']),\n frequency: zod.enum(['always', 'once', 'once_a_day', 'once_a_week']),\n ownerChannel: zod.string(),\n cta: zod\n .object({\n label: zod.string(),\n url: zod.string().url(),\n })\n .optional(),\n title: zod.string().optional(),\n minVersion: zod.string().optional(),\n maxVersion: zod.string().optional(),\n minDate: zod.string().optional(),\n maxDate: zod.string().optional(),\n commands: zod.array(zod.string()).optional(),\n surface: zod.string().optional(),\n})\nexport type Notification = zod.infer<typeof NotificationSchema>\n\nconst NotificationsSchema = zod.object({notifications: zod.array(NotificationSchema)})\nexport type Notifications = zod.infer<typeof NotificationsSchema>\n\n/**\n * Shows notifications to the user if they meet the criteria specified in the notifications.json file.\n *\n * @param currentSurfaces - The surfaces present in the current project (usually for app extensions).\n * @param environment - Process environment variables.\n * @returns - A promise that resolves when the notifications have been shown.\n */\nexport async function showNotificationsIfNeeded(\n currentSurfaces?: string[],\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<void> {\n try {\n const commandId = getCurrentCommandId()\n if (skipNotifications(commandId, environment) || jsonOutputEnabled(environment)) return\n\n const notifications = await getNotifications()\n const notificationsToShow = filterNotifications(notifications.notifications, commandId, currentSurfaces)\n outputDebug(`Notifications to show: ${notificationsToShow.length}`)\n await renderNotifications(notificationsToShow)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n if (error.message === EMPTY_CACHE_MESSAGE) {\n outputDebug('Notifications to show: 0 (Cache is empty)')\n return\n }\n if (error.message === 'abort') throw new AbortSilentError()\n const errorMessage = `Error showing notifications: ${error.message}`\n outputDebug(errorMessage)\n // This is very prone to becoming a circular dependency, so we import it dynamically\n const {sendErrorToBugsnag} = await import('./error-handler.js')\n await sendErrorToBugsnag(errorMessage, 'unexpected_error')\n }\n}\n\nfunction skipNotifications(currentCommand: string, environment: NodeJS.ProcessEnv = process.env): boolean {\n return (\n isTruthy(environment.CI) || isTruthy(environment.SHOPIFY_UNIT_TEST) || COMMANDS_TO_SKIP.includes(currentCommand)\n )\n}\n\n/**\n * Renders the first 2 notifications to the user.\n *\n * @param notifications - The notifications to render.\n */\nasync function renderNotifications(notifications: Notification[]) {\n notifications.slice(0, 2).forEach((notification) => {\n const content = {\n headline: notification.title,\n body: notification.message.replaceAll('\\\\n', '\\n'),\n link: notification.cta,\n }\n switch (notification.type) {\n case 'info': {\n renderInfo(content)\n break\n }\n case 'warning': {\n renderWarning(content)\n break\n }\n case 'error': {\n renderError(content)\n throw new Error('abort')\n }\n }\n cacheStore(`notification-${notification.id}`, new Date().getTime().toString())\n })\n}\n\n/**\n * Get notifications list from cache, that is updated in the background from bin/fetch-notifications.json.\n *\n * @returns A Notifications object.\n */\nexport async function getNotifications(): Promise<Notifications> {\n const cacheKey: NotificationsKey = `notifications-${url()}`\n const rawNotifications = cacheRetrieve(cacheKey)?.value as unknown as string\n if (!rawNotifications) throw new Error(EMPTY_CACHE_MESSAGE)\n const notifications: object = JSON.parse(rawNotifications)\n return NotificationsSchema.parse(notifications)\n}\n\n/**\n * Fetch notifications from the CDN and chache them.\n *\n * @returns A string with the notifications.\n */\nexport async function fetchNotifications(): Promise<Notifications> {\n outputDebug(`Fetching notifications...`)\n const response = await fetch(url(), {signal: AbortSignal.timeout(3 * 1000)})\n if (response.status !== 200) throw new Error(`Failed to fetch notifications: ${response.statusText}`)\n const rawNotifications = await response.text()\n const notifications: object = JSON.parse(rawNotifications)\n const result = NotificationsSchema.parse(notifications)\n await cacheNotifications(rawNotifications)\n return result\n}\n\n/**\n * Store the notifications in the cache.\n *\n * @param notifications - String with the notifications to cache.\n * @returns A Notifications object.\n */\nasync function cacheNotifications(notifications: string): Promise<void> {\n cacheStore(`notifications-${url()}`, notifications)\n outputDebug(`Notifications from ${url()} stored in the cache`)\n}\n\n/**\n * Fetch notifications in background as a detached process.\n *\n * @param currentCommand - The current Shopify command being run.\n * @param argv - The arguments passed to the current process.\n * @param environment - Process environment variables.\n */\nexport function fetchNotificationsInBackground(\n currentCommand: string,\n argv = process.argv,\n environment: NodeJS.ProcessEnv = process.env,\n): void {\n if (skipNotifications(currentCommand, environment)) return\n\n let command = 'shopify'\n const args = ['notifications', 'list', '--ignore-errors']\n // Run the Shopify command the same way as the current execution when it's not the global installation\n if (argv[0] && argv[0] !== 'shopify') {\n command = argv[0]\n const indexValue = currentCommand.split(':')[0] ?? ''\n const index = argv.indexOf(indexValue)\n if (index > 0) args.unshift(...argv.slice(1, index))\n }\n // eslint-disable-next-line no-void\n void exec(command, args, {background: true, env: {...process.env, SHOPIFY_CLI_NO_ANALYTICS: '1'}})\n}\n\n/**\n * Filters notifications based on the version of the CLI.\n *\n * @param notifications - The notifications to filter.\n * @param commandId - The command ID to filter by.\n * @param currentSurfaces - The surfaces present in the current project (usually for app extensions).\n * @param today - The current date.\n * @param currentVersion - The current version of the CLI.\n * @returns - The filtered notifications.\n */\nexport function filterNotifications(\n notifications: Notification[],\n commandId: string,\n currentSurfaces?: string[],\n today: Date = new Date(new Date().setUTCHours(0, 0, 0, 0)),\n currentVersion: string = CLI_KIT_VERSION,\n): Notification[] {\n return notifications\n .filter((notification) => filterByVersion(notification, currentVersion))\n .filter((notifications) => filterByDate(notifications, today))\n .filter((notification) => filterByCommand(notification, commandId))\n .filter((notification) => filterBySurface(notification, commandId, currentSurfaces))\n .filter((notification) => filterByFrequency(notification))\n}\n\n/**\n * Filters notifications based on the version of the CLI.\n *\n * @param notification - The notification to filter.\n * @param currentVersion - The current version of the CLI.\n */\nfunction filterByVersion(notification: Notification, currentVersion: string) {\n const minVersion = !notification.minVersion || versionSatisfies(currentVersion, `>=${notification.minVersion}`)\n const maxVersion = !notification.maxVersion || versionSatisfies(currentVersion, `<=${notification.maxVersion}`)\n return minVersion && maxVersion\n}\n\n/**\n * Filters notifications based on the date.\n *\n * @param notification - The notification to filter.\n * @param today - The current date.\n */\nfunction filterByDate(notification: Notification, today: Date) {\n const minDate = !notification.minDate || new Date(notification.minDate) <= today\n const maxDate = !notification.maxDate || new Date(notification.maxDate) >= today\n return minDate && maxDate\n}\n\n/**\n * Filters notifications based on the command ID.\n *\n * @param notification - The notification to filter.\n * @param commandId - The command ID to filter by.\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterByCommand(notification: Notification, commandId: string) {\n if (commandId === '') return true\n return !notification.commands || notification.commands.includes(commandId)\n}\n\n/**\n * Filters notifications based on the surface.\n *\n * @param notification - The notification to filter.\n * @param commandId - The command id.\n * @param surfacesFromContext - The surfaces present in the current project (usually for app extensions).\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterBySurface(notification: Notification, commandId: string, surfacesFromContext?: string[]) {\n const surfaceFromCommand = commandId.split(':')[0] ?? 'all'\n const notificationSurface = notification.surface ?? 'all'\n\n if (surfacesFromContext) return surfacesFromContext.includes(notificationSurface)\n\n return notificationSurface === surfaceFromCommand || notificationSurface === 'all'\n}\n\n/**\n * Filters notifications based on the frequency.\n *\n * @param notification - The notification to filter.\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterByFrequency(notification: Notification): boolean {\n if (!notification.frequency) return true\n const cacheKey: NotificationKey = `notification-${notification.id}`\n const lastShown = cacheRetrieve(cacheKey)?.value as unknown as string\n if (!lastShown) return true\n\n switch (notification.frequency) {\n case 'always': {\n return true\n }\n case 'once': {\n return false\n }\n case 'once_a_day': {\n return new Date().getTime() - Number(lastShown) > 24 * 3600 * 1000\n }\n case 'once_a_week': {\n return new Date().getTime() - Number(lastShown) > 7 * 24 * 3600 * 1000\n }\n }\n}\n\n/**\n * Returns a string with the filters from a notification, one by line.\n *\n * @param notification - The notification to get the filters from.\n * @returns A string with human-readable filters from the notification.\n */\nexport function stringifyFilters(notification: Notification): string {\n const filters = []\n if (notification.minDate) filters.push(`from ${notification.minDate}`)\n if (notification.maxDate) filters.push(`to ${notification.maxDate}`)\n if (notification.minVersion) filters.push(`from v${notification.minVersion}`)\n if (notification.maxVersion) filters.push(`to v${notification.maxVersion}`)\n if (notification.frequency === 'once') filters.push('show only once')\n if (notification.frequency === 'once_a_day') filters.push('show once a day')\n if (notification.frequency === 'once_a_week') filters.push('show once a week')\n if (notification.surface) filters.push(`surface = ${notification.surface}`)\n if (notification.commands) filters.push(`commands = ${notification.commands.join(', ')}`)\n return filters.join('\\n')\n}\n"]}
|
|
1
|
+
{"version":3,"file":"notifications-system.js","sourceRoot":"","sources":["../../../src/public/node/notifications-system.ts"],"names":[],"mappings":"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","sourcesContent":["import {versionSatisfies} from './node-package-manager.js'\nimport {renderError, renderInfo, renderWarning} from './ui.js'\nimport {getCurrentCommandId} from './global-context.js'\nimport {outputDebug} from './output.js'\nimport {zod} from './schema.js'\nimport {AbortSilentError} from './error.js'\nimport {isTruthy} from './context/utilities.js'\nimport {exec} from './system.js'\nimport {jsonOutputEnabled} from './environment.js'\nimport {CLI_KIT_VERSION} from '../common/version.js'\nimport {NotificationKey, NotificationsKey, cacheRetrieve, cacheStore} from '../../private/node/conf-store.js'\nimport {fetch} from '@shopify/cli-kit/node/http'\n\nconst URL = 'https://cdn.shopify.com/static/cli/notifications.json'\nconst EMPTY_CACHE_MESSAGE = 'Cache is empty'\nconst COMMANDS_TO_SKIP = [\n 'notifications:list',\n 'notifications:generate',\n 'init',\n 'app:init',\n 'theme:init',\n 'hydrogen:init',\n 'cache:clear',\n]\n\nfunction url(): string {\n return process.env.SHOPIFY_CLI_NOTIFICATIONS_URL ?? URL\n}\n\nconst NotificationSchema = zod.object({\n id: zod.string(),\n message: zod.string(),\n type: zod.enum(['info', 'warning', 'error']),\n frequency: zod.enum(['always', 'once', 'once_a_day', 'once_a_week']),\n ownerChannel: zod.string(),\n cta: zod\n .object({\n label: zod.string(),\n url: zod.string().url(),\n })\n .optional(),\n title: zod.string().optional(),\n minVersion: zod.string().optional(),\n maxVersion: zod.string().optional(),\n minDate: zod.string().optional(),\n maxDate: zod.string().optional(),\n commands: zod.array(zod.string()).optional(),\n surface: zod.string().optional(),\n})\nexport type Notification = zod.infer<typeof NotificationSchema>\n\nconst NotificationsSchema = zod.object({notifications: zod.array(NotificationSchema)})\nexport type Notifications = zod.infer<typeof NotificationsSchema>\n\n/**\n * Shows notifications to the user if they meet the criteria specified in the notifications.json file.\n *\n * @param currentSurfaces - The surfaces present in the current project (usually for app extensions).\n * @param environment - Process environment variables.\n * @returns - A promise that resolves when the notifications have been shown.\n */\nexport async function showNotificationsIfNeeded(\n currentSurfaces?: string[],\n environment: NodeJS.ProcessEnv = process.env,\n): Promise<void> {\n try {\n const commandId = getCurrentCommandId()\n if (skipNotifications(commandId, environment) || jsonOutputEnabled(environment)) return\n\n const notifications = await getNotifications()\n const notificationsToShow = filterNotifications(notifications.notifications, commandId, currentSurfaces)\n outputDebug(`Notifications to show: ${notificationsToShow.length}`)\n await renderNotifications(notificationsToShow)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n if (error.message === EMPTY_CACHE_MESSAGE) {\n outputDebug('Notifications to show: 0 (Cache is empty)')\n return\n }\n if (error.message === 'abort') throw new AbortSilentError()\n const errorMessage = `Error showing notifications: ${error.message}`\n outputDebug(errorMessage)\n // This is very prone to becoming a circular dependency, so we import it dynamically\n const {sendErrorToBugsnag} = await import('./error-handler.js')\n await sendErrorToBugsnag(errorMessage, 'unexpected_error')\n }\n}\n\nfunction skipNotifications(currentCommand: string, environment: NodeJS.ProcessEnv = process.env): boolean {\n return (\n isTruthy(environment.CI) || isTruthy(environment.SHOPIFY_UNIT_TEST) || COMMANDS_TO_SKIP.includes(currentCommand)\n )\n}\n\n/**\n * Renders the first 2 notifications to the user.\n *\n * @param notifications - The notifications to render.\n */\nasync function renderNotifications(notifications: Notification[]) {\n notifications.slice(0, 2).forEach((notification) => {\n const content = {\n headline: notification.title,\n body: notification.message.replaceAll('\\\\n', '\\n'),\n link: notification.cta,\n }\n switch (notification.type) {\n case 'info': {\n renderInfo(content)\n break\n }\n case 'warning': {\n renderWarning(content)\n break\n }\n case 'error': {\n renderError(content)\n throw new Error('abort')\n }\n }\n cacheStore(`notification-${notification.id}`, new Date().getTime().toString())\n })\n}\n\n/**\n * Get notifications list from cache, that is updated in the background from bin/fetch-notifications.json.\n *\n * @returns A Notifications object.\n */\nexport async function getNotifications(): Promise<Notifications> {\n const cacheKey: NotificationsKey = `notifications-${url()}`\n const rawNotifications = cacheRetrieve(cacheKey)?.value as unknown as string\n if (!rawNotifications) throw new Error(EMPTY_CACHE_MESSAGE)\n const notifications: object = JSON.parse(rawNotifications)\n return NotificationsSchema.parse(notifications)\n}\n\n/**\n * Fetch notifications from the CDN and chache them.\n *\n * @returns A string with the notifications.\n */\nexport async function fetchNotifications(): Promise<Notifications> {\n outputDebug(`Fetching notifications...`)\n const response = await fetch(url(), undefined, {\n useNetworkLevelRetry: false,\n useAbortSignal: true,\n timeoutMs: 3 * 1000,\n })\n if (response.status !== 200) throw new Error(`Failed to fetch notifications: ${response.statusText}`)\n const rawNotifications = await response.text()\n const notifications: object = JSON.parse(rawNotifications)\n const result = NotificationsSchema.parse(notifications)\n await cacheNotifications(rawNotifications)\n return result\n}\n\n/**\n * Store the notifications in the cache.\n *\n * @param notifications - String with the notifications to cache.\n * @returns A Notifications object.\n */\nasync function cacheNotifications(notifications: string): Promise<void> {\n cacheStore(`notifications-${url()}`, notifications)\n outputDebug(`Notifications from ${url()} stored in the cache`)\n}\n\n/**\n * Fetch notifications in background as a detached process.\n *\n * @param currentCommand - The current Shopify command being run.\n * @param argv - The arguments passed to the current process.\n * @param environment - Process environment variables.\n */\nexport function fetchNotificationsInBackground(\n currentCommand: string,\n argv = process.argv,\n environment: NodeJS.ProcessEnv = process.env,\n): void {\n if (skipNotifications(currentCommand, environment)) return\n\n let command = 'shopify'\n const args = ['notifications', 'list', '--ignore-errors']\n // Run the Shopify command the same way as the current execution when it's not the global installation\n if (argv[0] && argv[0] !== 'shopify') {\n command = argv[0]\n const indexValue = currentCommand.split(':')[0] ?? ''\n const index = argv.indexOf(indexValue)\n if (index > 0) args.unshift(...argv.slice(1, index))\n }\n // eslint-disable-next-line no-void\n void exec(command, args, {background: true, env: {...process.env, SHOPIFY_CLI_NO_ANALYTICS: '1'}})\n}\n\n/**\n * Filters notifications based on the version of the CLI.\n *\n * @param notifications - The notifications to filter.\n * @param commandId - The command ID to filter by.\n * @param currentSurfaces - The surfaces present in the current project (usually for app extensions).\n * @param today - The current date.\n * @param currentVersion - The current version of the CLI.\n * @returns - The filtered notifications.\n */\nexport function filterNotifications(\n notifications: Notification[],\n commandId: string,\n currentSurfaces?: string[],\n today: Date = new Date(new Date().setUTCHours(0, 0, 0, 0)),\n currentVersion: string = CLI_KIT_VERSION,\n): Notification[] {\n return notifications\n .filter((notification) => filterByVersion(notification, currentVersion))\n .filter((notifications) => filterByDate(notifications, today))\n .filter((notification) => filterByCommand(notification, commandId))\n .filter((notification) => filterBySurface(notification, commandId, currentSurfaces))\n .filter((notification) => filterByFrequency(notification))\n}\n\n/**\n * Filters notifications based on the version of the CLI.\n *\n * @param notification - The notification to filter.\n * @param currentVersion - The current version of the CLI.\n */\nfunction filterByVersion(notification: Notification, currentVersion: string) {\n const minVersion = !notification.minVersion || versionSatisfies(currentVersion, `>=${notification.minVersion}`)\n const maxVersion = !notification.maxVersion || versionSatisfies(currentVersion, `<=${notification.maxVersion}`)\n return minVersion && maxVersion\n}\n\n/**\n * Filters notifications based on the date.\n *\n * @param notification - The notification to filter.\n * @param today - The current date.\n */\nfunction filterByDate(notification: Notification, today: Date) {\n const minDate = !notification.minDate || new Date(notification.minDate) <= today\n const maxDate = !notification.maxDate || new Date(notification.maxDate) >= today\n return minDate && maxDate\n}\n\n/**\n * Filters notifications based on the command ID.\n *\n * @param notification - The notification to filter.\n * @param commandId - The command ID to filter by.\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterByCommand(notification: Notification, commandId: string) {\n if (commandId === '') return true\n return !notification.commands || notification.commands.includes(commandId)\n}\n\n/**\n * Filters notifications based on the surface.\n *\n * @param notification - The notification to filter.\n * @param commandId - The command id.\n * @param surfacesFromContext - The surfaces present in the current project (usually for app extensions).\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterBySurface(notification: Notification, commandId: string, surfacesFromContext?: string[]) {\n const surfaceFromCommand = commandId.split(':')[0] ?? 'all'\n const notificationSurface = notification.surface ?? 'all'\n\n if (surfacesFromContext) return surfacesFromContext.includes(notificationSurface)\n\n return notificationSurface === surfaceFromCommand || notificationSurface === 'all'\n}\n\n/**\n * Filters notifications based on the frequency.\n *\n * @param notification - The notification to filter.\n * @returns - A boolean indicating whether the notification should be shown.\n */\nfunction filterByFrequency(notification: Notification): boolean {\n if (!notification.frequency) return true\n const cacheKey: NotificationKey = `notification-${notification.id}`\n const lastShown = cacheRetrieve(cacheKey)?.value as unknown as string\n if (!lastShown) return true\n\n switch (notification.frequency) {\n case 'always': {\n return true\n }\n case 'once': {\n return false\n }\n case 'once_a_day': {\n return new Date().getTime() - Number(lastShown) > 24 * 3600 * 1000\n }\n case 'once_a_week': {\n return new Date().getTime() - Number(lastShown) > 7 * 24 * 3600 * 1000\n }\n }\n}\n\n/**\n * Returns a string with the filters from a notification, one by line.\n *\n * @param notification - The notification to get the filters from.\n * @returns A string with human-readable filters from the notification.\n */\nexport function stringifyFilters(notification: Notification): string {\n const filters = []\n if (notification.minDate) filters.push(`from ${notification.minDate}`)\n if (notification.maxDate) filters.push(`to ${notification.maxDate}`)\n if (notification.minVersion) filters.push(`from v${notification.minVersion}`)\n if (notification.maxVersion) filters.push(`to v${notification.maxVersion}`)\n if (notification.frequency === 'once') filters.push('show only once')\n if (notification.frequency === 'once_a_day') filters.push('show once a day')\n if (notification.frequency === 'once_a_week') filters.push('show once a week')\n if (notification.surface) filters.push(`surface = ${notification.surface}`)\n if (notification.commands) filters.push(`commands = ${notification.commands.join(', ')}`)\n return filters.join('\\n')\n}\n"]}
|
|
@@ -51,3 +51,9 @@ export declare function sleep(seconds: number): Promise<void>;
|
|
|
51
51
|
* @returns True if the standard input and output streams support prompting.
|
|
52
52
|
*/
|
|
53
53
|
export declare function terminalSupportsPrompting(): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Check if the current environment is a CI environment.
|
|
56
|
+
*
|
|
57
|
+
* @returns True if the current environment is a CI environment.
|
|
58
|
+
*/
|
|
59
|
+
export declare function isCI(): boolean;
|
|
@@ -158,4 +158,12 @@ export function terminalSupportsPrompting() {
|
|
|
158
158
|
}
|
|
159
159
|
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
160
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Check if the current environment is a CI environment.
|
|
163
|
+
*
|
|
164
|
+
* @returns True if the current environment is a CI environment.
|
|
165
|
+
*/
|
|
166
|
+
export function isCI() {
|
|
167
|
+
return isTruthy(process.env.CI);
|
|
168
|
+
}
|
|
161
169
|
//# sourceMappingURL=system.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/public/node/system.ts"],"names":[],"mappings":"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","sourcesContent":["import {AbortSignal} from './abort.js'\nimport {AbortError, ExternalError} from './error.js'\nimport {cwd, dirname} from './path.js'\nimport {treeKill} from './tree-kill.js'\nimport {isTruthy} from './context/utilities.js'\nimport {renderWarning} from './ui.js'\nimport {platformAndArch} from './os.js'\nimport {shouldDisplayColors, outputDebug} from '../../public/node/output.js'\nimport {execa, ExecaChildProcess} from 'execa'\nimport which from 'which'\nimport {delimiter} from 'pathe'\nimport type {Writable, Readable} from 'stream'\n\nexport interface ExecOptions {\n cwd?: string\n env?: {[key: string]: string | undefined}\n stdin?: Readable | 'inherit'\n stdout?: Writable | 'inherit'\n stderr?: Writable | 'inherit'\n stdio?: 'inherit'\n input?: string\n signal?: AbortSignal\n // Custom handler if process exits with a non-zero code\n externalErrorHandler?: (error: unknown) => Promise<void>\n // Ignored on Windows\n background?: boolean\n}\n\n/**\n * Opens a URL in the user's default browser.\n *\n * @param url - URL to open.\n * @returns A promise that resolves true if the URL was opened successfully, false otherwise.\n */\nexport async function openURL(url: string): Promise<boolean> {\n const externalOpen = await import('open')\n try {\n await externalOpen.default(url)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return false\n }\n}\n\n/**\n * Runs a command asynchronously, aggregates the stdout data, and returns it.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with the aggregatted stdout of the command.\n */\nexport async function captureOutput(command: string, args: string[], options?: ExecOptions): Promise<string> {\n const result = await buildExec(command, args, options)\n return result.stdout\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n */\nexport async function exec(command: string, args: string[], options?: ExecOptions): Promise<void> {\n if (options) {\n // Windows opens a new console window when running a command in the background, so we disable it.\n const runningOnWindows = platformAndArch().platform === 'windows'\n options.background = runningOnWindows ? false : options.background\n }\n\n const commandProcess = buildExec(command, args, options)\n\n if (options?.background) {\n commandProcess.unref()\n }\n\n if (options?.stderr && options.stderr !== 'inherit') {\n commandProcess.stderr?.pipe(options.stderr, {end: false})\n }\n if (options?.stdout && options.stdout !== 'inherit') {\n commandProcess.stdout?.pipe(options.stdout, {end: false})\n }\n let aborted = false\n options?.signal?.addEventListener('abort', () => {\n const pid = commandProcess.pid\n if (pid) {\n outputDebug(`Killing process ${pid}: ${command} ${args.join(' ')}`)\n aborted = true\n treeKill(pid, 'SIGTERM')\n }\n })\n try {\n await commandProcess\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (processError: any) {\n // Windows will throw an error whenever the process is killed, no matter the reason.\n // The aborted flag tell use that we killed it, so we can ignore the error.\n if (aborted) return\n if (options?.externalErrorHandler) {\n await options.externalErrorHandler(processError)\n } else {\n const abortError = new ExternalError(processError.message, command, args)\n abortError.stack = processError.stack\n throw abortError\n }\n }\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise for a result with stdout and stderr properties.\n */\nfunction buildExec(command: string, args: string[], options?: ExecOptions): ExecaChildProcess {\n const env = options?.env ?? process.env\n if (shouldDisplayColors()) {\n env.FORCE_COLOR = '1'\n }\n const executionCwd = options?.cwd ?? cwd()\n checkCommandSafety(command, {cwd: executionCwd})\n const commandProcess = execa(command, args, {\n env,\n cwd: executionCwd,\n input: options?.input,\n stdio: options?.background ? 'ignore' : options?.stdio,\n stdin: options?.stdin,\n stdout: options?.stdout === 'inherit' ? 'inherit' : undefined,\n stderr: options?.stderr === 'inherit' ? 'inherit' : undefined,\n // Setting this to false makes it possible to kill the main process\n // and all its sub-processes with Ctrl+C on Windows\n windowsHide: false,\n detached: options?.background,\n cleanup: !options?.background,\n })\n outputDebug(`Running system process${options?.background ? ' in background' : ''}:\n · Command: ${command} ${args.join(' ')}\n · Working directory: ${executionCwd}\n`)\n return commandProcess\n}\n\nfunction checkCommandSafety(command: string, _options: {cwd: string}): void {\n const pathIncludingLocal = `${_options.cwd}${delimiter}${process.env.PATH}`\n const commandPath = which.sync(command, {\n nothrow: true,\n path: pathIncludingLocal,\n })\n if (commandPath && dirname(commandPath) === _options.cwd) {\n const headline = ['Skipped run of unsecure binary', {command}, 'found in the current directory.']\n const body = 'Please remove that file or review your current PATH.'\n renderWarning({headline, body})\n throw new AbortError(headline, body)\n }\n}\n\n/**\n * Waits for a given number of seconds.\n *\n * @param seconds - Number of seconds to wait.\n * @returns A Promise resolving after the number of seconds.\n */\nexport async function sleep(seconds: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, 1000 * seconds)\n })\n}\n\n/**\n * Check if the standard input and output streams support prompting.\n *\n * @returns True if the standard input and output streams support prompting.\n */\nexport function terminalSupportsPrompting(): boolean {\n if (isTruthy(process.env.CI)) {\n return false\n }\n return Boolean(process.stdin.isTTY && process.stdout.isTTY)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/public/node/system.ts"],"names":[],"mappings":"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","sourcesContent":["import {AbortSignal} from './abort.js'\nimport {AbortError, ExternalError} from './error.js'\nimport {cwd, dirname} from './path.js'\nimport {treeKill} from './tree-kill.js'\nimport {isTruthy} from './context/utilities.js'\nimport {renderWarning} from './ui.js'\nimport {platformAndArch} from './os.js'\nimport {shouldDisplayColors, outputDebug} from '../../public/node/output.js'\nimport {execa, ExecaChildProcess} from 'execa'\nimport which from 'which'\nimport {delimiter} from 'pathe'\nimport type {Writable, Readable} from 'stream'\n\nexport interface ExecOptions {\n cwd?: string\n env?: {[key: string]: string | undefined}\n stdin?: Readable | 'inherit'\n stdout?: Writable | 'inherit'\n stderr?: Writable | 'inherit'\n stdio?: 'inherit'\n input?: string\n signal?: AbortSignal\n // Custom handler if process exits with a non-zero code\n externalErrorHandler?: (error: unknown) => Promise<void>\n // Ignored on Windows\n background?: boolean\n}\n\n/**\n * Opens a URL in the user's default browser.\n *\n * @param url - URL to open.\n * @returns A promise that resolves true if the URL was opened successfully, false otherwise.\n */\nexport async function openURL(url: string): Promise<boolean> {\n const externalOpen = await import('open')\n try {\n await externalOpen.default(url)\n return true\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n return false\n }\n}\n\n/**\n * Runs a command asynchronously, aggregates the stdout data, and returns it.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise that resolves with the aggregatted stdout of the command.\n */\nexport async function captureOutput(command: string, args: string[], options?: ExecOptions): Promise<string> {\n const result = await buildExec(command, args, options)\n return result.stdout\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n */\nexport async function exec(command: string, args: string[], options?: ExecOptions): Promise<void> {\n if (options) {\n // Windows opens a new console window when running a command in the background, so we disable it.\n const runningOnWindows = platformAndArch().platform === 'windows'\n options.background = runningOnWindows ? false : options.background\n }\n\n const commandProcess = buildExec(command, args, options)\n\n if (options?.background) {\n commandProcess.unref()\n }\n\n if (options?.stderr && options.stderr !== 'inherit') {\n commandProcess.stderr?.pipe(options.stderr, {end: false})\n }\n if (options?.stdout && options.stdout !== 'inherit') {\n commandProcess.stdout?.pipe(options.stdout, {end: false})\n }\n let aborted = false\n options?.signal?.addEventListener('abort', () => {\n const pid = commandProcess.pid\n if (pid) {\n outputDebug(`Killing process ${pid}: ${command} ${args.join(' ')}`)\n aborted = true\n treeKill(pid, 'SIGTERM')\n }\n })\n try {\n await commandProcess\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (processError: any) {\n // Windows will throw an error whenever the process is killed, no matter the reason.\n // The aborted flag tell use that we killed it, so we can ignore the error.\n if (aborted) return\n if (options?.externalErrorHandler) {\n await options.externalErrorHandler(processError)\n } else {\n const abortError = new ExternalError(processError.message, command, args)\n abortError.stack = processError.stack\n throw abortError\n }\n }\n}\n\n/**\n * Runs a command asynchronously.\n *\n * @param command - Command to be executed.\n * @param args - Arguments to pass to the command.\n * @param options - Optional settings for how to run the command.\n * @returns A promise for a result with stdout and stderr properties.\n */\nfunction buildExec(command: string, args: string[], options?: ExecOptions): ExecaChildProcess {\n const env = options?.env ?? process.env\n if (shouldDisplayColors()) {\n env.FORCE_COLOR = '1'\n }\n const executionCwd = options?.cwd ?? cwd()\n checkCommandSafety(command, {cwd: executionCwd})\n const commandProcess = execa(command, args, {\n env,\n cwd: executionCwd,\n input: options?.input,\n stdio: options?.background ? 'ignore' : options?.stdio,\n stdin: options?.stdin,\n stdout: options?.stdout === 'inherit' ? 'inherit' : undefined,\n stderr: options?.stderr === 'inherit' ? 'inherit' : undefined,\n // Setting this to false makes it possible to kill the main process\n // and all its sub-processes with Ctrl+C on Windows\n windowsHide: false,\n detached: options?.background,\n cleanup: !options?.background,\n })\n outputDebug(`Running system process${options?.background ? ' in background' : ''}:\n · Command: ${command} ${args.join(' ')}\n · Working directory: ${executionCwd}\n`)\n return commandProcess\n}\n\nfunction checkCommandSafety(command: string, _options: {cwd: string}): void {\n const pathIncludingLocal = `${_options.cwd}${delimiter}${process.env.PATH}`\n const commandPath = which.sync(command, {\n nothrow: true,\n path: pathIncludingLocal,\n })\n if (commandPath && dirname(commandPath) === _options.cwd) {\n const headline = ['Skipped run of unsecure binary', {command}, 'found in the current directory.']\n const body = 'Please remove that file or review your current PATH.'\n renderWarning({headline, body})\n throw new AbortError(headline, body)\n }\n}\n\n/**\n * Waits for a given number of seconds.\n *\n * @param seconds - Number of seconds to wait.\n * @returns A Promise resolving after the number of seconds.\n */\nexport async function sleep(seconds: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, 1000 * seconds)\n })\n}\n\n/**\n * Check if the standard input and output streams support prompting.\n *\n * @returns True if the standard input and output streams support prompting.\n */\nexport function terminalSupportsPrompting(): boolean {\n if (isTruthy(process.env.CI)) {\n return false\n }\n return Boolean(process.stdin.isTTY && process.stdout.isTTY)\n}\n\n/**\n * Check if the current environment is a CI environment.\n *\n * @returns True if the current environment is a CI environment.\n */\nexport function isCI(): boolean {\n return isTruthy(process.env.CI)\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { inTemporaryDirectory } from '../fs.js';
|
|
2
|
+
import { test } from 'vitest';
|
|
3
|
+
/**
|
|
4
|
+
* Vitest fixture providing the test with a temporary directory to work in.
|
|
5
|
+
*/
|
|
6
|
+
export const testWithTempDir = test.extend({
|
|
7
|
+
// eslint-disable-next-line no-empty-pattern
|
|
8
|
+
tempDir: async ({}, use) => {
|
|
9
|
+
await inTemporaryDirectory(async (tempDir) => {
|
|
10
|
+
await use(tempDir);
|
|
11
|
+
});
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=test-with-temp-dir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-with-temp-dir.js","sourceRoot":"","sources":["../../../../src/public/node/testing/test-with-temp-dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,oBAAoB,EAAC,MAAM,UAAU,CAAA;AAC7C,OAAO,EAAC,IAAI,EAAU,MAAM,QAAQ,CAAA;AAMpC;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAA4B,IAAI,CAAC,MAAM,CAAiB;IAClF,4CAA4C;IAC5C,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE;QACzB,MAAM,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC3C,MAAM,GAAG,CAAC,OAAO,CAAC,CAAA;QACpB,CAAC,CAAC,CAAA;IACJ,CAAC;CACF,CAAC,CAAA","sourcesContent":["import {inTemporaryDirectory} from '../fs.js'\nimport {test, TestAPI} from 'vitest'\n\ninterface TempDirFixture {\n tempDir: string\n}\n\n/**\n * Vitest fixture providing the test with a temporary directory to work in.\n */\nexport const testWithTempDir: TestAPI<TempDirFixture> = test.extend<TempDirFixture>({\n // eslint-disable-next-line no-empty-pattern\n tempDir: async ({}, use) => {\n await inTemporaryDirectory(async (tempDir) => {\n await use(tempDir)\n })\n },\n})\n"]}
|
|
@@ -4,18 +4,19 @@ import { AdminSession } from '../session.js';
|
|
|
4
4
|
*/
|
|
5
5
|
export type Key = string;
|
|
6
6
|
export type ThemeFSEventName = 'add' | 'change' | 'unlink';
|
|
7
|
+
type OnSync = (onSuccess: () => void, onError?: () => void) => void;
|
|
7
8
|
type ThemeFSEvent = {
|
|
8
9
|
type: 'unlink';
|
|
9
10
|
payload: {
|
|
10
11
|
fileKey: Key;
|
|
11
|
-
onSync
|
|
12
|
+
onSync: OnSync;
|
|
12
13
|
};
|
|
13
14
|
} | {
|
|
14
15
|
type: 'add' | 'change';
|
|
15
16
|
payload: {
|
|
16
17
|
fileKey: Key;
|
|
17
18
|
onContent: (fn: (content: string) => void) => void;
|
|
18
|
-
onSync:
|
|
19
|
+
onSync: OnSync;
|
|
19
20
|
};
|
|
20
21
|
};
|
|
21
22
|
export type ThemeFSEventPayload<T extends ThemeFSEventName = 'add'> = (ThemeFSEvent & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/public/node/themes/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/public/node/themes/types.ts"],"names":[],"mappings":"AA8NA,MAAM,CAAN,IAAY,SAGX;AAHD,WAAY,SAAS;IACnB,8BAAiB,CAAA;IACjB,8BAAiB,CAAA;AACnB,CAAC,EAHW,SAAS,KAAT,SAAS,QAGpB","sourcesContent":["import {AdminSession} from '../session.js'\n\n/**\n * {@link Key} represents the unique identifier of a file in a theme.\n */\nexport type Key = string\n\nexport type ThemeFSEventName = 'add' | 'change' | 'unlink'\n\ntype OnSync = (onSuccess: () => void, onError?: () => void) => void\n\ntype ThemeFSEvent =\n | {\n type: 'unlink'\n payload: {fileKey: Key; onSync: OnSync}\n }\n | {\n type: 'add' | 'change'\n payload: {\n fileKey: Key\n onContent: (fn: (content: string) => void) => void\n onSync: OnSync\n }\n }\n\nexport type ThemeFSEventPayload<T extends ThemeFSEventName = 'add'> = (ThemeFSEvent & {type: T})['payload']\n\nexport interface ThemeFileSystemOptions {\n filters?: {ignore?: string[]; only?: string[]}\n notify?: string\n noDelete?: boolean\n}\n\n/**\n * Represents a theme on the file system.\n */\nexport interface VirtualFileSystem {\n /**\n * The root path of the theme.\n */\n root: string\n\n /**\n * Local files.\n */\n files: Map<Key, ThemeAsset>\n\n /**\n * File keys that have been modified in memory and are not uploaded yet.\n */\n unsyncedFileKeys: Set<Key>\n\n /**\n * Promise that resolves when all the initial files are found.\n */\n ready: () => Promise<void>\n\n /**\n * Removes a file from the local disk and updates the file system\n *\n * @param fileKey - The key of the file to remove\n */\n delete: (fileKey: Key) => Promise<void>\n\n /**\n * Writes a file to the local disk and updates the file system\n *\n * @param asset - The ThemeAsset representing the file to write\n */\n write: (asset: ThemeAsset) => Promise<void>\n\n /**\n * Reads a file from the local disk and updates the file system\n * Returns a ThemeAsset representing the file that was read\n * Returns undefined if the file does not exist\n *\n * @param fileKey - The key of the file to read\n */\n read: (fileKey: Key) => Promise<string | Buffer | undefined>\n\n /**\n * Add callbacks to run after certain events are fired.\n */\n addEventListener: <T extends ThemeFSEventName>(eventName: T, cb: (params: ThemeFSEventPayload<T>) => void) => void\n}\n\n/**\n * Represents a theme on the file system.\n */\nexport interface ThemeFileSystem extends VirtualFileSystem {\n /**\n * Starts a file watcher for the theme directory.\n *\n * @param themeId - The ID of the theme being watched.\n * @param adminSession - The admin session for API communication.\n * @returns A Promise that resolves to an FSWatcher instance.\n */\n startWatcher: (themeId: string, adminSession: AdminSession) => Promise<void>\n\n /**\n * Applies filters to ignore files from .shopifyignore file, --ignore and --only flags.\n */\n applyIgnoreFilters: <T extends {key: string}>(files: T[]) => T[]\n\n /**\n * Stores upload errors returned when uploading files via the Asset API\n */\n uploadErrors: Map<Key, string[]>\n}\n\n/**\n * Represents a theme on the file system.\n */\nexport interface ThemeExtensionFileSystem extends VirtualFileSystem {\n /**\n * Starts a file watcher for the theme extension directory.\n */\n startWatcher: () => Promise<void>\n}\n\n/**\n * Represents a theme.\n */\nexport interface Theme {\n /**\n * The remote ID of the theme.\n */\n id: number\n\n /**\n * The remote name of the theme.\n */\n name: string\n\n /**\n * A boolean determining whether or not the theme was created at runtime.\n */\n createdAtRuntime: boolean\n\n /**\n * A boolean determining if the theme is processing at the theme library.\n */\n processing: boolean\n\n /**\n * The remote role of the theme.\n */\n role: string\n\n /**\n * A public URL where Shopify can access the theme code.\n */\n src?: string\n}\n\n/**\n * Represents the remote checksum for a file in a theme.\n */\nexport interface Checksum {\n /**\n * Identifier of the theme file.\n */\n key: Key\n\n /**\n * Represents the checksum value of the theme file.\n */\n checksum: string\n}\n\n/**\n * Represents a theme or theme extension asset.\n */\nexport interface ThemeAsset extends Checksum {\n /**\n * A base64-encoded image.\n */\n attachment?: string\n\n /**\n * The text content of the asset, such as the HTML and Liquid markup of a template file.\n */\n value?: string\n\n /**\n * File stats at time of last modification. For attachments, this is the size of the base64 string.\n */\n stats?: {mtime: number; size: number}\n}\n\n/**\n * Represents a single result for an upload or delete operation on a single file\n * Each result includes the unique identifier for the file, the type of the operation,\n * the success status of the operation, any errors that occurred, and the asset value of the file.\n */\nexport interface Result {\n /**\n * The unique identifier for the file being uploaded.\n */\n key: string\n\n /**\n * The operation associated with the result.\n */\n operation: Operation\n\n /**\n * Indicates whether the upload operation for this file was successful.\n */\n success: boolean\n\n /**\n * Error message that was generated during the upload operation for this file.\n */\n errors?: {asset?: string[]}\n\n /**\n * The asset that was uploaded as part of the upload operation for this file.\n */\n asset?: Omit<ThemeAsset, 'stats'>\n}\n\nexport enum Operation {\n Delete = 'DELETE',\n Upload = 'UPLOAD',\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { HostOptions } from './types.js';
|
|
2
|
+
export declare function createServer(projectName: string): {
|
|
3
|
+
host: (options?: HostOptions) => string;
|
|
4
|
+
url: (options?: HostOptions) => string;
|
|
5
|
+
};
|
|
6
|
+
declare function assertRunning2016(projectName: string): void;
|
|
7
|
+
declare let assertRunningOverride: typeof assertRunning2016 | undefined;
|
|
8
|
+
export declare function setAssertRunning(override: typeof assertRunningOverride): void;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import { assertConnectable } from './network/index.js';
|
|
4
|
+
import { assertCompatibleEnvironment } from './env.js';
|
|
5
|
+
export function createServer(projectName) {
|
|
6
|
+
return {
|
|
7
|
+
host: (options = {}) => host(projectName, options),
|
|
8
|
+
url: (options = {}) => url(projectName, options),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function host(projectName, options = {}) {
|
|
12
|
+
assertCompatibleEnvironment();
|
|
13
|
+
(assertRunningOverride || assertRunning2016)(projectName);
|
|
14
|
+
const prefix = options.nonstandardHostPrefix || projectName;
|
|
15
|
+
return `${prefix}.myshopify.io`;
|
|
16
|
+
}
|
|
17
|
+
function url(projectName, options = {}) {
|
|
18
|
+
return `https://${host(projectName, options)}`;
|
|
19
|
+
}
|
|
20
|
+
function assertRunning2016(projectName) {
|
|
21
|
+
const [addr, port] = getAddrPort(projectName);
|
|
22
|
+
assertConnectable({ projectName, addr, port });
|
|
23
|
+
}
|
|
24
|
+
function getAddrPort(name) {
|
|
25
|
+
try {
|
|
26
|
+
const portContent = fs.readFileSync(`${os.homedir()}/.local/run/services/${name}/server/port`, 'utf-8');
|
|
27
|
+
return ['localhost', parseInt(portContent, 10)];
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
throw new Error(`DevServer for '${name}' is not running: \`dev up ${name}\` to start it.`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Allow overrides for more concise test setup. Meh.
|
|
34
|
+
let assertRunningOverride;
|
|
35
|
+
export function setAssertRunning(override) {
|
|
36
|
+
assertRunningOverride = override;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=dev-server-2016.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-server-2016.js","sourceRoot":"","sources":["../../../../../src/public/node/vendor/dev_server/dev-server-2016.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAE7B,OAAO,EAAC,iBAAiB,EAAC,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAC,2BAA2B,EAAC,MAAM,UAAU,CAAA;AAGpD,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO;QACL,IAAI,EAAE,CAAC,UAAuB,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC;QAC/D,GAAG,EAAE,CAAC,UAAuB,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC;KAC9D,CAAA;AACH,CAAC;AAED,SAAS,IAAI,CAAC,WAAmB,EAAE,UAAuB,EAAE;IAC1D,2BAA2B,EAAE,CAC5B;IAAA,CAAC,qBAAqB,IAAI,iBAAiB,CAAC,CAAC,WAAW,CAAC,CAAA;IAE1D,MAAM,MAAM,GAAG,OAAO,CAAC,qBAAqB,IAAI,WAAW,CAAA;IAE3D,OAAO,GAAG,MAAM,eAAe,CAAA;AACjC,CAAC;AAED,SAAS,GAAG,CAAC,WAAmB,EAAE,UAAuB,EAAE;IACzD,OAAO,WAAW,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,CAAA;AAChD,CAAC;AAED,SAAS,iBAAiB,CAAC,WAAmB;IAC5C,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,WAAW,CAAC,WAAW,CAAC,CAAA;IAC7C,iBAAiB,CAAC,EAAC,WAAW,EAAE,IAAI,EAAE,IAAI,EAAC,CAAC,CAAA;AAC9C,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,wBAAwB,IAAI,cAAc,EAAE,OAAO,CAAC,CAAA;QACvG,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,8BAA8B,IAAI,iBAAiB,CAAC,CAAA;IAC5F,CAAC;AACH,CAAC;AAED,oDAAoD;AACpD,IAAI,qBAA2D,CAAA;AAE/D,MAAM,UAAU,gBAAgB,CAAC,QAAsC;IACrE,qBAAqB,GAAG,QAAQ,CAAA;AAClC,CAAC","sourcesContent":["import fs from 'fs'\nimport * as os from 'node:os'\n\nimport {assertConnectable} from './network/index.js'\nimport {assertCompatibleEnvironment} from './env.js'\nimport {HostOptions} from './types.js'\n\nexport function createServer(projectName: string) {\n return {\n host: (options: HostOptions = {}) => host(projectName, options),\n url: (options: HostOptions = {}) => url(projectName, options),\n }\n}\n\nfunction host(projectName: string, options: HostOptions = {}): string {\n assertCompatibleEnvironment()\n ;(assertRunningOverride || assertRunning2016)(projectName)\n\n const prefix = options.nonstandardHostPrefix || projectName\n\n return `${prefix}.myshopify.io`\n}\n\nfunction url(projectName: string, options: HostOptions = {}): string {\n return `https://${host(projectName, options)}`\n}\n\nfunction assertRunning2016(projectName: string): void {\n const [addr, port] = getAddrPort(projectName)\n assertConnectable({projectName, addr, port})\n}\n\nfunction getAddrPort(name: string): [string, number] {\n try {\n const portContent = fs.readFileSync(`${os.homedir()}/.local/run/services/${name}/server/port`, 'utf-8')\n return ['localhost', parseInt(portContent, 10)]\n } catch (error) {\n throw new Error(`DevServer for '${name}' is not running: \\`dev up ${name}\\` to start it.`)\n }\n}\n\n// Allow overrides for more concise test setup. Meh.\nlet assertRunningOverride: typeof assertRunning2016 | undefined\n\nexport function setAssertRunning(override: typeof assertRunningOverride) {\n assertRunningOverride = override\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { HostOptions } from './types.js';
|
|
2
|
+
export declare function createServer(projectName: string): {
|
|
3
|
+
host: (options?: HostOptions) => string;
|
|
4
|
+
url: (options?: HostOptions) => string;
|
|
5
|
+
};
|
|
6
|
+
declare function assertRunning2024(projectName: string): void;
|
|
7
|
+
declare let assertRunningOverride: typeof assertRunning2024 | undefined;
|
|
8
|
+
export declare function setAssertRunning(override: typeof assertRunningOverride): void;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import * as ni from 'network-interfaces';
|
|
3
|
+
import { assertConnectable, getIpFromHosts } from './network/index.js';
|
|
4
|
+
import { assertCompatibleEnvironment } from './env.js';
|
|
5
|
+
const NON_SHOP_PREFIXES = ['app', 'dev', 'shopify'];
|
|
6
|
+
const BACKEND_PORT = 8080;
|
|
7
|
+
export function createServer(projectName) {
|
|
8
|
+
return {
|
|
9
|
+
host: (options = {}) => host(projectName, options),
|
|
10
|
+
url: (options = {}) => url(projectName, options),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function host(projectName, options = {}) {
|
|
14
|
+
assertCompatibleEnvironment();
|
|
15
|
+
(assertRunningOverride || assertRunning2024)(projectName);
|
|
16
|
+
const prefix = (options.nonstandardHostPrefix || projectName).replace(/_/g, '-');
|
|
17
|
+
if (projectName === 'shopify') {
|
|
18
|
+
if (prefix.endsWith('-dev-api')) {
|
|
19
|
+
const shopName = prefix.replace('-dev-api', '');
|
|
20
|
+
return `${shopName}.dev-api.shop.dev`;
|
|
21
|
+
}
|
|
22
|
+
if (!NON_SHOP_PREFIXES.includes(prefix)) {
|
|
23
|
+
return `${prefix}.my.shop.dev`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return `${prefix}.shop.dev`;
|
|
27
|
+
}
|
|
28
|
+
function url(projectName, options = {}) {
|
|
29
|
+
return `https://${host(projectName, options)}`;
|
|
30
|
+
}
|
|
31
|
+
function assertRunning2024(projectName) {
|
|
32
|
+
assertConnectable({
|
|
33
|
+
projectName,
|
|
34
|
+
addr: getBackendIp(projectName),
|
|
35
|
+
port: BACKEND_PORT,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function getBackendIp(projectName) {
|
|
39
|
+
try {
|
|
40
|
+
const backendIp = resolveBackendHost(projectName);
|
|
41
|
+
ni.fromIp(backendIp, { internal: true, ipVersion: 4 });
|
|
42
|
+
return backendIp;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
throw new Error(`DevServer for '${projectName}' is not running: \`dev up ${projectName}\` to start it.`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function resolveBackendHost(name) {
|
|
49
|
+
let host;
|
|
50
|
+
try {
|
|
51
|
+
host = fs.readlinkSync(`/opt/nginx/etc/manifest/${name}/current`);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
host = `${name}.root.shopify.dev.internal`;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
return getIpFromHosts(host);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return host;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Allow overrides for more concise test setup. Meh.
|
|
64
|
+
let assertRunningOverride;
|
|
65
|
+
export function setAssertRunning(override) {
|
|
66
|
+
assertRunningOverride = override;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=dev-server-2024.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-server-2024.js","sourceRoot":"","sources":["../../../../../src/public/node/vendor/dev_server/dev-server-2024.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs'\n\nimport * as ni from 'network-interfaces'\n\nimport type {HostOptions} from './types.js'\nimport {assertConnectable, getIpFromHosts} from './network/index.js'\nimport {assertCompatibleEnvironment} from './env.js'\n\nconst NON_SHOP_PREFIXES = ['app', 'dev', 'shopify']\nconst BACKEND_PORT = 8080\n\nexport function createServer(projectName: string) {\n return {\n host: (options: HostOptions = {}) => host(projectName, options),\n url: (options: HostOptions = {}) => url(projectName, options),\n }\n}\n\nfunction host(projectName: string, options: HostOptions = {}): string {\n assertCompatibleEnvironment()\n ;(assertRunningOverride || assertRunning2024)(projectName)\n\n const prefix = (options.nonstandardHostPrefix || projectName).replace(/_/g, '-')\n\n if (projectName === 'shopify') {\n if (prefix.endsWith('-dev-api')) {\n const shopName = prefix.replace('-dev-api', '')\n return `${shopName}.dev-api.shop.dev`\n }\n if (!NON_SHOP_PREFIXES.includes(prefix)) {\n return `${prefix}.my.shop.dev`\n }\n }\n return `${prefix}.shop.dev`\n}\n\nfunction url(projectName: string, options: HostOptions = {}): string {\n return `https://${host(projectName, options)}`\n}\n\nfunction assertRunning2024(projectName: string): void {\n assertConnectable({\n projectName,\n addr: getBackendIp(projectName),\n port: BACKEND_PORT,\n })\n}\n\nfunction getBackendIp(projectName: string): string {\n try {\n const backendIp = resolveBackendHost(projectName)\n ni.fromIp(backendIp, {internal: true, ipVersion: 4})\n\n return backendIp\n } catch (error) {\n throw new Error(`DevServer for '${projectName}' is not running: \\`dev up ${projectName}\\` to start it.`)\n }\n}\n\nfunction resolveBackendHost(name: string): string {\n let host: string\n try {\n host = fs.readlinkSync(`/opt/nginx/etc/manifest/${name}/current`)\n } catch (error) {\n host = `${name}.root.shopify.dev.internal`\n }\n\n try {\n return getIpFromHosts(host)\n } catch {\n return host\n }\n}\n\n// Allow overrides for more concise test setup. Meh.\nlet assertRunningOverride: typeof assertRunning2024 | undefined\n\nexport function setAssertRunning(override: typeof assertRunningOverride) {\n assertRunningOverride = override\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { assertCompatibleEnvironment } from './env.js';
|
|
3
|
+
export function createServer(projectName) {
|
|
4
|
+
return {
|
|
5
|
+
host: (options = {}) => host(projectName, options),
|
|
6
|
+
url: (options = {}) => url(projectName, options),
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function host(projectName, { nonstandardHostPrefix } = {}) {
|
|
10
|
+
assertCompatibleEnvironment();
|
|
11
|
+
const services = fs.readdirSync('/run/ports2').filter((file) => file.endsWith(`--${projectName}`));
|
|
12
|
+
if (services.length === 0) {
|
|
13
|
+
throw new Error(`DevServer for '${projectName}' not present in this spin environment`);
|
|
14
|
+
}
|
|
15
|
+
// Spin mostly doesn't do alternative hostname prefixing for core.
|
|
16
|
+
if (projectName === 'shopify') {
|
|
17
|
+
const prefix = nonstandardHostPrefix?.replace(/[-_]dev[-_]api$/, '');
|
|
18
|
+
return `${prefix}.${projectName}.${process.env.SPIN_FQDN}`;
|
|
19
|
+
}
|
|
20
|
+
const match = new RegExp(`^(.+)${projectName}$`).exec(services[0]);
|
|
21
|
+
const organization = match ? match[1] : '';
|
|
22
|
+
const spinPrefix = organization === 'shopify--' ? '' : `${organization}`;
|
|
23
|
+
return `${spinPrefix}${projectName}.${process.env.SPIN_FQDN}`;
|
|
24
|
+
}
|
|
25
|
+
function url(projectName, options = {}) {
|
|
26
|
+
return `https://${host(projectName, options)}`;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=dev-server-spin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-server-spin.js","sourceRoot":"","sources":["../../../../../src/public/node/vendor/dev_server/dev-server-spin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AAGxB,OAAO,EAAC,2BAA2B,EAAC,MAAM,UAAU,CAAA;AAEpD,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO;QACL,IAAI,EAAE,CAAC,UAAuB,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC;QAC/D,GAAG,EAAE,CAAC,UAAuB,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC;KAC9D,CAAA;AACH,CAAC;AAED,SAAS,IAAI,CAAC,WAAmB,EAAE,EAAC,qBAAqB,KAAiB,EAAE;IAC1E,2BAA2B,EAAE,CAAA;IAE7B,MAAM,QAAQ,GAAG,EAAE,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,WAAW,EAAE,CAAC,CAAC,CAAA;IAClG,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,kBAAkB,WAAW,wCAAwC,CAAC,CAAA;IACxF,CAAC;IAED,kEAAkE;IAClE,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,qBAAqB,EAAE,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAA;QAEpE,OAAO,GAAG,MAAM,IAAI,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAA;IAC5D,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,QAAQ,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAA;IACnE,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC1C,MAAM,UAAU,GAAG,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,YAAY,EAAE,CAAA;IAExE,OAAO,GAAG,UAAU,GAAG,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAA;AAC/D,CAAC;AAED,SAAS,GAAG,CAAC,WAAmB,EAAE,UAAuB,EAAE;IACzD,OAAO,WAAW,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,CAAA;AAChD,CAAC","sourcesContent":["import fs from 'node:fs'\n\nimport type {HostOptions} from './types.js'\nimport {assertCompatibleEnvironment} from './env.js'\n\nexport function createServer(projectName: string) {\n return {\n host: (options: HostOptions = {}) => host(projectName, options),\n url: (options: HostOptions = {}) => url(projectName, options),\n }\n}\n\nfunction host(projectName: string, {nonstandardHostPrefix}: HostOptions = {}): string {\n assertCompatibleEnvironment()\n\n const services = fs.readdirSync('/run/ports2').filter((file) => file.endsWith(`--${projectName}`))\n if (services.length === 0) {\n throw new Error(`DevServer for '${projectName}' not present in this spin environment`)\n }\n\n // Spin mostly doesn't do alternative hostname prefixing for core.\n if (projectName === 'shopify') {\n const prefix = nonstandardHostPrefix?.replace(/[-_]dev[-_]api$/, '')\n\n return `${prefix}.${projectName}.${process.env.SPIN_FQDN}`\n }\n\n const match = new RegExp(`^(.+)${projectName}$`).exec(services[0]!)\n const organization = match ? match[1] : ''\n const spinPrefix = organization === 'shopify--' ? '' : `${organization}`\n\n return `${spinPrefix}${projectName}.${process.env.SPIN_FQDN}`\n}\n\nfunction url(projectName: string, options: HostOptions = {}) {\n return `https://${host(projectName, options)}`\n}\n"]}
|