-
-
Notifications
You must be signed in to change notification settings - Fork 9.9k
Expand file tree
/
Copy pathPreflightCheckCommand.ts
More file actions
105 lines (88 loc) · 3.8 KB
/
PreflightCheckCommand.ts
File metadata and controls
105 lines (88 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { detectPnp } from 'storybook/internal/cli';
import {
type JsPackageManager,
JsPackageManagerFactory,
invalidateProjectRootCache,
} from 'storybook/internal/common';
import { CLI_COLORS, deprecate, logger } from 'storybook/internal/node-logger';
import dedent from 'ts-dedent';
import type { CommandOptions } from '../generators/types';
import { currentDirectoryIsEmpty, scaffoldNewProject } from '../scaffold-new-project';
import { VersionService } from '../services';
export interface PreflightCheckResult {
packageManager: JsPackageManager;
isEmptyProject: boolean;
}
/**
* Command for running preflight checks before Storybook initialization
*
* Responsibilities:
*
* - Handle empty directory detection and scaffolding
* - Initialize package manager
* - Install base dependencies if needed
*/
export class PreflightCheckCommand {
/** Execute preflight checks */
constructor(private readonly versionService = new VersionService()) {}
async execute(options: CommandOptions): Promise<PreflightCheckResult> {
const { packageManager: pkgMgr, force } = options;
const isEmptyDirProject = force !== true && currentDirectoryIsEmpty();
let packageManagerType = JsPackageManagerFactory.getPackageManagerType();
// Check if the current directory is empty
if (isEmptyDirProject) {
// Initializing Storybook in an empty directory with yarn1
// will very likely fail due to different kinds of hoisting issues
// which doesn't get fixed anymore in yarn1.
// We will fallback to npm in this case.
if (packageManagerType === 'yarn1') {
packageManagerType = 'npm';
}
// Prompt the user to create a new project from our list
logger.intro(CLI_COLORS.info(`Initializing a new project`));
await scaffoldNewProject(packageManagerType, options);
logger.outro(CLI_COLORS.info(`Project created successfully`));
invalidateProjectRootCache();
}
logger.intro(CLI_COLORS.info(`Initializing Storybook`));
const packageManager = JsPackageManagerFactory.getPackageManager({
force: pkgMgr,
});
// Install base project dependencies if we scaffolded a new project
if (isEmptyDirProject && !options.skipInstall) {
await packageManager.installDependencies();
}
const pnp = await detectPnp();
if (pnp) {
deprecate(dedent`
As of Storybook 10.0, PnP is deprecated.
If you are using PnP, you can continue to use Storybook 10.0, but we recommend migrating to a different package manager or linker-mode. In future versions, PnP compatibility will be removed.
`);
}
await this.displayVersionInfo(packageManager);
return { packageManager, isEmptyProject: isEmptyDirProject };
}
/** Display version information and warnings */
private async displayVersionInfo(packageManager: JsPackageManager): Promise<void> {
const { currentVersion, latestVersion, isPrerelease, isOutdated } =
await this.versionService.getVersionInfo(packageManager);
if (isOutdated && !isPrerelease) {
logger.warn(dedent`
This version is behind the latest release, which is: ${latestVersion}!
You likely ran the init command through npx, which can use a locally cached version.
To get the latest, please run: ${CLI_COLORS.cta('npx storybook@latest init')}
You may want to ${CLI_COLORS.cta('CTRL+C')} to stop, and run with the latest version instead.
`);
} else if (isPrerelease) {
logger.warn(`This is a pre-release version: ${currentVersion}`);
} else {
logger.info(`Adding Storybook version ${currentVersion} to your project`);
}
}
}
export const executePreflightCheck = async (
options: CommandOptions
): Promise<PreflightCheckResult> => {
const command = new PreflightCheckCommand();
return command.execute(options);
};