mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-01 10:01:07 +02:00
feat(CTA): add official support for pnpm package manager (#2348)
* feat(CTA): add official support for `pnpm` package manager * adjust post-message formatting [skip ci] * optimize package managers checks
This commit is contained in:
5
.changes/cta-pnpm-support.md
Normal file
5
.changes/cta-pnpm-support.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"create-tauri-app": patch
|
||||
---
|
||||
|
||||
[`pnpm`](https://pnpm.io) package manager is now officially supported, either run `pnpx create-tauri-app` or explicitly specifiy it `npx create-tauri-app --manager pnpm`.
|
||||
@@ -5,7 +5,7 @@
|
||||
import { ManagementType, Result } from './types/deps'
|
||||
import { shell } from './shell'
|
||||
|
||||
export type PackageManager = 'npm' | 'yarn'
|
||||
export type PackageManager = 'npm' | 'yarn' | 'pnpm'
|
||||
|
||||
export async function install({
|
||||
appDir,
|
||||
@@ -50,16 +50,18 @@ async function installNpmPackage(
|
||||
packageManager: PackageManager,
|
||||
appDir: string
|
||||
): Promise<void> {
|
||||
if (packageNames.length === 0) return
|
||||
console.log(`Installing ${packageNames.join(', ')}...`)
|
||||
if (packageManager === 'yarn') {
|
||||
await shell('yarn', ['add', packageNames.join(' ')], {
|
||||
cwd: appDir
|
||||
})
|
||||
} else {
|
||||
await shell('npm', ['install', packageNames.join(' ')], {
|
||||
cwd: appDir
|
||||
})
|
||||
const packages = packageNames.filter((p) => p !== '')
|
||||
if (packages.length !== 0) {
|
||||
console.log(`- Installing ${packages.join(', ')}...`)
|
||||
if (packageManager === 'npm') {
|
||||
await shell('npm', ['install', packageNames.join(' ')], {
|
||||
cwd: appDir
|
||||
})
|
||||
} else {
|
||||
await shell(packageManager, ['add', packageNames.join(' ')], {
|
||||
cwd: appDir
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,23 +70,25 @@ async function installNpmDevPackage(
|
||||
packageManager: PackageManager,
|
||||
appDir: string
|
||||
): Promise<void> {
|
||||
if (packageNames.length === 0) return
|
||||
console.log(`Installing ${packageNames.join(', ')}...`)
|
||||
if (packageManager === 'yarn') {
|
||||
await shell(
|
||||
'yarn',
|
||||
['add', '--dev', '--ignore-scripts', packageNames.join(' ')],
|
||||
{
|
||||
cwd: appDir
|
||||
}
|
||||
)
|
||||
} else {
|
||||
await shell(
|
||||
'npm',
|
||||
['install', '--save-dev', '--ignore-scripts', packageNames.join(' ')],
|
||||
{
|
||||
cwd: appDir
|
||||
}
|
||||
)
|
||||
const packages = packageNames.filter((p) => p !== '')
|
||||
if (packages.length !== 0) {
|
||||
console.log(`- Installing ${packages.join(', ')}...`)
|
||||
if (packageManager === 'npm') {
|
||||
await shell(
|
||||
'npm',
|
||||
['install', '--save-dev', '--ignore-scripts', packageNames.join(' ')],
|
||||
{
|
||||
cwd: appDir
|
||||
}
|
||||
)
|
||||
} else {
|
||||
await shell(
|
||||
packageManager,
|
||||
['add', '-D', '--ignore-scripts', packageNames.join(' ')],
|
||||
{
|
||||
cwd: appDir
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ const printUsage = (): void => {
|
||||
--ci Skip prompts
|
||||
--force, -f Force init to overwrite [conf|template|all]
|
||||
--log, -l Logging [boolean]
|
||||
--manager, -d Set package manager to use [npm|yarn]
|
||||
--manager, -m Set package manager to use [npm|yarn|pnpm]
|
||||
--directory, -d Set target directory for init
|
||||
--app-name, -A Name of your Tauri application
|
||||
--window-title, -W Window title of your Tauri application
|
||||
@@ -255,12 +255,15 @@ const runInit = async (argv: Argv): Promise<void> => {
|
||||
}
|
||||
|
||||
const packageManager =
|
||||
argv.m === 'yarn' || argv.m === 'npm'
|
||||
argv.m === 'yarn' || argv.m === 'npm' || argv.m === 'pnpm'
|
||||
? argv.m
|
||||
: // @ts-expect-error
|
||||
// this little fun snippet pulled from vite determines the package manager the script was run from
|
||||
/yarn/.test(process?.env?.npm_execpath)
|
||||
? 'yarn'
|
||||
: // @ts-expect-error
|
||||
/pnpm/.test(process?.env?.npm_execpath)
|
||||
? 'pnpm'
|
||||
: 'npm'
|
||||
|
||||
const buildConfig = {
|
||||
@@ -367,10 +370,13 @@ const runInit = async (argv: Argv): Promise<void> => {
|
||||
|
||||
logStep(`Running: ${reset(yellow('tauri init'))}`)
|
||||
const binary = !argv.b ? packageManager : resolve(appDirectory, argv.b)
|
||||
// pnpm is equivalent to yarn and can run srcipts without using "run" but due to this bug https://github.com/pnpm/pnpm/issues/2764
|
||||
// we need to pass "--" to pnpm or arguments won't be parsed correctly so for this command only we are gonna treat pnpm as npm equivalent/
|
||||
const runTauriArgs =
|
||||
packageManager === 'npm' && !argv.b
|
||||
? ['run', 'tauri', '--', 'init']
|
||||
: ['tauri', 'init']
|
||||
packageManager === 'yarn' || argv.b
|
||||
? ['tauri', 'init']
|
||||
: ['run', 'tauri', '--', 'init']
|
||||
|
||||
await shell(binary, [...runTauriArgs, ...initArgs, '--ci'], {
|
||||
cwd: appDirectory
|
||||
})
|
||||
|
||||
@@ -17,9 +17,11 @@ export const dominator: Recipe = {
|
||||
...cfg,
|
||||
distDir: `../dist`,
|
||||
devPath: 'http://localhost:10001/',
|
||||
beforeDevCommand: `${packageManager === 'yarn' ? 'yarn' : 'npm run'} start`,
|
||||
beforeDevCommand: `${
|
||||
packageManager === 'npm' ? 'npm run' : packageManager
|
||||
} start`,
|
||||
beforeBuildCommand: `${
|
||||
packageManager === 'yarn' ? 'yarn' : 'npm run'
|
||||
packageManager === 'npm' ? 'npm run' : packageManager
|
||||
} build`
|
||||
}),
|
||||
extraNpmDevDependencies: [],
|
||||
@@ -46,12 +48,11 @@ export const dominator: Recipe = {
|
||||
console.log(`
|
||||
Your installation completed.
|
||||
|
||||
$ cd ${cfg.appName}.
|
||||
$ cd ${cfg.appName}
|
||||
$ ${packageManager} install
|
||||
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri ${
|
||||
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri ${
|
||||
packageManager === 'npm' ? '--' : ''
|
||||
} dev
|
||||
|
||||
}dev
|
||||
`)
|
||||
return await Promise.resolve()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PackageManager } from '../dependency-manager'
|
||||
import { shell } from '../shell'
|
||||
import { Recipe } from '../types/recipe'
|
||||
import { join } from 'path'
|
||||
|
||||
const addAdditionalPackage = async (
|
||||
packageManager: PackageManager,
|
||||
@@ -10,13 +11,13 @@ const addAdditionalPackage = async (
|
||||
): Promise<void> => {
|
||||
const ngCommand = ['ng', 'add', packageName, '--skip-confirmation']
|
||||
|
||||
if (packageManager === 'yarn') {
|
||||
await shell('yarn', ngCommand, {
|
||||
cwd: `${cwd}/${appName}`
|
||||
if (packageManager === 'npm') {
|
||||
await shell('npm', ['run', ...ngCommand], {
|
||||
cwd: join(cwd, appName)
|
||||
})
|
||||
} else {
|
||||
await shell('npm', ['run', ...ngCommand], {
|
||||
cwd: `${cwd}/${appName}`
|
||||
await shell(packageManager, ngCommand, {
|
||||
cwd: join(cwd, appName)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -33,9 +34,11 @@ const ngcli: Recipe = {
|
||||
...cfg,
|
||||
distDir: `../dist/${cfg.appName}`,
|
||||
devPath: 'http://localhost:4200',
|
||||
beforeDevCommand: `${packageManager === 'yarn' ? 'yarn' : 'npm run'} start`,
|
||||
beforeDevCommand: `${
|
||||
packageManager === 'npm' ? 'npm run' : packageManager
|
||||
} start`,
|
||||
beforeBuildCommand: `${
|
||||
packageManager === 'yarn' ? 'yarn' : 'npm run'
|
||||
packageManager === 'npm' ? 'npm run' : packageManager
|
||||
} build`
|
||||
}),
|
||||
extraQuestions: ({ ci }) => {
|
||||
@@ -94,12 +97,12 @@ const ngcli: Recipe = {
|
||||
},
|
||||
postInit: async ({ packageManager, cfg }) => {
|
||||
console.log(`
|
||||
Your installation completed.
|
||||
Your installation completed.
|
||||
|
||||
$ cd ${cfg.appName}
|
||||
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri ${
|
||||
$ cd ${cfg.appName}
|
||||
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri ${
|
||||
packageManager === 'npm' ? '--' : ''
|
||||
} dev
|
||||
}dev
|
||||
`)
|
||||
|
||||
return await Promise.resolve()
|
||||
|
||||
@@ -7,6 +7,7 @@ import { join } from 'path'
|
||||
import scaffe from 'scaffe'
|
||||
import { shell } from '../shell'
|
||||
import { Recipe } from '../types/recipe'
|
||||
import { rmSync, existsSync } from 'fs'
|
||||
|
||||
const afterCra = async (
|
||||
cwd: string,
|
||||
@@ -38,9 +39,11 @@ export const cra: Recipe = {
|
||||
...cfg,
|
||||
distDir: `../build`,
|
||||
devPath: 'http://localhost:3000',
|
||||
beforeDevCommand: `${packageManager === 'yarn' ? 'yarn' : 'npm run'} start`,
|
||||
beforeDevCommand: `${
|
||||
packageManager === 'npm' ? 'npm run' : packageManager
|
||||
} start`,
|
||||
beforeBuildCommand: `${
|
||||
packageManager === 'yarn' ? 'yarn' : 'npm run'
|
||||
packageManager === 'npm' ? 'npm run' : packageManager
|
||||
} build`
|
||||
}),
|
||||
extraNpmDevDependencies: [],
|
||||
@@ -50,7 +53,7 @@ export const cra: Recipe = {
|
||||
{
|
||||
type: 'list',
|
||||
name: 'template',
|
||||
message: 'Which vite template would you like to use?',
|
||||
message: 'Which create-react-app template would you like to use?',
|
||||
choices: [
|
||||
{ name: 'create-react-app (JavaScript)', value: 'cra.js' },
|
||||
{ name: 'create-react-app (Typescript)', value: 'cra.ts' }
|
||||
@@ -94,6 +97,22 @@ export const cra: Recipe = {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// create-react-app doesn't support pnpm, so we remove `node_modules` and any lock files then install them again using pnpm
|
||||
if (packageManager === 'pnpm') {
|
||||
const npmLock = join(cwd, cfg.appName, 'package-lock.json')
|
||||
const yarnLock = join(cwd, cfg.appName, 'yarn.lock')
|
||||
const nodeModules = join(cwd, cfg.appName, 'node_modules')
|
||||
if (existsSync(npmLock)) rmSync(npmLock)
|
||||
if (existsSync(yarnLock)) rmSync(yarnLock)
|
||||
if (existsSync(nodeModules))
|
||||
rmSync(nodeModules, {
|
||||
recursive: true,
|
||||
force: true
|
||||
})
|
||||
await shell('pnpm', ['install'], { cwd })
|
||||
}
|
||||
|
||||
await afterCra(cwd, cfg.appName, template === 'cra.ts')
|
||||
},
|
||||
postInit: async ({ packageManager, cfg }) => {
|
||||
@@ -101,10 +120,10 @@ export const cra: Recipe = {
|
||||
Your installation completed.
|
||||
|
||||
$ cd ${cfg.appName}
|
||||
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri ${
|
||||
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri ${
|
||||
packageManager === 'npm' ? '--' : ''
|
||||
} dev
|
||||
`)
|
||||
}dev
|
||||
`)
|
||||
return await Promise.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,11 @@ const svelte: Recipe = {
|
||||
...cfg,
|
||||
distDir: `../public`,
|
||||
devPath: 'http://localhost:5000',
|
||||
beforeDevCommand: `${packageManager === 'yarn' ? 'yarn' : 'npm run'} dev`,
|
||||
beforeDevCommand: `${
|
||||
packageManager === 'yarn' ? 'npm run' : packageManager
|
||||
} dev`,
|
||||
beforeBuildCommand: `${
|
||||
packageManager === 'yarn' ? 'yarn' : 'npm run'
|
||||
packageManager === 'yarn' ? 'npm run' : packageManager
|
||||
} build`
|
||||
}),
|
||||
preInit: async ({ cwd, cfg, answers }) => {
|
||||
@@ -56,11 +58,11 @@ const svelte: Recipe = {
|
||||
console.log(`
|
||||
Your installation completed.
|
||||
|
||||
$ cd ${cfg.appName}.
|
||||
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri ${
|
||||
$ cd ${cfg.appName}
|
||||
$ ${packageManager} install
|
||||
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri ${
|
||||
packageManager === 'npm' ? '--' : ''
|
||||
} dev
|
||||
|
||||
}dev
|
||||
`)
|
||||
|
||||
return await Promise.resolve()
|
||||
|
||||
@@ -43,12 +43,12 @@ export const vanillajs: Recipe = {
|
||||
console.log(`
|
||||
Your installation completed.
|
||||
|
||||
$ cd ${cfg.appName}
|
||||
$ ${packageManager} install
|
||||
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri ${
|
||||
packageManager === 'npm' ? '-- ' : ''
|
||||
$ cd ${cfg.appName}
|
||||
$ ${packageManager} install
|
||||
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri ${
|
||||
packageManager === 'npm' ? '--' : ''
|
||||
}dev
|
||||
`)
|
||||
`)
|
||||
return await Promise.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,23 +7,6 @@
|
||||
import { shell } from '../shell'
|
||||
import { Recipe } from '../types/recipe'
|
||||
|
||||
const afterViteCA = async (
|
||||
cwd: string,
|
||||
appName: string,
|
||||
template: string
|
||||
): Promise<void> => {
|
||||
// template dir temp removed, will eventually add it back for APIs
|
||||
// leaving this here until then
|
||||
// const templateDir = join(__dirname, `../src/templates/vite/${template}`)
|
||||
// try {
|
||||
// await scaffe.generate(templateDir, join(cwd, appName), {
|
||||
// overwrite: true
|
||||
// })
|
||||
// } catch (err) {
|
||||
// console.log(err)
|
||||
// }
|
||||
}
|
||||
|
||||
const vite: Recipe = {
|
||||
descriptiveName: {
|
||||
name: 'create-vite (https://vitejs.dev/guide/#scaffolding-your-first-vite-project)',
|
||||
@@ -34,9 +17,11 @@ const vite: Recipe = {
|
||||
...cfg,
|
||||
distDir: `../dist`,
|
||||
devPath: 'http://localhost:3000',
|
||||
beforeDevCommand: `${packageManager === 'yarn' ? 'yarn' : 'npm run'} dev`,
|
||||
beforeDevCommand: `${
|
||||
packageManager === 'npm' ? 'npm run' : packageManager
|
||||
} dev`,
|
||||
beforeBuildCommand: `${
|
||||
packageManager === 'yarn' ? 'yarn' : 'npm run'
|
||||
packageManager === 'npm' ? 'npm run' : packageManager
|
||||
} build`
|
||||
}),
|
||||
extraNpmDevDependencies: [],
|
||||
@@ -84,33 +69,32 @@ const vite: Recipe = {
|
||||
)
|
||||
} else {
|
||||
await shell(
|
||||
'npx',
|
||||
packageManager === 'pnpm' ? 'pnpx' : 'npx',
|
||||
['create-vite@latest', `${cfg.appName}`, '--template', `${template}`],
|
||||
{
|
||||
cwd
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
await afterViteCA(cwd, cfg.appName, template)
|
||||
},
|
||||
postInit: async ({ cwd, packageManager, cfg }) => {
|
||||
// we don't have a consistent way to rebuild and
|
||||
// esbuild has hit all the bugs and struggles to install on the postinstall
|
||||
await shell('node', ['./node_modules/esbuild/install.js'], { cwd })
|
||||
if (packageManager === 'yarn') {
|
||||
await shell('yarn', ['build'], { cwd })
|
||||
} else {
|
||||
if (packageManager === 'npm') {
|
||||
await shell('npm', ['run', 'build'], { cwd })
|
||||
} else {
|
||||
await shell(packageManager, ['build'], { cwd })
|
||||
}
|
||||
|
||||
console.log(`
|
||||
Your installation completed.
|
||||
|
||||
$ cd ${cfg.appName}.
|
||||
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri ${
|
||||
$ cd ${cfg.appName}
|
||||
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri ${
|
||||
packageManager === 'npm' ? '--' : ''
|
||||
} dev
|
||||
`)
|
||||
}dev
|
||||
`)
|
||||
return await Promise.resolve()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ const vuecli: Recipe = {
|
||||
Your installation completed.
|
||||
|
||||
$ cd ${cfg.appName}
|
||||
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri:serve
|
||||
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri:serve
|
||||
`)
|
||||
return await Promise.resolve()
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export const shell = async (
|
||||
): Promise<execa.ExecaReturnValue> => {
|
||||
try {
|
||||
if (options && options.shell === true) {
|
||||
const stringCommand = [command, ...(!args ? [] : args)].join(' ')
|
||||
const stringCommand = [command, ...(args ?? [])].join(' ')
|
||||
if (log) console.log(`[running]: ${stringCommand}`)
|
||||
return await execa(stringCommand, {
|
||||
stdio: 'inherit',
|
||||
|
||||
Reference in New Issue
Block a user