Skip to content

Commit 6e0598c

Browse files
committed
feat: derive package manager from env var
1 parent 22d1803 commit 6e0598c

6 files changed

Lines changed: 135 additions & 82 deletions

File tree

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+
Use a test based on an npm env var to determine which package manager to use.

tooling/create-tauri-app/bin/create-tauri-app.js

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ const {
1212
recipeByDescriptiveName,
1313
recipeByShortName,
1414
install,
15+
checkPackageManager,
1516
shell,
1617
} = require("../dist/");
17-
const { dir } = require("console");
1818

1919
/**
2020
* @type {object}
@@ -38,6 +38,7 @@ const createTauriApp = async (cliArgs) => {
3838
v: "version",
3939
f: "force",
4040
l: "log",
41+
m: "manager",
4142
d: "directory",
4243
b: "binary",
4344
t: "tauri-path",
@@ -81,6 +82,7 @@ function printUsage() {
8182
--ci Skip prompts
8283
--force, -f Force init to overwrite [conf|template|all]
8384
--log, -l Logging [boolean]
85+
--manager, -d Set package manager to use [npm|yarn]
8486
--directory, -d Set target directory for init
8587
--binary, -b Optional path to a tauri binary from which to run init
8688
--app-name, -A Name of your Tauri application
@@ -142,6 +144,8 @@ async function runInit(argv, config = {}) {
142144
window: { title },
143145
},
144146
} = config;
147+
// this little fun snippet pulled from vite determines the package manager the script was run from
148+
const packageManager = /yarn/.test(process.env.npm_execpath) ? "yarn" : "npm";
145149

146150
let recipe;
147151

@@ -157,7 +161,7 @@ async function runInit(argv, config = {}) {
157161
};
158162

159163
if (recipe !== undefined) {
160-
buildConfig = recipe.configUpdate(buildConfig);
164+
buildConfig = recipe.configUpdate({ buildConfig, packageManager });
161165
}
162166

163167
const directory = argv.d || process.cwd();
@@ -166,14 +170,18 @@ async function runInit(argv, config = {}) {
166170
appName: appName || argv.A,
167171
windowTitle: title || argv.w,
168172
};
173+
169174
// note that our app directory is reliant on the appName and
170175
// generally there are issues if the path has spaces (see Windows)
171176
// future TODO prevent app names with spaces or escape here?
172177
const appDirectory = join(directory, cfg.appName);
173178

179+
// this throws an error if we can't run the package manager they requested
180+
await checkPackageManager({ cwd: directory, packageManager });
181+
174182
if (recipe.preInit) {
175183
console.log("===== running initial command(s) =====");
176-
await recipe.preInit({ cwd: directory, cfg });
184+
await recipe.preInit({ cwd: directory, cfg, packageManager });
177185
}
178186

179187
const initArgs = [
@@ -183,24 +191,24 @@ async function runInit(argv, config = {}) {
183191
["--dev-path", cfg.devPath],
184192
].reduce((final, argSet) => {
185193
if (argSet[1]) {
186-
return final.concat([argSet[0], `\"${argSet[1]}\"`]);
194+
return final.concat(argSet);
187195
} else {
188196
return final;
189197
}
190198
}, []);
191199

192-
const installed = await install({
200+
console.log("===== installing any additional needed deps =====");
201+
await install({
193202
appDir: appDirectory,
194203
dependencies: recipe.extraNpmDependencies,
195-
devDependencies: ["tauri", ...recipe.extraNpmDevDependencies],
204+
devDependencies: ["@tauri-apps/cli", ...recipe.extraNpmDevDependencies],
205+
packageManager,
196206
});
197207

198208
console.log("===== running tauri init =====");
199-
const binary = !argv.b
200-
? installed.packageManager
201-
: resolve(appDirectory, argv.b);
209+
const binary = !argv.b ? packageManager : resolve(appDirectory, argv.b);
202210
const runTauriArgs =
203-
installed.packageManager === "npm" && !argv.b
211+
packageManager === "npm" && !argv.b
204212
? ["run", "tauri", "--", "init"]
205213
: ["tauri", "init"];
206214
await shell(binary, [...runTauriArgs, ...initArgs], {
@@ -212,6 +220,7 @@ async function runInit(argv, config = {}) {
212220
await recipe.postInit({
213221
cwd: appDirectory,
214222
cfg,
223+
packageManager,
215224
});
216225
}
217226
}

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

Lines changed: 29 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,68 +4,54 @@
44

55
import { ManagementType, Result } from "./types/deps";
66
import { shell } from "./shell";
7-
import { existsSync } from "fs";
8-
import { join } from "path";
7+
8+
export type PackageManager = "npm" | "yarn";
99

1010
export async function install({
1111
appDir,
1212
dependencies,
1313
devDependencies,
14+
packageManager,
1415
}: {
1516
appDir: string;
1617
dependencies: string[];
17-
devDependencies?: string[];
18-
}) {
19-
return await manageDependencies(appDir, dependencies, devDependencies);
20-
}
21-
22-
async function manageDependencies(
23-
appDir: string,
24-
dependencies: string[] = [],
25-
devDependencies: string[] = []
26-
): Promise<{ result: Result; packageManager: string }> {
27-
const installedDeps = [...dependencies, ...devDependencies];
28-
console.log(`Installing ${installedDeps.join(", ")}...`);
29-
30-
const packageManager = await usePackageManager(appDir);
31-
18+
devDependencies: string[];
19+
packageManager: PackageManager;
20+
}): Promise<Result> {
21+
const result: Result = new Map<ManagementType, string[]>();
3222
await installNpmDevPackage(devDependencies, packageManager, appDir);
33-
await installNpmPackage(dependencies, packageManager, appDir);
23+
result.set(ManagementType.Install, devDependencies);
3424

35-
const result: Result = new Map<ManagementType, string[]>();
36-
result.set(ManagementType.Install, installedDeps);
25+
await installNpmPackage(dependencies, packageManager, appDir);
26+
result.set(ManagementType.Install, dependencies);
3727

38-
return { result, packageManager };
28+
return result;
3929
}
4030

41-
async function usePackageManager(appDir: string): Promise<"yarn" | "npm"> {
42-
const hasYarnLockfile = existsSync(join(appDir, "yarn.lock"));
43-
let yarnChild;
44-
// try yarn first if there is a lockfile
45-
if (hasYarnLockfile) {
46-
yarnChild = await shell("yarn", ["--version"], { stdio: "pipe" });
47-
if (!yarnChild.failed) return "yarn";
31+
export async function checkPackageManager({
32+
cwd,
33+
packageManager,
34+
}: {
35+
cwd: string;
36+
packageManager: PackageManager;
37+
}): Promise<boolean> {
38+
try {
39+
await shell(packageManager, ["--version"], { stdio: "pipe", cwd });
40+
return true;
41+
} catch (error) {
42+
throw new Error(
43+
`Must have ${packageManager} installed to manage dependencies. Is either in your PATH? We tried running in ${cwd}`
44+
);
4845
}
49-
50-
// try npm then as the "default"
51-
const npmChild = await shell("npm", ["--version"], { stdio: "pipe" });
52-
if (!npmChild.failed) return "npm";
53-
54-
// try yarn as maybe only yarn is installed
55-
if (yarnChild && !yarnChild.failed) return "yarn";
56-
57-
// if we have reached here, we can't seem to run anything
58-
throw new Error(
59-
`Must have npm or yarn installed to manage dependencies. Is either in your PATH? We tried running in ${appDir}`
60-
);
6146
}
6247

6348
async function installNpmPackage(
6449
packageNames: string[],
65-
packageManager: string,
50+
packageManager: PackageManager,
6651
appDir: string
6752
): Promise<void> {
6853
if (packageNames.length === 0) return;
54+
console.log(`Installing ${packageNames.join(", ")}...`);
6955
if (packageManager === "yarn") {
7056
await shell("yarn", ["add", packageNames.join(" ")], {
7157
cwd: appDir,
@@ -79,10 +65,11 @@ async function installNpmPackage(
7965

8066
async function installNpmDevPackage(
8167
packageNames: string[],
82-
packageManager: string,
68+
packageManager: PackageManager,
8369
appDir: string
8470
): Promise<void> {
8571
if (packageNames.length === 0) return;
72+
console.log(`Installing ${packageNames.join(", ")}...`);
8673
if (packageManager === "yarn") {
8774
await shell(
8875
"yarn",

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,38 @@ import { reactjs, reactts } from "./recipes/react";
88
import { vanillajs } from "./recipes/vanilla";
99

1010
export { shell } from "./shell";
11-
export { install } from "./dependency-manager";
11+
export { install, checkPackageManager } from "./dependency-manager";
12+
import { PackageManager } from "./dependency-manager";
1213

1314
export interface Recipe {
1415
descriptiveName: string;
1516
shortName: string;
16-
configUpdate?: (cfg: TauriBuildConfig) => TauriBuildConfig;
17+
configUpdate?: ({
18+
cfg,
19+
packageManager,
20+
}: {
21+
cfg: TauriBuildConfig;
22+
packageManager: PackageManager;
23+
}) => TauriBuildConfig;
1724
extraNpmDependencies: string[];
1825
extraNpmDevDependencies: string[];
1926
preInit?: ({
2027
cwd,
2128
cfg,
29+
packageManager,
2230
}: {
2331
cwd: string;
2432
cfg: TauriBuildConfig;
33+
packageManager: PackageManager;
2534
}) => Promise<void>;
2635
postInit?: ({
2736
cwd,
2837
cfg,
38+
packageManager,
2939
}: {
3040
cwd: string;
3141
cfg: TauriBuildConfig;
42+
packageManager: PackageManager;
3243
}) => Promise<void>;
3344
}
3445

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

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,6 @@ import { join } from "path";
44
import scaffe from "scaffe";
55
import { shell } from "../shell";
66

7-
const completeLogMsg = `
8-
Your installation completed.
9-
To start, run yarn tauri dev
10-
`;
11-
127
const afterCra = async (cwd: string, appName: string, version: string) => {
138
const templateDir = join(__dirname, "../src/templates/react");
149
const variables = {
@@ -29,7 +24,7 @@ const afterCra = async (cwd: string, appName: string, version: string) => {
2924
const reactjs: Recipe = {
3025
descriptiveName: "React.js",
3126
shortName: "reactjs",
32-
configUpdate: (cfg) => ({
27+
configUpdate: ({ cfg }) => ({
3328
...cfg,
3429
distDir: `../build`,
3530
devPath: "http://localhost:3000",
@@ -38,17 +33,32 @@ const reactjs: Recipe = {
3833
}),
3934
extraNpmDevDependencies: [],
4035
extraNpmDependencies: [],
41-
preInit: async ({ cwd, cfg }) => {
36+
preInit: async ({ cwd, cfg, packageManager }) => {
4237
// CRA creates the folder for you
43-
await shell("npx", ["create-react-app", `${cfg.appName}`], { cwd });
38+
if (packageManager === "yarn") {
39+
await shell("yarn", ["create", "react-app", `${cfg.appName}`], {
40+
cwd,
41+
});
42+
} else {
43+
await shell(
44+
"npm",
45+
["init", "react-app", `${cfg.appName}`, "--", "--use-npm"],
46+
{
47+
cwd,
48+
}
49+
);
50+
}
4451
const version = await shell("npm", ["view", "tauri", "version"], {
4552
stdio: "pipe",
4653
});
4754
const versionNumber = version.stdout.trim();
4855
await afterCra(cwd, cfg.appName, versionNumber);
4956
},
50-
postInit: async ({ cfg }) => {
51-
console.log(completeLogMsg);
57+
postInit: async ({ packageManager }) => {
58+
console.log(`
59+
Your installation completed.
60+
To start, run ${packageManager} tauri dev
61+
`);
5262
},
5363
};
5464

@@ -57,16 +67,39 @@ const reactts: Recipe = {
5767
descriptiveName: "React with Typescript",
5868
shortName: "reactts",
5969
extraNpmDependencies: [],
60-
preInit: async ({ cwd, cfg }) => {
70+
preInit: async ({ cwd, cfg, packageManager }) => {
6171
// CRA creates the folder for you
62-
await shell(
63-
"npx",
64-
["create-react-app", "--template", "typescript", `${cfg.appName}`],
65-
{ cwd }
66-
);
72+
if (packageManager === "yarn") {
73+
await shell(
74+
"yarn",
75+
["create", "react-app", "--template", "typescript", `${cfg.appName}`],
76+
{
77+
cwd,
78+
}
79+
);
80+
} else {
81+
await shell(
82+
"npm",
83+
[
84+
"init",
85+
"react-app",
86+
`${cfg.appName}`,
87+
"--",
88+
"--use-npm",
89+
"--template",
90+
"typescript",
91+
],
92+
{
93+
cwd,
94+
}
95+
);
96+
}
6797
},
68-
postInit: async ({ cfg }) => {
69-
console.log(completeLogMsg);
98+
postInit: async ({ packageManager }) => {
99+
console.log(`
100+
Your installation completed.
101+
To start, run ${packageManager} tauri dev
102+
`);
70103
},
71104
};
72105

0 commit comments

Comments
 (0)