Skip to content

Commit a02d312

Browse files
authored
fix: make cli aware when run in npx/pnpx context (#7315)
1 parent 2b2cad3 commit a02d312

File tree

3 files changed

+41
-13
lines changed

3 files changed

+41
-13
lines changed

src/commands/init/init.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { OptionValues } from 'commander'
22
import inquirer from 'inquirer'
33
import isEmpty from 'lodash/isEmpty.js'
44

5-
import { chalk, exit, log } from '../../utils/command-helpers.js'
5+
import { chalk, exit, log, netlifyCommand } from '../../utils/command-helpers.js'
66
import getRepoData from '../../utils/get-repo-data.js'
77
import { ensureNetlifyIgnore } from '../../utils/gitignore.js'
88
import { configureRepo } from '../../utils/init/config.js'
@@ -31,8 +31,8 @@ const logExistingAndExit = ({ siteInfo }: { siteInfo: SiteInfo }): never => {
3131
log(`Admin URL: ${chalk.cyan(siteInfo.admin_url)}`)
3232
log()
3333
log(`To disconnect this directory and create a new project (or link to another project ID)`)
34-
log(`1. Run ${chalk.cyanBright.bold('netlify unlink')}`)
35-
log(`2. Then run ${chalk.cyanBright.bold('netlify init')} again`)
34+
log(`1. Run ${chalk.cyanBright.bold(`${netlifyCommand()} unlink`)}`)
35+
log(`2. Then run ${chalk.cyanBright.bold(`${netlifyCommand()} init`)} again`)
3636
return exit()
3737
}
3838

@@ -78,7 +78,7 @@ const createNewSiteAndExit = async ({
7878
}
7979

8080
log()
81-
log(`To deploy to this project, run ${chalk.cyanBright.bold('netlify deploy')}`)
81+
log(`To deploy to this project, run ${chalk.cyanBright.bold(`${netlifyCommand()} deploy`)}`)
8282

8383
return exit()
8484
}
@@ -111,7 +111,7 @@ const logGitSetupInstructionsAndExit = (): never => {
111111
112112
7. Initialize your Netlify Site
113113
114-
${chalk.cyanBright.bold('netlify init')}
114+
${chalk.cyanBright.bold(`${netlifyCommand()} init`)}
115115
`)
116116
return exit()
117117
}

src/commands/link/link.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { NetlifyAPI } from '@netlify/api'
66

77
import { listSites } from '../../lib/api.js'
88
import { startSpinner } from '../../lib/spinner.js'
9-
import { chalk, logAndThrowError, exit, log, APIError } from '../../utils/command-helpers.js'
9+
import { chalk, logAndThrowError, exit, log, APIError, netlifyCommand } from '../../utils/command-helpers.js'
1010
import getRepoData from '../../utils/get-repo-data.js'
1111
import { ensureNetlifyIgnore } from '../../utils/gitignore.js'
1212
import { track } from '../../utils/telemetry/index.js'
@@ -23,7 +23,9 @@ const findSiteByRepoUrl = async (api: NetlifyAPI, repoUrl: string): Promise<Site
2323
if (sites.length === 0) {
2424
spinner.error()
2525
return logAndThrowError(
26-
`You don't have any projects yet. Run ${chalk.cyanBright('netlify sites:create')} to create a project.`,
26+
`You don't have any projects yet. Run ${chalk.cyanBright(
27+
`${netlifyCommand()} sites:create`,
28+
)} to create a project.`,
2729
)
2830
}
2931

@@ -92,7 +94,7 @@ const linkPrompt = async (command: BaseCommand, options: LinkOptionValues): Prom
9294
}
9395

9496
log()
95-
log(`${chalk.cyanBright('netlify link')} will connect this folder to a project on Netlify`)
97+
log(`${chalk.cyanBright(`${netlifyCommand()} link`)} will connect this folder to a project on Netlify`)
9698
log()
9799
const { linkType } = await inquirer.prompt<{ linkType: string | undefined }>([
98100
{
@@ -142,8 +144,8 @@ const linkPrompt = async (command: BaseCommand, options: LinkOptionValues): Prom
142144
if (!matchingSites || matchingSites.length === 0) {
143145
return logAndThrowError(`No project names found containing '${searchTerm}'.
144146
145-
Run ${chalk.cyanBright('netlify link')} again to try a new search,
146-
or run ${chalk.cyanBright('netlify sites:create')} to create a project.`)
147+
Run ${chalk.cyanBright(`${netlifyCommand()} link`)} again to try a new search,
148+
or run ${chalk.cyanBright(`npx ${netlifyCommand()} sites:create`)} to create a project.`)
147149
}
148150

149151
if (matchingSites.length > 1) {
@@ -183,7 +185,9 @@ or run ${chalk.cyanBright('netlify sites:create')} to create a project.`)
183185

184186
if (!sites || sites.length === 0) {
185187
return logAndThrowError(
186-
`You don't have any projects yet. Run ${chalk.cyanBright('netlify sites:create')} to create a project.`,
188+
`You don't have any projects yet. Run ${chalk.cyanBright(
189+
`${netlifyCommand()} sites:create`,
190+
)} to create a project.`,
187191
)
188192
}
189193

@@ -271,7 +275,7 @@ export const link = async (options: LinkOptionValues, command: BaseCommand) => {
271275
// Site id is incorrect
272276
if (siteId && isEmpty(siteInfo)) {
273277
log(`"${siteId}" was not found in your Netlify account.`)
274-
log(`Please double check your project ID and which account you are logged into via \`netlify status\`.`)
278+
log(`Please double check your project ID and which account you are logged into via \`${netlifyCommand()} status\`.`)
275279
return exit()
276280
}
277281

@@ -281,7 +285,7 @@ export const link = async (options: LinkOptionValues, command: BaseCommand) => {
281285
log(`Project already linked to "${initialSiteData.name}"`)
282286
log(`Admin url: ${initialSiteData.admin_url}`)
283287
log()
284-
log(`To unlink this project, run: ${chalk.cyanBright('netlify unlink')}`)
288+
log(`To unlink this project, run: ${chalk.cyanBright(`${netlifyCommand()} unlink`)}`)
285289
} else if (options.id) {
286290
try {
287291
// @ts-expect-error FIXME(serhalp): Mismatch between hardcoded `SiteInfo` and new generated Netlify API types.

src/utils/command-helpers.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,27 @@ export const checkFileForLine = (filename: string, line: string) => {
348348

349349
export const TABTAB_CONFIG_LINE = '[[ -f ~/.config/tabtab/__tabtab.zsh ]] && . ~/.config/tabtab/__tabtab.zsh || true'
350350
export const AUTOLOAD_COMPINIT = 'autoload -U compinit; compinit'
351+
352+
function pkgFromUserAgent(userAgent: string | undefined): string | undefined {
353+
if (!userAgent) return undefined
354+
const pkgSpec = userAgent.split(' ')[0]
355+
const [pkgManagerName] = pkgSpec.split('/')
356+
return pkgManagerName
357+
}
358+
359+
export const netlifyCommand = () => {
360+
const { npm_command, npm_config_user_agent, npm_lifecycle_event } = process.env
361+
362+
// Captures both `npx netlify ...` and `npm exec netlify ...`
363+
if (npm_lifecycle_event === 'npx') {
364+
return `npx netlify`
365+
}
366+
367+
// Captures both `pnpx netlify ...` and `pnpm exec netlify ...`
368+
if (pkgFromUserAgent(npm_config_user_agent) === 'pnpm' && npm_command === 'exec') {
369+
return `pnpx netlify`
370+
}
371+
372+
// Default
373+
return 'netlify'
374+
}

0 commit comments

Comments
 (0)