@shopify/cli-kit 3.86.1 → 3.87.0

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.
Files changed (49) hide show
  1. package/README.md +2 -1
  2. package/dist/cli/api/graphql/admin/generated/theme_files_upsert.d.ts +1 -0
  3. package/dist/cli/api/graphql/admin/generated/theme_files_upsert.js +1 -0
  4. package/dist/cli/api/graphql/admin/generated/theme_files_upsert.js.map +1 -1
  5. package/dist/private/node/analytics.d.ts +1 -0
  6. package/dist/private/node/analytics.js +4 -0
  7. package/dist/private/node/analytics.js.map +1 -1
  8. package/dist/private/node/api.d.ts +24 -0
  9. package/dist/private/node/api.js +42 -4
  10. package/dist/private/node/api.js.map +1 -1
  11. package/dist/private/node/session/device-authorization.js +47 -8
  12. package/dist/private/node/session/device-authorization.js.map +1 -1
  13. package/dist/private/node/session/exchange.js +1 -1
  14. package/dist/private/node/session/exchange.js.map +1 -1
  15. package/dist/public/common/json.d.ts +17 -0
  16. package/dist/public/common/json.js +28 -0
  17. package/dist/public/common/json.js.map +1 -0
  18. package/dist/public/common/version.d.ts +1 -1
  19. package/dist/public/common/version.js +1 -1
  20. package/dist/public/common/version.js.map +1 -1
  21. package/dist/public/node/api/admin.js +8 -2
  22. package/dist/public/node/api/admin.js.map +1 -1
  23. package/dist/public/node/archiver.js +34 -14
  24. package/dist/public/node/archiver.js.map +1 -1
  25. package/dist/public/node/base-command.js +18 -0
  26. package/dist/public/node/base-command.js.map +1 -1
  27. package/dist/public/node/custom-oclif-loader.js +24 -19
  28. package/dist/public/node/custom-oclif-loader.js.map +1 -1
  29. package/dist/public/node/fs.d.ts +15 -0
  30. package/dist/public/node/fs.js +25 -0
  31. package/dist/public/node/fs.js.map +1 -1
  32. package/dist/public/node/git.js +56 -49
  33. package/dist/public/node/git.js.map +1 -1
  34. package/dist/public/node/hooks/postrun.d.ts +6 -0
  35. package/dist/public/node/hooks/postrun.js +10 -0
  36. package/dist/public/node/hooks/postrun.js.map +1 -1
  37. package/dist/public/node/import-extractor.d.ts +27 -0
  38. package/dist/public/node/import-extractor.js +178 -0
  39. package/dist/public/node/import-extractor.js.map +1 -0
  40. package/dist/public/node/metadata.d.ts +3 -0
  41. package/dist/public/node/monorail.d.ts +2 -1
  42. package/dist/public/node/monorail.js +1 -1
  43. package/dist/public/node/monorail.js.map +1 -1
  44. package/dist/public/node/node-package-manager.js +3 -2
  45. package/dist/public/node/node-package-manager.js.map +1 -1
  46. package/dist/public/node/themes/api.js +4 -0
  47. package/dist/public/node/themes/api.js.map +1 -1
  48. package/dist/tsconfig.tsbuildinfo +1 -1
  49. package/package.json +2 -2
@@ -1 +1 @@
1
- export declare const CLI_KIT_VERSION = "3.86.1";
1
+ export declare const CLI_KIT_VERSION = "3.87.0";
@@ -1,2 +1,2 @@
1
- export const CLI_KIT_VERSION = '3.86.1';
1
+ export const CLI_KIT_VERSION = '3.87.0';
2
2
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '3.86.1'\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/public/common/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAA","sourcesContent":["export const CLI_KIT_VERSION = '3.87.0'\n"]}
@@ -2,6 +2,7 @@ import { graphqlRequest, graphqlRequestDoc, } from './graphql.js';
2
2
  import { outputContent, outputToken } from '../../../public/node/output.js';
3
3
  import { AbortError, BugError } from '../error.js';
4
4
  import { restRequestBody, restRequestHeaders, restRequestUrl, isThemeAccessSession, } from '../../../private/node/api/rest.js';
5
+ import { isNetworkError } from '../../../private/node/api.js';
5
6
  import { shopifyFetch } from '../http.js';
6
7
  import { PublicApiVersions } from '../../../cli/api/graphql/admin/generated/public_api_versions.js';
7
8
  import { themeKitAccessDomain } from '../../../private/node/constants.js';
@@ -127,9 +128,14 @@ async function fetchApiVersions(session, preferredBehaviour) {
127
128
  if (error instanceof ClientError && (error.response.status === 401 || error.response.status === 404)) {
128
129
  throw new AbortError(`Error connecting to your store ${session.storeFqdn}: ${error.message} ${error.response.status} ${error.response.data}`);
129
130
  }
130
- else {
131
- throw new BugError(`Unknown error connecting to your store ${session.storeFqdn}: ${error instanceof Error ? error.message : String(error)}`);
131
+ // Check for network-level errors (connection issues, timeouts, DNS failures, TLS/certificate errors, etc.)
132
+ // All network errors should be treated as user-facing errors, not CLI bugs
133
+ // Note: Some of these may have been retried already by lower-level retry logic
134
+ if (isNetworkError(error)) {
135
+ throw new AbortError(`Network error connecting to your store ${session.storeFqdn}: ${error instanceof Error ? error.message : String(error)}`, 'Check your internet connection and try again.');
132
136
  }
137
+ // Unknown errors are likely bugs in the CLI
138
+ throw new BugError(`Unknown error connecting to your store ${session.storeFqdn}: ${error instanceof Error ? error.message : String(error)}`);
133
139
  }
134
140
  }
135
141
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../../src/public/node/api/admin.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n graphqlRequest,\n graphqlRequestDoc,\n GraphQLResponseOptions,\n GraphQLVariables,\n UnauthorizedHandler,\n} from './graphql.js'\nimport {AdminSession} from '../session.js'\nimport {outputContent, outputToken} from '../../../public/node/output.js'\nimport {AbortError, BugError} from '../error.js'\nimport {\n restRequestBody,\n restRequestHeaders,\n restRequestUrl,\n isThemeAccessSession,\n} from '../../../private/node/api/rest.js'\nimport {RequestModeInput, shopifyFetch} from '../http.js'\nimport {PublicApiVersions} from '../../../cli/api/graphql/admin/generated/public_api_versions.js'\n\nimport {themeKitAccessDomain} from '../../../private/node/constants.js'\nimport {serviceEnvironment} from '../../../private/node/context/service.js'\nimport {DevServerCore} from '../vendor/dev_server/index.js'\nimport {ClientError, Variables} from 'graphql-request'\nimport {TypedDocumentNode} from '@graphql-typed-document-node/core'\n\nconst LatestApiVersionByFQDN = new Map<string, string>()\n\n/**\n * Executes a GraphQL query against the Admin API.\n *\n * @param query - GraphQL query to execute.\n * @param session - Shopify admin session including token and Store FQDN.\n * @param variables - GraphQL variables to pass to the query.\n * @returns The response of the query of generic type <T>.\n */\nexport async function adminRequest<T>(query: string, session: AdminSession, variables?: GraphQLVariables): Promise<T> {\n const api = 'Admin'\n const version = await fetchLatestSupportedApiVersion(session)\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const url = adminUrl(storeDomain, version, session)\n return graphqlRequest({query, api, addedHeaders, url, token: session.token, variables})\n}\n\nexport interface AdminRequestOptions<TResult, TVariables extends Variables> {\n /** GraphQL query to execute. */\n query: TypedDocumentNode<TResult, TVariables>\n /** Shopify admin session including token and Store FQDN. */\n session: AdminSession\n /** GraphQL variables to pass to the query. */\n variables?: TVariables\n /** API version. */\n version?: string\n /** Control how API responses will be handled. */\n responseOptions?: GraphQLResponseOptions<TResult>\n /** Custom request behaviour for retries and timeouts. */\n preferredBehaviour?: RequestModeInput\n}\n\n/**\n * Executes a GraphQL query against the Admin API. Uses typed documents.\n *\n * @param options - Admin request options.\n * @returns The response of the query of generic type <TResult>.\n */\nexport async function adminRequestDoc<TResult, TVariables extends Variables>(\n options: AdminRequestOptions<TResult, TVariables>,\n): Promise<TResult> {\n const {query, session, variables, version, responseOptions, preferredBehaviour} = options\n\n let apiVersion = version ?? LatestApiVersionByFQDN.get(session.storeFqdn)\n if (!apiVersion) {\n apiVersion = await fetchLatestSupportedApiVersion(session, preferredBehaviour)\n }\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const opts = {\n url: adminUrl(storeDomain, apiVersion, session),\n api: 'Admin',\n token: session.token,\n addedHeaders,\n }\n let unauthorizedHandler: UnauthorizedHandler | undefined\n if ('refresh' in session) {\n unauthorizedHandler = {type: 'token_refresh', handler: session.refresh as () => Promise<{token: string}>}\n }\n const result = graphqlRequestDoc<TResult, TVariables>({\n ...opts,\n query,\n variables,\n responseOptions,\n unauthorizedHandler,\n preferredBehaviour,\n })\n return result\n}\n\nfunction themeAccessHeaders(session: AdminSession): {[header: string]: string} {\n return isThemeAccessSession(session)\n ? {'X-Shopify-Shop': session.storeFqdn, 'X-Shopify-Access-Token': session.token}\n : {}\n}\n\n/**\n * GraphQL query to retrieve the latest supported API version.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - The latest supported API version.\n */\nasync function fetchLatestSupportedApiVersion(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string> {\n const apiVersions = await supportedApiVersions(session, preferredBehaviour)\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const latest = apiVersions.reverse()[0]!\n LatestApiVersionByFQDN.set(session.storeFqdn, latest)\n return latest\n}\n\n/**\n * GraphQL query to retrieve all supported API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported API versions.\n */\nexport async function supportedApiVersions(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string[]> {\n const apiVersions = await fetchApiVersions(session, preferredBehaviour)\n return apiVersions\n .filter((item) => item.supported)\n .map((item) => item.handle)\n .sort()\n}\n\n/**\n * GraphQL query to retrieve all API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported and unsupported API versions.\n */\nasync function fetchApiVersions(session: AdminSession, preferredBehaviour?: RequestModeInput): Promise<ApiVersion[]> {\n try {\n const response = await adminRequestDoc({\n query: PublicApiVersions,\n session,\n variables: {},\n version: 'unstable',\n responseOptions: {handleErrors: false},\n preferredBehaviour,\n })\n return response.publicApiVersions\n } catch (error) {\n if (error instanceof ClientError && error.response.status === 403) {\n const storeName = session.storeFqdn.replace('.myshopify.com', '')\n throw new AbortError(\n outputContent`Looks like you don't have access this dev store: (${outputToken.link(\n storeName,\n `https://${session.storeFqdn}`,\n )})`,\n outputContent`If you're not the owner, create a dev store staff account for yourself`,\n )\n }\n if (error instanceof ClientError && (error.response.status === 401 || error.response.status === 404)) {\n throw new AbortError(\n `Error connecting to your store ${session.storeFqdn}: ${error.message} ${error.response.status} ${error.response.data}`,\n )\n } else {\n throw new BugError(\n `Unknown error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n }\n}\n\n/**\n * Returns the Admin API URL for the given store and version.\n *\n * @param store - Store FQDN.\n * @param version - API version.\n * @param session - User session.\n * @returns - Admin API URL.\n */\nexport function adminUrl(store: string, version: string | undefined, session?: AdminSession): string {\n const realVersion = version ?? 'unstable'\n\n const url =\n session && isThemeAccessSession(session)\n ? `https://${themeKitAccessDomain}/cli/admin/api/${realVersion}/graphql.json`\n : `https://${store}/admin/api/${realVersion}/graphql.json`\n return url\n}\n\ninterface ApiVersion {\n handle: string\n supported: boolean\n}\n\n/**\n * Executes a REST request against the Admin API.\n *\n * @param method - Request's HTTP method.\n * @param path - Path of the REST resource.\n * @param session - Shopify Admin session including token and Store FQDN.\n * @param requestBody - Request body of including REST resource specific parameters.\n * @param searchParams - Search params, appended to the URL.\n * @param apiVersion - Admin API version.\n * @returns - The {@link RestResponse}.\n */\nexport async function restRequest<T>(\n method: string,\n path: string,\n session: AdminSession,\n requestBody?: T,\n searchParams: {[name: string]: string} = {},\n apiVersion = 'unstable',\n): Promise<RestResponse> {\n const url = restRequestUrl(session, apiVersion, path, searchParams)\n const body = restRequestBody<T>(requestBody)\n\n const headers = restRequestHeaders(session)\n const response = await shopifyFetch(url, {\n headers,\n method,\n body,\n })\n\n const json = await response.json().catch(() => ({}))\n\n return {\n json,\n status: response.status,\n headers: response.headers.raw(),\n }\n}\n\n/**\n * Respose of a REST request.\n */\nexport interface RestResponse {\n /**\n * REST JSON respose.\n */\n // Using `any` to avoid introducing extra DTO layers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n json: any\n\n /**\n * HTTP response status.\n */\n status: number\n\n /**\n * HTTP response headers.\n */\n headers: {[key: string]: string[]}\n}\n"]}
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../../src/public/node/api/admin.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n graphqlRequest,\n graphqlRequestDoc,\n GraphQLResponseOptions,\n GraphQLVariables,\n UnauthorizedHandler,\n} from './graphql.js'\nimport {AdminSession} from '../session.js'\nimport {outputContent, outputToken} from '../../../public/node/output.js'\nimport {AbortError, BugError} from '../error.js'\nimport {\n restRequestBody,\n restRequestHeaders,\n restRequestUrl,\n isThemeAccessSession,\n} from '../../../private/node/api/rest.js'\nimport {isNetworkError} from '../../../private/node/api.js'\nimport {RequestModeInput, shopifyFetch} from '../http.js'\nimport {PublicApiVersions} from '../../../cli/api/graphql/admin/generated/public_api_versions.js'\n\nimport {themeKitAccessDomain} from '../../../private/node/constants.js'\nimport {serviceEnvironment} from '../../../private/node/context/service.js'\nimport {DevServerCore} from '../vendor/dev_server/index.js'\nimport {ClientError, Variables} from 'graphql-request'\nimport {TypedDocumentNode} from '@graphql-typed-document-node/core'\n\nconst LatestApiVersionByFQDN = new Map<string, string>()\n\n/**\n * Executes a GraphQL query against the Admin API.\n *\n * @param query - GraphQL query to execute.\n * @param session - Shopify admin session including token and Store FQDN.\n * @param variables - GraphQL variables to pass to the query.\n * @returns The response of the query of generic type <T>.\n */\nexport async function adminRequest<T>(query: string, session: AdminSession, variables?: GraphQLVariables): Promise<T> {\n const api = 'Admin'\n const version = await fetchLatestSupportedApiVersion(session)\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const url = adminUrl(storeDomain, version, session)\n return graphqlRequest({query, api, addedHeaders, url, token: session.token, variables})\n}\n\nexport interface AdminRequestOptions<TResult, TVariables extends Variables> {\n /** GraphQL query to execute. */\n query: TypedDocumentNode<TResult, TVariables>\n /** Shopify admin session including token and Store FQDN. */\n session: AdminSession\n /** GraphQL variables to pass to the query. */\n variables?: TVariables\n /** API version. */\n version?: string\n /** Control how API responses will be handled. */\n responseOptions?: GraphQLResponseOptions<TResult>\n /** Custom request behaviour for retries and timeouts. */\n preferredBehaviour?: RequestModeInput\n}\n\n/**\n * Executes a GraphQL query against the Admin API. Uses typed documents.\n *\n * @param options - Admin request options.\n * @returns The response of the query of generic type <TResult>.\n */\nexport async function adminRequestDoc<TResult, TVariables extends Variables>(\n options: AdminRequestOptions<TResult, TVariables>,\n): Promise<TResult> {\n const {query, session, variables, version, responseOptions, preferredBehaviour} = options\n\n let apiVersion = version ?? LatestApiVersionByFQDN.get(session.storeFqdn)\n if (!apiVersion) {\n apiVersion = await fetchLatestSupportedApiVersion(session, preferredBehaviour)\n }\n let storeDomain = session.storeFqdn\n const addedHeaders = themeAccessHeaders(session)\n\n if (serviceEnvironment() === 'local') {\n addedHeaders['x-forwarded-host'] = storeDomain\n storeDomain = new DevServerCore().host('app')\n }\n\n const opts = {\n url: adminUrl(storeDomain, apiVersion, session),\n api: 'Admin',\n token: session.token,\n addedHeaders,\n }\n let unauthorizedHandler: UnauthorizedHandler | undefined\n if ('refresh' in session) {\n unauthorizedHandler = {type: 'token_refresh', handler: session.refresh as () => Promise<{token: string}>}\n }\n const result = graphqlRequestDoc<TResult, TVariables>({\n ...opts,\n query,\n variables,\n responseOptions,\n unauthorizedHandler,\n preferredBehaviour,\n })\n return result\n}\n\nfunction themeAccessHeaders(session: AdminSession): {[header: string]: string} {\n return isThemeAccessSession(session)\n ? {'X-Shopify-Shop': session.storeFqdn, 'X-Shopify-Access-Token': session.token}\n : {}\n}\n\n/**\n * GraphQL query to retrieve the latest supported API version.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - The latest supported API version.\n */\nasync function fetchLatestSupportedApiVersion(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string> {\n const apiVersions = await supportedApiVersions(session, preferredBehaviour)\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const latest = apiVersions.reverse()[0]!\n LatestApiVersionByFQDN.set(session.storeFqdn, latest)\n return latest\n}\n\n/**\n * GraphQL query to retrieve all supported API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported API versions.\n */\nexport async function supportedApiVersions(\n session: AdminSession,\n preferredBehaviour?: RequestModeInput,\n): Promise<string[]> {\n const apiVersions = await fetchApiVersions(session, preferredBehaviour)\n return apiVersions\n .filter((item) => item.supported)\n .map((item) => item.handle)\n .sort()\n}\n\n/**\n * GraphQL query to retrieve all API versions.\n *\n * @param session - Shopify admin session including token and Store FQDN.\n * @param preferredBehaviour - Custom request behaviour for retries and timeouts.\n * @returns - An array of supported and unsupported API versions.\n */\nasync function fetchApiVersions(session: AdminSession, preferredBehaviour?: RequestModeInput): Promise<ApiVersion[]> {\n try {\n const response = await adminRequestDoc({\n query: PublicApiVersions,\n session,\n variables: {},\n version: 'unstable',\n responseOptions: {handleErrors: false},\n preferredBehaviour,\n })\n return response.publicApiVersions\n } catch (error) {\n if (error instanceof ClientError && error.response.status === 403) {\n const storeName = session.storeFqdn.replace('.myshopify.com', '')\n throw new AbortError(\n outputContent`Looks like you don't have access this dev store: (${outputToken.link(\n storeName,\n `https://${session.storeFqdn}`,\n )})`,\n outputContent`If you're not the owner, create a dev store staff account for yourself`,\n )\n }\n if (error instanceof ClientError && (error.response.status === 401 || error.response.status === 404)) {\n throw new AbortError(\n `Error connecting to your store ${session.storeFqdn}: ${error.message} ${error.response.status} ${error.response.data}`,\n )\n }\n\n // Check for network-level errors (connection issues, timeouts, DNS failures, TLS/certificate errors, etc.)\n // All network errors should be treated as user-facing errors, not CLI bugs\n // Note: Some of these may have been retried already by lower-level retry logic\n if (isNetworkError(error)) {\n throw new AbortError(\n `Network error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n 'Check your internet connection and try again.',\n )\n }\n\n // Unknown errors are likely bugs in the CLI\n throw new BugError(\n `Unknown error connecting to your store ${session.storeFqdn}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n}\n\n/**\n * Returns the Admin API URL for the given store and version.\n *\n * @param store - Store FQDN.\n * @param version - API version.\n * @param session - User session.\n * @returns - Admin API URL.\n */\nexport function adminUrl(store: string, version: string | undefined, session?: AdminSession): string {\n const realVersion = version ?? 'unstable'\n\n const url =\n session && isThemeAccessSession(session)\n ? `https://${themeKitAccessDomain}/cli/admin/api/${realVersion}/graphql.json`\n : `https://${store}/admin/api/${realVersion}/graphql.json`\n return url\n}\n\ninterface ApiVersion {\n handle: string\n supported: boolean\n}\n\n/**\n * Executes a REST request against the Admin API.\n *\n * @param method - Request's HTTP method.\n * @param path - Path of the REST resource.\n * @param session - Shopify Admin session including token and Store FQDN.\n * @param requestBody - Request body of including REST resource specific parameters.\n * @param searchParams - Search params, appended to the URL.\n * @param apiVersion - Admin API version.\n * @returns - The {@link RestResponse}.\n */\nexport async function restRequest<T>(\n method: string,\n path: string,\n session: AdminSession,\n requestBody?: T,\n searchParams: {[name: string]: string} = {},\n apiVersion = 'unstable',\n): Promise<RestResponse> {\n const url = restRequestUrl(session, apiVersion, path, searchParams)\n const body = restRequestBody<T>(requestBody)\n\n const headers = restRequestHeaders(session)\n const response = await shopifyFetch(url, {\n headers,\n method,\n body,\n })\n\n const json = await response.json().catch(() => ({}))\n\n return {\n json,\n status: response.status,\n headers: response.headers.raw(),\n }\n}\n\n/**\n * Respose of a REST request.\n */\nexport interface RestResponse {\n /**\n * REST JSON respose.\n */\n // Using `any` to avoid introducing extra DTO layers.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n json: any\n\n /**\n * HTTP response status.\n */\n status: number\n\n /**\n * HTTP response headers.\n */\n headers: {[key: string]: string[]}\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { relativePath, joinPath, dirname } from './path.js';
2
- import { glob, removeFile } from './fs.js';
2
+ import { glob, removeFile, readFile } from './fs.js';
3
3
  import { outputDebug, outputContent, outputToken } from '../../public/node/output.js';
4
4
  import archiver from 'archiver';
5
5
  import { createWriteStream, readFileSync, writeFileSync } from 'fs';
@@ -41,13 +41,21 @@ export async function zip(options) {
41
41
  const dirName = dir.endsWith('/') ? dir : `${dir}/`;
42
42
  archive.append(Buffer.alloc(0), { name: dirName });
43
43
  }
44
- for (const filePath of pathsToZip) {
45
- const fileRelativePath = relativePath(inputDirectory, filePath);
46
- if (filePath && fileRelativePath)
47
- archive.file(filePath, { name: fileRelativePath });
48
- }
49
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
50
- archive.finalize();
44
+ // Read all files immediately before adding to archive to prevent ENOENT errors
45
+ // Using archive.file() causes lazy loading which fails if files are deleted before finalize()
46
+ const addFilesPromises = pathsToZip.map(async (filePath) => {
47
+ await archiveFile(inputDirectory, filePath, archive);
48
+ });
49
+ // Wait for all files to be read and added before finalizing
50
+ Promise.all(addFilesPromises)
51
+ .then(() => {
52
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
53
+ archive.finalize();
54
+ })
55
+ .catch((error) => {
56
+ // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
57
+ reject(error);
58
+ });
51
59
  });
52
60
  }
53
61
  function collectParentDirectories(fileRelativePath, accumulator) {
@@ -60,6 +68,15 @@ function collectParentDirectories(fileRelativePath, accumulator) {
60
68
  currentDir = parent;
61
69
  }
62
70
  }
71
+ async function archiveFile(inputDirectory, filePath, archive) {
72
+ const fileRelativePath = relativePath(inputDirectory, filePath);
73
+ if (!filePath || !fileRelativePath)
74
+ return;
75
+ // Read file content immediately to avoid race conditions
76
+ const fileContent = await readFile(filePath);
77
+ // Use append with Buffer instead of file() to avoid lazy file reading
78
+ archive.append(fileContent, { name: fileRelativePath });
79
+ }
63
80
  /**
64
81
  * It compresses a directory with Brotli.
65
82
  * First creates a tar archive to preserve directory structure,
@@ -83,15 +100,18 @@ export async function brotliCompress(options) {
83
100
  dot: true,
84
101
  followSymbolicLinks: false,
85
102
  })
86
- .then((pathsToZip) => {
87
- for (const filePath of pathsToZip) {
88
- const fileRelativePath = relativePath(options.inputDirectory, filePath);
89
- archive.file(filePath, { name: fileRelativePath });
90
- }
103
+ .then(async (pathsToZip) => {
104
+ // Read all files immediately to prevent ENOENT errors during race conditions
105
+ const addFilesPromises = pathsToZip.map(async (filePath) => {
106
+ await archiveFile(options.inputDirectory, filePath, archive);
107
+ });
108
+ await Promise.all(addFilesPromises);
91
109
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
92
110
  archive.finalize();
93
111
  })
94
- .catch((error) => reject(error instanceof Error ? error : new Error(String(error))));
112
+ .catch((error) => {
113
+ reject(error instanceof Error ? error : new Error(String(error)));
114
+ });
95
115
  });
96
116
  const tarContent = readFileSync(tempTarPath);
97
117
  const brotli = await import('brotli');
@@ -1 +1 @@
1
- {"version":3,"file":"archiver.js","sourceRoot":"","sources":["../../../src/public/node/archiver.ts"],"names":[],"mappings":"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","sourcesContent":["import {relativePath, joinPath, dirname} from './path.js'\nimport {glob, removeFile} from './fs.js'\nimport {outputDebug, outputContent, outputToken} from '../../public/node/output.js'\nimport archiver from 'archiver'\nimport {createWriteStream, readFileSync, writeFileSync} from 'fs'\nimport {tmpdir} from 'os'\nimport {randomUUID} from 'crypto'\n\ninterface ZipOptions {\n /**\n * The absolute path to the directory to be zipped.\n */\n inputDirectory: string\n\n /**\n * The absolute path to the output zip file.\n */\n outputZipPath: string\n\n /**\n * Pattern(s) to match when adding files to zip, uses glob expressions.\n */\n matchFilePattern?: string | string[]\n}\n\n/**\n * It zips a directory and by default normalizes the paths to be forward-slash.\n * Even with forward-slash paths, zip files should still be able to be opened on\n * Windows.\n *\n * @param options - ZipOptions.\n */\nexport async function zip(options: ZipOptions): Promise<void> {\n const {inputDirectory, outputZipPath, matchFilePattern = '**/*'} = options\n outputDebug(outputContent`Zipping ${outputToken.path(inputDirectory)} into ${outputToken.path(outputZipPath)}`)\n const pathsToZip = await glob(matchFilePattern, {\n cwd: inputDirectory,\n absolute: true,\n dot: true,\n followSymbolicLinks: false,\n })\n\n return new Promise((resolve, reject) => {\n const archive = archiver('zip')\n\n const output = createWriteStream(outputZipPath)\n output.on('close', () => {\n resolve()\n })\n archive.on('error', (error) => {\n reject(error)\n })\n archive.pipe(output)\n\n const directoriesToAdd = new Set<string>()\n for (const filePath of pathsToZip) {\n const fileRelativePath = relativePath(inputDirectory, filePath)\n collectParentDirectories(fileRelativePath, directoriesToAdd)\n }\n\n const sortedDirs = Array.from(directoriesToAdd).sort((left, right) => left.localeCompare(right))\n for (const dir of sortedDirs) {\n const dirName = dir.endsWith('/') ? dir : `${dir}/`\n archive.append(Buffer.alloc(0), {name: dirName})\n }\n\n for (const filePath of pathsToZip) {\n const fileRelativePath = relativePath(inputDirectory, filePath)\n if (filePath && fileRelativePath) archive.file(filePath, {name: fileRelativePath})\n }\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n archive.finalize()\n })\n}\n\nfunction collectParentDirectories(fileRelativePath: string, accumulator: Set<string>): void {\n let currentDir = dirname(fileRelativePath)\n while (currentDir && currentDir !== '.' && currentDir !== '/') {\n accumulator.add(currentDir)\n const parent = dirname(currentDir)\n if (parent === currentDir) break\n currentDir = parent\n }\n}\n\nexport interface BrotliOptions {\n /**\n * The directory to compress.\n */\n inputDirectory: string\n\n /**\n * The path where the compressed file will be saved.\n */\n outputPath: string\n\n /**\n * An optional glob pattern to match files.\n */\n matchFilePattern?: string | string[]\n\n /**\n * Brotli compression level (0-11, default: 11).\n */\n level?: number\n}\n\n/**\n * Options for decompressing a Brotli compressed tar archive.\n */\nexport interface DecompressionOptions {\n /**\n * Path to the compressed file.\n */\n inputFile: string\n\n /**\n * Directory where files should be extracted.\n */\n outputDirectory: string\n}\n\n/**\n * It compresses a directory with Brotli.\n * First creates a tar archive to preserve directory structure,\n * then compresses it with Brotli.\n *\n * @param options - BrotliOptions.\n */\nexport async function brotliCompress(options: BrotliOptions): Promise<void> {\n const tempTarPath = joinPath(tmpdir(), `${randomUUID()}.tar`)\n\n try {\n // Create tar archive using archiver\n await new Promise<void>((resolve, reject) => {\n const archive = archiver('tar')\n const output = createWriteStream(tempTarPath)\n\n output.on('close', () => resolve())\n archive.on('error', (error) => reject(error))\n archive.pipe(output)\n\n glob(options.matchFilePattern ?? '**/*', {\n cwd: options.inputDirectory,\n absolute: true,\n dot: true,\n followSymbolicLinks: false,\n })\n .then((pathsToZip) => {\n for (const filePath of pathsToZip) {\n const fileRelativePath = relativePath(options.inputDirectory, filePath)\n archive.file(filePath, {name: fileRelativePath})\n }\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n archive.finalize()\n })\n .catch((error) => reject(error instanceof Error ? error : new Error(String(error))))\n })\n\n const tarContent = readFileSync(tempTarPath)\n const brotli = await import('brotli')\n const compressed = brotli.default.compress(tarContent, {\n quality: 7,\n mode: 0,\n })\n\n if (!compressed) {\n throw new Error('Brotli compression failed')\n }\n\n writeFileSync(options.outputPath, compressed)\n } finally {\n try {\n await removeFile(tempTarPath)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n outputDebug(outputContent`Failed to clean up temporary file: ${outputToken.path(tempTarPath)}`)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"archiver.js","sourceRoot":"","sources":["../../../src/public/node/archiver.ts"],"names":[],"mappings":"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","sourcesContent":["import {relativePath, joinPath, dirname} from './path.js'\nimport {glob, removeFile, readFile} from './fs.js'\nimport {outputDebug, outputContent, outputToken} from '../../public/node/output.js'\nimport archiver from 'archiver'\nimport {createWriteStream, readFileSync, writeFileSync} from 'fs'\nimport {tmpdir} from 'os'\nimport {randomUUID} from 'crypto'\n\ninterface ZipOptions {\n /**\n * The absolute path to the directory to be zipped.\n */\n inputDirectory: string\n\n /**\n * The absolute path to the output zip file.\n */\n outputZipPath: string\n\n /**\n * Pattern(s) to match when adding files to zip, uses glob expressions.\n */\n matchFilePattern?: string | string[]\n}\n\n/**\n * It zips a directory and by default normalizes the paths to be forward-slash.\n * Even with forward-slash paths, zip files should still be able to be opened on\n * Windows.\n *\n * @param options - ZipOptions.\n */\nexport async function zip(options: ZipOptions): Promise<void> {\n const {inputDirectory, outputZipPath, matchFilePattern = '**/*'} = options\n outputDebug(outputContent`Zipping ${outputToken.path(inputDirectory)} into ${outputToken.path(outputZipPath)}`)\n const pathsToZip = await glob(matchFilePattern, {\n cwd: inputDirectory,\n absolute: true,\n dot: true,\n followSymbolicLinks: false,\n })\n\n return new Promise((resolve, reject) => {\n const archive = archiver('zip')\n\n const output = createWriteStream(outputZipPath)\n output.on('close', () => {\n resolve()\n })\n archive.on('error', (error) => {\n reject(error)\n })\n archive.pipe(output)\n\n const directoriesToAdd = new Set<string>()\n for (const filePath of pathsToZip) {\n const fileRelativePath = relativePath(inputDirectory, filePath)\n collectParentDirectories(fileRelativePath, directoriesToAdd)\n }\n\n const sortedDirs = Array.from(directoriesToAdd).sort((left, right) => left.localeCompare(right))\n for (const dir of sortedDirs) {\n const dirName = dir.endsWith('/') ? dir : `${dir}/`\n archive.append(Buffer.alloc(0), {name: dirName})\n }\n\n // Read all files immediately before adding to archive to prevent ENOENT errors\n // Using archive.file() causes lazy loading which fails if files are deleted before finalize()\n const addFilesPromises = pathsToZip.map(async (filePath) => {\n await archiveFile(inputDirectory, filePath, archive)\n })\n\n // Wait for all files to be read and added before finalizing\n Promise.all(addFilesPromises)\n .then(() => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n archive.finalize()\n })\n .catch((error) => {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n reject(error)\n })\n })\n}\n\nfunction collectParentDirectories(fileRelativePath: string, accumulator: Set<string>): void {\n let currentDir = dirname(fileRelativePath)\n while (currentDir && currentDir !== '.' && currentDir !== '/') {\n accumulator.add(currentDir)\n const parent = dirname(currentDir)\n if (parent === currentDir) break\n currentDir = parent\n }\n}\n\nasync function archiveFile(inputDirectory: string, filePath: string, archive: archiver.Archiver): Promise<void> {\n const fileRelativePath = relativePath(inputDirectory, filePath)\n if (!filePath || !fileRelativePath) return\n\n // Read file content immediately to avoid race conditions\n const fileContent = await readFile(filePath)\n // Use append with Buffer instead of file() to avoid lazy file reading\n archive.append(fileContent, {name: fileRelativePath})\n}\n\nexport interface BrotliOptions {\n /**\n * The directory to compress.\n */\n inputDirectory: string\n\n /**\n * The path where the compressed file will be saved.\n */\n outputPath: string\n\n /**\n * An optional glob pattern to match files.\n */\n matchFilePattern?: string | string[]\n\n /**\n * Brotli compression level (0-11, default: 11).\n */\n level?: number\n}\n\n/**\n * Options for decompressing a Brotli compressed tar archive.\n */\nexport interface DecompressionOptions {\n /**\n * Path to the compressed file.\n */\n inputFile: string\n\n /**\n * Directory where files should be extracted.\n */\n outputDirectory: string\n}\n\n/**\n * It compresses a directory with Brotli.\n * First creates a tar archive to preserve directory structure,\n * then compresses it with Brotli.\n *\n * @param options - BrotliOptions.\n */\nexport async function brotliCompress(options: BrotliOptions): Promise<void> {\n const tempTarPath = joinPath(tmpdir(), `${randomUUID()}.tar`)\n\n try {\n // Create tar archive using archiver\n await new Promise<void>((resolve, reject) => {\n const archive = archiver('tar')\n const output = createWriteStream(tempTarPath)\n\n output.on('close', () => resolve())\n archive.on('error', (error) => reject(error))\n archive.pipe(output)\n\n glob(options.matchFilePattern ?? '**/*', {\n cwd: options.inputDirectory,\n absolute: true,\n dot: true,\n followSymbolicLinks: false,\n })\n .then(async (pathsToZip) => {\n // Read all files immediately to prevent ENOENT errors during race conditions\n const addFilesPromises = pathsToZip.map(async (filePath) => {\n await archiveFile(options.inputDirectory, filePath, archive)\n })\n\n await Promise.all(addFilesPromises)\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n archive.finalize()\n })\n .catch((error) => {\n reject(error instanceof Error ? error : new Error(String(error)))\n })\n })\n\n const tarContent = readFileSync(tempTarPath)\n const brotli = await import('brotli')\n const compressed = brotli.default.compress(tarContent, {\n quality: 7,\n mode: 0,\n })\n\n if (!compressed) {\n throw new Error('Brotli compression failed')\n }\n\n writeFileSync(options.outputPath, compressed)\n } finally {\n try {\n await removeFile(tempTarPath)\n // eslint-disable-next-line no-catch-all/no-catch-all\n } catch (error) {\n outputDebug(outputContent`Failed to clean up temporary file: ${outputToken.path(tempTarPath)}`)\n }\n }\n}\n"]}
@@ -36,6 +36,7 @@ class BaseCommand extends Command {
36
36
  // This function runs just prior to `run`
37
37
  await registerCleanBugsnagErrorsFromWithinPlugins(this.config);
38
38
  }
39
+ await removeDuplicatedPlugins(this.config);
39
40
  this.showNpmFlagWarning();
40
41
  await showNotificationsIfNeeded();
41
42
  return super.init();
@@ -247,5 +248,22 @@ function argsFromEnvironment(environment, options, noDefaultsResult) {
247
248
  function commandSupportsFlag(flags, flagName) {
248
249
  return Boolean(flags) && Object.prototype.hasOwnProperty.call(flags, flagName);
249
250
  }
251
+ async function removeDuplicatedPlugins(config) {
252
+ const plugins = Array.from(config.plugins.values());
253
+ const bundlePlugins = ['@shopify/app', '@shopify/plugin-cloudflare'];
254
+ const pluginsToRemove = plugins.filter((plugin) => bundlePlugins.includes(plugin.name));
255
+ if (pluginsToRemove.length > 0) {
256
+ const commandsToRun = pluginsToRemove.map((plugin) => ` - shopify plugins remove ${plugin.name}`).join('\n');
257
+ renderWarning({
258
+ headline: `Unsupported plugins detected: ${pluginsToRemove.map((plugin) => plugin.name).join(', ')}`,
259
+ body: [
260
+ 'They are already included in the CLI and installing them as custom plugins can cause conflicts.',
261
+ `You can fix it by running:\n${commandsToRun}`,
262
+ ],
263
+ });
264
+ }
265
+ const filteredPlugins = plugins.filter((plugin) => !bundlePlugins.includes(plugin.name));
266
+ config.plugins = new Map(filteredPlugins.map((plugin) => [plugin.name, plugin]));
267
+ }
250
268
  export default BaseCommand;
251
269
  //# sourceMappingURL=base-command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"base-command.js","sourceRoot":"","sources":["../../../src/public/node/base-command.ts"],"names":[],"mappings":"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","sourcesContent":["import {errorHandler, registerCleanBugsnagErrorsFromWithinPlugins} from './error-handler.js'\nimport {loadEnvironment, environmentFilePath} from './environments.js'\nimport {isDevelopment} from './context/local.js'\nimport {addPublicMetadata} from './metadata.js'\nimport {AbortError} from './error.js'\nimport {renderInfo, renderWarning} from './ui.js'\nimport {outputContent, outputResult, outputToken} from './output.js'\nimport {terminalSupportsPrompting} from './system.js'\nimport {hashString} from './crypto.js'\nimport {isTruthy} from './context/utilities.js'\nimport {showNotificationsIfNeeded} from './notifications-system.js'\nimport {setCurrentCommandId} from './global-context.js'\nimport {JsonMap} from '../../private/common/json.js'\nimport {underscore} from '../common/string.js'\nimport {Command, Errors} from '@oclif/core'\nimport {OutputFlags, Input, ParserOutput, FlagInput, OutputArgs} from '@oclif/core/parser'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ArgOutput = OutputArgs<any>\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type FlagOutput = OutputFlags<any>\n\ninterface EnvironmentFlags {\n environment?: string[]\n path?: string\n}\n\nabstract class BaseCommand extends Command {\n // eslint-disable-next-line @typescript-eslint/ban-types\n static baseFlags: FlagInput<{}> = {}\n\n // Replace markdown links to plain text like: \"link label\" (url)\n public static descriptionWithoutMarkdown(): string | undefined {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return ((this as any).descriptionWithMarkdown ?? '').replace(/(\\[)(.*?)(])(\\()(.*?)(\\))/gm, '\"$2\" ($5)')\n }\n\n public static analyticsNameOverride(): string | undefined {\n return undefined\n }\n\n public static analyticsStopCommand(): string | undefined {\n return undefined\n }\n\n async catch(error: Error & {skipOclifErrorHandling: boolean}): Promise<void> {\n error.skipOclifErrorHandling = true\n await errorHandler(error, this.config)\n return Errors.handle(error)\n }\n\n protected async init(): Promise<unknown> {\n this.exitWithTimestampWhenEnvVariablePresent()\n setCurrentCommandId(this.id ?? '')\n if (!isDevelopment()) {\n // This function runs just prior to `run`\n await registerCleanBugsnagErrorsFromWithinPlugins(this.config)\n }\n this.showNpmFlagWarning()\n await showNotificationsIfNeeded()\n return super.init()\n }\n\n // NPM creates an environment variable for every flag passed to a script.\n // This function checks for the presence of any of the available CLI flags\n // and warns the user to use the `--` separator.\n protected showNpmFlagWarning(): void {\n const commandVariables = this.constructor as unknown as {flags: JsonMap}\n const commandFlags = Object.keys(commandVariables.flags || {})\n const possibleNpmEnvVars = commandFlags.map((key) => `npm_config_${underscore(key).replace(/^no_/, '')}`)\n\n if (possibleNpmEnvVars.some((flag) => process.env[flag] !== undefined)) {\n renderWarning({\n body: [\n 'NPM scripts require an extra',\n {command: '--'},\n 'separator to pass the flags. Example:',\n {command: 'npm run dev -- --reset'},\n ],\n })\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n protected exitWithTimestampWhenEnvVariablePresent() {\n if (isTruthy(process.env.SHOPIFY_CLI_ENV_STARTUP_PERFORMANCE_RUN)) {\n outputResult(`\n SHOPIFY_CLI_TIMESTAMP_START\n { \"timestamp\": ${Date.now()} }\n SHOPIFY_CLI_TIMESTAMP_END\n `)\n process.exit(0)\n }\n }\n\n protected async parse<\n TFlags extends FlagOutput & {path?: string; verbose?: boolean},\n TGlobalFlags extends FlagOutput,\n TArgs extends ArgOutput,\n >(\n options?: Input<TFlags, TGlobalFlags, TArgs>,\n argv?: string[],\n ): Promise<ParserOutput<TFlags, TGlobalFlags, TArgs> & {argv: string[]}> {\n let result = await super.parse<TFlags, TGlobalFlags, TArgs>(options, argv)\n result = await this.resultWithEnvironment<TFlags, TGlobalFlags, TArgs>(result, options, argv)\n await addFromParsedFlags(result.flags)\n return {...result, ...{argv: result.argv as string[]}}\n }\n\n protected environmentsFilename(): string | undefined {\n // To be re-implemented if needed\n return undefined\n }\n\n protected failMissingNonTTYFlags(flags: FlagOutput, requiredFlags: string[]): void {\n if (terminalSupportsPrompting()) return\n\n requiredFlags.forEach((name: string) => {\n if (!(name in flags)) {\n throw new AbortError(\n outputContent`Flag not specified:\n\n${outputToken.cyan(name)}\n\nThis flag is required in non-interactive terminal environments, such as a CI environment, or when piping input from another process.`,\n 'To resolve this, specify the option in the command, or run the command in an interactive environment such as your local terminal.',\n )\n }\n })\n }\n\n private async resultWithEnvironment<\n TFlags extends FlagOutput & {path?: string; verbose?: boolean},\n TGlobalFlags extends FlagOutput,\n TArgs extends ArgOutput,\n >(\n originalResult: ParserOutput<TFlags, TGlobalFlags, TArgs>,\n options?: Input<TFlags, TGlobalFlags, TArgs>,\n argv?: string[],\n ): Promise<ParserOutput<TFlags, TGlobalFlags, TArgs>> {\n const flags = originalResult.flags as EnvironmentFlags\n const environmentsFileName = this.environmentsFilename()\n\n if (!environmentsFileName) return originalResult\n\n const environmentFileExists = await environmentFilePath(environmentsFileName, {from: flags.path})\n\n // Handle both string and array cases for environment flag\n let environments: string[] = []\n if (flags.environment) {\n environments = Array.isArray(flags.environment) ? flags.environment : [flags.environment]\n }\n\n const environmentSpecified = environments.length > 0\n\n // Noop if no environment file exists and none was specified\n if (!environmentFileExists && !environmentSpecified) return originalResult\n\n // Noop if multiple environments were specified (let commands handle this)\n if (environmentSpecified && environments.length > 1) return originalResult\n\n const {environment, isDefaultEnvironment} = await this.loadEnvironmentForCommand(\n flags.path,\n environmentsFileName,\n environments[0],\n )\n\n if (!environment) return originalResult\n if (isDefaultEnvironment && !commandSupportsFlag(options?.flags, 'environment')) return originalResult\n\n // Parse using noDefaultsOptions to derive a list of flags specified as\n // command-line arguments.\n const noDefaultsResult = await super.parse<TFlags, TGlobalFlags, TArgs>(noDefaultsOptions(options), argv)\n\n // Add the environment's settings to argv and pass them to `super.parse`. This\n // invokes oclif's validation system without breaking the oclif black box.\n // Replace the original result with this one.\n const result = await super.parse<TFlags, TGlobalFlags, TArgs>(options, [\n // Need to specify argv default because we're merging with argsFromEnvironment.\n ...(argv ?? this.argv),\n ...argsFromEnvironment<TFlags, TGlobalFlags, TArgs>(environment, options, noDefaultsResult),\n ...(isDefaultEnvironment ? ['--environment', 'default'] : []),\n ])\n\n // Report successful application of the environment.\n reportEnvironmentApplication<TFlags, TGlobalFlags, TArgs>(\n noDefaultsResult.flags,\n result.flags,\n isDefaultEnvironment ? 'default' : (environments[0] as string),\n environment,\n )\n\n return result\n }\n\n /**\n * Tries to load an environment to forward to the command. If no environment\n * is specified it will try to load a default environment.\n */\n private async loadEnvironmentForCommand(\n path: string | undefined,\n environmentsFileName: string,\n specifiedEnvironment: string | undefined,\n ): Promise<{environment: JsonMap | undefined; isDefaultEnvironment: boolean}> {\n if (specifiedEnvironment) {\n const environment = await loadEnvironment(specifiedEnvironment, environmentsFileName, {from: path})\n return {environment, isDefaultEnvironment: false}\n }\n\n const environment = await loadEnvironment('default', environmentsFileName, {from: path, silent: true})\n return {environment, isDefaultEnvironment: true}\n }\n}\n\nexport async function addFromParsedFlags(flags: {path?: string; verbose?: boolean}): Promise<void> {\n await addPublicMetadata(() => ({\n cmd_all_verbose: flags.verbose,\n cmd_all_path_override: flags.path !== undefined,\n cmd_all_path_override_hash: flags.path === undefined ? undefined : hashString(flags.path),\n }))\n}\n\n/**\n * Any flag which is:\n *\n * 1. Present in the final set of flags\n * 2. Specified in the environment\n * 3. Not specified by the user as a command line argument\n *\n * should be reported.\n *\n * It doesn't matter if the environment flag's value was the same as the default; from\n * the user's perspective, they want to know their environment was applied.\n */\nfunction reportEnvironmentApplication<\n TFlags extends FlagOutput,\n TGlobalFlags extends FlagOutput,\n TArgs extends ArgOutput,\n>(\n noDefaultsFlags: ParserOutput<TFlags, TGlobalFlags, TArgs>['flags'],\n flagsWithEnvironments: ParserOutput<TFlags, TGlobalFlags, TArgs>['flags'],\n environmentName: string,\n environment: JsonMap,\n): void {\n const changes: JsonMap = {}\n for (const [name, value] of Object.entries(flagsWithEnvironments)) {\n const userSpecifiedThisFlag = Object.prototype.hasOwnProperty.call(noDefaultsFlags, name)\n const environmentContainsFlag = Object.prototype.hasOwnProperty.call(environment, name)\n if (!userSpecifiedThisFlag && environmentContainsFlag) {\n const valueToReport = name === 'password' ? `********${value.substr(-4)}` : value\n changes[name] = valueToReport\n }\n }\n if (Object.keys(changes).length === 0) return\n\n const items = Object.entries(changes).map(([name, value]) => `${name}: ${value}`)\n renderInfo({\n headline: ['Using applicable flags from', {userInput: environmentName}, 'environment:'],\n body: [{list: {items}}],\n })\n}\n\n/**\n * Strips the defaults from configured flags. For example, if flags contains:\n *\n * ```\n * someFlag: Flags.boolean({\n * description: 'some flag',\n * default: false\n * })\n * ```\n *\n * it becomes:\n *\n * ```\n * someFlag: Flags.boolean({\n * description: 'some flag'\n * })\n * ```\n *\n * If we parse using this configuration, the only specified flags will be those\n * the user actually passed on the command line.\n */\nexport function noDefaultsOptions<TFlags extends FlagOutput, TGlobalFlags extends FlagOutput, TArgs extends ArgOutput>(\n options: Input<TFlags, TGlobalFlags, TArgs> | undefined,\n): Input<TFlags, TGlobalFlags, TArgs> | undefined {\n if (!options?.flags) return options\n return {\n ...options,\n flags: Object.fromEntries(\n Object.entries(options.flags).map(([label, settings]) => {\n const copiedSettings = {...(settings as {default?: unknown})}\n delete copiedSettings.default\n return [label, copiedSettings]\n }),\n ) as FlagInput<TFlags>,\n }\n}\n\n/**\n * Converts the environment's settings to arguments as though passed on the command\n * line, skipping any arguments the user specified on the command line.\n */\nfunction argsFromEnvironment<TFlags extends FlagOutput, TGlobalFlags extends FlagOutput, TArgs extends ArgOutput>(\n environment: JsonMap,\n options: Input<TFlags, TGlobalFlags, TArgs> | undefined,\n noDefaultsResult: ParserOutput<TFlags, TArgs>,\n): string[] {\n const args: string[] = []\n for (const [label, value] of Object.entries(environment)) {\n const flagIsRelevantToCommand = commandSupportsFlag(options?.flags, label)\n const userSpecifiedThisFlag =\n noDefaultsResult.flags && Object.prototype.hasOwnProperty.call(noDefaultsResult.flags, label)\n if (flagIsRelevantToCommand && !userSpecifiedThisFlag) {\n if (typeof value === 'boolean') {\n if (value) {\n args.push(`--${label}`)\n } else {\n throw new AbortError(\n outputContent`Environments can only specify true for boolean flags. Attempted to set ${outputToken.yellow(\n label,\n )} to false.`,\n )\n }\n } else if (Array.isArray(value)) {\n value.forEach((element) => args.push(`--${label}`, `${element}`))\n } else {\n args.push(`--${label}`, `${value}`)\n }\n }\n }\n return args\n}\n\nfunction commandSupportsFlag(flags: FlagInput | undefined, flagName: string): boolean {\n return Boolean(flags) && Object.prototype.hasOwnProperty.call(flags, flagName)\n}\n\nexport default BaseCommand\n"]}
1
+ {"version":3,"file":"base-command.js","sourceRoot":"","sources":["../../../src/public/node/base-command.ts"],"names":[],"mappings":"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","sourcesContent":["import {errorHandler, registerCleanBugsnagErrorsFromWithinPlugins} from './error-handler.js'\nimport {loadEnvironment, environmentFilePath} from './environments.js'\nimport {isDevelopment} from './context/local.js'\nimport {addPublicMetadata} from './metadata.js'\nimport {AbortError} from './error.js'\nimport {renderInfo, renderWarning} from './ui.js'\nimport {outputContent, outputResult, outputToken} from './output.js'\nimport {terminalSupportsPrompting} from './system.js'\nimport {hashString} from './crypto.js'\nimport {isTruthy} from './context/utilities.js'\nimport {showNotificationsIfNeeded} from './notifications-system.js'\nimport {setCurrentCommandId} from './global-context.js'\nimport {JsonMap} from '../../private/common/json.js'\nimport {underscore} from '../common/string.js'\nimport {Command, Config, Errors} from '@oclif/core'\nimport {OutputFlags, Input, ParserOutput, FlagInput, OutputArgs} from '@oclif/core/parser'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type ArgOutput = OutputArgs<any>\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type FlagOutput = OutputFlags<any>\n\ninterface EnvironmentFlags {\n environment?: string[]\n path?: string\n}\n\nabstract class BaseCommand extends Command {\n // eslint-disable-next-line @typescript-eslint/ban-types\n static baseFlags: FlagInput<{}> = {}\n\n // Replace markdown links to plain text like: \"link label\" (url)\n public static descriptionWithoutMarkdown(): string | undefined {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return ((this as any).descriptionWithMarkdown ?? '').replace(/(\\[)(.*?)(])(\\()(.*?)(\\))/gm, '\"$2\" ($5)')\n }\n\n public static analyticsNameOverride(): string | undefined {\n return undefined\n }\n\n public static analyticsStopCommand(): string | undefined {\n return undefined\n }\n\n async catch(error: Error & {skipOclifErrorHandling: boolean}): Promise<void> {\n error.skipOclifErrorHandling = true\n await errorHandler(error, this.config)\n return Errors.handle(error)\n }\n\n protected async init(): Promise<unknown> {\n this.exitWithTimestampWhenEnvVariablePresent()\n setCurrentCommandId(this.id ?? '')\n if (!isDevelopment()) {\n // This function runs just prior to `run`\n await registerCleanBugsnagErrorsFromWithinPlugins(this.config)\n }\n await removeDuplicatedPlugins(this.config)\n this.showNpmFlagWarning()\n await showNotificationsIfNeeded()\n return super.init()\n }\n\n // NPM creates an environment variable for every flag passed to a script.\n // This function checks for the presence of any of the available CLI flags\n // and warns the user to use the `--` separator.\n protected showNpmFlagWarning(): void {\n const commandVariables = this.constructor as unknown as {flags: JsonMap}\n const commandFlags = Object.keys(commandVariables.flags || {})\n const possibleNpmEnvVars = commandFlags.map((key) => `npm_config_${underscore(key).replace(/^no_/, '')}`)\n\n if (possibleNpmEnvVars.some((flag) => process.env[flag] !== undefined)) {\n renderWarning({\n body: [\n 'NPM scripts require an extra',\n {command: '--'},\n 'separator to pass the flags. Example:',\n {command: 'npm run dev -- --reset'},\n ],\n })\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\n protected exitWithTimestampWhenEnvVariablePresent() {\n if (isTruthy(process.env.SHOPIFY_CLI_ENV_STARTUP_PERFORMANCE_RUN)) {\n outputResult(`\n SHOPIFY_CLI_TIMESTAMP_START\n { \"timestamp\": ${Date.now()} }\n SHOPIFY_CLI_TIMESTAMP_END\n `)\n process.exit(0)\n }\n }\n\n protected async parse<\n TFlags extends FlagOutput & {path?: string; verbose?: boolean},\n TGlobalFlags extends FlagOutput,\n TArgs extends ArgOutput,\n >(\n options?: Input<TFlags, TGlobalFlags, TArgs>,\n argv?: string[],\n ): Promise<ParserOutput<TFlags, TGlobalFlags, TArgs> & {argv: string[]}> {\n let result = await super.parse<TFlags, TGlobalFlags, TArgs>(options, argv)\n result = await this.resultWithEnvironment<TFlags, TGlobalFlags, TArgs>(result, options, argv)\n await addFromParsedFlags(result.flags)\n return {...result, ...{argv: result.argv as string[]}}\n }\n\n protected environmentsFilename(): string | undefined {\n // To be re-implemented if needed\n return undefined\n }\n\n protected failMissingNonTTYFlags(flags: FlagOutput, requiredFlags: string[]): void {\n if (terminalSupportsPrompting()) return\n\n requiredFlags.forEach((name: string) => {\n if (!(name in flags)) {\n throw new AbortError(\n outputContent`Flag not specified:\n\n${outputToken.cyan(name)}\n\nThis flag is required in non-interactive terminal environments, such as a CI environment, or when piping input from another process.`,\n 'To resolve this, specify the option in the command, or run the command in an interactive environment such as your local terminal.',\n )\n }\n })\n }\n\n private async resultWithEnvironment<\n TFlags extends FlagOutput & {path?: string; verbose?: boolean},\n TGlobalFlags extends FlagOutput,\n TArgs extends ArgOutput,\n >(\n originalResult: ParserOutput<TFlags, TGlobalFlags, TArgs>,\n options?: Input<TFlags, TGlobalFlags, TArgs>,\n argv?: string[],\n ): Promise<ParserOutput<TFlags, TGlobalFlags, TArgs>> {\n const flags = originalResult.flags as EnvironmentFlags\n const environmentsFileName = this.environmentsFilename()\n\n if (!environmentsFileName) return originalResult\n\n const environmentFileExists = await environmentFilePath(environmentsFileName, {from: flags.path})\n\n // Handle both string and array cases for environment flag\n let environments: string[] = []\n if (flags.environment) {\n environments = Array.isArray(flags.environment) ? flags.environment : [flags.environment]\n }\n\n const environmentSpecified = environments.length > 0\n\n // Noop if no environment file exists and none was specified\n if (!environmentFileExists && !environmentSpecified) return originalResult\n\n // Noop if multiple environments were specified (let commands handle this)\n if (environmentSpecified && environments.length > 1) return originalResult\n\n const {environment, isDefaultEnvironment} = await this.loadEnvironmentForCommand(\n flags.path,\n environmentsFileName,\n environments[0],\n )\n\n if (!environment) return originalResult\n if (isDefaultEnvironment && !commandSupportsFlag(options?.flags, 'environment')) return originalResult\n\n // Parse using noDefaultsOptions to derive a list of flags specified as\n // command-line arguments.\n const noDefaultsResult = await super.parse<TFlags, TGlobalFlags, TArgs>(noDefaultsOptions(options), argv)\n\n // Add the environment's settings to argv and pass them to `super.parse`. This\n // invokes oclif's validation system without breaking the oclif black box.\n // Replace the original result with this one.\n const result = await super.parse<TFlags, TGlobalFlags, TArgs>(options, [\n // Need to specify argv default because we're merging with argsFromEnvironment.\n ...(argv ?? this.argv),\n ...argsFromEnvironment<TFlags, TGlobalFlags, TArgs>(environment, options, noDefaultsResult),\n ...(isDefaultEnvironment ? ['--environment', 'default'] : []),\n ])\n\n // Report successful application of the environment.\n reportEnvironmentApplication<TFlags, TGlobalFlags, TArgs>(\n noDefaultsResult.flags,\n result.flags,\n isDefaultEnvironment ? 'default' : (environments[0] as string),\n environment,\n )\n\n return result\n }\n\n /**\n * Tries to load an environment to forward to the command. If no environment\n * is specified it will try to load a default environment.\n */\n private async loadEnvironmentForCommand(\n path: string | undefined,\n environmentsFileName: string,\n specifiedEnvironment: string | undefined,\n ): Promise<{environment: JsonMap | undefined; isDefaultEnvironment: boolean}> {\n if (specifiedEnvironment) {\n const environment = await loadEnvironment(specifiedEnvironment, environmentsFileName, {from: path})\n return {environment, isDefaultEnvironment: false}\n }\n\n const environment = await loadEnvironment('default', environmentsFileName, {from: path, silent: true})\n return {environment, isDefaultEnvironment: true}\n }\n}\n\nexport async function addFromParsedFlags(flags: {path?: string; verbose?: boolean}): Promise<void> {\n await addPublicMetadata(() => ({\n cmd_all_verbose: flags.verbose,\n cmd_all_path_override: flags.path !== undefined,\n cmd_all_path_override_hash: flags.path === undefined ? undefined : hashString(flags.path),\n }))\n}\n\n/**\n * Any flag which is:\n *\n * 1. Present in the final set of flags\n * 2. Specified in the environment\n * 3. Not specified by the user as a command line argument\n *\n * should be reported.\n *\n * It doesn't matter if the environment flag's value was the same as the default; from\n * the user's perspective, they want to know their environment was applied.\n */\nfunction reportEnvironmentApplication<\n TFlags extends FlagOutput,\n TGlobalFlags extends FlagOutput,\n TArgs extends ArgOutput,\n>(\n noDefaultsFlags: ParserOutput<TFlags, TGlobalFlags, TArgs>['flags'],\n flagsWithEnvironments: ParserOutput<TFlags, TGlobalFlags, TArgs>['flags'],\n environmentName: string,\n environment: JsonMap,\n): void {\n const changes: JsonMap = {}\n for (const [name, value] of Object.entries(flagsWithEnvironments)) {\n const userSpecifiedThisFlag = Object.prototype.hasOwnProperty.call(noDefaultsFlags, name)\n const environmentContainsFlag = Object.prototype.hasOwnProperty.call(environment, name)\n if (!userSpecifiedThisFlag && environmentContainsFlag) {\n const valueToReport = name === 'password' ? `********${value.substr(-4)}` : value\n changes[name] = valueToReport\n }\n }\n if (Object.keys(changes).length === 0) return\n\n const items = Object.entries(changes).map(([name, value]) => `${name}: ${value}`)\n renderInfo({\n headline: ['Using applicable flags from', {userInput: environmentName}, 'environment:'],\n body: [{list: {items}}],\n })\n}\n\n/**\n * Strips the defaults from configured flags. For example, if flags contains:\n *\n * ```\n * someFlag: Flags.boolean({\n * description: 'some flag',\n * default: false\n * })\n * ```\n *\n * it becomes:\n *\n * ```\n * someFlag: Flags.boolean({\n * description: 'some flag'\n * })\n * ```\n *\n * If we parse using this configuration, the only specified flags will be those\n * the user actually passed on the command line.\n */\nexport function noDefaultsOptions<TFlags extends FlagOutput, TGlobalFlags extends FlagOutput, TArgs extends ArgOutput>(\n options: Input<TFlags, TGlobalFlags, TArgs> | undefined,\n): Input<TFlags, TGlobalFlags, TArgs> | undefined {\n if (!options?.flags) return options\n return {\n ...options,\n flags: Object.fromEntries(\n Object.entries(options.flags).map(([label, settings]) => {\n const copiedSettings = {...(settings as {default?: unknown})}\n delete copiedSettings.default\n return [label, copiedSettings]\n }),\n ) as FlagInput<TFlags>,\n }\n}\n\n/**\n * Converts the environment's settings to arguments as though passed on the command\n * line, skipping any arguments the user specified on the command line.\n */\nfunction argsFromEnvironment<TFlags extends FlagOutput, TGlobalFlags extends FlagOutput, TArgs extends ArgOutput>(\n environment: JsonMap,\n options: Input<TFlags, TGlobalFlags, TArgs> | undefined,\n noDefaultsResult: ParserOutput<TFlags, TArgs>,\n): string[] {\n const args: string[] = []\n for (const [label, value] of Object.entries(environment)) {\n const flagIsRelevantToCommand = commandSupportsFlag(options?.flags, label)\n const userSpecifiedThisFlag =\n noDefaultsResult.flags && Object.prototype.hasOwnProperty.call(noDefaultsResult.flags, label)\n if (flagIsRelevantToCommand && !userSpecifiedThisFlag) {\n if (typeof value === 'boolean') {\n if (value) {\n args.push(`--${label}`)\n } else {\n throw new AbortError(\n outputContent`Environments can only specify true for boolean flags. Attempted to set ${outputToken.yellow(\n label,\n )} to false.`,\n )\n }\n } else if (Array.isArray(value)) {\n value.forEach((element) => args.push(`--${label}`, `${element}`))\n } else {\n args.push(`--${label}`, `${value}`)\n }\n }\n }\n return args\n}\n\nfunction commandSupportsFlag(flags: FlagInput | undefined, flagName: string): boolean {\n return Boolean(flags) && Object.prototype.hasOwnProperty.call(flags, flagName)\n}\n\nasync function removeDuplicatedPlugins(config: Config): Promise<void> {\n const plugins = Array.from(config.plugins.values())\n const bundlePlugins = ['@shopify/app', '@shopify/plugin-cloudflare']\n const pluginsToRemove = plugins.filter((plugin) => bundlePlugins.includes(plugin.name))\n if (pluginsToRemove.length > 0) {\n const commandsToRun = pluginsToRemove.map((plugin) => ` - shopify plugins remove ${plugin.name}`).join('\\n')\n renderWarning({\n headline: `Unsupported plugins detected: ${pluginsToRemove.map((plugin) => plugin.name).join(', ')}`,\n body: [\n 'They are already included in the CLI and installing them as custom plugins can cause conflicts.',\n `You can fix it by running:\\n${commandsToRun}`,\n ],\n })\n }\n const filteredPlugins = plugins.filter((plugin) => !bundlePlugins.includes(plugin.name))\n config.plugins = new Map(filteredPlugins.map((plugin) => [plugin.name, plugin]))\n}\n\nexport default BaseCommand\n"]}
@@ -1,30 +1,35 @@
1
1
  import { fileExistsSync } from './fs.js';
2
2
  import { cwd, joinPath, sniffForPath } from './path.js';
3
+ import { isDevelopment } from './context/local.js';
3
4
  import { execaSync } from 'execa';
4
5
  import { Config } from '@oclif/core';
5
6
  export class ShopifyConfig extends Config {
6
7
  constructor(options) {
7
- const currentPath = cwd();
8
- let path = sniffForPath() ?? currentPath;
9
- // Hydrogen CI uses `hydrogen/hydrogen` path, while local dev uses `shopify/hydrogen`.
10
- const currentPathMightBeHydrogenMonorepo = /(shopify|hydrogen)\/hydrogen/i.test(currentPath);
11
- const ignoreHydrogenMonorepo = process.env.IGNORE_HYDROGEN_MONOREPO;
12
- if (currentPathMightBeHydrogenMonorepo && !ignoreHydrogenMonorepo) {
13
- path = execaSync('npm', ['prefix']).stdout.trim();
14
- }
15
- if (fileExistsSync(joinPath(path, 'package.json'))) {
16
- // Hydrogen is bundled, but we still want to support loading it as an external plugin for two reasons:
17
- // 1. To allow users to use an older version of Hydrogen. (to not force upgrades)
18
- // 2. To allow the Hydrogen team to load a local version for testing.
19
- options.pluginAdditions = {
20
- core: ['@shopify/cli-hydrogen'],
21
- path,
22
- };
8
+ if (isDevelopment()) {
9
+ const currentPath = cwd();
10
+ let path = sniffForPath() ?? currentPath;
11
+ // Hydrogen CI uses `hydrogen/hydrogen` path, while local dev uses `shopify/hydrogen`.
12
+ const currentPathMightBeHydrogenMonorepo = /(shopify|hydrogen)\/hydrogen/i.test(currentPath);
13
+ const ignoreHydrogenMonorepo = process.env.IGNORE_HYDROGEN_MONOREPO;
14
+ if (currentPathMightBeHydrogenMonorepo && !ignoreHydrogenMonorepo) {
15
+ path = execaSync('npm', ['prefix']).stdout.trim();
16
+ }
17
+ if (fileExistsSync(joinPath(path, 'package.json'))) {
18
+ // Hydrogen is bundled, but we still want to support loading it as an external plugin for two reasons:
19
+ // 1. To allow users to use an older version of Hydrogen. (to not force upgrades)
20
+ // 2. To allow the Hydrogen team to load a local version for testing.
21
+ options.pluginAdditions = {
22
+ core: ['@shopify/cli-hydrogen'],
23
+ path,
24
+ };
25
+ }
23
26
  }
24
27
  super(options);
25
- // @ts-expect-error: This is a private method that we are overriding. OCLIF doesn't provide a way to extend it.
26
- // eslint-disable-next-line @typescript-eslint/unbound-method
27
- this.determinePriority = this.customPriority;
28
+ if (isDevelopment()) {
29
+ // @ts-expect-error: This is a private method that we are overriding. OCLIF doesn't provide a way to extend it.
30
+ // eslint-disable-next-line @typescript-eslint/unbound-method
31
+ this.determinePriority = this.customPriority;
32
+ }
28
33
  }
29
34
  customPriority(commands) {
30
35
  const oclifPlugins = this.pjson.oclif.plugins ?? [];
@@ -1 +1 @@
1
- {"version":3,"file":"custom-oclif-loader.js","sourceRoot":"","sources":["../../../src/public/node/custom-oclif-loader.ts"],"names":[],"mappings":"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","sourcesContent":["import {fileExistsSync} from './fs.js'\nimport {cwd, joinPath, sniffForPath} from './path.js'\nimport {execaSync} from 'execa'\nimport {Command, Config} from '@oclif/core'\nimport {Options} from '@oclif/core/interfaces'\n\nexport class ShopifyConfig extends Config {\n constructor(options: Options) {\n const currentPath = cwd()\n\n let path = sniffForPath() ?? currentPath\n // Hydrogen CI uses `hydrogen/hydrogen` path, while local dev uses `shopify/hydrogen`.\n const currentPathMightBeHydrogenMonorepo = /(shopify|hydrogen)\\/hydrogen/i.test(currentPath)\n const ignoreHydrogenMonorepo = process.env.IGNORE_HYDROGEN_MONOREPO\n if (currentPathMightBeHydrogenMonorepo && !ignoreHydrogenMonorepo) {\n path = execaSync('npm', ['prefix']).stdout.trim()\n }\n if (fileExistsSync(joinPath(path, 'package.json'))) {\n // Hydrogen is bundled, but we still want to support loading it as an external plugin for two reasons:\n // 1. To allow users to use an older version of Hydrogen. (to not force upgrades)\n // 2. To allow the Hydrogen team to load a local version for testing.\n options.pluginAdditions = {\n core: ['@shopify/cli-hydrogen'],\n path,\n }\n }\n super(options)\n\n // @ts-expect-error: This is a private method that we are overriding. OCLIF doesn't provide a way to extend it.\n // eslint-disable-next-line @typescript-eslint/unbound-method\n this.determinePriority = this.customPriority\n }\n\n customPriority(commands: Command.Loadable[]): Command.Loadable | undefined {\n const oclifPlugins = this.pjson.oclif.plugins ?? []\n const commandPlugins = commands.sort((aCommand, bCommand) => {\n // eslint-disable-next-line no-restricted-syntax\n const pluginAliasA = aCommand.pluginAlias ?? 'A-Cannot-Find-This'\n // eslint-disable-next-line no-restricted-syntax\n const pluginAliasB = bCommand.pluginAlias ?? 'B-Cannot-Find-This'\n const aIndex = oclifPlugins.indexOf(pluginAliasA)\n const bIndex = oclifPlugins.indexOf(pluginAliasB)\n\n // If there is an external cli-hydrogen plugin, its commands should take priority over bundled ('core') commands\n if (aCommand.pluginType === 'core' && bCommand.pluginAlias === '@shopify/cli-hydrogen') {\n // If b is hydrogen and a is core sort b first\n return 1\n }\n\n if (aCommand.pluginAlias === '@shopify/cli-hydrogen' && bCommand.pluginType === 'core') {\n // If a is hydrogen and b is core sort a first\n return -1\n }\n\n // All other cases are the default implementation from the private `determinePriority` method\n // When both plugin types are 'core' plugins sort based on index\n if (aCommand.pluginType === 'core' && bCommand.pluginType === 'core') {\n // If b appears first in the pjson.plugins sort it first\n return aIndex - bIndex\n }\n\n // if b is a core plugin and a is not sort b first\n if (bCommand.pluginType === 'core' && aCommand.pluginType !== 'core') {\n return 1\n }\n\n // if a is a core plugin and b is not sort a first\n if (aCommand.pluginType === 'core' && bCommand.pluginType !== 'core') {\n return -1\n }\n\n // if a is a jit plugin and b is not sort b first\n if (aCommand.pluginType === 'jit' && bCommand.pluginType !== 'jit') {\n return 1\n }\n\n // if b is a jit plugin and a is not sort a first\n if (bCommand.pluginType === 'jit' && aCommand.pluginType !== 'jit') {\n return -1\n }\n\n // neither plugin is core, so do not change the order\n return 0\n })\n return commandPlugins[0]\n }\n}\n"]}
1
+ {"version":3,"file":"custom-oclif-loader.js","sourceRoot":"","sources":["../../../src/public/node/custom-oclif-loader.ts"],"names":[],"mappings":"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","sourcesContent":["import {fileExistsSync} from './fs.js'\nimport {cwd, joinPath, sniffForPath} from './path.js'\nimport {isDevelopment} from './context/local.js'\nimport {execaSync} from 'execa'\nimport {Command, Config} from '@oclif/core'\nimport {Options} from '@oclif/core/interfaces'\n\nexport class ShopifyConfig extends Config {\n constructor(options: Options) {\n if (isDevelopment()) {\n const currentPath = cwd()\n\n let path = sniffForPath() ?? currentPath\n // Hydrogen CI uses `hydrogen/hydrogen` path, while local dev uses `shopify/hydrogen`.\n const currentPathMightBeHydrogenMonorepo = /(shopify|hydrogen)\\/hydrogen/i.test(currentPath)\n const ignoreHydrogenMonorepo = process.env.IGNORE_HYDROGEN_MONOREPO\n if (currentPathMightBeHydrogenMonorepo && !ignoreHydrogenMonorepo) {\n path = execaSync('npm', ['prefix']).stdout.trim()\n }\n if (fileExistsSync(joinPath(path, 'package.json'))) {\n // Hydrogen is bundled, but we still want to support loading it as an external plugin for two reasons:\n // 1. To allow users to use an older version of Hydrogen. (to not force upgrades)\n // 2. To allow the Hydrogen team to load a local version for testing.\n options.pluginAdditions = {\n core: ['@shopify/cli-hydrogen'],\n path,\n }\n }\n }\n\n super(options)\n\n if (isDevelopment()) {\n // @ts-expect-error: This is a private method that we are overriding. OCLIF doesn't provide a way to extend it.\n // eslint-disable-next-line @typescript-eslint/unbound-method\n this.determinePriority = this.customPriority\n }\n }\n\n customPriority(commands: Command.Loadable[]): Command.Loadable | undefined {\n const oclifPlugins = this.pjson.oclif.plugins ?? []\n const commandPlugins = commands.sort((aCommand, bCommand) => {\n // eslint-disable-next-line no-restricted-syntax\n const pluginAliasA = aCommand.pluginAlias ?? 'A-Cannot-Find-This'\n // eslint-disable-next-line no-restricted-syntax\n const pluginAliasB = bCommand.pluginAlias ?? 'B-Cannot-Find-This'\n const aIndex = oclifPlugins.indexOf(pluginAliasA)\n const bIndex = oclifPlugins.indexOf(pluginAliasB)\n\n // If there is an external cli-hydrogen plugin, its commands should take priority over bundled ('core') commands\n if (aCommand.pluginType === 'core' && bCommand.pluginAlias === '@shopify/cli-hydrogen') {\n // If b is hydrogen and a is core sort b first\n return 1\n }\n\n if (aCommand.pluginAlias === '@shopify/cli-hydrogen' && bCommand.pluginType === 'core') {\n // If a is hydrogen and b is core sort a first\n return -1\n }\n\n // All other cases are the default implementation from the private `determinePriority` method\n // When both plugin types are 'core' plugins sort based on index\n if (aCommand.pluginType === 'core' && bCommand.pluginType === 'core') {\n // If b appears first in the pjson.plugins sort it first\n return aIndex - bIndex\n }\n\n // if b is a core plugin and a is not sort b first\n if (bCommand.pluginType === 'core' && aCommand.pluginType !== 'core') {\n return 1\n }\n\n // if a is a core plugin and b is not sort a first\n if (aCommand.pluginType === 'core' && bCommand.pluginType !== 'core') {\n return -1\n }\n\n // if a is a jit plugin and b is not sort b first\n if (aCommand.pluginType === 'jit' && bCommand.pluginType !== 'jit') {\n return 1\n }\n\n // if b is a jit plugin and a is not sort a first\n if (bCommand.pluginType === 'jit' && aCommand.pluginType !== 'jit') {\n return -1\n }\n\n // neither plugin is core, so do not change the order\n return 0\n })\n return commandPlugins[0]\n }\n}\n"]}
@@ -155,6 +155,13 @@ export declare function mkTmpDir(): Promise<string>;
155
155
  * @returns True if the path is a directory, false otherwise.
156
156
  */
157
157
  export declare function isDirectory(path: string): Promise<boolean>;
158
+ /**
159
+ * Check whether a path is a directory.
160
+ *
161
+ * @param path - Path to check.
162
+ * @returns True if the path is a directory, false otherwise.
163
+ */
164
+ export declare function isDirectorySync(path: string): boolean;
158
165
  /**
159
166
  * Get the size of a file.
160
167
  *
@@ -273,6 +280,14 @@ export declare function generateRandomNameForSubdirectory(options: GenerateRando
273
280
  * @returns A promise that resolves to an array of pathnames that match the given pattern.
274
281
  */
275
282
  export declare function glob(pattern: Pattern | Pattern[], options?: GlobOptions): Promise<string[]>;
283
+ /**
284
+ * Synchronously traverse the file system and return pathnames that match the given pattern.
285
+ *
286
+ * @param pattern - A glob pattern or an array of glob patterns.
287
+ * @param options - Options for the glob.
288
+ * @returns An array of pathnames that match the given pattern.
289
+ */
290
+ export declare function globSync(pattern: Pattern | Pattern[], options?: GlobOptions): string[];
276
291
  /**
277
292
  * Convert a path to a File URL.
278
293
  *
@@ -9,6 +9,7 @@ import { temporaryDirectory, temporaryDirectoryTask } from 'tempy';
9
9
  import { sep, join } from 'pathe';
10
10
  import { findUp as internalFindUp } from 'find-up';
11
11
  import { minimatch } from 'minimatch';
12
+ import fastGlobLib from 'fast-glob';
12
13
  import { mkdirSync as fsMkdirSync, readFileSync as fsReadFileSync, writeFileSync as fsWriteFileSync, appendFileSync as fsAppendFileSync, statSync as fsStatSync, createReadStream as fsCreateReadStream, createWriteStream as fsCreateWriteStream, constants as fsConstants, existsSync as fsFileExistsSync, unlinkSync as fsUnlinkSync, accessSync, statSync, } from 'fs';
13
14
  import { mkdir as fsMkdir, writeFile as fsWriteFile, readFile as fsReadFile, realpath as fsRealPath, appendFile as fsAppendFile, mkdtemp as fsMkdtemp, stat as fsStat, lstat as fsLstat, chmod as fsChmod, access as fsAccess, rename as fsRename, unlink as fsUnlink, readdir as fsReaddir, } from 'fs/promises';
14
15
  import { pathToFileURL as pathToFile } from 'url';
@@ -221,6 +222,16 @@ export async function isDirectory(path) {
221
222
  outputDebug(outputContent `Checking if ${outputToken.path(path)} is a directory...`);
222
223
  return (await fsLstat(path)).isDirectory();
223
224
  }
225
+ /**
226
+ * Check whether a path is a directory.
227
+ *
228
+ * @param path - Path to check.
229
+ * @returns True if the path is a directory, false otherwise.
230
+ */
231
+ export function isDirectorySync(path) {
232
+ outputDebug(outputContent `Checking if ${outputToken.path(path)} is a directory...`);
233
+ return fsStatSync(path).isDirectory();
234
+ }
224
235
  /**
225
236
  * Get the size of a file.
226
237
  *
@@ -415,6 +426,20 @@ export async function glob(pattern, options) {
415
426
  }
416
427
  return fastGlob(pattern, overridenOptions);
417
428
  }
429
+ /**
430
+ * Synchronously traverse the file system and return pathnames that match the given pattern.
431
+ *
432
+ * @param pattern - A glob pattern or an array of glob patterns.
433
+ * @param options - Options for the glob.
434
+ * @returns An array of pathnames that match the given pattern.
435
+ */
436
+ export function globSync(pattern, options) {
437
+ let overridenOptions = options;
438
+ if (options?.dot == null) {
439
+ overridenOptions = { ...options, dot: true };
440
+ }
441
+ return fastGlobLib.sync(pattern, overridenOptions);
442
+ }
418
443
  /**
419
444
  * Convert a path to a File URL.
420
445
  *