Skip to content

Commit 235e0f6

Browse files
authored
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
1 parent fee3c58 commit 235e0f6

11 files changed

Lines changed: 123 additions & 99 deletions

File tree

.changes/cta-pnpm-support.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"create-tauri-app": patch
3+
---
4+
5+
[`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`.

tooling/create-tauri-app/src/dependency-manager.ts

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import { ManagementType, Result } from './types/deps'
66
import { shell } from './shell'
77

8-
export type PackageManager = 'npm' | 'yarn'
8+
export type PackageManager = 'npm' | 'yarn' | 'pnpm'
99

1010
export async function install({
1111
appDir,
@@ -50,16 +50,18 @@ async function installNpmPackage(
5050
packageManager: PackageManager,
5151
appDir: string
5252
): Promise<void> {
53-
if (packageNames.length === 0) return
54-
console.log(`Installing ${packageNames.join(', ')}...`)
55-
if (packageManager === 'yarn') {
56-
await shell('yarn', ['add', packageNames.join(' ')], {
57-
cwd: appDir
58-
})
59-
} else {
60-
await shell('npm', ['install', packageNames.join(' ')], {
61-
cwd: appDir
62-
})
53+
const packages = packageNames.filter((p) => p !== '')
54+
if (packages.length !== 0) {
55+
console.log(`- Installing ${packages.join(', ')}...`)
56+
if (packageManager === 'npm') {
57+
await shell('npm', ['install', packageNames.join(' ')], {
58+
cwd: appDir
59+
})
60+
} else {
61+
await shell(packageManager, ['add', packageNames.join(' ')], {
62+
cwd: appDir
63+
})
64+
}
6365
}
6466
}
6567

@@ -68,23 +70,25 @@ async function installNpmDevPackage(
6870
packageManager: PackageManager,
6971
appDir: string
7072
): Promise<void> {
71-
if (packageNames.length === 0) return
72-
console.log(`Installing ${packageNames.join(', ')}...`)
73-
if (packageManager === 'yarn') {
74-
await shell(
75-
'yarn',
76-
['add', '--dev', '--ignore-scripts', packageNames.join(' ')],
77-
{
78-
cwd: appDir
79-
}
80-
)
81-
} else {
82-
await shell(
83-
'npm',
84-
['install', '--save-dev', '--ignore-scripts', packageNames.join(' ')],
85-
{
86-
cwd: appDir
87-
}
88-
)
73+
const packages = packageNames.filter((p) => p !== '')
74+
if (packages.length !== 0) {
75+
console.log(`- Installing ${packages.join(', ')}...`)
76+
if (packageManager === 'npm') {
77+
await shell(
78+
'npm',
79+
['install', '--save-dev', '--ignore-scripts', packageNames.join(' ')],
80+
{
81+
cwd: appDir
82+
}
83+
)
84+
} else {
85+
await shell(
86+
packageManager,
87+
['add', '-D', '--ignore-scripts', packageNames.join(' ')],
88+
{
89+
cwd: appDir
90+
}
91+
)
92+
}
8993
}
9094
}

tooling/create-tauri-app/src/index.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ const printUsage = (): void => {
6363
--ci Skip prompts
6464
--force, -f Force init to overwrite [conf|template|all]
6565
--log, -l Logging [boolean]
66-
--manager, -d Set package manager to use [npm|yarn]
66+
--manager, -m Set package manager to use [npm|yarn|pnpm]
6767
--directory, -d Set target directory for init
6868
--app-name, -A Name of your Tauri application
6969
--window-title, -W Window title of your Tauri application
@@ -255,12 +255,15 @@ const runInit = async (argv: Argv): Promise<void> => {
255255
}
256256

257257
const packageManager =
258-
argv.m === 'yarn' || argv.m === 'npm'
258+
argv.m === 'yarn' || argv.m === 'npm' || argv.m === 'pnpm'
259259
? argv.m
260260
: // @ts-expect-error
261261
// this little fun snippet pulled from vite determines the package manager the script was run from
262262
/yarn/.test(process?.env?.npm_execpath)
263263
? 'yarn'
264+
: // @ts-expect-error
265+
/pnpm/.test(process?.env?.npm_execpath)
266+
? 'pnpm'
264267
: 'npm'
265268

266269
const buildConfig = {
@@ -367,10 +370,13 @@ const runInit = async (argv: Argv): Promise<void> => {
367370

368371
logStep(`Running: ${reset(yellow('tauri init'))}`)
369372
const binary = !argv.b ? packageManager : resolve(appDirectory, argv.b)
373+
// pnpm is equivalent to yarn and can run srcipts without using "run" but due to this bug https://github.com/pnpm/pnpm/issues/2764
374+
// 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/
370375
const runTauriArgs =
371-
packageManager === 'npm' && !argv.b
372-
? ['run', 'tauri', '--', 'init']
373-
: ['tauri', 'init']
376+
packageManager === 'yarn' || argv.b
377+
? ['tauri', 'init']
378+
: ['run', 'tauri', '--', 'init']
379+
374380
await shell(binary, [...runTauriArgs, ...initArgs, '--ci'], {
375381
cwd: appDirectory
376382
})

tooling/create-tauri-app/src/recipes/dominator.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ export const dominator: Recipe = {
1717
...cfg,
1818
distDir: `../dist`,
1919
devPath: 'http://localhost:10001/',
20-
beforeDevCommand: `${packageManager === 'yarn' ? 'yarn' : 'npm run'} start`,
20+
beforeDevCommand: `${
21+
packageManager === 'npm' ? 'npm run' : packageManager
22+
} start`,
2123
beforeBuildCommand: `${
22-
packageManager === 'yarn' ? 'yarn' : 'npm run'
24+
packageManager === 'npm' ? 'npm run' : packageManager
2325
} build`
2426
}),
2527
extraNpmDevDependencies: [],
@@ -46,12 +48,11 @@ export const dominator: Recipe = {
4648
console.log(`
4749
Your installation completed.
4850
49-
$ cd ${cfg.appName}.
51+
$ cd ${cfg.appName}
5052
$ ${packageManager} install
51-
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri ${
53+
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri ${
5254
packageManager === 'npm' ? '--' : ''
53-
} dev
54-
55+
}dev
5556
`)
5657
return await Promise.resolve()
5758
}

tooling/create-tauri-app/src/recipes/ng-cli.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { PackageManager } from '../dependency-manager'
22
import { shell } from '../shell'
33
import { Recipe } from '../types/recipe'
4+
import { join } from 'path'
45

56
const addAdditionalPackage = async (
67
packageManager: PackageManager,
@@ -10,13 +11,13 @@ const addAdditionalPackage = async (
1011
): Promise<void> => {
1112
const ngCommand = ['ng', 'add', packageName, '--skip-confirmation']
1213

13-
if (packageManager === 'yarn') {
14-
await shell('yarn', ngCommand, {
15-
cwd: `${cwd}/${appName}`
14+
if (packageManager === 'npm') {
15+
await shell('npm', ['run', ...ngCommand], {
16+
cwd: join(cwd, appName)
1617
})
1718
} else {
18-
await shell('npm', ['run', ...ngCommand], {
19-
cwd: `${cwd}/${appName}`
19+
await shell(packageManager, ngCommand, {
20+
cwd: join(cwd, appName)
2021
})
2122
}
2223
}
@@ -33,9 +34,11 @@ const ngcli: Recipe = {
3334
...cfg,
3435
distDir: `../dist/${cfg.appName}`,
3536
devPath: 'http://localhost:4200',
36-
beforeDevCommand: `${packageManager === 'yarn' ? 'yarn' : 'npm run'} start`,
37+
beforeDevCommand: `${
38+
packageManager === 'npm' ? 'npm run' : packageManager
39+
} start`,
3740
beforeBuildCommand: `${
38-
packageManager === 'yarn' ? 'yarn' : 'npm run'
41+
packageManager === 'npm' ? 'npm run' : packageManager
3942
} build`
4043
}),
4144
extraQuestions: ({ ci }) => {
@@ -94,12 +97,12 @@ const ngcli: Recipe = {
9497
},
9598
postInit: async ({ packageManager, cfg }) => {
9699
console.log(`
97-
Your installation completed.
100+
Your installation completed.
98101
99-
$ cd ${cfg.appName}
100-
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri ${
102+
$ cd ${cfg.appName}
103+
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri ${
101104
packageManager === 'npm' ? '--' : ''
102-
} dev
105+
}dev
103106
`)
104107

105108
return await Promise.resolve()

tooling/create-tauri-app/src/recipes/react.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { join } from 'path'
77
import scaffe from 'scaffe'
88
import { shell } from '../shell'
99
import { Recipe } from '../types/recipe'
10+
import { rmSync, existsSync } from 'fs'
1011

1112
const afterCra = async (
1213
cwd: string,
@@ -38,9 +39,11 @@ export const cra: Recipe = {
3839
...cfg,
3940
distDir: `../build`,
4041
devPath: 'http://localhost:3000',
41-
beforeDevCommand: `${packageManager === 'yarn' ? 'yarn' : 'npm run'} start`,
42+
beforeDevCommand: `${
43+
packageManager === 'npm' ? 'npm run' : packageManager
44+
} start`,
4245
beforeBuildCommand: `${
43-
packageManager === 'yarn' ? 'yarn' : 'npm run'
46+
packageManager === 'npm' ? 'npm run' : packageManager
4447
} build`
4548
}),
4649
extraNpmDevDependencies: [],
@@ -50,7 +53,7 @@ export const cra: Recipe = {
5053
{
5154
type: 'list',
5255
name: 'template',
53-
message: 'Which vite template would you like to use?',
56+
message: 'Which create-react-app template would you like to use?',
5457
choices: [
5558
{ name: 'create-react-app (JavaScript)', value: 'cra.js' },
5659
{ name: 'create-react-app (Typescript)', value: 'cra.ts' }
@@ -94,17 +97,33 @@ export const cra: Recipe = {
9497
}
9598
)
9699
}
100+
101+
// create-react-app doesn't support pnpm, so we remove `node_modules` and any lock files then install them again using pnpm
102+
if (packageManager === 'pnpm') {
103+
const npmLock = join(cwd, cfg.appName, 'package-lock.json')
104+
const yarnLock = join(cwd, cfg.appName, 'yarn.lock')
105+
const nodeModules = join(cwd, cfg.appName, 'node_modules')
106+
if (existsSync(npmLock)) rmSync(npmLock)
107+
if (existsSync(yarnLock)) rmSync(yarnLock)
108+
if (existsSync(nodeModules))
109+
rmSync(nodeModules, {
110+
recursive: true,
111+
force: true
112+
})
113+
await shell('pnpm', ['install'], { cwd })
114+
}
115+
97116
await afterCra(cwd, cfg.appName, template === 'cra.ts')
98117
},
99118
postInit: async ({ packageManager, cfg }) => {
100119
console.log(`
101120
Your installation completed.
102121
103122
$ cd ${cfg.appName}
104-
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri ${
123+
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri ${
105124
packageManager === 'npm' ? '--' : ''
106-
} dev
107-
`)
125+
}dev
126+
`)
108127
return await Promise.resolve()
109128
}
110129
}

tooling/create-tauri-app/src/recipes/svelte.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@ const svelte: Recipe = {
3030
...cfg,
3131
distDir: `../public`,
3232
devPath: 'http://localhost:5000',
33-
beforeDevCommand: `${packageManager === 'yarn' ? 'yarn' : 'npm run'} dev`,
33+
beforeDevCommand: `${
34+
packageManager === 'yarn' ? 'npm run' : packageManager
35+
} dev`,
3436
beforeBuildCommand: `${
35-
packageManager === 'yarn' ? 'yarn' : 'npm run'
37+
packageManager === 'yarn' ? 'npm run' : packageManager
3638
} build`
3739
}),
3840
preInit: async ({ cwd, cfg, answers }) => {
@@ -56,11 +58,11 @@ const svelte: Recipe = {
5658
console.log(`
5759
Your installation completed.
5860
59-
$ cd ${cfg.appName}.
60-
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri ${
61+
$ cd ${cfg.appName}
62+
$ ${packageManager} install
63+
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri ${
6164
packageManager === 'npm' ? '--' : ''
62-
} dev
63-
65+
}dev
6466
`)
6567

6668
return await Promise.resolve()

tooling/create-tauri-app/src/recipes/vanilla.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ export const vanillajs: Recipe = {
4343
console.log(`
4444
Your installation completed.
4545
46-
$ cd ${cfg.appName}
47-
$ ${packageManager} install
48-
$ ${packageManager === 'yarn' ? 'yarn' : 'npm run'} tauri ${
49-
packageManager === 'npm' ? '-- ' : ''
46+
$ cd ${cfg.appName}
47+
$ ${packageManager} install
48+
$ ${packageManager === 'npm' ? 'npm run' : packageManager} tauri ${
49+
packageManager === 'npm' ? '--' : ''
5050
}dev
51-
`)
51+
`)
5252
return await Promise.resolve()
5353
}
5454
}

0 commit comments

Comments
 (0)