Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
> vp create vite:application --no-interactive # verify next command suggests vp dev

Using default package name: vite-plus-application
◇ Scaffolded vite-plus-application with Vite application
• Node <semver> pnpm <semver>
→ Next: cd vite-plus-application && vp dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"commands": [
{
"command": "vp create vite:application --no-interactive # verify next command suggests vp dev",
"ignoreOutput": false
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
> vp create vite:library --no-interactive # verify next command suggests vp run dev

Using default package name: vite-plus-library
◇ Scaffolded vite-plus-library with TypeScript library
• Node <semver> pnpm <semver>
→ Next: cd vite-plus-library && vp run dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"commands": [
{
"command": "vp create vite:library --no-interactive # verify next command suggests vp run dev",
"ignoreOutput": false
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "existing-app"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "test-monorepo",
"workspaces": [
"apps/*"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
> vp create vite:application --no-interactive # monorepo: next command should suggest vp dev <dir>

Using default package name: vite-plus-application
◇ Scaffolded apps/vite-plus-application with Vite application
• Node <semver> pnpm <semver>
→ Next: vp dev apps/vite-plus-application
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"commands": [
{
"command": "vp create vite:application --no-interactive # monorepo: next command should suggest vp dev <dir>",
"ignoreOutput": false
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "test-monorepo",
"workspaces": [
"packages/*"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "existing-lib"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
> vp create vite:library --no-interactive # monorepo: next command should suggest cd <dir> && vp run dev

Using default package name: vite-plus-library
◇ Scaffolded packages/vite-plus-library with TypeScript library
• Node <semver> pnpm <semver>
→ Next: cd packages/vite-plus-library && vp run dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"commands": [
{
"command": "vp create vite:library --no-interactive # monorepo: next command should suggest cd <dir> && vp run dev",
"ignoreOutput": false
}
]
}
63 changes: 63 additions & 0 deletions packages/cli/src/create/__tests__/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { describe, expect, it } from 'vitest';
import {
deriveDefaultPackageName,
formatTargetDir,
getCreateNextCommand,
getNextCommand,
getProjectDirFromPackageName,
} from '../utils.js';

Expand Down Expand Up @@ -63,6 +65,67 @@ describe('formatTargetDir', () => {
});
});

describe('getNextCommand', () => {
it('should prepend cd when projectDir is a named directory', () => {
expect(getNextCommand('my-app', 'vp dev')).toBe('cd my-app && vp dev');
expect(getNextCommand('my-app', 'vp run dev')).toBe('cd my-app && vp run dev');
});

it('should return command only when projectDir is "."', () => {
expect(getNextCommand('.', 'vp dev')).toBe('vp dev');
});

it('should return command only when projectDir is empty', () => {
expect(getNextCommand('', 'vp dev')).toBe('vp dev');
});
});

describe('getCreateNextCommand', () => {
// standalone
it('should suggest vp dev for builtin application (standalone)', () => {
expect(getCreateNextCommand('my-app', 'vite:application', false)).toBe('cd my-app && vp dev');
});

it('should suggest vp run dev for builtin library (standalone)', () => {
expect(getCreateNextCommand('my-app', 'vite:library', false)).toBe('cd my-app && vp run dev');
});

it('should suggest vp run dev for remote template (standalone)', () => {
expect(getCreateNextCommand('my-astro', 'astro', false)).toBe('cd my-astro && vp run dev');
});

it('should suggest vp run dev for bingo template (standalone)', () => {
expect(getCreateNextCommand('my-app', 'my-bingo-template', false)).toBe(
'cd my-app && vp run dev',
);
});

// monorepo
it('should suggest vp dev <dir> for builtin application (monorepo)', () => {
expect(getCreateNextCommand('packages/my-app', 'vite:application', true)).toBe(
'vp dev packages/my-app',
);
});

it('should suggest cd + vp run dev for builtin library (monorepo)', () => {
expect(getCreateNextCommand('packages/my-lib', 'vite:library', true)).toBe(
'cd packages/my-lib && vp run dev',
);
});

it('should suggest cd + vp run dev for remote template (monorepo)', () => {
expect(getCreateNextCommand('packages/my-nuxt', 'nuxt', true)).toBe(
'cd packages/my-nuxt && vp run dev',
);
});

// projectDir edge cases
it('should omit cd when projectDir is "." (standalone)', () => {
expect(getCreateNextCommand('.', 'vite:application', false)).toBe('vp dev');
expect(getCreateNextCommand('.', 'astro', false)).toBe('vp run dev');
});
});

describe('deriveDefaultPackageName', () => {
it('should derive package name from directory basename', () => {
expect(deriveDefaultPackageName('/home/user/my-app', undefined, 'fallback')).toBe('my-app');
Expand Down
21 changes: 7 additions & 14 deletions packages/cli/src/create/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ import {
} from './templates/index.js';
import { InitialMonorepoAppDir } from './templates/monorepo.js';
import { BuiltinTemplate, TemplateType } from './templates/types.js';
import { deriveDefaultPackageName, formatTargetDir } from './utils.js';
import {
deriveDefaultPackageName,
formatTargetDir,
getCreateNextCommand,
getNextCommand,
} from './utils.js';

const helpMessage = renderCliDoc({
usage: 'vp create [TEMPLATE] [OPTIONS] [-- TEMPLATE_OPTIONS]',
Expand Down Expand Up @@ -307,13 +312,6 @@ function formatDuration(durationMs: number) {
return `${Math.round(durationSeconds)}s`;
}

function getNextCommand(projectDir: string, command: string) {
if (!projectDir || projectDir === '.') {
return command;
}
return `cd ${projectDir} && ${command}`;
}

function showCreateSummary(options: {
description?: string;
installSummary?: CommandRunSummary;
Expand Down Expand Up @@ -963,12 +961,7 @@ Use \`vp create --list\` to list all available templates, or run \`vp create --h
showCreateSummary({
description: describeScaffold(selectedTemplateName, selectedTemplateArgs),
installSummary,
nextCommand: isMonorepo
? `vp dev ${projectDir}`
: getNextCommand(
projectDir,
selectedTemplateName === BuiltinTemplate.library ? 'vp run dev' : 'vp dev',
),
nextCommand: getCreateNextCommand(projectDir, selectedTemplateName, isMonorepo),
packageManager: workspaceInfo.packageManager,
packageManagerVersion: workspaceInfo.downloadPackageManager.version,
projectDir,
Expand Down
29 changes: 29 additions & 0 deletions packages/cli/src/create/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import validateNpmPackageName from 'validate-npm-package-name';

import { editJsonFile } from '../utils/json.js';
import { getRandomProjectName } from './random-name.js';
import { BuiltinTemplate } from './templates/types.js';

// Helper functions for file operations
export function copy(src: string, dest: string) {
Expand Down Expand Up @@ -139,3 +140,31 @@ export function deriveDefaultPackageName(
? candidate
: getRandomProjectName({ scope, fallbackName });
}

export function getNextCommand(projectDir: string, command: string) {
if (!projectDir || projectDir === '.') {
return command;
}
return `cd ${projectDir} && ${command}`;
}

/**
* Determine the "Next:" command to show after `vp create`.
*
* - Builtin templates (except `vite:library`) use Vite's dev server directly → `vp dev`
* - Non-builtin templates (Astro, Nuxt, etc.) and `vite:library` run the
* package.json `dev` script → `vp run dev`
*/
export function getCreateNextCommand(
projectDir: string,
selectedTemplateName: string,
isMonorepo: boolean,
): string {
const isBuiltinTemplate = selectedTemplateName.startsWith('vite:');
const hasBuiltinDevServer = isBuiltinTemplate && selectedTemplateName !== BuiltinTemplate.library;

if (isMonorepo) {
Comment thread
fengmk2 marked this conversation as resolved.
Outdated
return hasBuiltinDevServer ? `vp dev ${projectDir}` : getNextCommand(projectDir, 'vp run dev');
}
return getNextCommand(projectDir, hasBuiltinDevServer ? 'vp dev' : 'vp run dev');
}
Loading