Skip to content

Commit c36a6a4

Browse files
feat: adds --install <package-manager> flag to create and add (#531)
* adds `--install <pm>` flag * changeset * fix check * docs * forgot the arg * fix docs --------- Co-authored-by: Manuel Serret <[email protected]>
1 parent f11bae5 commit c36a6a4

File tree

9 files changed

+52
-22
lines changed

9 files changed

+52
-22
lines changed

.changeset/happy-moles-glow.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'sv': patch
3+
---
4+
5+
feat: adds `--install <package-manager>` flag to `create` and `add`

community-addon-template/tests/setup/suite.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { execSync } from 'node:child_process';
44
import * as vitest from 'vitest';
55
import { installAddon, type AddonMap, type OptionMap } from 'sv';
66
import {
7-
addPnpmBuildDependendencies,
7+
addPnpmBuildDependencies,
88
createProject,
99
startPreview,
1010
type CreateProject,
@@ -78,7 +78,7 @@ export function setupTest<Addons extends AddonMap>(addons: Addons) {
7878
options,
7979
packageManager: 'pnpm'
8080
});
81-
addPnpmBuildDependendencies(cwd, 'pnpm', ['esbuild', ...pnpmBuildDependencies]);
81+
addPnpmBuildDependencies(cwd, 'pnpm', ['esbuild', ...pnpmBuildDependencies]);
8282

8383
return cwd;
8484
};

documentation/docs/20-commands/10-sv-create.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,19 @@ Prevent typechecking from being added. Not recommended!
3535

3636
Run the command without the interactive add-ons prompt
3737

38+
### `--install <package-manager>`
39+
40+
Installs dependencies with a specified package manager:
41+
42+
- `npm`
43+
- `pnpm`
44+
- `yarn`
45+
- `bun`
46+
- `deno`
47+
3848
### `--no-install`
3949

40-
Skip dependency installation
50+
Prevents installing dependencies.
4151

4252
<!-- ## Programmatic interface
4353

documentation/docs/20-commands/20-sv-add.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ You can select multiple space-separated add-ons from [the list below](#Official-
2020

2121
- `-C`, `--cwd` — path to the root of your Svelte(Kit) project
2222
- `--no-preconditions` — skip checking preconditions <!-- TODO what does this mean? -->
23-
- `--no-install` — skip dependency installation
23+
- `--install` — installs dependencies with a specified package manager
24+
- `--no-install` — prevents installing dependencies
2425

2526
## Official add-ons
2627

packages/addons/_tests/_setup/suite.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { installAddon, type AddonMap, type OptionMap } from 'sv';
66
import {
77
createProject,
88
startPreview,
9-
addPnpmBuildDependendencies,
9+
addPnpmBuildDependencies,
1010
type CreateProject,
1111
type ProjectVariant
1212
} from 'sv/testing';
@@ -75,7 +75,7 @@ export function setupTest<Addons extends AddonMap>(addons: Addons) {
7575
options,
7676
packageManager: 'pnpm'
7777
});
78-
addPnpmBuildDependendencies(cwd, 'pnpm', ['esbuild', ...pnpmBuildDependencies]);
78+
addPnpmBuildDependencies(cwd, 'pnpm', ['esbuild', ...pnpmBuildDependencies]);
7979

8080
return cwd;
8181
};

packages/cli/commands/add/index.ts

+9-5
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ import { createWorkspace } from './workspace.ts';
1919
import { formatFiles, getHighlighter } from './utils.ts';
2020
import { Directive, downloadPackage, getPackageJSON } from './fetch-packages.ts';
2121
import {
22-
addPnpmBuildDependendencies,
22+
addPnpmBuildDependencies,
23+
AGENT_NAMES,
2324
installDependencies,
25+
installOption,
2426
packageManagerPrompt
2527
} from '../../utils/package-manager.ts';
2628
import { getGlobalPreconditions } from './preconditions.ts';
@@ -41,7 +43,7 @@ const AddonsSchema = v.array(v.string());
4143
const AddonOptionFlagsSchema = v.object(addonOptionFlags);
4244
const OptionsSchema = v.strictObject({
4345
cwd: v.string(),
44-
install: v.boolean(),
46+
install: v.union([v.boolean(), v.picklist(AGENT_NAMES)]),
4547
preconditions: v.boolean(),
4648
community: v.optional(v.union([AddonsSchema, v.boolean()])),
4749
...AddonOptionFlagsSchema.entries
@@ -56,8 +58,9 @@ export const add = new Command('add')
5658
.description('applies specified add-ons into a project')
5759
.argument('[add-on...]', 'add-ons to install')
5860
.option('-C, --cwd <path>', 'path to working directory', defaultCwd)
59-
.option('--no-install', 'skip installing dependencies')
6061
.option('--no-preconditions', 'skip validating preconditions')
62+
.option('--no-install', 'skip installing dependencies')
63+
.addOption(installOption)
6164
//.option('--community [add-on...]', 'community addons to install')
6265
.configureHelp(common.helpConfig)
6366
.action((addonArgs, opts) => {
@@ -449,12 +452,13 @@ export async function runAddCommand(
449452
// prompt for package manager and install dependencies
450453
let packageManager: PackageManager | undefined;
451454
if (options.install) {
452-
packageManager = await packageManagerPrompt(options.cwd);
455+
packageManager =
456+
options.install === true ? await packageManagerPrompt(options.cwd) : options.install;
453457

454458
if (packageManager) {
455459
workspace.packageManager = packageManager;
456460

457-
addPnpmBuildDependendencies(workspace.cwd, packageManager, [
461+
addPnpmBuildDependencies(workspace.cwd, packageManager, [
458462
'esbuild',
459463
...addonPnpmBuildDependencies
460464
]);

packages/cli/commands/create.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ import * as common from '../utils/common.ts';
1515
import { runAddCommand } from './add/index.ts';
1616
import { detect, resolveCommand, type AgentName } from 'package-manager-detector';
1717
import {
18-
addPnpmBuildDependendencies,
18+
addPnpmBuildDependencies,
19+
AGENT_NAMES,
1920
getUserAgent,
2021
installDependencies,
22+
installOption,
2123
packageManagerPrompt
2224
} from '../utils/package-manager.ts';
2325

@@ -40,7 +42,7 @@ const OptionsSchema = v.strictObject({
4042
v.transform((lang) => langMap[String(lang)])
4143
),
4244
addOns: v.boolean(),
43-
install: v.boolean(),
45+
install: v.union([v.boolean(), v.picklist(AGENT_NAMES)]),
4446
template: v.optional(v.picklist(templateChoices))
4547
});
4648
type Options = v.InferOutput<typeof OptionsSchema>;
@@ -54,6 +56,7 @@ export const create = new Command('create')
5456
.option('--no-types')
5557
.option('--no-add-ons', 'skips interactive add-on installer')
5658
.option('--no-install', 'skip installing dependencies')
59+
.addOption(installOption)
5760
.configureHelp(common.helpConfig)
5861
.action((projectPath, opts) => {
5962
const cwd = v.parse(ProjectPathSchema, projectPath);
@@ -164,9 +167,10 @@ async function createProject(cwd: ProjectPath, options: Options) {
164167

165168
let packageManager: AgentName | undefined | null;
166169
let addOnNextSteps: string | undefined;
167-
const installDeps = async () => {
168-
packageManager = await packageManagerPrompt(projectPath);
169-
addPnpmBuildDependendencies(projectPath, packageManager, ['esbuild']);
170+
171+
const installDeps = async (install: true | AgentName) => {
172+
packageManager = install === true ? await packageManagerPrompt(projectPath) : install;
173+
addPnpmBuildDependencies(projectPath, packageManager, ['esbuild']);
170174
if (packageManager) await installDependencies(packageManager, projectPath);
171175
};
172176

@@ -180,13 +184,13 @@ async function createProject(cwd: ProjectPath, options: Options) {
180184
addOnNextSteps = nextSteps;
181185
} else if (options.install) {
182186
// `--no-add-ons` was set, so we'll prompt to install deps manually
183-
await installDeps();
187+
await installDeps(options.install);
184188
}
185189

186190
// no add-ons were selected (which means the install prompt was skipped in `runAddCommand`),
187191
// so we'll prompt to install
188192
if (packageManager === null && options.install) {
189-
await installDeps();
193+
await installDeps(options.install);
190194
}
191195

192196
return { directory: projectPath, addOnNextSteps, packageManager };

packages/cli/lib/testing.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { exec } from 'tinyexec';
66
import { create } from '@sveltejs/create';
77
import pstree, { type PS } from 'ps-tree';
88

9-
export { addPnpmBuildDependendencies } from '../utils/package-manager.ts';
9+
export { addPnpmBuildDependencies } from '../utils/package-manager.ts';
1010
export type ProjectVariant = 'kit-js' | 'kit-ts' | 'vite-js' | 'vite-ts';
1111

1212
const TEMPLATES_DIR = '.templates';

packages/cli/utils/package-manager.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import path from 'node:path';
33
import process from 'node:process';
44
import * as find from 'empathic/find';
55
import { exec } from 'tinyexec';
6+
import { Option } from 'commander';
67
import * as p from '@sveltejs/clack-prompts';
78
import {
89
AGENTS,
@@ -13,10 +14,15 @@ import {
1314
} from 'package-manager-detector';
1415
import { parseJson } from '@sveltejs/cli-core/parsers';
1516

16-
const agents = AGENTS.filter((agent): agent is AgentName => !agent.includes('@'));
17-
const agentOptions: PackageManagerOptions = agents.map((pm) => ({ value: pm, label: pm }));
17+
export const AGENT_NAMES = AGENTS.filter((agent): agent is AgentName => !agent.includes('@'));
18+
const agentOptions: PackageManagerOptions = AGENT_NAMES.map((pm) => ({ value: pm, label: pm }));
1819
agentOptions.unshift({ label: 'None', value: undefined });
1920

21+
export const installOption = new Option(
22+
'--install <package-manager>',
23+
'installs dependencies with a specified package manager'
24+
).choices(AGENT_NAMES);
25+
2026
type PackageManagerOptions = Array<{ value: AgentName | undefined; label: AgentName | 'None' }>;
2127
export async function packageManagerPrompt(cwd: string): Promise<AgentName | undefined> {
2228
const detected = await detect({ cwd });
@@ -76,7 +82,7 @@ export function getUserAgent(): AgentName | undefined {
7682
return AGENTS.includes(name) ? name : undefined;
7783
}
7884

79-
export function addPnpmBuildDependendencies(
85+
export function addPnpmBuildDependencies(
8086
cwd: string,
8187
packageManager: AgentName | null | undefined,
8288
allowedPackages: string[]

0 commit comments

Comments
 (0)