mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-05 10:13:00 +02:00
feat: derive package manager from env var
This commit is contained in:
5
.changes/cta-derive-packageManager.md
Normal file
5
.changes/cta-derive-packageManager.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"create-tauri-app": patch
|
||||
---
|
||||
|
||||
Use a test based on an npm env var to determine which package manager to use.
|
||||
@@ -12,9 +12,9 @@ const {
|
||||
recipeByDescriptiveName,
|
||||
recipeByShortName,
|
||||
install,
|
||||
checkPackageManager,
|
||||
shell,
|
||||
} = require("../dist/");
|
||||
const { dir } = require("console");
|
||||
|
||||
/**
|
||||
* @type {object}
|
||||
@@ -38,6 +38,7 @@ const createTauriApp = async (cliArgs) => {
|
||||
v: "version",
|
||||
f: "force",
|
||||
l: "log",
|
||||
m: "manager",
|
||||
d: "directory",
|
||||
b: "binary",
|
||||
t: "tauri-path",
|
||||
@@ -81,6 +82,7 @@ function printUsage() {
|
||||
--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]
|
||||
--directory, -d Set target directory for init
|
||||
--binary, -b Optional path to a tauri binary from which to run init
|
||||
--app-name, -A Name of your Tauri application
|
||||
@@ -142,6 +144,8 @@ async function runInit(argv, config = {}) {
|
||||
window: { title },
|
||||
},
|
||||
} = config;
|
||||
// this little fun snippet pulled from vite determines the package manager the script was run from
|
||||
const packageManager = /yarn/.test(process.env.npm_execpath) ? "yarn" : "npm";
|
||||
|
||||
let recipe;
|
||||
|
||||
@@ -157,7 +161,7 @@ async function runInit(argv, config = {}) {
|
||||
};
|
||||
|
||||
if (recipe !== undefined) {
|
||||
buildConfig = recipe.configUpdate(buildConfig);
|
||||
buildConfig = recipe.configUpdate({ buildConfig, packageManager });
|
||||
}
|
||||
|
||||
const directory = argv.d || process.cwd();
|
||||
@@ -166,14 +170,18 @@ async function runInit(argv, config = {}) {
|
||||
appName: appName || argv.A,
|
||||
windowTitle: title || argv.w,
|
||||
};
|
||||
|
||||
// note that our app directory is reliant on the appName and
|
||||
// generally there are issues if the path has spaces (see Windows)
|
||||
// future TODO prevent app names with spaces or escape here?
|
||||
const appDirectory = join(directory, cfg.appName);
|
||||
|
||||
// this throws an error if we can't run the package manager they requested
|
||||
await checkPackageManager({ cwd: directory, packageManager });
|
||||
|
||||
if (recipe.preInit) {
|
||||
console.log("===== running initial command(s) =====");
|
||||
await recipe.preInit({ cwd: directory, cfg });
|
||||
await recipe.preInit({ cwd: directory, cfg, packageManager });
|
||||
}
|
||||
|
||||
const initArgs = [
|
||||
@@ -183,24 +191,24 @@ async function runInit(argv, config = {}) {
|
||||
["--dev-path", cfg.devPath],
|
||||
].reduce((final, argSet) => {
|
||||
if (argSet[1]) {
|
||||
return final.concat([argSet[0], `\"${argSet[1]}\"`]);
|
||||
return final.concat(argSet);
|
||||
} else {
|
||||
return final;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const installed = await install({
|
||||
console.log("===== installing any additional needed deps =====");
|
||||
await install({
|
||||
appDir: appDirectory,
|
||||
dependencies: recipe.extraNpmDependencies,
|
||||
devDependencies: ["tauri", ...recipe.extraNpmDevDependencies],
|
||||
devDependencies: ["@tauri-apps/cli", ...recipe.extraNpmDevDependencies],
|
||||
packageManager,
|
||||
});
|
||||
|
||||
console.log("===== running tauri init =====");
|
||||
const binary = !argv.b
|
||||
? installed.packageManager
|
||||
: resolve(appDirectory, argv.b);
|
||||
const binary = !argv.b ? packageManager : resolve(appDirectory, argv.b);
|
||||
const runTauriArgs =
|
||||
installed.packageManager === "npm" && !argv.b
|
||||
packageManager === "npm" && !argv.b
|
||||
? ["run", "tauri", "--", "init"]
|
||||
: ["tauri", "init"];
|
||||
await shell(binary, [...runTauriArgs, ...initArgs], {
|
||||
@@ -212,6 +220,7 @@ async function runInit(argv, config = {}) {
|
||||
await recipe.postInit({
|
||||
cwd: appDirectory,
|
||||
cfg,
|
||||
packageManager,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,68 +4,54 @@
|
||||
|
||||
import { ManagementType, Result } from "./types/deps";
|
||||
import { shell } from "./shell";
|
||||
import { existsSync } from "fs";
|
||||
import { join } from "path";
|
||||
|
||||
export type PackageManager = "npm" | "yarn";
|
||||
|
||||
export async function install({
|
||||
appDir,
|
||||
dependencies,
|
||||
devDependencies,
|
||||
packageManager,
|
||||
}: {
|
||||
appDir: string;
|
||||
dependencies: string[];
|
||||
devDependencies?: string[];
|
||||
}) {
|
||||
return await manageDependencies(appDir, dependencies, devDependencies);
|
||||
}
|
||||
|
||||
async function manageDependencies(
|
||||
appDir: string,
|
||||
dependencies: string[] = [],
|
||||
devDependencies: string[] = []
|
||||
): Promise<{ result: Result; packageManager: string }> {
|
||||
const installedDeps = [...dependencies, ...devDependencies];
|
||||
console.log(`Installing ${installedDeps.join(", ")}...`);
|
||||
|
||||
const packageManager = await usePackageManager(appDir);
|
||||
|
||||
await installNpmDevPackage(devDependencies, packageManager, appDir);
|
||||
await installNpmPackage(dependencies, packageManager, appDir);
|
||||
|
||||
devDependencies: string[];
|
||||
packageManager: PackageManager;
|
||||
}): Promise<Result> {
|
||||
const result: Result = new Map<ManagementType, string[]>();
|
||||
result.set(ManagementType.Install, installedDeps);
|
||||
await installNpmDevPackage(devDependencies, packageManager, appDir);
|
||||
result.set(ManagementType.Install, devDependencies);
|
||||
|
||||
return { result, packageManager };
|
||||
await installNpmPackage(dependencies, packageManager, appDir);
|
||||
result.set(ManagementType.Install, dependencies);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async function usePackageManager(appDir: string): Promise<"yarn" | "npm"> {
|
||||
const hasYarnLockfile = existsSync(join(appDir, "yarn.lock"));
|
||||
let yarnChild;
|
||||
// try yarn first if there is a lockfile
|
||||
if (hasYarnLockfile) {
|
||||
yarnChild = await shell("yarn", ["--version"], { stdio: "pipe" });
|
||||
if (!yarnChild.failed) return "yarn";
|
||||
export async function checkPackageManager({
|
||||
cwd,
|
||||
packageManager,
|
||||
}: {
|
||||
cwd: string;
|
||||
packageManager: PackageManager;
|
||||
}): Promise<boolean> {
|
||||
try {
|
||||
await shell(packageManager, ["--version"], { stdio: "pipe", cwd });
|
||||
return true;
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Must have ${packageManager} installed to manage dependencies. Is either in your PATH? We tried running in ${cwd}`
|
||||
);
|
||||
}
|
||||
|
||||
// try npm then as the "default"
|
||||
const npmChild = await shell("npm", ["--version"], { stdio: "pipe" });
|
||||
if (!npmChild.failed) return "npm";
|
||||
|
||||
// try yarn as maybe only yarn is installed
|
||||
if (yarnChild && !yarnChild.failed) return "yarn";
|
||||
|
||||
// if we have reached here, we can't seem to run anything
|
||||
throw new Error(
|
||||
`Must have npm or yarn installed to manage dependencies. Is either in your PATH? We tried running in ${appDir}`
|
||||
);
|
||||
}
|
||||
|
||||
async function installNpmPackage(
|
||||
packageNames: string[],
|
||||
packageManager: string,
|
||||
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,
|
||||
@@ -79,10 +65,11 @@ async function installNpmPackage(
|
||||
|
||||
async function installNpmDevPackage(
|
||||
packageNames: string[],
|
||||
packageManager: string,
|
||||
packageManager: PackageManager,
|
||||
appDir: string
|
||||
): Promise<void> {
|
||||
if (packageNames.length === 0) return;
|
||||
console.log(`Installing ${packageNames.join(", ")}...`);
|
||||
if (packageManager === "yarn") {
|
||||
await shell(
|
||||
"yarn",
|
||||
|
||||
@@ -8,27 +8,38 @@ import { reactjs, reactts } from "./recipes/react";
|
||||
import { vanillajs } from "./recipes/vanilla";
|
||||
|
||||
export { shell } from "./shell";
|
||||
export { install } from "./dependency-manager";
|
||||
export { install, checkPackageManager } from "./dependency-manager";
|
||||
import { PackageManager } from "./dependency-manager";
|
||||
|
||||
export interface Recipe {
|
||||
descriptiveName: string;
|
||||
shortName: string;
|
||||
configUpdate?: (cfg: TauriBuildConfig) => TauriBuildConfig;
|
||||
configUpdate?: ({
|
||||
cfg,
|
||||
packageManager,
|
||||
}: {
|
||||
cfg: TauriBuildConfig;
|
||||
packageManager: PackageManager;
|
||||
}) => TauriBuildConfig;
|
||||
extraNpmDependencies: string[];
|
||||
extraNpmDevDependencies: string[];
|
||||
preInit?: ({
|
||||
cwd,
|
||||
cfg,
|
||||
packageManager,
|
||||
}: {
|
||||
cwd: string;
|
||||
cfg: TauriBuildConfig;
|
||||
packageManager: PackageManager;
|
||||
}) => Promise<void>;
|
||||
postInit?: ({
|
||||
cwd,
|
||||
cfg,
|
||||
packageManager,
|
||||
}: {
|
||||
cwd: string;
|
||||
cfg: TauriBuildConfig;
|
||||
packageManager: PackageManager;
|
||||
}) => Promise<void>;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,6 @@ import { join } from "path";
|
||||
import scaffe from "scaffe";
|
||||
import { shell } from "../shell";
|
||||
|
||||
const completeLogMsg = `
|
||||
Your installation completed.
|
||||
To start, run yarn tauri dev
|
||||
`;
|
||||
|
||||
const afterCra = async (cwd: string, appName: string, version: string) => {
|
||||
const templateDir = join(__dirname, "../src/templates/react");
|
||||
const variables = {
|
||||
@@ -29,7 +24,7 @@ const afterCra = async (cwd: string, appName: string, version: string) => {
|
||||
const reactjs: Recipe = {
|
||||
descriptiveName: "React.js",
|
||||
shortName: "reactjs",
|
||||
configUpdate: (cfg) => ({
|
||||
configUpdate: ({ cfg }) => ({
|
||||
...cfg,
|
||||
distDir: `../build`,
|
||||
devPath: "http://localhost:3000",
|
||||
@@ -38,17 +33,32 @@ const reactjs: Recipe = {
|
||||
}),
|
||||
extraNpmDevDependencies: [],
|
||||
extraNpmDependencies: [],
|
||||
preInit: async ({ cwd, cfg }) => {
|
||||
preInit: async ({ cwd, cfg, packageManager }) => {
|
||||
// CRA creates the folder for you
|
||||
await shell("npx", ["create-react-app", `${cfg.appName}`], { cwd });
|
||||
if (packageManager === "yarn") {
|
||||
await shell("yarn", ["create", "react-app", `${cfg.appName}`], {
|
||||
cwd,
|
||||
});
|
||||
} else {
|
||||
await shell(
|
||||
"npm",
|
||||
["init", "react-app", `${cfg.appName}`, "--", "--use-npm"],
|
||||
{
|
||||
cwd,
|
||||
}
|
||||
);
|
||||
}
|
||||
const version = await shell("npm", ["view", "tauri", "version"], {
|
||||
stdio: "pipe",
|
||||
});
|
||||
const versionNumber = version.stdout.trim();
|
||||
await afterCra(cwd, cfg.appName, versionNumber);
|
||||
},
|
||||
postInit: async ({ cfg }) => {
|
||||
console.log(completeLogMsg);
|
||||
postInit: async ({ packageManager }) => {
|
||||
console.log(`
|
||||
Your installation completed.
|
||||
To start, run ${packageManager} tauri dev
|
||||
`);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -57,16 +67,39 @@ const reactts: Recipe = {
|
||||
descriptiveName: "React with Typescript",
|
||||
shortName: "reactts",
|
||||
extraNpmDependencies: [],
|
||||
preInit: async ({ cwd, cfg }) => {
|
||||
preInit: async ({ cwd, cfg, packageManager }) => {
|
||||
// CRA creates the folder for you
|
||||
await shell(
|
||||
"npx",
|
||||
["create-react-app", "--template", "typescript", `${cfg.appName}`],
|
||||
{ cwd }
|
||||
);
|
||||
if (packageManager === "yarn") {
|
||||
await shell(
|
||||
"yarn",
|
||||
["create", "react-app", "--template", "typescript", `${cfg.appName}`],
|
||||
{
|
||||
cwd,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
await shell(
|
||||
"npm",
|
||||
[
|
||||
"init",
|
||||
"react-app",
|
||||
`${cfg.appName}`,
|
||||
"--",
|
||||
"--use-npm",
|
||||
"--template",
|
||||
"typescript",
|
||||
],
|
||||
{
|
||||
cwd,
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
postInit: async ({ cfg }) => {
|
||||
console.log(completeLogMsg);
|
||||
postInit: async ({ packageManager }) => {
|
||||
console.log(`
|
||||
Your installation completed.
|
||||
To start, run ${packageManager} tauri dev
|
||||
`);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { shell } from "../shell";
|
||||
export const vanillajs: Recipe = {
|
||||
descriptiveName: "Vanilla.js",
|
||||
shortName: "vanillajs",
|
||||
configUpdate: (cfg) => ({
|
||||
configUpdate: ({ cfg }) => ({
|
||||
...cfg,
|
||||
distDir: `../dist`,
|
||||
devPath: `../dist`,
|
||||
@@ -24,16 +24,24 @@ export const vanillajs: Recipe = {
|
||||
const versionNumber = version.stdout.trim();
|
||||
await run(cfg, cwd, versionNumber);
|
||||
},
|
||||
postInit: async ({ cfg }) => {
|
||||
postInit: async ({ cfg, packageManager }) => {
|
||||
const setApp =
|
||||
packageManager === "npm"
|
||||
? `
|
||||
set tauri script once
|
||||
$ npm set-script tauri tauri
|
||||
`
|
||||
: "";
|
||||
|
||||
console.log(`
|
||||
change directory:
|
||||
$ cd ${cfg.appName}
|
||||
|
||||
install dependencies:
|
||||
$ yarn # npm install
|
||||
|
||||
run the app:
|
||||
$ yarn tauri dev # npm run tauri dev
|
||||
change directory:
|
||||
$ cd ${cfg.appName}
|
||||
${setApp}
|
||||
install dependencies:
|
||||
$ ${packageManager} install
|
||||
|
||||
run the app:
|
||||
$ ${packageManager} tauri ${packageManager === "npm" ? "-- " : ""}dev
|
||||
`);
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user