@storybook/cli 10.4.0-alpha.15 → 10.4.0-alpha.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_node-chunks/{block-dependencies-versions-3JQG5RZL.js → block-dependencies-versions-S3TJGYC2.js} +11 -11
- package/dist/_node-chunks/{block-experimental-addon-test-DYNRVKQS.js → block-experimental-addon-test-WWZCXLB2.js} +9 -9
- package/dist/_node-chunks/{block-major-version-WUJ2IYKH.js → block-major-version-JNM4ZAKB.js} +9 -9
- package/dist/_node-chunks/{block-node-version-ML6OV5FZ.js → block-node-version-HDPTJUPH.js} +9 -9
- package/dist/_node-chunks/{block-webpack5-frameworks-IY3NOB6J.js → block-webpack5-frameworks-TETWAJLZ.js} +11 -11
- package/dist/_node-chunks/chunk-7BQI2DK6.js +20 -0
- package/dist/_node-chunks/chunk-7H4XHFS5.js +527 -0
- package/dist/_node-chunks/chunk-JYLYIY6L.js +810 -0
- package/dist/_node-chunks/{chunk-MNTUL4IJ.js → chunk-NDN75UAD.js} +7 -7
- package/dist/_node-chunks/chunk-QBNIQBHH.js +23 -0
- package/dist/_node-chunks/{chunk-KMODVRZU.js → chunk-QQ7E4GEX.js} +15 -15
- package/dist/_node-chunks/chunk-TSPB5MCI.js +11 -0
- package/dist/_node-chunks/{chunk-522W525H.js → chunk-TZ336D6R.js} +6 -6
- package/dist/_node-chunks/{chunk-TQZC6S4H.js → chunk-UKVJ7RQN.js} +7 -7
- package/dist/_node-chunks/{globby-PFUJPJPH.js → globby-5IGUGWE7.js} +8 -8
- package/dist/_node-chunks/monorepo-4B4ULRGC.js +110 -0
- package/dist/_node-chunks/optimized-tests-MJI5NXQA.js +106 -0
- package/dist/_node-chunks/{p-limit-FVG52ILT.js → p-limit-VO6RWWBJ.js} +7 -7
- package/dist/_node-chunks/pattern-copy-play-JNOATHUQ.js +20 -0
- package/dist/_node-chunks/relaxed-limits-MKAIPGR2.js +106 -0
- package/dist/_node-chunks/{run-KUMQEGOH.js → run-EJWCFREQ.js} +303 -1040
- package/dist/_node-chunks/{setup-VZ6IVNC4.js → setup-PUNMMEGI.js} +10 -10
- package/dist/bin/index.js +7 -7
- package/package.json +4 -4
- package/dist/_node-chunks/chunk-WSXOTENG.js +0 -11
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import CJS_COMPAT_NODE_URL_sgh3w93ap7c from 'node:url';
|
|
2
|
+
import CJS_COMPAT_NODE_PATH_sgh3w93ap7c from 'node:path';
|
|
3
|
+
import CJS_COMPAT_NODE_MODULE_sgh3w93ap7c from "node:module";
|
|
4
4
|
|
|
5
|
-
var __filename =
|
|
6
|
-
var __dirname =
|
|
7
|
-
var require =
|
|
5
|
+
var __filename = CJS_COMPAT_NODE_URL_sgh3w93ap7c.fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = CJS_COMPAT_NODE_PATH_sgh3w93ap7c.dirname(__filename);
|
|
7
|
+
var require = CJS_COMPAT_NODE_MODULE_sgh3w93ap7c.createRequire(import.meta.url);
|
|
8
8
|
|
|
9
9
|
// ------------------------------------------------------------
|
|
10
10
|
// end of CJS compatibility banner, injected by Storybook's esbuild configuration
|
|
11
11
|
// ------------------------------------------------------------
|
|
12
|
+
import {
|
|
13
|
+
instructions
|
|
14
|
+
} from "./chunk-JYLYIY6L.js";
|
|
15
|
+
import "./chunk-QBNIQBHH.js";
|
|
16
|
+
import "./chunk-7BQI2DK6.js";
|
|
12
17
|
import {
|
|
13
18
|
bannerComment,
|
|
14
19
|
containsDirnameUsage,
|
|
@@ -26,18 +31,18 @@ import {
|
|
|
26
31
|
up,
|
|
27
32
|
updateMainConfig,
|
|
28
33
|
upgradeStorybookDependencies
|
|
29
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-QQ7E4GEX.js";
|
|
30
35
|
import {
|
|
31
36
|
slash
|
|
32
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-UKVJ7RQN.js";
|
|
33
38
|
import {
|
|
34
39
|
require_semver
|
|
35
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-NDN75UAD.js";
|
|
36
41
|
import {
|
|
37
42
|
__commonJS,
|
|
38
43
|
__require,
|
|
39
44
|
__toESM
|
|
40
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-TZ336D6R.js";
|
|
41
46
|
|
|
42
47
|
// ../../../node_modules/envinfo/dist/envinfo.js
|
|
43
48
|
var require_envinfo = __commonJS({
|
|
@@ -4418,9 +4423,9 @@ var require_isexe = __commonJS({
|
|
|
4418
4423
|
if (typeof options == "function" && (cb = options, options = {}), !cb) {
|
|
4419
4424
|
if (typeof Promise != "function")
|
|
4420
4425
|
throw new TypeError("callback not provided");
|
|
4421
|
-
return new Promise(function(
|
|
4426
|
+
return new Promise(function(resolve5, reject) {
|
|
4422
4427
|
isexe(path4, options || {}, function(er, is) {
|
|
4423
|
-
er ? reject(er) :
|
|
4428
|
+
er ? reject(er) : resolve5(is);
|
|
4424
4429
|
});
|
|
4425
4430
|
});
|
|
4426
4431
|
}
|
|
@@ -4457,22 +4462,22 @@ var require_which = __commonJS({
|
|
|
4457
4462
|
};
|
|
4458
4463
|
}, which = (cmd, opt, cb) => {
|
|
4459
4464
|
typeof opt == "function" && (cb = opt, opt = {}), opt || (opt = {});
|
|
4460
|
-
let { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt), found = [], step = (i) => new Promise((
|
|
4465
|
+
let { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt), found = [], step = (i) => new Promise((resolve5, reject) => {
|
|
4461
4466
|
if (i === pathEnv.length)
|
|
4462
|
-
return opt.all && found.length ?
|
|
4467
|
+
return opt.all && found.length ? resolve5(found) : reject(getNotFoundError(cmd));
|
|
4463
4468
|
let ppRaw = pathEnv[i], pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw, pCmd = path4.join(pathPart, cmd), p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
4464
|
-
|
|
4465
|
-
}), subStep = (p, i, ii) => new Promise((
|
|
4469
|
+
resolve5(subStep(p, i, 0));
|
|
4470
|
+
}), subStep = (p, i, ii) => new Promise((resolve5, reject) => {
|
|
4466
4471
|
if (ii === pathExt.length)
|
|
4467
|
-
return
|
|
4472
|
+
return resolve5(step(i + 1));
|
|
4468
4473
|
let ext = pathExt[ii];
|
|
4469
4474
|
isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
|
|
4470
4475
|
if (!er && is)
|
|
4471
4476
|
if (opt.all)
|
|
4472
4477
|
found.push(p + ext);
|
|
4473
4478
|
else
|
|
4474
|
-
return
|
|
4475
|
-
return
|
|
4479
|
+
return resolve5(p + ext);
|
|
4480
|
+
return resolve5(subStep(p, i, ii + 1));
|
|
4476
4481
|
});
|
|
4477
4482
|
});
|
|
4478
4483
|
return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
|
|
@@ -4719,7 +4724,7 @@ import {
|
|
|
4719
4724
|
versions as versions5
|
|
4720
4725
|
} from "storybook/internal/common";
|
|
4721
4726
|
import { withTelemetry } from "storybook/internal/core-server";
|
|
4722
|
-
import { CLI_COLORS as CLI_COLORS5, logTracker as logTracker4, logger as
|
|
4727
|
+
import { CLI_COLORS as CLI_COLORS5, logTracker as logTracker4, logger as logger25 } from "storybook/internal/node-logger";
|
|
4723
4728
|
import { addToGlobalContext, telemetry as telemetry3 } from "storybook/internal/telemetry";
|
|
4724
4729
|
import { Option, program } from "commander";
|
|
4725
4730
|
|
|
@@ -4761,7 +4766,7 @@ function leven(first, second, options) {
|
|
|
4761
4766
|
var import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
4762
4767
|
|
|
4763
4768
|
// package.json
|
|
4764
|
-
var version = "10.4.0-alpha.
|
|
4769
|
+
var version = "10.4.0-alpha.16";
|
|
4765
4770
|
|
|
4766
4771
|
// src/add.ts
|
|
4767
4772
|
var import_semver = __toESM(require_semver(), 1);
|
|
@@ -5001,9 +5006,9 @@ var DIR_CWD = process.cwd(), require2 = createRequire2(DIR_CWD), postinstallAddo
|
|
|
5001
5006
|
} catch {
|
|
5002
5007
|
return;
|
|
5003
5008
|
}
|
|
5004
|
-
let postinstall = moduledLoaded?.default || moduledLoaded?.postinstall || moduledLoaded,
|
|
5009
|
+
let postinstall = moduledLoaded?.default || moduledLoaded?.postinstall || moduledLoaded, logger26 = options.logger;
|
|
5005
5010
|
if (!postinstall || typeof postinstall != "function") {
|
|
5006
|
-
|
|
5011
|
+
logger26.error(`Error finding postinstall function for ${addonName}`);
|
|
5007
5012
|
return;
|
|
5008
5013
|
}
|
|
5009
5014
|
try {
|
|
@@ -5024,7 +5029,7 @@ async function add(addon, {
|
|
|
5024
5029
|
configDir: userSpecifiedConfigDir,
|
|
5025
5030
|
yes,
|
|
5026
5031
|
skipInstall
|
|
5027
|
-
},
|
|
5032
|
+
}, logger26 = nodeLogger) {
|
|
5028
5033
|
let [addonName, inputVersion] = getVersionSpecifier(addon), { mainConfig, mainConfigPath, configDir, previewConfigPath, packageManager } = await getStorybookData({
|
|
5029
5034
|
configDir: userSpecifiedConfigDir,
|
|
5030
5035
|
packageManagerName: pkgMgr
|
|
@@ -5034,16 +5039,16 @@ async function add(addon, {
|
|
|
5034
5039
|
Unable to find storybook config directory. Please specify your Storybook config directory with the --config-dir flag.
|
|
5035
5040
|
`);
|
|
5036
5041
|
if (!mainConfigPath) {
|
|
5037
|
-
|
|
5042
|
+
logger26.error("Unable to find Storybook main.js config");
|
|
5038
5043
|
return;
|
|
5039
5044
|
}
|
|
5040
5045
|
let shouldAddToMain = !0;
|
|
5041
|
-
if (checkInstalled(addonName, mainConfig) && (shouldAddToMain = !1, !yes && (
|
|
5046
|
+
if (checkInstalled(addonName, mainConfig) && (shouldAddToMain = !1, !yes && (logger26.log(`The Storybook addon "${addonName}" is already present in ${mainConfigPath}.`), !await prompt.confirm({
|
|
5042
5047
|
message: "Do you wish to install it again?"
|
|
5043
5048
|
}))))
|
|
5044
5049
|
return;
|
|
5045
5050
|
let main = await readConfig(mainConfigPath);
|
|
5046
|
-
|
|
5051
|
+
logger26.log(`Verifying ${addonName}`);
|
|
5047
5052
|
let version2 = inputVersion;
|
|
5048
5053
|
if (!version2 && isCoreAddon(addonName) && (version2 = versions.storybook), !version2) {
|
|
5049
5054
|
let latestVersion = await packageManager.latestVersion(addonName);
|
|
@@ -5052,14 +5057,14 @@ async function add(addon, {
|
|
|
5052
5057
|
version2 = latestVersion;
|
|
5053
5058
|
}
|
|
5054
5059
|
let storybookVersion = versions.storybook, versionIsStorybook = version2 === versions.storybook;
|
|
5055
|
-
isCoreAddon(addonName) && !versionIsStorybook &&
|
|
5060
|
+
isCoreAddon(addonName) && !versionIsStorybook && logger26.warn(
|
|
5056
5061
|
`The version of ${addonName} (${version2}) you are installing is not the same as the version of Storybook you are using (${storybookVersion}). This may lead to unexpected behavior.`
|
|
5057
5062
|
);
|
|
5058
5063
|
let versionRange = packageManager.getDependencyVersion("storybook")?.match(/^[~^]/)?.[0] ?? "", addonWithVersion = versionIsStorybook ? `${addonName}@${versionRange}${storybookVersion}` : isValidVersion(version2) && !version2.includes("-pr-") ? `${addonName}@^${version2}` : `${addonName}@${version2}`;
|
|
5059
|
-
|
|
5064
|
+
logger26.log(`Installing ${addonWithVersion}`), await packageManager.addDependencies(
|
|
5060
5065
|
{ type: "devDependencies", writeOutputToFile: !1, skipInstall },
|
|
5061
5066
|
[addonWithVersion]
|
|
5062
|
-
), shouldAddToMain && (
|
|
5067
|
+
), shouldAddToMain && (logger26.log(`Adding '${addon}' to the "addons" field in ${mainConfigPath}`), await setupAddonInConfig({
|
|
5063
5068
|
addonName,
|
|
5064
5069
|
mainConfigCSFFile: main,
|
|
5065
5070
|
previewConfigPath,
|
|
@@ -5068,7 +5073,7 @@ async function add(addon, {
|
|
|
5068
5073
|
packageManager: packageManager.type,
|
|
5069
5074
|
configDir,
|
|
5070
5075
|
yes,
|
|
5071
|
-
logger:
|
|
5076
|
+
logger: logger26,
|
|
5072
5077
|
prompt,
|
|
5073
5078
|
skipInstall
|
|
5074
5079
|
});
|
|
@@ -5080,7 +5085,7 @@ function isValidVersion(version2) {
|
|
|
5080
5085
|
// src/automigrate/index.ts
|
|
5081
5086
|
var import_picocolors14 = __toESM(require_picocolors(), 1);
|
|
5082
5087
|
import { versions as versions3 } from "storybook/internal/common";
|
|
5083
|
-
import { logTracker as logTracker2, logger as
|
|
5088
|
+
import { logTracker as logTracker2, logger as logger17, prompt as prompt3 } from "storybook/internal/node-logger";
|
|
5084
5089
|
import { AutomigrateError } from "storybook/internal/server-errors";
|
|
5085
5090
|
|
|
5086
5091
|
// ../../../node_modules/tiny-invariant/dist/esm/tiny-invariant.js
|
|
@@ -5625,7 +5630,7 @@ import { logger as logger3 } from "storybook/internal/node-logger";
|
|
|
5625
5630
|
import { promises as fs } from "fs";
|
|
5626
5631
|
var maxConcurrentTasks = Math.max(1, os.cpus().length - 1);
|
|
5627
5632
|
async function runCodemod(globPattern = "**/*.{stories,story}.{js,jsx,ts,tsx,mjs,mjsx,mts,mtsx}", transform, { dryRun = !1, skipFormatting = !1 } = {}) {
|
|
5628
|
-
let modifiedCount = 0, unmodifiedCount = 0, errorCount = 0, { globby } = await import("./globby-
|
|
5633
|
+
let modifiedCount = 0, unmodifiedCount = 0, errorCount = 0, { globby } = await import("./globby-5IGUGWE7.js"), files = await globby(slash(globPattern), {
|
|
5629
5634
|
followSymbolicLinks: !0,
|
|
5630
5635
|
ignore: ["**/node_modules/**", "**/dist/**", "**/storybook-static/**", "**/build/**"]
|
|
5631
5636
|
});
|
|
@@ -5636,7 +5641,7 @@ Please try a different pattern.
|
|
|
5636
5641
|
`
|
|
5637
5642
|
), new Error("No files matched");
|
|
5638
5643
|
try {
|
|
5639
|
-
let pLimit = (await import("./p-limit-
|
|
5644
|
+
let pLimit = (await import("./p-limit-VO6RWWBJ.js")).default, limit = pLimit(maxConcurrentTasks);
|
|
5640
5645
|
await Promise.all(
|
|
5641
5646
|
files.map(
|
|
5642
5647
|
(file) => limit(async () => {
|
|
@@ -6479,7 +6484,7 @@ var addonA11yParameters = {
|
|
|
6479
6484
|
errors.push({ file: previewFileToUpdate, error });
|
|
6480
6485
|
}
|
|
6481
6486
|
}
|
|
6482
|
-
let { default: pLimit } = await import("./p-limit-
|
|
6487
|
+
let { default: pLimit } = await import("./p-limit-VO6RWWBJ.js"), limit = pLimit(10);
|
|
6483
6488
|
if (await Promise.all(
|
|
6484
6489
|
storyFilesToUpdate.map(
|
|
6485
6490
|
(file) => limit(async () => {
|
|
@@ -6633,7 +6638,7 @@ var addonGlobalsApi = {
|
|
|
6633
6638
|
}
|
|
6634
6639
|
};
|
|
6635
6640
|
async function transformStoryFiles(files, options, dryRun) {
|
|
6636
|
-
let errors = [], { default: pLimit } = await import("./p-limit-
|
|
6641
|
+
let errors = [], { default: pLimit } = await import("./p-limit-VO6RWWBJ.js"), limit = pLimit(10);
|
|
6637
6642
|
return await Promise.all(
|
|
6638
6643
|
files.map(
|
|
6639
6644
|
(file) => limit(async () => {
|
|
@@ -6825,7 +6830,7 @@ function transformPackageJson(content) {
|
|
|
6825
6830
|
return hasChanges ? JSON.stringify(packageJson, null, 2) : null;
|
|
6826
6831
|
}
|
|
6827
6832
|
var transformPackageJsonFiles = async (files, dryRun) => {
|
|
6828
|
-
let errors = [], { default: pLimit } = await import("./p-limit-
|
|
6833
|
+
let errors = [], { default: pLimit } = await import("./p-limit-VO6RWWBJ.js"), limit = pLimit(10);
|
|
6829
6834
|
return await Promise.all(
|
|
6830
6835
|
files.map(
|
|
6831
6836
|
(file) => limit(async () => {
|
|
@@ -6864,7 +6869,7 @@ var transformPackageJsonFiles = async (files, dryRun) => {
|
|
|
6864
6869
|
dryRun
|
|
6865
6870
|
);
|
|
6866
6871
|
errors.push(...packageJsonErrors);
|
|
6867
|
-
let { globby } = await import("./globby-
|
|
6872
|
+
let { globby } = await import("./globby-5IGUGWE7.js"), configFiles = await globby([`${configDir}/**/*`]), importErrors = await transformImportFiles(
|
|
6868
6873
|
[...storiesPaths, ...configFiles].filter(Boolean),
|
|
6869
6874
|
{
|
|
6870
6875
|
...consolidatedPackages,
|
|
@@ -7220,7 +7225,7 @@ var VITE_DEFAULT_VERSION = "^7.0.0", transformMainConfig = async (mainConfigPath
|
|
|
7220
7225
|
]);
|
|
7221
7226
|
}
|
|
7222
7227
|
mainConfigPath && (logger11.debug("Updating main config file..."), await transformMainConfig(mainConfigPath, dryRun)), logger11.debug("Scanning and updating import statements...");
|
|
7223
|
-
let { globby } = await import("./globby-
|
|
7228
|
+
let { globby } = await import("./globby-5IGUGWE7.js"), configFiles = await globby([`${configDir}/**/*`]), allFiles = [...storiesPaths, ...configFiles].filter(Boolean), transformErrors = await transformImportFiles2(
|
|
7224
7229
|
allFiles,
|
|
7225
7230
|
{
|
|
7226
7231
|
"@storybook/nextjs": "@storybook/nextjs-vite"
|
|
@@ -7430,7 +7435,7 @@ var getAllDependencies = (packageJson) => Object.keys({
|
|
|
7430
7435
|
let regex = new RegExp(`(['"])${renderer}(['"])`, "g");
|
|
7431
7436
|
return regex.test(source) ? source.replace(regex, `$1${framework}$2`) : null;
|
|
7432
7437
|
}, transformSourceFiles = async (files, renderer, framework, dryRun) => {
|
|
7433
|
-
let errors = [], { default: pLimit } = await import("./p-limit-
|
|
7438
|
+
let errors = [], { default: pLimit } = await import("./p-limit-VO6RWWBJ.js"), limit = pLimit(10);
|
|
7434
7439
|
return await Promise.all(
|
|
7435
7440
|
files.map(
|
|
7436
7441
|
(file) => limit(async () => {
|
|
@@ -7497,7 +7502,7 @@ var getAllDependencies = (packageJson) => Object.keys({
|
|
|
7497
7502
|
continue;
|
|
7498
7503
|
logger13.debug(`
|
|
7499
7504
|
Migrating ${rendererPackage} to ${selectedFramework}`);
|
|
7500
|
-
let { globby } = await import("./globby-
|
|
7505
|
+
let { globby } = await import("./globby-5IGUGWE7.js"), configFiles = await globby([`${configDir}/**/*`]);
|
|
7501
7506
|
await transformSourceFiles(
|
|
7502
7507
|
[...storiesPaths, ...configFiles].filter(Boolean),
|
|
7503
7508
|
rendererPackage,
|
|
@@ -7512,16 +7517,87 @@ Migrating ${rendererPackage} to ${selectedFramework}`);
|
|
|
7512
7517
|
}
|
|
7513
7518
|
};
|
|
7514
7519
|
|
|
7515
|
-
// src/automigrate/fixes/
|
|
7520
|
+
// src/automigrate/fixes/rn-ondevice-addons-to-device-addons.ts
|
|
7516
7521
|
import { existsSync as existsSync2 } from "node:fs";
|
|
7517
|
-
import {
|
|
7518
|
-
import {
|
|
7519
|
-
import {
|
|
7522
|
+
import { basename as basename2, dirname as dirname2, isAbsolute as isAbsolute2, join as join2, resolve as resolve2 } from "node:path";
|
|
7523
|
+
import { findConfigFile, loadMainConfig } from "storybook/internal/common";
|
|
7524
|
+
import { logger as logger14 } from "storybook/internal/node-logger";
|
|
7520
7525
|
|
|
7521
7526
|
// ../../core/src/shared/constants/config-folder.ts
|
|
7522
7527
|
var RN_STORYBOOK_DIR = ".rnstorybook";
|
|
7523
7528
|
|
|
7529
|
+
// src/automigrate/fixes/rn-ondevice-addons-to-device-addons.ts
|
|
7530
|
+
var resolveAbsoluteConfigDir = (configDir) => isAbsolute2(configDir) ? configDir : join2(process.cwd(), configDir), getSiblingStorybookConfigDir = (configDirAbs) => {
|
|
7531
|
+
let base = basename2(configDirAbs), parent = dirname2(configDirAbs);
|
|
7532
|
+
if (base === ".storybook") {
|
|
7533
|
+
let rn = join2(parent, RN_STORYBOOK_DIR);
|
|
7534
|
+
return existsSync2(rn) ? rn : null;
|
|
7535
|
+
}
|
|
7536
|
+
if (base === RN_STORYBOOK_DIR) {
|
|
7537
|
+
let web = join2(parent, ".storybook");
|
|
7538
|
+
return existsSync2(web) ? web : null;
|
|
7539
|
+
}
|
|
7540
|
+
return null;
|
|
7541
|
+
}, isReactNativeMain = (mainConfigPath, mainConfig) => basename2(dirname2(mainConfigPath)) === RN_STORYBOOK_DIR ? !0 : getFrameworkPackageName(mainConfig) === "@storybook/react-native", hasAddonsToRename = (cfg) => {
|
|
7542
|
+
let addons = cfg.addons;
|
|
7543
|
+
return !(!Array.isArray(addons) || addons.length === 0 || cfg.deviceAddons !== void 0);
|
|
7544
|
+
}, rnOndeviceAddonsToDeviceAddons = {
|
|
7545
|
+
id: "rn-ondevice-addons-to-device-addons",
|
|
7546
|
+
link: "https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#react-native-on-device-addons-moved-to-deviceaddons",
|
|
7547
|
+
async check({ mainConfig, packageManager, configDir, mainConfigPath }) {
|
|
7548
|
+
if (!packageManager.getAllDependencies()["@storybook/react-native"])
|
|
7549
|
+
return null;
|
|
7550
|
+
let candidateDirs = [];
|
|
7551
|
+
if (configDir) {
|
|
7552
|
+
let absConfigDir = resolveAbsoluteConfigDir(configDir);
|
|
7553
|
+
candidateDirs.push(absConfigDir);
|
|
7554
|
+
let siblingConfigDir = getSiblingStorybookConfigDir(absConfigDir);
|
|
7555
|
+
siblingConfigDir && candidateDirs.push(siblingConfigDir);
|
|
7556
|
+
}
|
|
7557
|
+
let targets = [], seenResolvedMainPaths = /* @__PURE__ */ new Set();
|
|
7558
|
+
if (candidateDirs.length > 0)
|
|
7559
|
+
for (let dir of candidateDirs) {
|
|
7560
|
+
let mainPath = findConfigFile("main", dir);
|
|
7561
|
+
if (!mainPath)
|
|
7562
|
+
continue;
|
|
7563
|
+
let resolvedMain = resolve2(mainPath);
|
|
7564
|
+
if (seenResolvedMainPaths.has(resolvedMain))
|
|
7565
|
+
continue;
|
|
7566
|
+
seenResolvedMainPaths.add(resolvedMain);
|
|
7567
|
+
let cfg;
|
|
7568
|
+
if (mainConfigPath && resolve2(mainConfigPath) === resolvedMain)
|
|
7569
|
+
cfg = mainConfig;
|
|
7570
|
+
else
|
|
7571
|
+
try {
|
|
7572
|
+
cfg = await loadMainConfig({ configDir: dir });
|
|
7573
|
+
} catch (e) {
|
|
7574
|
+
logger14.debug(
|
|
7575
|
+
`Failed to load Storybook main config at ${dir}: ${e instanceof Error ? e.message : String(e)}`
|
|
7576
|
+
);
|
|
7577
|
+
continue;
|
|
7578
|
+
}
|
|
7579
|
+
isReactNativeMain(mainPath, cfg) && hasAddonsToRename(cfg) && targets.push({ mainConfigPath: mainPath });
|
|
7580
|
+
}
|
|
7581
|
+
else mainConfigPath && isReactNativeMain(mainConfigPath, mainConfig) && hasAddonsToRename(mainConfig) && targets.push({ mainConfigPath });
|
|
7582
|
+
return targets.length === 0 ? null : { targets };
|
|
7583
|
+
},
|
|
7584
|
+
prompt() {
|
|
7585
|
+
return "Renaming `addons` to `deviceAddons` in your React Native Storybook config (on-device addons must not be evaluated as Node.js presets).";
|
|
7586
|
+
},
|
|
7587
|
+
async run({ result, dryRun }) {
|
|
7588
|
+
for (let { mainConfigPath } of result.targets)
|
|
7589
|
+
await updateMainConfig({ mainConfigPath, dryRun: !!dryRun }, (main) => {
|
|
7590
|
+
let node = main.getFieldNode(["addons"]);
|
|
7591
|
+
node && (main.setFieldNode(["deviceAddons"], node), main.removeField(["addons"]));
|
|
7592
|
+
});
|
|
7593
|
+
}
|
|
7594
|
+
};
|
|
7595
|
+
|
|
7524
7596
|
// src/automigrate/fixes/rnstorybook-config.ts
|
|
7597
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
7598
|
+
import { readFile as readFile8, rename, writeFile as writeFile7 } from "node:fs/promises";
|
|
7599
|
+
import { join as join3 } from "node:path";
|
|
7600
|
+
import { dedent as dedent9 } from "ts-dedent";
|
|
7525
7601
|
async function renameInFile(filePath, oldText, newText) {
|
|
7526
7602
|
try {
|
|
7527
7603
|
let updatedContent = (await readFile8(filePath, "utf8")).replaceAll(oldText, newText);
|
|
@@ -7532,7 +7608,7 @@ async function renameInFile(filePath, oldText, newText) {
|
|
|
7532
7608
|
}
|
|
7533
7609
|
var getDotStorybookReferences = async (searchDir) => {
|
|
7534
7610
|
try {
|
|
7535
|
-
let { globby } = await import("./globby-
|
|
7611
|
+
let { globby } = await import("./globby-5IGUGWE7.js"), { readFile: readFile10 } = await import("node:fs/promises"), files = await globby(`${searchDir}/**/*`, {
|
|
7536
7612
|
onlyFiles: !0,
|
|
7537
7613
|
gitignore: !0
|
|
7538
7614
|
}), referencedFiles = [];
|
|
@@ -7553,8 +7629,8 @@ var getDotStorybookReferences = async (searchDir) => {
|
|
|
7553
7629
|
async check({ packageManager, mainConfigPath }) {
|
|
7554
7630
|
if (!packageManager.getAllDependencies()["@storybook/react-native"])
|
|
7555
7631
|
return null;
|
|
7556
|
-
let projectDir = mainConfigPath ?
|
|
7557
|
-
return
|
|
7632
|
+
let projectDir = mainConfigPath ? join3(mainConfigPath, "..", "..") : process.cwd(), storybookDir = join3(projectDir, ".storybook"), rnStorybookDir = join3(projectDir, RN_STORYBOOK_DIR), { globby } = await import("./globby-5IGUGWE7.js"), requiresFiles = await globby(join3(storybookDir, "storybook.requires.*"));
|
|
7633
|
+
return existsSync3(storybookDir) && requiresFiles.length > 0 && !existsSync3(rnStorybookDir) ? { storybookDir, rnStorybookDir } : null;
|
|
7558
7634
|
},
|
|
7559
7635
|
prompt() {
|
|
7560
7636
|
return dedent9`We'll rename your .storybook directory to .rnstorybook and update all references to it.`;
|
|
@@ -7597,9 +7673,9 @@ var storybookPackageNameConflict = {
|
|
|
7597
7673
|
// src/automigrate/fixes/upgrade-storybook-related-dependencies.ts
|
|
7598
7674
|
var import_semver5 = __toESM(require_semver(), 1);
|
|
7599
7675
|
import { readFileSync as readFileSync4 } from "node:fs";
|
|
7600
|
-
import { dirname as
|
|
7676
|
+
import { dirname as dirname3 } from "node:path";
|
|
7601
7677
|
import { isCorePackage, isSatelliteAddon } from "storybook/internal/common";
|
|
7602
|
-
import { logger as
|
|
7678
|
+
import { logger as logger15 } from "storybook/internal/node-logger";
|
|
7603
7679
|
import { dedent as dedent11 } from "ts-dedent";
|
|
7604
7680
|
async function getLatestVersions(packageManager, packages) {
|
|
7605
7681
|
return Promise.all(
|
|
@@ -7611,14 +7687,14 @@ async function getLatestVersions(packageManager, packages) {
|
|
|
7611
7687
|
);
|
|
7612
7688
|
}
|
|
7613
7689
|
function isValidVersionType(packageName, specifier) {
|
|
7614
|
-
return specifier.startsWith("patch:") || specifier.startsWith("file:") || specifier.startsWith("link:") || specifier.startsWith("portal:") || specifier.startsWith("git:") || specifier.startsWith("git+") || specifier.startsWith("http:") || specifier.startsWith("https:") || specifier.startsWith("workspace:") ? (
|
|
7690
|
+
return specifier.startsWith("patch:") || specifier.startsWith("file:") || specifier.startsWith("link:") || specifier.startsWith("portal:") || specifier.startsWith("git:") || specifier.startsWith("git+") || specifier.startsWith("http:") || specifier.startsWith("https:") || specifier.startsWith("workspace:") ? (logger15.debug(`Skipping ${packageName} as it does not have a valid version type: ${specifier}`), !1) : !0;
|
|
7615
7691
|
}
|
|
7616
7692
|
var upgradeStorybookRelatedDependencies = {
|
|
7617
7693
|
id: "upgrade-storybook-related-dependencies",
|
|
7618
7694
|
promptType: "auto",
|
|
7619
7695
|
defaultSelected: !1,
|
|
7620
7696
|
async check({ packageManager, storybookVersion }) {
|
|
7621
|
-
|
|
7697
|
+
logger15.debug("Checking for incompatible storybook packages...");
|
|
7622
7698
|
let analyzedPackages = await getIncompatibleStorybookPackages({
|
|
7623
7699
|
currentStorybookVersion: storybookVersion,
|
|
7624
7700
|
packageManager,
|
|
@@ -7639,7 +7715,7 @@ var upgradeStorybookRelatedDependencies = {
|
|
|
7639
7715
|
},
|
|
7640
7716
|
async run({ result: { upgradable }, packageManager, dryRun }) {
|
|
7641
7717
|
if (dryRun) {
|
|
7642
|
-
|
|
7718
|
+
logger15.log(dedent11`
|
|
7643
7719
|
The following would have been upgraded:
|
|
7644
7720
|
${upgradable.map(
|
|
7645
7721
|
({ packageName, afterVersion, beforeVersion }) => `${packageName}: ${beforeVersion} => ${afterVersion}`
|
|
@@ -7655,7 +7731,7 @@ var upgradeStorybookRelatedDependencies = {
|
|
|
7655
7731
|
return;
|
|
7656
7732
|
let { packageName, afterVersion: version2 } = item, prefixed = `^${version2}`;
|
|
7657
7733
|
packageJson.dependencies?.[packageName] && (packageJson.dependencies[packageName] = prefixed), packageJson.devDependencies?.[packageName] && (packageJson.devDependencies[packageName] = prefixed), packageJson.peerDependencies?.[packageName] && (packageJson.peerDependencies[packageName] = prefixed);
|
|
7658
|
-
}), packageManager.writePackageJson(packageJson,
|
|
7734
|
+
}), packageManager.writePackageJson(packageJson, dirname3(packageJsonPath));
|
|
7659
7735
|
});
|
|
7660
7736
|
}
|
|
7661
7737
|
};
|
|
@@ -7717,6 +7793,7 @@ var allFixes = [
|
|
|
7717
7793
|
consolidatedImports,
|
|
7718
7794
|
addonExperimentalTest,
|
|
7719
7795
|
rnstorybookConfig,
|
|
7796
|
+
rnOndeviceAddonsToDeviceAddons,
|
|
7720
7797
|
migrateAddonConsole,
|
|
7721
7798
|
nextjsToNextjsVite,
|
|
7722
7799
|
removeAddonInteractions,
|
|
@@ -7732,7 +7809,7 @@ var commandFixes = [csfFactories];
|
|
|
7732
7809
|
|
|
7733
7810
|
// src/automigrate/helpers/logMigrationSummary.ts
|
|
7734
7811
|
var import_picocolors13 = __toESM(require_picocolors(), 1);
|
|
7735
|
-
import { CLI_COLORS as CLI_COLORS2, logger as
|
|
7812
|
+
import { CLI_COLORS as CLI_COLORS2, logger as logger16 } from "storybook/internal/node-logger";
|
|
7736
7813
|
import { dedent as dedent13 } from "ts-dedent";
|
|
7737
7814
|
var messageDivider2 = `
|
|
7738
7815
|
|
|
@@ -7770,21 +7847,21 @@ function logMigrationSummary({
|
|
|
7770
7847
|
let hasNoFixes = Object.values(fixResults).every((r) => r === "unnecessary" /* UNNECESSARY */), hasFailures2 = Object.values(fixResults).some(
|
|
7771
7848
|
(r) => r === "failed" /* FAILED */ || r === "check_failed" /* CHECK_FAILED */
|
|
7772
7849
|
);
|
|
7773
|
-
hasNoFixes ?
|
|
7850
|
+
hasNoFixes ? logger16.warn("No migrations were applicable to your project") : hasFailures2 ? logger16.error("Migration check ran with failures") : logger16.step(CLI_COLORS2.success("Migration check ran successfully")), logger16.log(messages2.filter(Boolean).join(segmentDivider));
|
|
7774
7851
|
}
|
|
7775
7852
|
|
|
7776
7853
|
// src/automigrate/index.ts
|
|
7777
7854
|
var logAvailableMigrations = () => {
|
|
7778
7855
|
let availableFixes = [...allFixes, ...commandFixes].map((f) => import_picocolors14.default.yellow(f.id)).map((x) => `- ${x}`).join(`
|
|
7779
7856
|
`);
|
|
7780
|
-
|
|
7857
|
+
logger17.log(dedent14`
|
|
7781
7858
|
The following migrations are available:
|
|
7782
7859
|
${availableFixes}
|
|
7783
7860
|
`);
|
|
7784
7861
|
}, hasFailures = (fixResults) => Object.values(fixResults || {}).some(
|
|
7785
7862
|
(r) => r === "failed" /* FAILED */ || r === "check_failed" /* CHECK_FAILED */
|
|
7786
7863
|
), doAutomigrate = async (options) => {
|
|
7787
|
-
|
|
7864
|
+
logger17.debug("Extracting storybook data...");
|
|
7788
7865
|
let {
|
|
7789
7866
|
mainConfig,
|
|
7790
7867
|
mainConfigPath,
|
|
@@ -7847,7 +7924,7 @@ var logAvailableMigrations = () => {
|
|
|
7847
7924
|
return logAvailableMigrations(), null;
|
|
7848
7925
|
let commandFix = commandFixes.find((f) => f.id === fixId);
|
|
7849
7926
|
if (commandFix)
|
|
7850
|
-
return
|
|
7927
|
+
return logger17.step(`Running migration ${import_picocolors14.default.magenta(fixId)}..`), await commandFix.run({
|
|
7851
7928
|
mainConfigPath,
|
|
7852
7929
|
previewConfigPath,
|
|
7853
7930
|
packageManager,
|
|
@@ -7862,8 +7939,8 @@ var logAvailableMigrations = () => {
|
|
|
7862
7939
|
}), null;
|
|
7863
7940
|
let selectedFixes = inputFixes || allFixes.filter((fix) => !(fix.id === upgradeStorybookRelatedDependencies.id && isLatest === !1 && fixId !== upgradeStorybookRelatedDependencies.id)), fixes = fixId ? selectedFixes.filter((f) => f.id === fixId) : selectedFixes;
|
|
7864
7941
|
if (fixId && fixes.length === 0)
|
|
7865
|
-
return
|
|
7866
|
-
|
|
7942
|
+
return logger17.log(`\u{1F4ED} No migrations found for ${import_picocolors14.default.magenta(fixId)}.`), logAvailableMigrations(), null;
|
|
7943
|
+
logger17.step("Checking possible migrations..");
|
|
7867
7944
|
let { fixResults, fixSummary, preCheckFailure } = await runFixes({
|
|
7868
7945
|
fixes,
|
|
7869
7946
|
packageManager,
|
|
@@ -7904,7 +7981,7 @@ async function runFixes({
|
|
|
7904
7981
|
for (let i = 0; i < fixes.length; i += 1) {
|
|
7905
7982
|
let f = fixes[i], result;
|
|
7906
7983
|
try {
|
|
7907
|
-
|
|
7984
|
+
logger17.debug(`Running ${import_picocolors14.default.cyan(f.id)} migration checks`), result = await f.check({
|
|
7908
7985
|
packageManager,
|
|
7909
7986
|
configDir,
|
|
7910
7987
|
rendererPackage,
|
|
@@ -7914,14 +7991,14 @@ async function runFixes({
|
|
|
7914
7991
|
mainConfigPath,
|
|
7915
7992
|
storiesPaths,
|
|
7916
7993
|
hasCsfFactoryPreview
|
|
7917
|
-
}),
|
|
7994
|
+
}), logger17.debug(`End of ${import_picocolors14.default.cyan(f.id)} migration checks`);
|
|
7918
7995
|
} catch (error) {
|
|
7919
|
-
|
|
7996
|
+
logger17.warn(`\u26A0\uFE0F failed to check fix ${import_picocolors14.default.bold(f.id)}`), error instanceof Error && (logger17.error(`
|
|
7920
7997
|
${error.stack}`), fixSummary.failed[f.id] = error.message), fixResults[f.id] = "check_failed" /* CHECK_FAILED */;
|
|
7921
7998
|
}
|
|
7922
7999
|
if (result) {
|
|
7923
8000
|
let promptType = typeof f.promptType == "function" ? await f.promptType(result) : f.promptType ?? "auto";
|
|
7924
|
-
|
|
8001
|
+
logger17.log(`\u{1F50E} found a '${import_picocolors14.default.cyan(f.id)}' migration:`);
|
|
7925
8002
|
let getTitle = () => {
|
|
7926
8003
|
switch (promptType) {
|
|
7927
8004
|
case "auto":
|
|
@@ -7935,7 +8012,7 @@ ${error.stack}`), fixSummary.failed[f.id] = error.message), fixResults[f.id] = "
|
|
|
7935
8012
|
id: `automigrate-task-${f.id}`,
|
|
7936
8013
|
title: `${getTitle()}: ${import_picocolors14.default.cyan(f.id)}`
|
|
7937
8014
|
});
|
|
7938
|
-
|
|
8015
|
+
logger17.logBox(f.prompt());
|
|
7939
8016
|
let runAnswer;
|
|
7940
8017
|
try {
|
|
7941
8018
|
if (dryRun)
|
|
@@ -7997,7 +8074,7 @@ ${error.stack}`), fixSummary.failed[f.id] = error.message), fixResults[f.id] = "
|
|
|
7997
8074
|
storybookVersion,
|
|
7998
8075
|
storiesPaths,
|
|
7999
8076
|
yes
|
|
8000
|
-
}),
|
|
8077
|
+
}), logger17.log(`\u2705 ran ${import_picocolors14.default.cyan(f.id)} migration`), fixResults[f.id] = "succeeded" /* SUCCEEDED */, fixSummary.succeeded.push(f.id), currentTaskLogger.success(`Ran ${import_picocolors14.default.cyan(f.id)} migration`);
|
|
8001
8078
|
} catch (error) {
|
|
8002
8079
|
fixResults[f.id] = "failed" /* FAILED */;
|
|
8003
8080
|
let errorMessage = error instanceof Error ? error.message : "Failed to run migration";
|
|
@@ -8014,9 +8091,9 @@ ${error.stack}`), fixSummary.failed[f.id] = error.message), fixResults[f.id] = "
|
|
|
8014
8091
|
// src/link.ts
|
|
8015
8092
|
var import_cross_spawn = __toESM(require_cross_spawn(), 1);
|
|
8016
8093
|
import { mkdir, readFile as readFile9, writeFile as writeFile8 } from "node:fs/promises";
|
|
8017
|
-
import { basename as
|
|
8094
|
+
import { basename as basename3, extname as extname2, join as join4 } from "node:path";
|
|
8018
8095
|
import { executeCommand } from "storybook/internal/common";
|
|
8019
|
-
import { logger as
|
|
8096
|
+
import { logger as logger18 } from "storybook/internal/node-logger";
|
|
8020
8097
|
var link = async ({ target, local, start }) => {
|
|
8021
8098
|
let storybookDir = process.cwd();
|
|
8022
8099
|
try {
|
|
@@ -8025,14 +8102,14 @@ var link = async ({ target, local, start }) => {
|
|
|
8025
8102
|
} catch {
|
|
8026
8103
|
throw new Error("Expected to run link from the root of the storybook monorepo");
|
|
8027
8104
|
}
|
|
8028
|
-
let reproDir = target, reproName =
|
|
8105
|
+
let reproDir = target, reproName = basename3(target);
|
|
8029
8106
|
if (!local) {
|
|
8030
|
-
let reprosDir =
|
|
8031
|
-
|
|
8107
|
+
let reprosDir = join4(storybookDir, "../storybook-repros");
|
|
8108
|
+
logger18.info(`Ensuring directory ${reprosDir}`), await mkdir(reprosDir, { recursive: !0 }), logger18.info(`Cloning ${target}`), await executeCommand({
|
|
8032
8109
|
command: "git",
|
|
8033
8110
|
args: ["clone", target],
|
|
8034
8111
|
cwd: reprosDir
|
|
8035
|
-
}), reproName =
|
|
8112
|
+
}), reproName = basename3(target, extname2(target)), reproDir = join4(reprosDir, reproName);
|
|
8036
8113
|
}
|
|
8037
8114
|
let version2 = (0, import_cross_spawn.sync)("yarn", ["--version"], {
|
|
8038
8115
|
cwd: reproDir,
|
|
@@ -8040,16 +8117,16 @@ var link = async ({ target, local, start }) => {
|
|
|
8040
8117
|
shell: !0
|
|
8041
8118
|
}).stdout.toString();
|
|
8042
8119
|
if (!/^[2-4]\./.test(version2)) {
|
|
8043
|
-
|
|
8120
|
+
logger18.warn(`\u{1F6A8} Expected yarn 2 or higher in ${reproDir}!`), logger18.warn(""), logger18.warn("Please set it up with `yarn set version berry`,"), logger18.warn(`then link '${reproDir}' with the '--local' flag.`);
|
|
8044
8121
|
return;
|
|
8045
8122
|
}
|
|
8046
|
-
|
|
8123
|
+
logger18.info(`Linking ${reproDir}`), await executeCommand({
|
|
8047
8124
|
command: "yarn",
|
|
8048
8125
|
args: ["link", "--all", "--relative", storybookDir],
|
|
8049
8126
|
cwd: reproDir
|
|
8050
|
-
}),
|
|
8127
|
+
}), logger18.info(`Installing ${reproName}`);
|
|
8051
8128
|
let reproPackageJson = JSON.parse(
|
|
8052
|
-
await readFile9(
|
|
8129
|
+
await readFile9(join4(reproDir, "package.json"), { encoding: "utf8" })
|
|
8053
8130
|
);
|
|
8054
8131
|
reproPackageJson.devDependencies?.vite || (reproPackageJson.devDependencies = {
|
|
8055
8132
|
...reproPackageJson.devDependencies,
|
|
@@ -8057,11 +8134,11 @@ var link = async ({ target, local, start }) => {
|
|
|
8057
8134
|
}), reproPackageJson.devDependencies = {
|
|
8058
8135
|
...reproPackageJson.devDependencies,
|
|
8059
8136
|
"@types/node": "^22"
|
|
8060
|
-
}, await writeFile8(
|
|
8137
|
+
}, await writeFile8(join4(reproDir, "package.json"), JSON.stringify(reproPackageJson, null, 2)), await executeCommand({
|
|
8061
8138
|
command: "yarn",
|
|
8062
8139
|
args: ["install"],
|
|
8063
8140
|
cwd: reproDir
|
|
8064
|
-
}), start && (
|
|
8141
|
+
}), start && (logger18.info(`Running ${reproName} storybook`), await executeCommand({
|
|
8065
8142
|
command: "yarn",
|
|
8066
8143
|
args: ["run", "storybook"],
|
|
8067
8144
|
cwd: reproDir
|
|
@@ -8069,22 +8146,22 @@ var link = async ({ target, local, start }) => {
|
|
|
8069
8146
|
};
|
|
8070
8147
|
|
|
8071
8148
|
// src/migrate.ts
|
|
8072
|
-
import { logger as
|
|
8149
|
+
import { logger as logger19 } from "storybook/internal/node-logger";
|
|
8073
8150
|
import { listCodemods, runCodemod as runCodemod2 } from "@storybook/codemod";
|
|
8074
8151
|
async function migrate(migration, { glob, dryRun, list, rename: rename2, parser }) {
|
|
8075
8152
|
if (list)
|
|
8076
|
-
listCodemods().forEach((key) =>
|
|
8153
|
+
listCodemods().forEach((key) => logger19.log(key));
|
|
8077
8154
|
else if (migration)
|
|
8078
|
-
await runCodemod2(migration, { glob, dryRun, logger:
|
|
8155
|
+
await runCodemod2(migration, { glob, dryRun, logger: logger19, rename: rename2, parser });
|
|
8079
8156
|
else
|
|
8080
8157
|
throw new Error("Migrate: please specify a migration name or --list");
|
|
8081
8158
|
}
|
|
8082
8159
|
|
|
8083
8160
|
// src/sandbox.ts
|
|
8084
8161
|
var import_cross_spawn2 = __toESM(require_cross_spawn(), 1);
|
|
8085
|
-
import { existsSync as
|
|
8162
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
8086
8163
|
import { mkdir as mkdir2, readdir, rm } from "node:fs/promises";
|
|
8087
|
-
import { isAbsolute as
|
|
8164
|
+
import { isAbsolute as isAbsolute3 } from "node:path";
|
|
8088
8165
|
import { PackageManagerName } from "storybook/internal/common";
|
|
8089
8166
|
import {
|
|
8090
8167
|
JsPackageManagerFactory,
|
|
@@ -8092,7 +8169,7 @@ import {
|
|
|
8092
8169
|
optionalEnvToBoolean as optionalEnvToBoolean2,
|
|
8093
8170
|
versions as versions4
|
|
8094
8171
|
} from "storybook/internal/common";
|
|
8095
|
-
import { logger as
|
|
8172
|
+
import { logger as logger20, prompt as prompt4 } from "storybook/internal/node-logger";
|
|
8096
8173
|
var import_picocolors15 = __toESM(require_picocolors(), 1), import_semver6 = __toESM(require_semver(), 1);
|
|
8097
8174
|
import { dedent as dedent15 } from "ts-dedent";
|
|
8098
8175
|
|
|
@@ -9017,7 +9094,7 @@ var toChoices = (c) => ({ label: allTemplates[c].name, value: c }), sandbox = as
|
|
|
9017
9094
|
),
|
|
9018
9095
|
prerelease: import_picocolors15.default.yellow("This is a pre-release version.")
|
|
9019
9096
|
};
|
|
9020
|
-
if (
|
|
9097
|
+
if (logger20.logBox(
|
|
9021
9098
|
[messages2.welcome].concat(isOutdated && !isPrerelease ? [messages2.notLatest] : []).concat(init && (isOutdated || isPrerelease) ? [messages2.longInitTime] : []).concat(isPrerelease ? [messages2.prerelease] : []).join(`
|
|
9022
9099
|
`),
|
|
9023
9100
|
{
|
|
@@ -9028,7 +9105,7 @@ var toChoices = (c) => ({ label: allTemplates[c].name, value: c }), sandbox = as
|
|
|
9028
9105
|
let current = allTemplates[group];
|
|
9029
9106
|
return (!filterValue || current.name.match(filterRegex) || group.match(filterRegex) || current.expected.builder.match(filterRegex) || current.expected.framework.match(filterRegex) || current.expected.renderer.match(filterRegex)) && acc.push(group), acc;
|
|
9030
9107
|
}, []);
|
|
9031
|
-
if (choices.length === 0 && (
|
|
9108
|
+
if (choices.length === 0 && (logger20.logBox(
|
|
9032
9109
|
dedent15`
|
|
9033
9110
|
🔎 You filtered out all templates. 🔍
|
|
9034
9111
|
|
|
@@ -9041,7 +9118,7 @@ var toChoices = (c) => ({ label: allTemplates[c].name, value: c }), sandbox = as
|
|
|
9041
9118
|
`)}
|
|
9042
9119
|
`.trim(),
|
|
9043
9120
|
{ borderStyle: "round", padding: 1, borderColor: "#F1618C" }
|
|
9044
|
-
), process.exit(1)), choices.length === 1 ? [templateId] = choices : (
|
|
9121
|
+
), process.exit(1)), choices.length === 1 ? [templateId] = choices : (logger20.logBox(
|
|
9045
9122
|
dedent15`
|
|
9046
9123
|
🤗 Welcome to ${import_picocolors15.default.yellow("sb sandbox")}! 🤗
|
|
9047
9124
|
|
|
@@ -9054,28 +9131,28 @@ var toChoices = (c) => ({ label: allTemplates[c].name, value: c }), sandbox = as
|
|
|
9054
9131
|
`.trim(),
|
|
9055
9132
|
{ borderStyle: "round", padding: 1, borderColor: "#F1618C" }
|
|
9056
9133
|
), templateId = await promptSelectedTemplate(choices)), !!!(templateId ?? null)) {
|
|
9057
|
-
|
|
9134
|
+
logger20.error("Somehow we got no templates. Please rerun this command!");
|
|
9058
9135
|
return;
|
|
9059
9136
|
}
|
|
9060
9137
|
if (selectedConfig = templateId ? allTemplates[templateId] : void 0, !selectedConfig)
|
|
9061
9138
|
throw new Error("\u{1F6A8} Sandbox: please specify a valid template type");
|
|
9062
9139
|
}
|
|
9063
9140
|
let selectedDirectory = outputDirectory, outputDirectoryName = outputDirectory || templateId;
|
|
9064
|
-
selectedDirectory &&
|
|
9141
|
+
selectedDirectory && existsSync4(`${selectedDirectory}`) && (logger20.log(`\u26A0\uFE0F ${selectedDirectory} already exists! Overwriting...`), await rm(selectedDirectory, { recursive: !0, force: !0 })), selectedDirectory || (selectedDirectory = await prompt4.text(
|
|
9065
9142
|
{
|
|
9066
9143
|
message: "Enter the output directory",
|
|
9067
9144
|
initialValue: outputDirectoryName ?? void 0,
|
|
9068
|
-
validate: (directoryName) => directoryName &&
|
|
9145
|
+
validate: (directoryName) => directoryName && existsSync4(directoryName) ? `${directoryName} already exists. Please choose another name.` : void 0
|
|
9069
9146
|
},
|
|
9070
9147
|
{
|
|
9071
9148
|
onCancel: () => {
|
|
9072
|
-
|
|
9149
|
+
logger20.log("Command cancelled by the user. Exiting..."), process.exit(1);
|
|
9073
9150
|
}
|
|
9074
9151
|
}
|
|
9075
9152
|
)), invariant(selectedDirectory);
|
|
9076
9153
|
try {
|
|
9077
|
-
let templateDestination =
|
|
9078
|
-
|
|
9154
|
+
let templateDestination = isAbsolute3(selectedDirectory) ? selectedDirectory : join(process.cwd(), selectedDirectory);
|
|
9155
|
+
logger20.log(`\u{1F3C3} Adding ${selectedConfig.name} into ${templateDestination}`), logger20.log(`\u{1F4E6} Downloading sandbox template (${import_picocolors15.default.bold(downloadType)})...`);
|
|
9079
9156
|
try {
|
|
9080
9157
|
let gitPath = `storybookjs/sandboxes/tree/${branch}/${templateId}/${downloadType}`;
|
|
9081
9158
|
if (await mkdir2(templateDestination, { recursive: !0 }), (0, import_cross_spawn2.sync)("npx", ["gitpick@4.12.4", gitPath, templateDestination, "-o"], {
|
|
@@ -9099,13 +9176,13 @@ var toChoices = (c) => ({ label: allTemplates[c].name, value: c }), sandbox = as
|
|
|
9099
9176
|
}), process.chdir(before);
|
|
9100
9177
|
}
|
|
9101
9178
|
} catch (err) {
|
|
9102
|
-
throw
|
|
9179
|
+
throw logger20.error(`\u{1F6A8} Failed to download sandbox template: ${String(err)}`), err;
|
|
9103
9180
|
}
|
|
9104
9181
|
let initMessage = init ? import_picocolors15.default.yellow(dedent15`
|
|
9105
9182
|
yarn install
|
|
9106
9183
|
yarn storybook
|
|
9107
9184
|
`) : `Recreate your setup, then ${import_picocolors15.default.yellow("npx storybook@latest init")}`;
|
|
9108
|
-
|
|
9185
|
+
logger20.logBox(
|
|
9109
9186
|
dedent15`
|
|
9110
9187
|
🎉 Your Storybook reproduction project is ready to use! 🎉
|
|
9111
9188
|
|
|
@@ -9123,7 +9200,7 @@ var toChoices = (c) => ({ label: allTemplates[c].name, value: c }), sandbox = as
|
|
|
9123
9200
|
{ rounded: !0 }
|
|
9124
9201
|
);
|
|
9125
9202
|
} catch (error) {
|
|
9126
|
-
throw
|
|
9203
|
+
throw logger20.error("\u{1F6A8} Failed to create sandbox"), error;
|
|
9127
9204
|
}
|
|
9128
9205
|
};
|
|
9129
9206
|
async function promptSelectedTemplate(choices) {
|
|
@@ -9135,33 +9212,28 @@ async function promptSelectedTemplate(choices) {
|
|
|
9135
9212
|
|
|
9136
9213
|
// src/ai/index.ts
|
|
9137
9214
|
import { writeFile as writeFile9 } from "node:fs/promises";
|
|
9138
|
-
import { resolve as
|
|
9139
|
-
import {
|
|
9140
|
-
import { logger as
|
|
9141
|
-
import {
|
|
9142
|
-
getSessionId,
|
|
9143
|
-
isTelemetryModuleEnabled,
|
|
9144
|
-
snapshotPreviewFile,
|
|
9145
|
-
telemetry
|
|
9146
|
-
} from "storybook/internal/telemetry";
|
|
9215
|
+
import { resolve as resolve4 } from "node:path";
|
|
9216
|
+
import { getPrettyPackageManagerName } from "storybook/internal/common";
|
|
9217
|
+
import { logger as logger22 } from "storybook/internal/node-logger";
|
|
9218
|
+
import { telemetry } from "storybook/internal/telemetry";
|
|
9147
9219
|
import { SupportedLanguage as SupportedLanguage2 } from "storybook/internal/types";
|
|
9148
9220
|
|
|
9149
9221
|
// ../create-storybook/src/services/ProjectTypeService.ts
|
|
9150
|
-
import { existsSync as
|
|
9151
|
-
import { resolve as
|
|
9222
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
9223
|
+
import { resolve as resolve3 } from "node:path";
|
|
9152
9224
|
import { ProjectType as ProjectType2 } from "storybook/internal/cli";
|
|
9153
9225
|
import { HandledError, getProjectRoot } from "storybook/internal/common";
|
|
9154
|
-
import { logger as
|
|
9226
|
+
import { logger as logger21 } from "storybook/internal/node-logger";
|
|
9155
9227
|
import { NxProjectDetectedError } from "storybook/internal/server-errors";
|
|
9156
9228
|
import { SupportedLanguage } from "storybook/internal/types";
|
|
9157
9229
|
|
|
9158
9230
|
// ../../../node_modules/empathic/find.mjs
|
|
9159
|
-
import { join as
|
|
9160
|
-
import { existsSync as
|
|
9231
|
+
import { join as join5 } from "node:path";
|
|
9232
|
+
import { existsSync as existsSync5, statSync } from "node:fs";
|
|
9161
9233
|
function up2(name, options) {
|
|
9162
9234
|
let dir, tmp, start = options && options.cwd || "";
|
|
9163
9235
|
for (dir of up(start, options))
|
|
9164
|
-
if (tmp =
|
|
9236
|
+
if (tmp = join5(dir, name), existsSync5(tmp)) return tmp;
|
|
9165
9237
|
}
|
|
9166
9238
|
|
|
9167
9239
|
// ../create-storybook/src/services/ProjectTypeService.ts
|
|
@@ -9255,15 +9327,15 @@ var ProjectTypeService = class {
|
|
|
9255
9327
|
}
|
|
9256
9328
|
];
|
|
9257
9329
|
}
|
|
9258
|
-
isStorybookInstantiated(configDir =
|
|
9259
|
-
return
|
|
9330
|
+
isStorybookInstantiated(configDir = resolve3(process.cwd(), ".storybook")) {
|
|
9331
|
+
return existsSync6(configDir);
|
|
9260
9332
|
}
|
|
9261
9333
|
async validateProvidedType(projectTypeProvided) {
|
|
9262
9334
|
if (Object.values(ProjectType2).filter(
|
|
9263
9335
|
(t10) => !["undetected", "unsupported", "nx"].includes(String(t10))
|
|
9264
9336
|
).includes(projectTypeProvided))
|
|
9265
9337
|
return projectTypeProvided;
|
|
9266
|
-
throw
|
|
9338
|
+
throw logger21.error(
|
|
9267
9339
|
`The provided project type ${projectTypeProvided} was not recognized by Storybook`
|
|
9268
9340
|
), new HandledError(`Unknown project type supplied: ${projectTypeProvided}`);
|
|
9269
9341
|
}
|
|
@@ -9271,7 +9343,7 @@ var ProjectTypeService = class {
|
|
|
9271
9343
|
try {
|
|
9272
9344
|
let detectedType = await this.detectProjectType(options);
|
|
9273
9345
|
if (detectedType === ProjectType2.UNDETECTED || detectedType === null)
|
|
9274
|
-
throw
|
|
9346
|
+
throw logger21.error(dedent16`
|
|
9275
9347
|
Unable to initialize Storybook in this directory.
|
|
9276
9348
|
|
|
9277
9349
|
Storybook couldn't detect a supported framework or configuration for your project. Make sure you're inside a framework project (e.g., React, Vue, Svelte, Angular, Next.js) and that its dependencies are installed.
|
|
@@ -9284,12 +9356,12 @@ var ProjectTypeService = class {
|
|
|
9284
9356
|
throw new NxProjectDetectedError();
|
|
9285
9357
|
return detectedType;
|
|
9286
9358
|
} catch (err) {
|
|
9287
|
-
throw err instanceof HandledError || err instanceof NxProjectDetectedError ? err : (
|
|
9359
|
+
throw err instanceof HandledError || err instanceof NxProjectDetectedError ? err : (logger21.error(String(err)), new HandledError(err instanceof Error ? err.message : String(err)));
|
|
9288
9360
|
}
|
|
9289
9361
|
}
|
|
9290
9362
|
async detectLanguage() {
|
|
9291
9363
|
let language = SupportedLanguage.JAVASCRIPT;
|
|
9292
|
-
if (
|
|
9364
|
+
if (existsSync6("jsconfig.json"))
|
|
9293
9365
|
return language;
|
|
9294
9366
|
let isTypescriptDirectDependency = !!this.jsPackageManager.getAllDependencies().typescript, getModulePackageJSONVersion = async (pkg) => (await this.jsPackageManager.getModulePackageJSON(pkg))?.version ?? null, [
|
|
9295
9367
|
typescriptVersion,
|
|
@@ -9304,9 +9376,9 @@ var ProjectTypeService = class {
|
|
|
9304
9376
|
getModulePackageJSONVersion("@typescript-eslint/parser"),
|
|
9305
9377
|
getModulePackageJSONVersion("eslint-plugin-storybook")
|
|
9306
9378
|
]), satisfies = (version2, range) => version2 ? import_semver7.default.satisfies(version2, range, { includePrerelease: !0 }) : !1;
|
|
9307
|
-
return isTypescriptDirectDependency && typescriptVersion ? satisfies(typescriptVersion, ">=4.9.0") && (!prettierVersion || import_semver7.default.gte(prettierVersion, "2.8.0")) && (!babelPluginTransformTypescriptVersion || satisfies(babelPluginTransformTypescriptVersion, ">=7.20.0")) && (!typescriptEslintParserVersion || satisfies(typescriptEslintParserVersion, ">=5.44.0")) && (!eslintPluginStorybookVersion || satisfies(eslintPluginStorybookVersion, ">=0.6.8")) ? language = SupportedLanguage.TYPESCRIPT :
|
|
9379
|
+
return isTypescriptDirectDependency && typescriptVersion ? satisfies(typescriptVersion, ">=4.9.0") && (!prettierVersion || import_semver7.default.gte(prettierVersion, "2.8.0")) && (!babelPluginTransformTypescriptVersion || satisfies(babelPluginTransformTypescriptVersion, ">=7.20.0")) && (!typescriptEslintParserVersion || satisfies(typescriptEslintParserVersion, ">=5.44.0")) && (!eslintPluginStorybookVersion || satisfies(eslintPluginStorybookVersion, ">=0.6.8")) ? language = SupportedLanguage.TYPESCRIPT : logger21.warn(
|
|
9308
9380
|
"Detected TypeScript < 4.9 or incompatible tooling, populating with JavaScript examples"
|
|
9309
|
-
) :
|
|
9381
|
+
) : existsSync6("tsconfig.json") && (language = SupportedLanguage.TYPESCRIPT), language;
|
|
9310
9382
|
}
|
|
9311
9383
|
eqMajor(versionRange, major) {
|
|
9312
9384
|
return import_semver7.default.validRange(versionRange) ? import_semver7.default.minVersion(versionRange)?.major === major : !1;
|
|
@@ -9349,7 +9421,7 @@ var ProjectTypeService = class {
|
|
|
9349
9421
|
let peerDependencySearches = [];
|
|
9350
9422
|
return Array.isArray(peerDependencies) ? peerDependencySearches = peerDependencies.map((name) => [name, void 0]) : typeof peerDependencies == "object" && (peerDependencySearches = Object.entries(peerDependencies)), peerDependencySearches.length > 0 && (matcher.peerDependencies = peerDependencySearches.map(
|
|
9351
9423
|
([name, matchFn]) => this.hasPeerDependency(packageJson, name, matchFn)
|
|
9352
|
-
)), Array.isArray(files) && files.length > 0 && (matcher.files = files.map((name) =>
|
|
9424
|
+
)), Array.isArray(files) && files.length > 0 && (matcher.files = files.map((name) => existsSync6(name))), matcherFunction(matcher) ? preset : null;
|
|
9353
9425
|
}
|
|
9354
9426
|
hasDependency(packageJson, name, matcher) {
|
|
9355
9427
|
let version2 = packageJson.dependencies?.[name] || packageJson.devDependencies?.[name];
|
|
@@ -9364,876 +9436,74 @@ var ProjectTypeService = class {
|
|
|
9364
9436
|
}
|
|
9365
9437
|
};
|
|
9366
9438
|
|
|
9367
|
-
// src/ai/
|
|
9368
|
-
import { dedent as dedent18 } from "ts-dedent";
|
|
9369
|
-
|
|
9370
|
-
// src/ai/setup-prompts/pattern-copy-play.ts
|
|
9439
|
+
// src/ai/setup-prompts/index.ts
|
|
9371
9440
|
import { dedent as dedent17 } from "ts-dedent";
|
|
9372
|
-
function getDocsMarkdownUrl(path4, projectInfo) {
|
|
9373
|
-
let { majorVersion, renderer = "react", language = "ts" } = projectInfo ?? {}, versionSegment = majorVersion ? `/${majorVersion}` : "", params = new URLSearchParams();
|
|
9374
|
-
renderer && params.set("renderer", renderer), params.set("language", language);
|
|
9375
|
-
let query = params.toString();
|
|
9376
|
-
return `https://storybook.js.org/docs${versionSegment}/${path4}.md${query ? `?${query}` : ""}`;
|
|
9377
|
-
}
|
|
9378
|
-
function getTypeImportSource(projectInfo) {
|
|
9379
|
-
return projectInfo.framework || projectInfo.rendererPackage || "@storybook/react";
|
|
9380
|
-
}
|
|
9381
|
-
function getDocsReferenceSection(projectInfo) {
|
|
9382
|
-
let docsUrl = (path4) => getDocsMarkdownUrl(path4, projectInfo);
|
|
9383
|
-
return dedent17`
|
|
9384
|
-
### Storybook Documentation Reference
|
|
9385
|
-
|
|
9386
|
-
Use the following references to look up Storybook APIs, concepts, or examples:
|
|
9387
|
-
|
|
9388
|
-
- Full docs index: https://storybook.js.org/llms.txt
|
|
9389
|
-
- See code snippets only with codeOnly=true param e.g. ${docsUrl("writing-stories")}&codeOnly=true
|
|
9390
|
-
|
|
9391
|
-
Key documentation pages for this task:
|
|
9392
|
-
- Writing stories: ${docsUrl("writing-stories")}
|
|
9393
|
-
- Decorators: ${docsUrl("writing-stories/decorators")}
|
|
9394
|
-
- Args: ${docsUrl("writing-stories/args")}
|
|
9395
|
-
- Play functions: ${docsUrl("writing-stories/play-function")}
|
|
9396
|
-
- Vitest integration: ${docsUrl("writing-tests/vitest-plugin")}
|
|
9397
|
-
|
|
9398
|
-
Fetch these URLs directly when you need guidance on Storybook APIs or patterns.
|
|
9399
|
-
`;
|
|
9400
|
-
}
|
|
9401
|
-
function getPreviewConfigExample(projectInfo) {
|
|
9402
|
-
let configDir = projectInfo.configDir, typeImport = getTypeImportSource(projectInfo);
|
|
9403
|
-
return projectInfo.hasCsfFactoryPreview ? dedent17`
|
|
9404
|
-
\`\`\`tsx
|
|
9405
|
-
// ${configDir}/preview.tsx
|
|
9406
|
-
import '../src/index.css'; // import global styles
|
|
9407
|
-
import MockDate from 'mockdate';
|
|
9408
|
-
|
|
9409
|
-
import { definePreview } from 'storybook/preview';
|
|
9410
|
-
import { SessionProvider } from '../src/contexts/SessionContext';
|
|
9411
|
-
|
|
9412
|
-
export default definePreview({
|
|
9413
|
-
decorators: [
|
|
9414
|
-
(Story) => (
|
|
9415
|
-
<SessionProvider>
|
|
9416
|
-
<Story />
|
|
9417
|
-
</SessionProvider>
|
|
9418
|
-
),
|
|
9419
|
-
],
|
|
9420
|
-
async beforeEach() {
|
|
9421
|
-
localStorage.setItem('theme', 'dark');
|
|
9422
|
-
localStorage.setItem('sidebar:open', 'true');
|
|
9423
|
-
MockDate.set('2024-04-01T12:00:00Z');
|
|
9424
|
-
},
|
|
9425
|
-
});
|
|
9426
|
-
\`\`\`
|
|
9427
|
-
` : dedent17`
|
|
9428
|
-
\`\`\`tsx
|
|
9429
|
-
// ${configDir}/preview.tsx
|
|
9430
|
-
import type { Preview } from '${typeImport}';
|
|
9431
|
-
import MockDate from 'mockdate';
|
|
9432
|
-
import '../src/index.css'; // import global styles
|
|
9433
|
-
import { SessionProvider } from '../src/contexts/SessionContext';
|
|
9434
|
-
|
|
9435
|
-
const preview: Preview = {
|
|
9436
|
-
decorators: [
|
|
9437
|
-
(Story) => (
|
|
9438
|
-
<SessionProvider>
|
|
9439
|
-
<Story />
|
|
9440
|
-
</SessionProvider>
|
|
9441
|
-
),
|
|
9442
|
-
],
|
|
9443
|
-
async beforeEach() {
|
|
9444
|
-
localStorage.setItem('theme', 'dark');
|
|
9445
|
-
localStorage.setItem('sidebar:open', 'true');
|
|
9446
|
-
MockDate.set('2024-04-01T12:00:00Z');
|
|
9447
|
-
},
|
|
9448
|
-
};
|
|
9449
|
-
|
|
9450
|
-
export default preview;
|
|
9451
|
-
\`\`\`
|
|
9452
|
-
`;
|
|
9453
|
-
}
|
|
9454
|
-
function getMockDateExample(projectInfo) {
|
|
9455
|
-
let typeImport = getTypeImportSource(projectInfo);
|
|
9456
|
-
return projectInfo.hasCsfFactoryPreview ? dedent17`
|
|
9457
|
-
\`\`\`tsx
|
|
9458
|
-
import MockDate from 'mockdate';
|
|
9459
|
-
import { definePreview } from 'storybook/preview';
|
|
9460
|
-
|
|
9461
|
-
export default definePreview({
|
|
9462
|
-
async beforeEach() {
|
|
9463
|
-
MockDate.set('2024-04-01T12:00:00Z');
|
|
9464
|
-
},
|
|
9465
|
-
});
|
|
9466
|
-
\`\`\`
|
|
9467
|
-
` : dedent17`
|
|
9468
|
-
\`\`\`tsx
|
|
9469
|
-
import type { Preview } from '${typeImport}';
|
|
9470
|
-
import MockDate from 'mockdate';
|
|
9471
|
-
|
|
9472
|
-
const preview: Preview = {
|
|
9473
|
-
async beforeEach() {
|
|
9474
|
-
MockDate.set('2024-04-01T12:00:00Z');
|
|
9475
|
-
},
|
|
9476
|
-
};
|
|
9477
|
-
|
|
9478
|
-
export default preview;
|
|
9479
|
-
\`\`\`
|
|
9480
|
-
`;
|
|
9481
|
-
}
|
|
9482
|
-
function getMswPreviewExample(projectInfo) {
|
|
9483
|
-
let configDir = projectInfo.configDir, typeImport = getTypeImportSource(projectInfo);
|
|
9484
|
-
return projectInfo.hasCsfFactoryPreview ? dedent17`
|
|
9485
|
-
\`\`\`tsx
|
|
9486
|
-
// ${configDir}/preview.tsx
|
|
9487
|
-
import { definePreview } from 'storybook/preview';
|
|
9488
|
-
import { initialize, mswLoader } from 'msw-storybook-addon';
|
|
9489
|
-
import { mswHandlers } from './msw-handlers';
|
|
9490
|
-
|
|
9491
|
-
initialize({
|
|
9492
|
-
onUnhandledRequest: 'bypass',
|
|
9493
|
-
});
|
|
9494
|
-
|
|
9495
|
-
export default definePreview({
|
|
9496
|
-
loaders: [mswLoader],
|
|
9497
|
-
parameters: {
|
|
9498
|
-
msw: {
|
|
9499
|
-
handlers: mswHandlers,
|
|
9500
|
-
},
|
|
9501
|
-
},
|
|
9502
|
-
});
|
|
9503
|
-
\`\`\`
|
|
9504
|
-
` : dedent17`
|
|
9505
|
-
\`\`\`tsx
|
|
9506
|
-
// ${configDir}/preview.tsx
|
|
9507
|
-
import type { Preview } from '${typeImport}';
|
|
9508
|
-
import { initialize, mswLoader } from 'msw-storybook-addon';
|
|
9509
|
-
import { mswHandlers } from './msw-handlers';
|
|
9510
|
-
|
|
9511
|
-
initialize({
|
|
9512
|
-
onUnhandledRequest: 'bypass',
|
|
9513
|
-
});
|
|
9514
|
-
|
|
9515
|
-
const preview: Preview = {
|
|
9516
|
-
loaders: [mswLoader],
|
|
9517
|
-
parameters: {
|
|
9518
|
-
msw: {
|
|
9519
|
-
handlers: mswHandlers,
|
|
9520
|
-
},
|
|
9521
|
-
},
|
|
9522
|
-
};
|
|
9523
|
-
|
|
9524
|
-
export default preview;
|
|
9525
|
-
\`\`\`
|
|
9526
|
-
`;
|
|
9527
|
-
}
|
|
9528
|
-
function getStoryExample(projectInfo) {
|
|
9529
|
-
if (projectInfo.hasCsfFactoryPreview)
|
|
9530
|
-
return dedent17`
|
|
9531
|
-
\`\`\`tsx
|
|
9532
|
-
import preview from '#.storybook/preview';
|
|
9533
|
-
import { expect } from 'storybook/test';
|
|
9534
|
-
import { SomeComponent } from './SomeComponent';
|
|
9535
|
-
|
|
9536
|
-
const meta = preview.meta({
|
|
9537
|
-
component: SomeComponent,
|
|
9538
|
-
tags: ['ai-generated'],
|
|
9539
|
-
});
|
|
9540
|
-
|
|
9541
|
-
export const Default = meta.story({
|
|
9542
|
-
render: () => <SomeComponent variant="primary" disabled={false} />,
|
|
9543
|
-
play: async ({ canvas }) => {
|
|
9544
|
-
await expect(canvas.getByRole('button')).toBeVisible();
|
|
9545
|
-
},
|
|
9546
|
-
});
|
|
9547
|
-
\`\`\`
|
|
9548
|
-
`;
|
|
9549
|
-
let typeImport = getTypeImportSource(projectInfo);
|
|
9550
|
-
return dedent17`
|
|
9551
|
-
\`\`\`tsx
|
|
9552
|
-
import type { Meta, StoryObj } from '${typeImport}';
|
|
9553
|
-
import { expect } from 'storybook/test';
|
|
9554
|
-
import { SomeComponent } from './SomeComponent';
|
|
9555
|
-
|
|
9556
|
-
const meta = {
|
|
9557
|
-
component: SomeComponent,
|
|
9558
|
-
tags: ['ai-generated'],
|
|
9559
|
-
} satisfies Meta<typeof SomeComponent>;
|
|
9560
|
-
|
|
9561
|
-
export default meta;
|
|
9562
|
-
type Story = StoryObj<typeof meta>;
|
|
9563
|
-
|
|
9564
|
-
export const Default: Story = {
|
|
9565
|
-
render: () => <SomeComponent variant="primary" disabled={false} />,
|
|
9566
|
-
play: async ({ canvas }) => {
|
|
9567
|
-
await expect(canvas.getByRole('button')).toBeVisible();
|
|
9568
|
-
},
|
|
9569
|
-
};
|
|
9570
|
-
\`\`\`
|
|
9571
|
-
`;
|
|
9572
|
-
}
|
|
9573
|
-
function getNeedsWorkTagExample(projectInfo) {
|
|
9574
|
-
return projectInfo.hasCsfFactoryPreview ? dedent17`
|
|
9575
|
-
\`\`\`ts
|
|
9576
|
-
const meta = preview.meta({
|
|
9577
|
-
component: SomeComponent,
|
|
9578
|
-
tags: ['ai-generated', 'needs-work'],
|
|
9579
|
-
});
|
|
9580
|
-
\`\`\`
|
|
9581
|
-
` : dedent17`
|
|
9582
|
-
\`\`\`ts
|
|
9583
|
-
const meta = {
|
|
9584
|
-
component: SomeComponent,
|
|
9585
|
-
tags: ['ai-generated', 'needs-work'],
|
|
9586
|
-
} satisfies Meta<typeof SomeComponent>;
|
|
9587
|
-
\`\`\`
|
|
9588
|
-
`;
|
|
9589
|
-
}
|
|
9590
|
-
function getArgsStoryExample(projectInfo) {
|
|
9591
|
-
if (projectInfo.hasCsfFactoryPreview)
|
|
9592
|
-
return dedent17`
|
|
9593
|
-
\`\`\`tsx
|
|
9594
|
-
import preview from '#.storybook/preview';
|
|
9595
|
-
import { expect } from 'storybook/test';
|
|
9596
|
-
import { Button } from './Button';
|
|
9597
|
-
|
|
9598
|
-
const meta = preview.meta({
|
|
9599
|
-
component: Button,
|
|
9600
|
-
tags: ['ai-generated'],
|
|
9601
|
-
});
|
|
9602
|
-
|
|
9603
|
-
export const Primary = meta.story({
|
|
9604
|
-
args: {
|
|
9605
|
-
variant: 'primary',
|
|
9606
|
-
children: 'Save',
|
|
9607
|
-
},
|
|
9608
|
-
play: async ({ canvas }) => {
|
|
9609
|
-
await expect(canvas.getByRole('button', { name: /save/i })).toBeVisible();
|
|
9610
|
-
},
|
|
9611
|
-
});
|
|
9612
|
-
|
|
9613
|
-
export const Disabled = meta.story({
|
|
9614
|
-
args: {
|
|
9615
|
-
variant: 'primary',
|
|
9616
|
-
disabled: true,
|
|
9617
|
-
children: 'Save',
|
|
9618
|
-
},
|
|
9619
|
-
play: async ({ canvas }) => {
|
|
9620
|
-
await expect(canvas.getByRole('button')).toBeDisabled();
|
|
9621
|
-
},
|
|
9622
|
-
});
|
|
9623
|
-
\`\`\`
|
|
9624
|
-
`;
|
|
9625
|
-
let typeImport = getTypeImportSource(projectInfo);
|
|
9626
|
-
return dedent17`
|
|
9627
|
-
\`\`\`tsx
|
|
9628
|
-
import type { Meta, StoryObj } from '${typeImport}';
|
|
9629
|
-
import { expect } from 'storybook/test';
|
|
9630
|
-
import { Button } from './Button';
|
|
9631
|
-
|
|
9632
|
-
const meta = {
|
|
9633
|
-
component: Button,
|
|
9634
|
-
tags: ['ai-generated'],
|
|
9635
|
-
} satisfies Meta<typeof Button>;
|
|
9636
|
-
|
|
9637
|
-
export default meta;
|
|
9638
|
-
type Story = StoryObj<typeof meta>;
|
|
9639
|
-
|
|
9640
|
-
export const Primary: Story = {
|
|
9641
|
-
args: {
|
|
9642
|
-
variant: 'primary',
|
|
9643
|
-
children: 'Save',
|
|
9644
|
-
},
|
|
9645
|
-
play: async ({ canvas }) => {
|
|
9646
|
-
await expect(canvas.getByRole('button', { name: /save/i })).toBeVisible();
|
|
9647
|
-
},
|
|
9648
|
-
};
|
|
9649
|
-
|
|
9650
|
-
export const Disabled: Story = {
|
|
9651
|
-
args: {
|
|
9652
|
-
variant: 'primary',
|
|
9653
|
-
disabled: true,
|
|
9654
|
-
children: 'Save',
|
|
9655
|
-
},
|
|
9656
|
-
play: async ({ canvas }) => {
|
|
9657
|
-
await expect(canvas.getByRole('button')).toBeDisabled();
|
|
9658
|
-
},
|
|
9659
|
-
};
|
|
9660
|
-
\`\`\`
|
|
9661
|
-
`;
|
|
9662
|
-
}
|
|
9663
|
-
function getRenderCompositionExample(projectInfo) {
|
|
9664
|
-
if (projectInfo.hasCsfFactoryPreview)
|
|
9665
|
-
return dedent17`
|
|
9666
|
-
\`\`\`tsx
|
|
9667
|
-
import preview from '#.storybook/preview';
|
|
9668
|
-
import { expect } from 'storybook/test';
|
|
9669
|
-
import { Button } from './Button';
|
|
9670
|
-
import { Card } from './Card';
|
|
9671
|
-
|
|
9672
|
-
const meta = preview.meta({
|
|
9673
|
-
component: Button,
|
|
9674
|
-
tags: ['ai-generated'],
|
|
9675
|
-
});
|
|
9676
|
-
|
|
9677
|
-
export const InsideCard = meta.story({
|
|
9678
|
-
render: () => (
|
|
9679
|
-
<Card>
|
|
9680
|
-
<Button disabled={false}>Save</Button>
|
|
9681
|
-
</Card>
|
|
9682
|
-
),
|
|
9683
|
-
play: async ({ canvas, userEvent }) => {
|
|
9684
|
-
await expect(canvas.getByRole('button', { name: /save/i })).toBeVisible();
|
|
9685
|
-
await userEvent.click(canvas.getByRole('button', { name: /save/i }));
|
|
9686
|
-
},
|
|
9687
|
-
});
|
|
9688
|
-
\`\`\`
|
|
9689
|
-
`;
|
|
9690
|
-
let typeImport = getTypeImportSource(projectInfo);
|
|
9691
|
-
return dedent17`
|
|
9692
|
-
\`\`\`tsx
|
|
9693
|
-
import type { Meta, StoryObj } from '${typeImport}';
|
|
9694
|
-
import { expect } from 'storybook/test';
|
|
9695
|
-
import { Button } from './Button';
|
|
9696
|
-
import { Card } from './Card';
|
|
9697
|
-
|
|
9698
|
-
const meta = {
|
|
9699
|
-
component: Button,
|
|
9700
|
-
tags: ['ai-generated'],
|
|
9701
|
-
} satisfies Meta<typeof Button>;
|
|
9702
|
-
|
|
9703
|
-
export default meta;
|
|
9704
|
-
type Story = StoryObj<typeof meta>;
|
|
9705
|
-
|
|
9706
|
-
export const InsideCard: Story = {
|
|
9707
|
-
render: () => (
|
|
9708
|
-
<Card>
|
|
9709
|
-
<Button disabled={false}>Save</Button>
|
|
9710
|
-
</Card>
|
|
9711
|
-
),
|
|
9712
|
-
play: async ({ canvas, userEvent }) => {
|
|
9713
|
-
await expect(canvas.getByRole('button', { name: /save/i })).toBeVisible();
|
|
9714
|
-
await userEvent.click(canvas.getByRole('button', { name: /save/i }));
|
|
9715
|
-
},
|
|
9716
|
-
};
|
|
9717
|
-
\`\`\`
|
|
9718
|
-
`;
|
|
9719
|
-
}
|
|
9720
|
-
function getPageStoryExample(projectInfo) {
|
|
9721
|
-
if (projectInfo.hasCsfFactoryPreview)
|
|
9722
|
-
return dedent17`
|
|
9723
|
-
\`\`\`tsx
|
|
9724
|
-
import preview from '#.storybook/preview';
|
|
9725
|
-
import { expect } from 'storybook/test';
|
|
9726
|
-
import { ProductPage } from './ProductPage';
|
|
9727
|
-
|
|
9728
|
-
const meta = preview.meta({
|
|
9729
|
-
component: ProductPage,
|
|
9730
|
-
tags: ['ai-generated'],
|
|
9731
|
-
});
|
|
9732
|
-
|
|
9733
|
-
export const Default = meta.story({
|
|
9734
|
-
render: () => <ProductPage />,
|
|
9735
|
-
play: async ({ canvas }) => {
|
|
9736
|
-
await expect(
|
|
9737
|
-
canvas.getByRole('heading', { name: /products/i }),
|
|
9738
|
-
).toBeVisible();
|
|
9739
|
-
},
|
|
9740
|
-
});
|
|
9741
|
-
\`\`\`
|
|
9742
|
-
`;
|
|
9743
|
-
let typeImport = getTypeImportSource(projectInfo);
|
|
9744
|
-
return dedent17`
|
|
9745
|
-
\`\`\`tsx
|
|
9746
|
-
import type { Meta, StoryObj } from '${typeImport}';
|
|
9747
|
-
import { expect } from 'storybook/test';
|
|
9748
|
-
import { ProductPage } from './ProductPage';
|
|
9749
|
-
|
|
9750
|
-
const meta = {
|
|
9751
|
-
component: ProductPage,
|
|
9752
|
-
tags: ['ai-generated'],
|
|
9753
|
-
} satisfies Meta<typeof ProductPage>;
|
|
9754
|
-
|
|
9755
|
-
export default meta;
|
|
9756
|
-
type Story = StoryObj<typeof meta>;
|
|
9757
|
-
|
|
9758
|
-
export const Default: Story = {
|
|
9759
|
-
render: () => <ProductPage />,
|
|
9760
|
-
play: async ({ canvas }) => {
|
|
9761
|
-
await expect(
|
|
9762
|
-
canvas.getByRole('heading', { name: /products/i }),
|
|
9763
|
-
).toBeVisible();
|
|
9764
|
-
},
|
|
9765
|
-
};
|
|
9766
|
-
\`\`\`
|
|
9767
|
-
`;
|
|
9768
|
-
}
|
|
9769
|
-
function instructions(projectInfo) {
|
|
9770
|
-
let configDir = projectInfo.configDir, typeImport = getTypeImportSource(projectInfo);
|
|
9771
|
-
return dedent17`
|
|
9772
|
-
Attention: The following instructions must be followed in order to successfully set up Storybook in this project. Do not skip steps or attempt to do them out of order.
|
|
9773
|
-
|
|
9774
|
-
Your goal is to make Storybook fully functional in this project by analyzing the codebase,
|
|
9775
|
-
configuring the preview with the right decorators, and writing stories for some components.
|
|
9776
|
-
|
|
9777
|
-
The end state should be a Storybook where any component — from a small button to a full page — can be added without story-specific workarounds. All necessary providers, CSS, browser state, and network mocks should live in the shared preview so that just rendering the component in the story is enough.
|
|
9778
|
-
|
|
9779
|
-
After each created story, run Vitest to verify it renders.
|
|
9780
|
-
If the test fails, read the error, fix the issue, and re-run until it passes before moving on.
|
|
9781
9441
|
|
|
9782
|
-
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
- which CSS files are injected
|
|
9798
|
-
- which queries fetch data
|
|
9799
|
-
- which browser-state reads happen
|
|
9800
|
-
- which portals and portal roots exist
|
|
9801
|
-
- which pages and components show the real usage patterns
|
|
9802
|
-
|
|
9803
|
-
Example of what to copy:
|
|
9804
|
-
|
|
9805
|
-
\`\`\`tsx
|
|
9806
|
-
// src/main.tsx
|
|
9807
|
-
import "./index.css";
|
|
9808
|
-
import App from "./App";
|
|
9809
|
-
import { SessionProvider } from "./contexts/SessionContext";
|
|
9810
|
-
|
|
9811
|
-
createRoot(document.getElementById("root")!).render(
|
|
9812
|
-
<SessionProvider>
|
|
9813
|
-
<App />
|
|
9814
|
-
</SessionProvider>,
|
|
9815
|
-
);
|
|
9816
|
-
\`\`\`
|
|
9817
|
-
|
|
9818
|
-
That means Storybook should copy:
|
|
9819
|
-
|
|
9820
|
-
- the \`index.css\` import
|
|
9821
|
-
- the \`SessionProvider\`
|
|
9822
|
-
- the same provider order
|
|
9823
|
-
|
|
9824
|
-
Example of tracing the app deeper:
|
|
9825
|
-
|
|
9826
|
-
\`\`\`tsx
|
|
9827
|
-
// src/App.tsx
|
|
9828
|
-
function App() {
|
|
9829
|
-
const { products, loadMoreProducts } = useProducts();
|
|
9830
|
-
const { currentUser, signOut } = useSession();
|
|
9831
|
-
// ...
|
|
9832
|
-
}
|
|
9833
|
-
\`\`\`
|
|
9834
|
-
|
|
9835
|
-
\`\`\`ts
|
|
9836
|
-
// src/hooks/useProducts.ts
|
|
9837
|
-
const response = await fetch(apiBaseUrl + "/products?page=1");
|
|
9838
|
-
\`\`\`
|
|
9839
|
-
|
|
9840
|
-
\`\`\`ts
|
|
9841
|
-
// src/hooks/useTheme.ts
|
|
9842
|
-
const savedTheme = localStorage.getItem("theme");
|
|
9843
|
-
\`\`\`
|
|
9844
|
-
|
|
9845
|
-
That means the default Storybook setup should discover and prepare:
|
|
9846
|
-
|
|
9847
|
-
- provider state
|
|
9848
|
-
- MSW handlers for queries
|
|
9849
|
-
- browser-state values that are actually read during render
|
|
9850
|
-
|
|
9851
|
-
### Step 2: Build one default app environment in preview
|
|
9852
|
-
|
|
9853
|
-
Set up Storybook once so most stories work without story-specific setup.
|
|
9854
|
-
|
|
9855
|
-
Start with the smallest faithful environment:
|
|
9856
|
-
|
|
9857
|
-
- the real provider tree
|
|
9858
|
-
- the real root CSS
|
|
9859
|
-
- seeded browser state if the app reads it during render
|
|
9860
|
-
- MSW for network/data queries
|
|
9861
|
-
|
|
9862
|
-
It is fine to seed browser state such as \`localStorage\`, \`sessionStorage\`, and cookies when the app reads them during render.
|
|
9863
|
-
Seed only the specific app-owned keys and values you need.
|
|
9864
|
-
Do not clear all \`localStorage\`, \`sessionStorage\`, or cookies, and do not reset Storybook's own state.
|
|
9865
|
-
Do not mock or redefine the browser runtime itself.
|
|
9866
|
-
The stories run in Vitest browser mode, so the real browser environment should already exist.
|
|
9867
|
-
|
|
9868
|
-
${getPreviewConfigExample(projectInfo)}
|
|
9869
|
-
|
|
9870
|
-
Use this same idea for:
|
|
9871
|
-
|
|
9872
|
-
- providers
|
|
9873
|
-
- root CSS
|
|
9874
|
-
- browser state
|
|
9875
|
-
- dates, and if the app logic depends on them during render then always use \`mockdate\`
|
|
9876
|
-
|
|
9877
|
-
Example with the \`mockdate\` package:
|
|
9878
|
-
|
|
9879
|
-
${getMockDateExample(projectInfo)}
|
|
9880
|
-
|
|
9881
|
-
### Step 3: Support portals with preview-body.html
|
|
9882
|
-
|
|
9883
|
-
If the app uses portals, copy that setup into Storybook too.
|
|
9884
|
-
|
|
9885
|
-
Look for patterns like:
|
|
9886
|
-
|
|
9887
|
-
- \`createPortal(...)\`
|
|
9888
|
-
- modal, dialog, drawer, popover, tooltip, toast, or dropdown portal components
|
|
9889
|
-
- hard-coded roots such as \`#portal-root\`, \`#modal-root\`, \`#drawer-root\`, or \`#toast-root\`
|
|
9890
|
-
|
|
9891
|
-
Example of what to copy:
|
|
9892
|
-
|
|
9893
|
-
\`\`\`tsx
|
|
9894
|
-
// real component
|
|
9895
|
-
return createPortal(<ModalContent />, document.getElementById("portal-root")!);
|
|
9896
|
-
\`\`\`
|
|
9897
|
-
|
|
9898
|
-
That means Storybook should create the same portal root in \`${configDir}/preview-body.html\`:
|
|
9899
|
-
|
|
9900
|
-
\`\`\`html
|
|
9901
|
-
<!-- ${configDir}/preview-body.html -->
|
|
9902
|
-
<div id="portal-root"></div>
|
|
9903
|
-
\`\`\`
|
|
9904
|
-
|
|
9905
|
-
If the app uses multiple portal roots, create all of them there:
|
|
9906
|
-
|
|
9907
|
-
\`\`\`html
|
|
9908
|
-
<!-- ${configDir}/preview-body.html -->
|
|
9909
|
-
<div id="modal-root"></div>
|
|
9910
|
-
<div id="drawer-root"></div>
|
|
9911
|
-
<div id="toast-root"></div>
|
|
9912
|
-
\`\`\`
|
|
9913
|
-
|
|
9914
|
-
If a library portals directly to \`document.body\`, do not add extra roots for it.
|
|
9915
|
-
Make sure the copied page shell, CSS, and layout still allow overlays, fixed positioning, and z-index stacking to render correctly.
|
|
9916
|
-
|
|
9917
|
-
### Step 4: Mock side effects globally
|
|
9918
|
-
|
|
9919
|
-
All network/data queries should be handled by the default Storybook environment.
|
|
9920
|
-
|
|
9921
|
-
- Always use \`msw-storybook-addon\` for query mocking.
|
|
9922
|
-
- If you introduce MSW, run \`npx msw init ./public --save\` to create the worker file.
|
|
9923
|
-
- Make sure Storybook serves \`./public\` as a static dir so \`mockServiceWorker.js\` is available.
|
|
9924
|
-
- Do not mock \`fetch\` directly.
|
|
9925
|
-
- Network/data queries should return deterministic mock data.
|
|
9926
|
-
- If you need to change dependencies, first check the lockfile and use that package manager for the change.
|
|
9927
|
-
|
|
9928
|
-
Example of copying a real fetch pattern into shared handlers:
|
|
9929
|
-
|
|
9930
|
-
\`\`\`ts
|
|
9931
|
-
// real app hook
|
|
9932
|
-
const response = await fetch(
|
|
9933
|
-
apiBaseUrl +
|
|
9934
|
-
"/products?" +
|
|
9935
|
-
new URLSearchParams({
|
|
9936
|
-
page: "1",
|
|
9937
|
-
sort: "featured",
|
|
9938
|
-
}),
|
|
9939
|
-
);
|
|
9940
|
-
\`\`\`
|
|
9941
|
-
|
|
9942
|
-
\`\`\`ts
|
|
9943
|
-
// ${configDir}/msw-handlers.ts
|
|
9944
|
-
import { http, HttpResponse } from "msw";
|
|
9945
|
-
|
|
9946
|
-
export const mswHandlers = {
|
|
9947
|
-
products: [
|
|
9948
|
-
http.get("https://api.example.com/products", () =>
|
|
9949
|
-
HttpResponse.json({
|
|
9950
|
-
items: [
|
|
9951
|
-
{
|
|
9952
|
-
id: "product-1",
|
|
9953
|
-
name: "Example product",
|
|
9954
|
-
description: "Mock product description",
|
|
9955
|
-
imageUrl: "https://images.example.com/product.jpg",
|
|
9956
|
-
price: 42,
|
|
9957
|
-
},
|
|
9958
|
-
],
|
|
9959
|
-
}),
|
|
9960
|
-
),
|
|
9961
|
-
],
|
|
9962
|
-
};
|
|
9963
|
-
\`\`\`
|
|
9964
|
-
|
|
9965
|
-
${getMswPreviewExample(projectInfo)}
|
|
9966
|
-
|
|
9967
|
-
\`\`\`ts
|
|
9968
|
-
// ${configDir}/main.ts
|
|
9969
|
-
import type { StorybookConfig } from "${typeImport}";
|
|
9970
|
-
|
|
9971
|
-
const config: StorybookConfig = {
|
|
9972
|
-
staticDirs: ["../public"],
|
|
9973
|
-
};
|
|
9974
|
-
|
|
9975
|
-
export default config;
|
|
9976
|
-
\`\`\`
|
|
9977
|
-
|
|
9978
|
-
Keep these mocks global.
|
|
9979
|
-
Do not put fetch mocks in individual stories.
|
|
9980
|
-
Only add handlers for requests that the shared preview setup or the stories actually use.
|
|
9981
|
-
Do not add catch-all handlers that can hide unrelated failures.
|
|
9982
|
-
If the defaults are not enough, improve the shared default setup instead.
|
|
9983
|
-
Seed browser state when needed, but do not mock \`window\`, \`document\`, \`navigator\`, observers, or similar runtime APIs.
|
|
9984
|
-
The only exception is \`mockdate\` when date-based rendering exists.
|
|
9985
|
-
|
|
9986
|
-
### Step 5: Write stories
|
|
9987
|
-
|
|
9988
|
-
Try to find around 10 good candidate components for story files.
|
|
9989
|
-
Write colocated stories for top-level components, from low-level reusable components up to page components.
|
|
9990
|
-
Write up to 10 story files, or fewer only if the codebase clearly has fewer meaningful targets.
|
|
9991
|
-
|
|
9992
|
-
The stories should use JSX copied from real usage patterns in:
|
|
9993
|
-
|
|
9994
|
-
- pages
|
|
9995
|
-
- app shells
|
|
9996
|
-
- routes
|
|
9997
|
-
- tests
|
|
9998
|
-
- existing feature code
|
|
9999
|
-
|
|
10000
|
-
As a rule of thumb, each story file should have around 3 story exports when the component or page has enough meaningful states.
|
|
10001
|
-
It can have more when the real usage supports it, up to 10 story exports in one file.
|
|
10002
|
-
|
|
10003
|
-
Always show all imports explicitly in story and preview files.
|
|
10004
|
-
Do not rely on omitted or implied imports in examples or generated code.
|
|
10005
|
-
|
|
10006
|
-
#### Story tags
|
|
10007
|
-
|
|
10008
|
-
Every story meta must include the \`ai-generated\` tag to identify AI-created stories:
|
|
10009
|
-
|
|
10010
|
-
${getStoryExample(projectInfo)}
|
|
10011
|
-
|
|
10012
|
-
If a story could not be fully fixed after the self-healing loop (the test still fails
|
|
10013
|
-
or the rendering is incomplete), add the \`needs-work\` tag alongside \`ai-generated\`:
|
|
10014
|
-
|
|
10015
|
-
${getNeedsWorkTagExample(projectInfo)}
|
|
10016
|
-
|
|
10017
|
-
#### Args vs render
|
|
10018
|
-
|
|
10019
|
-
For simple components where props drive the state, prefer \`args\` stories — no \`render\` function needed:
|
|
10020
|
-
|
|
10021
|
-
${getArgsStoryExample(projectInfo)}
|
|
10022
|
-
|
|
10023
|
-
Use \`render\` when the story needs composition — wrapping the component in layout, combining multiple components, or passing children as JSX:
|
|
10024
|
-
|
|
10025
|
-
${getRenderCompositionExample(projectInfo)}
|
|
10026
|
-
|
|
10027
|
-
Keep app mocking and runtime setup in preview, not in the stories.
|
|
10028
|
-
Do not build large story-specific harnesses.
|
|
10029
|
-
Do not write story files for subcomponents, hooks, contexts, or helpers.
|
|
10030
|
-
Do not create new application components.
|
|
10031
|
-
Do not add a custom \`title\`.
|
|
10032
|
-
Do not stop after only a few easy targets if the codebase has more meaningful components or pages available.
|
|
10033
|
-
|
|
10034
|
-
### Step 6: Write a play function for every story
|
|
10035
|
-
|
|
10036
|
-
Every named story export must have a \`play\` function.
|
|
10037
|
-
The \`play\` function is not optional, even for simple stories.
|
|
10038
|
-
|
|
10039
|
-
The purpose of the \`play\` function is to prove that the story actually works in the copied Storybook environment:
|
|
10040
|
-
|
|
10041
|
-
- the story renders something real and non-empty
|
|
10042
|
-
- the decorators provide the needed context
|
|
10043
|
-
- the CSS is applied well enough for the intended state to be visible
|
|
10044
|
-
- the MSW mocks or seeded browser state are actually being used
|
|
10045
|
-
- important interactions, async loading states, and portals behave correctly
|
|
10046
|
-
|
|
10047
|
-
Use \`play\` functions to verify behavior, not just to click around.
|
|
10048
|
-
A story without assertions is incomplete.
|
|
10049
|
-
|
|
10050
|
-
Use tools from \`storybook/test\` such as:
|
|
10051
|
-
|
|
10052
|
-
- \`expect\`
|
|
10053
|
-
- \`waitFor\`
|
|
10054
|
-
|
|
10055
|
-
Prefer \`canvas\` and \`userEvent\` from the \`play\` context.
|
|
10056
|
-
Do not destructure \`canvasElement\` just to create \`const canvas = within(canvasElement)\`.
|
|
10057
|
-
Do not import \`userEvent\` from \`storybook/test\`; use \`userEvent\` from the \`play\` context instead.
|
|
10058
|
-
Only use \`canvasElement.ownerDocument\` when you need to query outside the canvas, such as for portals.
|
|
10059
|
-
|
|
10060
|
-
Example:
|
|
10061
|
-
|
|
10062
|
-
\`\`\`tsx
|
|
10063
|
-
import type { StoryObj } from "${typeImport}";
|
|
10064
|
-
|
|
10065
|
-
export const FilledForm: Story = {
|
|
10066
|
-
play: async ({ canvas, userEvent }) => {
|
|
10067
|
-
const emailInput = canvas.getByLabelText("email", {
|
|
10068
|
-
selector: "input",
|
|
10069
|
-
});
|
|
10070
|
-
|
|
10071
|
-
await userEvent.type(emailInput, "example-email@email.com", {
|
|
10072
|
-
delay: 100,
|
|
10073
|
-
});
|
|
10074
|
-
|
|
10075
|
-
const passwordInput = canvas.getByLabelText("password", {
|
|
10076
|
-
selector: "input",
|
|
10077
|
-
});
|
|
10078
|
-
|
|
10079
|
-
await userEvent.type(passwordInput, "ExamplePassword", {
|
|
10080
|
-
delay: 100,
|
|
10081
|
-
});
|
|
10082
|
-
|
|
10083
|
-
const submitButton = canvas.getByRole("button");
|
|
10084
|
-
await userEvent.click(submitButton);
|
|
10085
|
-
},
|
|
10086
|
-
};
|
|
10087
|
-
\`\`\`
|
|
10088
|
-
|
|
10089
|
-
The assertions should match the real pattern you copied:
|
|
10090
|
-
|
|
10091
|
-
- for provider-backed stories, assert the provider-dependent UI appears correctly
|
|
10092
|
-
- for mocked-data stories, wait for the mocked data to appear and assert on it
|
|
10093
|
-
- for CSS-sensitive states, assert on visibility, text layout, class-driven states, or meaningful computed styles
|
|
10094
|
-
- for routing or navigation stories, assert the routed state or navigation outcome
|
|
10095
|
-
- for portal stories, query from \`canvasElement.ownerDocument\` when the UI renders outside the canvas
|
|
10096
|
-
|
|
10097
|
-
Examples of useful checks:
|
|
10098
|
-
|
|
10099
|
-
- a themed button has the expected label and is visibly enabled or disabled
|
|
10100
|
-
- a modal opened through a decorator or provider is visible in the portal root
|
|
10101
|
-
- mocked API data appears in the page instead of a loading spinner forever
|
|
10102
|
-
- a selected tab actually shows the selected panel
|
|
10103
|
-
- a toast, alert, or badge has the expected accessible text and visual state
|
|
10104
|
-
- a CSS class or computed style confirms the real state that matters
|
|
10105
|
-
|
|
10106
|
-
### Step 7: Prove CSS is loaded in exactly one story named \`CssCheck\`
|
|
10107
|
-
|
|
10108
|
-
In exactly one story, named \`CssCheck\`, assert a component-specific computed style. \`toBeVisible\` passes on an unstyled component; a concrete style value proves the shared preview loaded the app's CSS.
|
|
10109
|
-
|
|
10110
|
-
Pick a visually distinctive component, read a styling value from its source, and assert it with \`getComputedStyle\`:
|
|
10111
|
-
|
|
10112
|
-
\`\`\`tsx
|
|
10113
|
-
export const CssCheck: Story = {
|
|
10114
|
-
args: { children: "Submit" },
|
|
10115
|
-
play: async ({ canvas }) => {
|
|
10116
|
-
const button = canvas.getByRole("button", { name: /submit/i });
|
|
10117
|
-
// PrimaryButton uses bg-blue-600 — fails if Tailwind / global CSS did not load.
|
|
10118
|
-
await expect(getComputedStyle(button).backgroundColor).toBe("rgb(37, 99, 235)");
|
|
10119
|
-
},
|
|
10120
|
-
};
|
|
10121
|
-
\`\`\`
|
|
10122
|
-
|
|
10123
|
-
### Step 8: Cover the patterns you found
|
|
10124
|
-
|
|
10125
|
-
Write stories for the real patterns in the codebase, for example:
|
|
10126
|
-
|
|
10127
|
-
- a low-level reusable component in real JSX usage
|
|
10128
|
-
- a provider-backed component
|
|
10129
|
-
- a browser-state-backed component
|
|
10130
|
-
- a fetched-data component
|
|
10131
|
-
- a real page component
|
|
10132
|
-
|
|
10133
|
-
Use \`App.tsx\` to inspect the real provider tree and usage patterns, but do not make a story for \`App\` when the codebase has actual page components.
|
|
10134
|
-
|
|
10135
|
-
Example page story:
|
|
10136
|
-
|
|
10137
|
-
${getPageStoryExample(projectInfo)}
|
|
10138
|
-
|
|
10139
|
-
### Step 9: Verify both rendering and types
|
|
10140
|
-
|
|
10141
|
-
As you work, verify the stories with Vitest:
|
|
10142
|
-
|
|
10143
|
-
\`\`\`bash
|
|
10144
|
-
npx vitest --project storybook <path-to-story-file>
|
|
10145
|
-
\`\`\`
|
|
10146
|
-
|
|
10147
|
-
Also verify types so you catch missing required props, broken imports, and preview typing issues. Run the same TypeScript command the project itself uses.
|
|
10148
|
-
|
|
10149
|
-
\`\`\`bash
|
|
10150
|
-
<project-specific-typescript-command>
|
|
10151
|
-
\`\`\`
|
|
10152
|
-
|
|
10153
|
-
After verification passes, review every changed file and remove anything that is not needed for the final solution, especially debug fixes, overly broad mocks, unnecessary dependencies, and eval artifacts.
|
|
10154
|
-
|
|
10155
|
-
Keep iterating until:
|
|
10156
|
-
|
|
10157
|
-
- every story you wrote passes
|
|
10158
|
-
- every story you wrote has a meaningful passing \`play\` function
|
|
10159
|
-
- the changed stories and preview setup pass the project's real TypeScript check
|
|
10160
|
-
- the rendered output looks sensible
|
|
10161
|
-
- the default global mocked environment is strong enough that stories do not need manual fetch overrides
|
|
10162
|
-
- stories no longer fail because the shared preview setup and story JSX are fixed
|
|
10163
|
-
- all passing stories have \`tags: ['ai-generated']\` in their meta
|
|
10164
|
-
- any stories that still need work have \`tags: ['ai-generated', 'needs-work']\` in their meta
|
|
10165
|
-
`;
|
|
9442
|
+
// src/ai/utils/project-overview.ts
|
|
9443
|
+
function getProjectOverview(projectInfo) {
|
|
9444
|
+
let rows = [
|
|
9445
|
+
["Version", projectInfo.storybookVersion || "unknown"],
|
|
9446
|
+
["Renderer", projectInfo.rendererPackage || "unknown"],
|
|
9447
|
+
["Framework", projectInfo.framework || "unknown"],
|
|
9448
|
+
["Builder", projectInfo.builderPackage || "unknown"],
|
|
9449
|
+
["Config Dir", `\`${projectInfo.configDir}\``],
|
|
9450
|
+
["Language", projectInfo.language === "ts" ? "TypeScript" : "JavaScript"]
|
|
9451
|
+
];
|
|
9452
|
+
return projectInfo.packageManager && rows.push(["Package Manager", projectInfo.packageManagerName || "unknown"]), rows.push(["Addons", projectInfo.addons.length > 0 ? projectInfo.addons.join(", ") : "none"]), ["## Project Info", "", "| Property | Value |", "|----------|-------|", rows.map(([key, value]) => `| ${key} | ${value} |`).join(`
|
|
9453
|
+
`)].join(
|
|
9454
|
+
`
|
|
9455
|
+
`
|
|
9456
|
+
);
|
|
10166
9457
|
}
|
|
10167
9458
|
|
|
10168
9459
|
// src/ai/setup-prompts/index.ts
|
|
10169
|
-
var CURRENTLY_USED_PROMPT = {
|
|
10170
|
-
|
|
9460
|
+
var DEFAULT_PROMPT_NAME = "pattern-copy-play", CURRENTLY_USED_PROMPT = {
|
|
9461
|
+
[DEFAULT_PROMPT_NAME]: instructions
|
|
10171
9462
|
}, FORMERLY_USED_PROMPTS = {
|
|
10172
|
-
|
|
9463
|
+
monorepo: async () => (await import("./monorepo-4B4ULRGC.js")).instructions,
|
|
9464
|
+
"optimized-tests": async () => (await import("./optimized-tests-MJI5NXQA.js")).instructions,
|
|
9465
|
+
"relaxed-limits": async () => (await import("./relaxed-limits-MKAIPGR2.js")).instructions,
|
|
9466
|
+
setup: async () => (await import("./setup-PUNMMEGI.js")).instructions,
|
|
9467
|
+
"pattern-copy-play": async () => (await import("./pattern-copy-play-JNOATHUQ.js")).instructions
|
|
10173
9468
|
}, PROMPT_NAMES = [
|
|
10174
9469
|
...Object.keys(CURRENTLY_USED_PROMPT),
|
|
10175
9470
|
...Object.keys(FORMERLY_USED_PROMPTS)
|
|
10176
|
-
],
|
|
9471
|
+
], EVAL_SETUP_PROMPT_ENV = "EVAL_SETUP_PROMPT";
|
|
10177
9472
|
function resolvePromptName() {
|
|
10178
9473
|
let requested = process.env[EVAL_SETUP_PROMPT_ENV]?.trim();
|
|
10179
9474
|
return requested && (Object.hasOwn(CURRENTLY_USED_PROMPT, requested) || Object.hasOwn(FORMERLY_USED_PROMPTS, requested)) ? requested : DEFAULT_PROMPT_NAME;
|
|
10180
9475
|
}
|
|
10181
|
-
async function
|
|
10182
|
-
let name = resolvePromptName()
|
|
10183
|
-
return
|
|
10184
|
-
prompts: [
|
|
10185
|
-
{
|
|
10186
|
-
name,
|
|
10187
|
-
description: "Set up Storybook for success",
|
|
10188
|
-
instructions: builder(projectInfo)
|
|
10189
|
-
}
|
|
10190
|
-
]
|
|
10191
|
-
};
|
|
9476
|
+
async function getAiSetupPrompt(projectInfo) {
|
|
9477
|
+
let name = resolvePromptName();
|
|
9478
|
+
return (CURRENTLY_USED_PROMPT[name] ?? await FORMERLY_USED_PROMPTS[name]())(projectInfo);
|
|
10192
9479
|
}
|
|
10193
|
-
|
|
10194
|
-
|
|
10195
|
-
|
|
10196
|
-
return dedent18`
|
|
10197
|
-
## Project Info
|
|
10198
|
-
|
|
10199
|
-
| Property | Value |
|
|
10200
|
-
|----------|-------|
|
|
10201
|
-
| Version | ${projectInfo.storybookVersion || "unknown"} |
|
|
10202
|
-
| Renderer | ${projectInfo.rendererPackage || "unknown"} |
|
|
10203
|
-
| Framework | ${projectInfo.framework || "unknown"} |
|
|
10204
|
-
| Builder | ${projectInfo.builderPackage || "unknown"} |
|
|
10205
|
-
| Config Dir | \`${projectInfo.configDir}\` |
|
|
10206
|
-
| CSF Format | ${projectInfo.hasCsfFactoryPreview ? "CSF Factory" : "CSF3"} |
|
|
10207
|
-
| Addons | ${projectInfo.addons.length > 0 ? projectInfo.addons.join(", ") : "none"} |
|
|
10208
|
-
`;
|
|
10209
|
-
}
|
|
10210
|
-
async function generateMarkdownOutput(projectInfo) {
|
|
10211
|
-
let { prompts: aiPrompts } = await getPrompts(projectInfo), sections = [];
|
|
10212
|
-
sections.push(dedent18`
|
|
9480
|
+
async function getAiSetupMarkdownOutput(projectInfo) {
|
|
9481
|
+
return {
|
|
9482
|
+
markdown: dedent17`
|
|
10213
9483
|
# Storybook Setup
|
|
10214
|
-
`), sections.push(getProjectOverview(projectInfo));
|
|
10215
|
-
for (let aiPrompt of aiPrompts)
|
|
10216
|
-
sections.push(aiPrompt.instructions);
|
|
10217
|
-
return { markdown: sections.join(`
|
|
10218
9484
|
|
|
10219
|
-
|
|
9485
|
+
${getProjectOverview(projectInfo)}
|
|
9486
|
+
|
|
9487
|
+
${await getAiSetupPrompt(projectInfo)}
|
|
9488
|
+
`
|
|
9489
|
+
};
|
|
10220
9490
|
}
|
|
10221
9491
|
|
|
10222
9492
|
// src/ai/index.ts
|
|
10223
9493
|
async function aiSetup(options) {
|
|
10224
|
-
let { configDir: userConfigDir, packageManager
|
|
9494
|
+
let { configDir: userConfigDir, packageManager, output } = options, projectInfo;
|
|
10225
9495
|
try {
|
|
10226
9496
|
let data = await getStorybookData({
|
|
10227
9497
|
configDir: userConfigDir,
|
|
10228
|
-
packageManagerName
|
|
10229
|
-
})
|
|
9498
|
+
packageManagerName: packageManager
|
|
9499
|
+
});
|
|
10230
9500
|
if (!data.frameworkPackage || !data.rendererPackage || !data.builderPackage) {
|
|
10231
|
-
|
|
9501
|
+
logger22.error(
|
|
10232
9502
|
"Could not detect framework, renderer, or builder from your Storybook config. Make sure you are running this command from your project root, or specify --config-dir."
|
|
10233
9503
|
);
|
|
10234
9504
|
return;
|
|
10235
9505
|
}
|
|
10236
|
-
let language = await new ProjectTypeService(data.packageManager).detectLanguage() === SupportedLanguage2.TYPESCRIPT ? "ts" : "js";
|
|
9506
|
+
let majorVersion = data.versionInstalled ? parseMajorVersion(data.versionInstalled) : void 0, language = await new ProjectTypeService(data.packageManager).detectLanguage() === SupportedLanguage2.TYPESCRIPT ? "ts" : "js";
|
|
10237
9507
|
projectInfo = {
|
|
10238
9508
|
storybookVersion: data.versionInstalled,
|
|
10239
9509
|
majorVersion,
|
|
@@ -10244,51 +9514,44 @@ async function aiSetup(options) {
|
|
|
10244
9514
|
addons: data.addons ?? [],
|
|
10245
9515
|
configDir: data.configDir,
|
|
10246
9516
|
storiesPaths: data.storiesPaths,
|
|
10247
|
-
|
|
10248
|
-
|
|
9517
|
+
packageManager: data.packageManager,
|
|
9518
|
+
packageManagerName: getPrettyPackageManagerName(data.packageManager.type),
|
|
9519
|
+
language,
|
|
9520
|
+
hasCsfFactoryPreview: data.hasCsfFactoryPreview
|
|
10249
9521
|
};
|
|
10250
9522
|
} catch (err) {
|
|
10251
|
-
|
|
9523
|
+
logger22.error(
|
|
10252
9524
|
`Failed to read Storybook configuration: ${err instanceof Error ? err.message : String(err)}`
|
|
10253
|
-
),
|
|
9525
|
+
), logger22.log(
|
|
10254
9526
|
"Make sure you are running this command from your project root, or specify --config-dir."
|
|
10255
9527
|
);
|
|
10256
9528
|
return;
|
|
10257
9529
|
}
|
|
10258
9530
|
if (projectInfo.rendererPackage !== "@storybook/react" || projectInfo.builderPackage !== "@storybook/builder-vite") {
|
|
10259
|
-
|
|
9531
|
+
logger22.log(
|
|
10260
9532
|
"AI-assisted setup is currently only available for projects using the React renderer with Vite builder. Detected renderer: " + projectInfo.rendererPackage + ", builder: " + projectInfo.builderPackage
|
|
10261
9533
|
);
|
|
10262
9534
|
return;
|
|
10263
9535
|
}
|
|
10264
|
-
let markdownOutput = (await
|
|
9536
|
+
let markdownOutput = (await getAiSetupMarkdownOutput(projectInfo)).markdown;
|
|
10265
9537
|
if (await telemetry("ai-setup", {
|
|
10266
9538
|
cliOptions: {
|
|
10267
9539
|
output: output ? "file" : void 0,
|
|
10268
9540
|
configDir: projectInfo.configDir,
|
|
10269
|
-
packageManager:
|
|
9541
|
+
packageManager: projectInfo.packageManager.type
|
|
10270
9542
|
},
|
|
10271
9543
|
project: {
|
|
10272
9544
|
framework: projectInfo.framework,
|
|
10273
9545
|
renderer: projectInfo.rendererPackage,
|
|
10274
9546
|
builder: projectInfo.builderPackage,
|
|
10275
|
-
language: projectInfo.language
|
|
10276
|
-
hasCsfFactoryPreview: projectInfo.hasCsfFactoryPreview
|
|
9547
|
+
language: projectInfo.language
|
|
10277
9548
|
}
|
|
10278
|
-
}),
|
|
10279
|
-
let
|
|
10280
|
-
|
|
10281
|
-
sessionId,
|
|
10282
|
-
configDir: resolvedConfigDir,
|
|
10283
|
-
...previewSnapshot
|
|
10284
|
-
};
|
|
10285
|
-
await cache.set("ai-setup-pending", pendingRecord);
|
|
10286
|
-
}
|
|
10287
|
-
if (output) {
|
|
10288
|
-
let outputPath = resolve3(output);
|
|
10289
|
-
await writeFile9(outputPath, markdownOutput, "utf-8"), logger21.log(`Prompt written to ${outputPath}`);
|
|
9549
|
+
}), output) {
|
|
9550
|
+
let outputPath = resolve4(output);
|
|
9551
|
+
await writeFile9(outputPath, markdownOutput, "utf-8"), logger22.log(`Prompt written to ${outputPath}`);
|
|
10290
9552
|
} else
|
|
10291
|
-
|
|
9553
|
+
process.stdout.write(`${markdownOutput}
|
|
9554
|
+
`);
|
|
10292
9555
|
}
|
|
10293
9556
|
function parseMajorVersion(version2) {
|
|
10294
9557
|
let match = version2.match(/^(\d+)/);
|
|
@@ -10303,7 +9566,7 @@ import {
|
|
|
10303
9566
|
CLI_COLORS as CLI_COLORS4,
|
|
10304
9567
|
createHyperlink,
|
|
10305
9568
|
logTracker as logTracker3,
|
|
10306
|
-
logger as
|
|
9569
|
+
logger as logger24,
|
|
10307
9570
|
prompt as prompt6
|
|
10308
9571
|
} from "storybook/internal/node-logger";
|
|
10309
9572
|
import {
|
|
@@ -10311,14 +9574,14 @@ import {
|
|
|
10311
9574
|
UpgradeStorybookUnknownCurrentVersionError
|
|
10312
9575
|
} from "storybook/internal/server-errors";
|
|
10313
9576
|
import { telemetry as telemetry2 } from "storybook/internal/telemetry";
|
|
10314
|
-
import { dedent as
|
|
9577
|
+
import { dedent as dedent18 } from "ts-dedent";
|
|
10315
9578
|
|
|
10316
9579
|
// src/automigrate/multi-project.ts
|
|
10317
|
-
import { CLI_COLORS as CLI_COLORS3, logger as
|
|
9580
|
+
import { CLI_COLORS as CLI_COLORS3, logger as logger23, prompt as prompt5 } from "storybook/internal/node-logger";
|
|
10318
9581
|
import { ErrorCollector, sanitizeError } from "storybook/internal/telemetry";
|
|
10319
9582
|
async function collectAutomigrationsAcrossProjects(options) {
|
|
10320
9583
|
let { fixes, projects, taskLog } = options, automigrationMap = /* @__PURE__ */ new Map();
|
|
10321
|
-
|
|
9584
|
+
logger23.debug(
|
|
10322
9585
|
`Starting automigration collection across ${projects.length} projects and ${fixes.length} fixes...`
|
|
10323
9586
|
);
|
|
10324
9587
|
function collectResult(fix, project, status, result) {
|
|
@@ -10340,10 +9603,10 @@ async function collectAutomigrationsAcrossProjects(options) {
|
|
|
10340
9603
|
}
|
|
10341
9604
|
for (let project of projects) {
|
|
10342
9605
|
let projectName = shortenPath(project.configDir);
|
|
10343
|
-
taskLog.message(`Checking automigrations for ${projectName}...`),
|
|
9606
|
+
taskLog.message(`Checking automigrations for ${projectName}...`), logger23.debug(`Processing project: ${projectName}`);
|
|
10344
9607
|
for (let fix of fixes)
|
|
10345
9608
|
try {
|
|
10346
|
-
|
|
9609
|
+
logger23.debug(`Checking fix ${fix.id} for project ${projectName}...`);
|
|
10347
9610
|
let checkOptions = {
|
|
10348
9611
|
packageManager: project.packageManager,
|
|
10349
9612
|
configDir: project.configDir,
|
|
@@ -10356,9 +9619,9 @@ async function collectAutomigrationsAcrossProjects(options) {
|
|
|
10356
9619
|
}, result = await fix.check(checkOptions);
|
|
10357
9620
|
result !== null ? collectResult(fix, project, "check_succeeded", result) : collectResult(fix, project, "not_applicable");
|
|
10358
9621
|
} catch (error) {
|
|
10359
|
-
collectResult(fix, project, "check_failed"),
|
|
9622
|
+
collectResult(fix, project, "check_failed"), logger23.debug(
|
|
10360
9623
|
`Failed to check fix ${fix.id} for project ${shortenPath(project.configDir)}.`
|
|
10361
|
-
),
|
|
9624
|
+
), logger23.debug(`${error instanceof Error ? error.stack : String(error)}`), ErrorCollector.addError(error);
|
|
10362
9625
|
}
|
|
10363
9626
|
}
|
|
10364
9627
|
let allAutomigrations = Array.from(automigrationMap.values()), applicableAutomigrations = allAutomigrations.filter(
|
|
@@ -10372,9 +9635,9 @@ async function collectAutomigrationsAcrossProjects(options) {
|
|
|
10372
9635
|
);
|
|
10373
9636
|
return taskLog.message(`
|
|
10374
9637
|
Automigrations detected:`), successAutomigrations.forEach((fixId) => {
|
|
10375
|
-
taskLog.message(`${CLI_COLORS3.success(`${
|
|
9638
|
+
taskLog.message(`${CLI_COLORS3.success(`${logger23.SYMBOLS.success} ${fixId}`)}`);
|
|
10376
9639
|
}), failedAutomigrations.forEach((fixId) => {
|
|
10377
|
-
taskLog.message(`${CLI_COLORS3.error(`${
|
|
9640
|
+
taskLog.message(`${CLI_COLORS3.error(`${logger23.SYMBOLS.error} ${fixId}`)}`);
|
|
10378
9641
|
}), failedAutomigrations.length > 0 ? taskLog.error(
|
|
10379
9642
|
`${failedAutomigrations.length} automigration ${failedAutomigrations.length > 1 ? "checks" : "check"} failed`
|
|
10380
9643
|
) : taskLog.success(
|
|
@@ -10392,12 +9655,12 @@ async function promptForAutomigrations(automigrations, options) {
|
|
|
10392
9655
|
if (automigrations.length === 0)
|
|
10393
9656
|
return [];
|
|
10394
9657
|
if (options.dryRun)
|
|
10395
|
-
return
|
|
10396
|
-
|
|
9658
|
+
return logger23.log("Detected automigrations (dry run - no changes will be made):"), automigrations.forEach(({ fix, reports: list }) => {
|
|
9659
|
+
logger23.log(` - ${fix.id} (${formatProjectDirs(list)})`);
|
|
10397
9660
|
}), [];
|
|
10398
9661
|
if (options.yes)
|
|
10399
|
-
return
|
|
10400
|
-
|
|
9662
|
+
return logger23.log("Running all detected automigrations:"), automigrations.forEach(({ fix, reports: list }) => {
|
|
9663
|
+
logger23.log(` - ${fix.id} (${formatProjectDirs(list)})`);
|
|
10401
9664
|
}), automigrations;
|
|
10402
9665
|
let choices = automigrations.map((am) => {
|
|
10403
9666
|
let hint = [];
|
|
@@ -10446,13 +9709,13 @@ async function runAutomigrationsForProjects(selectedAutomigrations, options) {
|
|
|
10446
9709
|
title: `${countPrefix}Running automigrations for ${projectName}`
|
|
10447
9710
|
}) : {
|
|
10448
9711
|
message: (message) => {
|
|
10449
|
-
|
|
9712
|
+
logger23.debug(`${message}`);
|
|
10450
9713
|
},
|
|
10451
9714
|
error: (message) => {
|
|
10452
|
-
|
|
9715
|
+
logger23.debug(`${message}`);
|
|
10453
9716
|
},
|
|
10454
9717
|
success: (message) => {
|
|
10455
|
-
|
|
9718
|
+
logger23.debug(`${message}`);
|
|
10456
9719
|
}
|
|
10457
9720
|
}, fixResults = {}, fixFailures = {};
|
|
10458
9721
|
for (let automigration of projectAutomigration) {
|
|
@@ -10486,11 +9749,11 @@ async function runAutomigrationsForProjects(selectedAutomigrations, options) {
|
|
|
10486
9749
|
storiesPaths: project2.storiesPaths,
|
|
10487
9750
|
yes
|
|
10488
9751
|
};
|
|
10489
|
-
await fix.run(runOptions), fixResults[fix.id] = "succeeded" /* SUCCEEDED */, taskLog.message(CLI_COLORS3.success(`${
|
|
9752
|
+
await fix.run(runOptions), fixResults[fix.id] = "succeeded" /* SUCCEEDED */, taskLog.message(CLI_COLORS3.success(`${logger23.SYMBOLS.success} ${fix.id}`));
|
|
10490
9753
|
}
|
|
10491
9754
|
} catch (error) {
|
|
10492
9755
|
let errorMessage = (error instanceof Error ? error.stack : String(error)) ?? "Unknown error";
|
|
10493
|
-
fixResults[fix.id] = "failed" /* FAILED */, fixFailures[fix.id] = sanitizeError(error), taskLog.message(CLI_COLORS3.error(`${
|
|
9756
|
+
fixResults[fix.id] = "failed" /* FAILED */, fixFailures[fix.id] = sanitizeError(error), taskLog.message(CLI_COLORS3.error(`${logger23.SYMBOLS.error} ${automigration.fix.id}`)), logger23.debug(errorMessage), ErrorCollector.addError(error);
|
|
10494
9757
|
}
|
|
10495
9758
|
}
|
|
10496
9759
|
let automigrationsWithErrors = Object.values(fixResults).filter(
|
|
@@ -10600,28 +9863,28 @@ function logUpgradeResults(projectResults, detectedAutomigrations, doctorResults
|
|
|
10600
9863
|
doctorResults
|
|
10601
9864
|
);
|
|
10602
9865
|
if (failedProjects.length > 0) {
|
|
10603
|
-
if (logTracker3.enableLogWriting(),
|
|
9866
|
+
if (logTracker3.enableLogWriting(), logger24.step(
|
|
10604
9867
|
"The upgrade is complete, but some projects failed to upgrade or migrate completely. Please see the debug logs for more details."
|
|
10605
9868
|
), successfulProjects.length > 0) {
|
|
10606
9869
|
let successfulProjectsList = successfulProjects.map((dir) => ` \u2022 ${shortenPath(dir)}`).join(`
|
|
10607
9870
|
`);
|
|
10608
|
-
|
|
9871
|
+
logger24.log(`${CLI_COLORS4.success("Successfully upgraded:")}
|
|
10609
9872
|
${successfulProjectsList}`);
|
|
10610
9873
|
}
|
|
10611
9874
|
let failedProjectsList = failedProjects.map((dir) => ` \u2022 ${shortenPath(dir)}`).join(`
|
|
10612
9875
|
`);
|
|
10613
|
-
if (
|
|
9876
|
+
if (logger24.log(
|
|
10614
9877
|
`${CLI_COLORS4.error("Failed to upgrade:")}
|
|
10615
9878
|
Some automigrations failed, please check the logs in the log file for more details.
|
|
10616
9879
|
${failedProjectsList}`
|
|
10617
9880
|
), projectsWithNoFixes.length > 0) {
|
|
10618
9881
|
let projectList = projectsWithNoFixes.map((dir) => ` \u2022 ${shortenPath(dir)}`).join(`
|
|
10619
9882
|
`);
|
|
10620
|
-
|
|
9883
|
+
logger24.log(`${CLI_COLORS4.info("No applicable migrations:")}
|
|
10621
9884
|
${projectList}`);
|
|
10622
9885
|
}
|
|
10623
9886
|
} else
|
|
10624
|
-
Object.values(doctorResults).every((result) => result.status === "healthy") ?
|
|
9887
|
+
Object.values(doctorResults).every((result) => result.status === "healthy") ? logger24.step(`${CLI_COLORS4.success("Your project(s) have been upgraded successfully! \u{1F389}")}`) : logger24.step(
|
|
10625
9888
|
`${import_picocolors16.default.yellow("Your project(s) have been upgraded successfully, but some issues were found which need your attention, please check Storybook doctor logs above.")}`
|
|
10626
9889
|
);
|
|
10627
9890
|
let automigrationLinks = detectedAutomigrations.filter(
|
|
@@ -10635,9 +9898,9 @@ ${projectList}`);
|
|
|
10635
9898
|
...automigrationLinks
|
|
10636
9899
|
].join(`
|
|
10637
9900
|
`);
|
|
10638
|
-
|
|
9901
|
+
logger24.log(automigrationLinksMessage);
|
|
10639
9902
|
}
|
|
10640
|
-
|
|
9903
|
+
logger24.log(
|
|
10641
9904
|
`For a full list of changes, please check our migration guide: ${CLI_COLORS4.cta("https://storybook.js.org/docs/releases/migration-guide?ref=upgrade")}`
|
|
10642
9905
|
);
|
|
10643
9906
|
}
|
|
@@ -10669,7 +9932,7 @@ async function sendMultiUpgradeTelemetry(options) {
|
|
|
10669
9932
|
hasUserInterrupted
|
|
10670
9933
|
});
|
|
10671
9934
|
} catch (error) {
|
|
10672
|
-
|
|
9935
|
+
logger24.debug(`Failed to send multi-upgrade telemetry: ${String(error)}`);
|
|
10673
9936
|
}
|
|
10674
9937
|
}
|
|
10675
9938
|
async function upgrade(options) {
|
|
@@ -10677,13 +9940,13 @@ async function upgrade(options) {
|
|
|
10677
9940
|
if (projectsResult === void 0 || projectsResult.selectedProjects.length === 0)
|
|
10678
9941
|
return;
|
|
10679
9942
|
let { allProjects, selectedProjects: storybookProjects } = projectsResult;
|
|
10680
|
-
storybookProjects.length > 1 ?
|
|
9943
|
+
storybookProjects.length > 1 ? logger24.info(`Upgrading the following projects:
|
|
10681
9944
|
${storybookProjects.map((p) => `${import_picocolors16.default.cyan(shortenPath(p.configDir))}: ${import_picocolors16.default.bold(p.beforeVersion)} -> ${import_picocolors16.default.bold(p.currentCLIVersion)}`).join(`
|
|
10682
|
-
`)}`) :
|
|
9945
|
+
`)}`) : logger24.info(
|
|
10683
9946
|
`Upgrading from ${import_picocolors16.default.bold(storybookProjects[0].beforeVersion)} to ${import_picocolors16.default.bold(storybookProjects[0].currentCLIVersion)}`
|
|
10684
9947
|
);
|
|
10685
9948
|
let automigrationResults = {}, doctorResults = {}, handleInterruption = async () => {
|
|
10686
|
-
throw
|
|
9949
|
+
throw logger24.log(`
|
|
10687
9950
|
|
|
10688
9951
|
Upgrade interrupted by user.`), allProjects.length > 1 && await sendMultiUpgradeTelemetry({
|
|
10689
9952
|
allProjects,
|
|
@@ -10696,7 +9959,7 @@ Upgrade interrupted by user.`), allProjects.length > 1 && await sendMultiUpgrade
|
|
|
10696
9959
|
process.on("SIGINT", handleInterruption), process.on("SIGTERM", handleInterruption);
|
|
10697
9960
|
try {
|
|
10698
9961
|
if (processAutoblockerResults(storybookProjects, (message) => {
|
|
10699
|
-
|
|
9962
|
+
logger24.error(dedent18`Blockers detected\n\n${message}`);
|
|
10700
9963
|
}))
|
|
10701
9964
|
throw new HandledError2("Blockers detected");
|
|
10702
9965
|
if (storybookProjects.some((project) => {
|
|
@@ -10715,7 +9978,7 @@ Upgrade interrupted by user.`), allProjects.length > 1 && await sendMultiUpgrade
|
|
|
10715
9978
|
try {
|
|
10716
9979
|
let loggedPaths = [];
|
|
10717
9980
|
for (let project of storybookProjects) {
|
|
10718
|
-
|
|
9981
|
+
logger24.debug(`Updating dependencies in ${shortenPath(project.configDir)}...`);
|
|
10719
9982
|
let newPaths = project.packageManager.packageJsonPaths.map(shortenPath).filter((path4) => !loggedPaths.includes(path4));
|
|
10720
9983
|
newPaths.length > 0 && (task.message(newPaths.join(`
|
|
10721
9984
|
`)), loggedPaths.push(...newPaths)), await upgradeStorybookDependencies({
|
|
@@ -10733,17 +9996,17 @@ Upgrade interrupted by user.`), allProjects.length > 1 && await sendMultiUpgrade
|
|
|
10733
9996
|
}
|
|
10734
9997
|
}
|
|
10735
9998
|
let automigrationResults2 = {}, detectedAutomigrations = [];
|
|
10736
|
-
options.skipAutomigrations ?
|
|
9999
|
+
options.skipAutomigrations ? logger24.log("Skipping automigrations (--skip-automigrations).") : { automigrationResults: automigrationResults2, detectedAutomigrations } = await runAutomigrations(
|
|
10737
10000
|
storybookProjects,
|
|
10738
10001
|
options
|
|
10739
10002
|
);
|
|
10740
10003
|
let rootPackageManager = storybookProjects.length > 1 ? JsPackageManagerFactory2.getPackageManager({ force: options.packageManager }) : storybookProjects[0].packageManager;
|
|
10741
|
-
rootPackageManager.type === "npm" ? await rootPackageManager.installDependencies({ force: !0 }) : await rootPackageManager.installDependencies(), rootPackageManager.type !== PackageManagerName2.YARN1 && rootPackageManager.isStorybookInMonorepo() && (
|
|
10004
|
+
rootPackageManager.type === "npm" ? await rootPackageManager.installDependencies({ force: !0 }) : await rootPackageManager.installDependencies(), rootPackageManager.type !== PackageManagerName2.YARN1 && rootPackageManager.isStorybookInMonorepo() && (logger24.warn(
|
|
10742
10005
|
"Since you are in a monorepo, we advise you to deduplicate your dependencies. We can do this for you but it might take some time."
|
|
10743
10006
|
), options.yes || await prompt6.confirm({
|
|
10744
10007
|
message: `Execute ${rootPackageManager.getRunCommand("dedupe")}?`,
|
|
10745
10008
|
initialValue: !0
|
|
10746
|
-
}) ? rootPackageManager.type === "npm" ? await rootPackageManager.dedupeDependencies({ force: !0 }) : await rootPackageManager.dedupeDependencies() :
|
|
10009
|
+
}) ? rootPackageManager.type === "npm" ? await rootPackageManager.dedupeDependencies({ force: !0 }) : await rootPackageManager.dedupeDependencies() : logger24.log(
|
|
10747
10010
|
`If you find any issues running Storybook, you can run ${rootPackageManager.getRunCommand("dedupe")} manually to deduplicate your dependencies and try again.`
|
|
10748
10011
|
));
|
|
10749
10012
|
let doctorProjects = storybookProjects.map((project) => ({
|
|
@@ -10752,7 +10015,7 @@ Upgrade interrupted by user.`), allProjects.length > 1 && await sendMultiUpgrade
|
|
|
10752
10015
|
storybookVersion: project.currentCLIVersion,
|
|
10753
10016
|
mainConfig: project.mainConfig
|
|
10754
10017
|
}));
|
|
10755
|
-
|
|
10018
|
+
logger24.step("Checking the health of your project(s).."), doctorResults = await runMultiProjectDoctor(doctorProjects), displayDoctorResults(doctorResults) && logTracker3.enableLogWriting(), logUpgradeResults(automigrationResults2, detectedAutomigrations, doctorResults);
|
|
10756
10019
|
for (let project of storybookProjects) {
|
|
10757
10020
|
let resultData = automigrationResults2[project.configDir] || {
|
|
10758
10021
|
automigrationStatuses: {},
|
|
@@ -10788,13 +10051,13 @@ Upgrade interrupted by user.`), allProjects.length > 1 && await sendMultiUpgrade
|
|
|
10788
10051
|
// src/bin/run.ts
|
|
10789
10052
|
addToGlobalContext("cliVersion", versions5.storybook);
|
|
10790
10053
|
var handleCommandFailure = (logFilePath) => async (error) => {
|
|
10791
|
-
error instanceof HandledError3 ||
|
|
10054
|
+
error instanceof HandledError3 || logger25.error(String(error));
|
|
10792
10055
|
try {
|
|
10793
10056
|
let logFile = await logTracker4.writeToFile(logFilePath);
|
|
10794
|
-
|
|
10057
|
+
logger25.log(`Debug logs are written to: ${logFile}`);
|
|
10795
10058
|
} catch {
|
|
10796
10059
|
}
|
|
10797
|
-
|
|
10060
|
+
logger25.outro(""), process.exit(1);
|
|
10798
10061
|
}, command = (name) => program.command(name).option(
|
|
10799
10062
|
"--disable-telemetry",
|
|
10800
10063
|
"Disable sending telemetry data",
|
|
@@ -10804,21 +10067,21 @@ var handleCommandFailure = (logFilePath) => async (error) => {
|
|
|
10804
10067
|
"Write all debug logs to the specified file at the end of the run. Defaults to debug-storybook.log when [path] is not provided"
|
|
10805
10068
|
).option("--loglevel <trace | debug | info | warn | error | silent>", "Define log level", "info").hook("preAction", async (self2) => {
|
|
10806
10069
|
let options = self2.opts();
|
|
10807
|
-
options.debug &&
|
|
10070
|
+
options.debug && logger25.setLogLevel("debug"), options.loglevel && logger25.setLogLevel(options.loglevel), options.logfile && logTracker4.enableLogWriting();
|
|
10808
10071
|
try {
|
|
10809
10072
|
await globalSettings();
|
|
10810
10073
|
} catch (e) {
|
|
10811
|
-
|
|
10074
|
+
logger25.error(`Error loading global settings:
|
|
10812
10075
|
` + String(e));
|
|
10813
10076
|
}
|
|
10814
10077
|
}).hook("postAction", async (command2) => {
|
|
10815
10078
|
if (logTracker4.shouldWriteLogsToFile) {
|
|
10816
10079
|
try {
|
|
10817
10080
|
let logFile = await logTracker4.writeToFile(command2.getOptionValue("logfile"));
|
|
10818
|
-
|
|
10081
|
+
logger25.log(`Debug logs are written to: ${logFile}`);
|
|
10819
10082
|
} catch {
|
|
10820
10083
|
}
|
|
10821
|
-
|
|
10084
|
+
logger25.outro(CLI_COLORS5.success("Done!"));
|
|
10822
10085
|
}
|
|
10823
10086
|
});
|
|
10824
10087
|
command("init").description("Initialize Storybook into your project").option("-f --force", "Force add Storybook").option("-s --skip-install", "Skip installing deps").addOption(
|
|
@@ -10835,7 +10098,7 @@ command("add <addon>").description("Add an addon to your Storybook").addOption(
|
|
|
10835
10098
|
)
|
|
10836
10099
|
).option("-c, --config-dir <dir-name>", "Directory where to load Storybook configurations from").option("--skip-install", "Skip installing deps").option("-s --skip-postinstall", "Skip package specific postinstall config modifications").option("-y --yes", "Skip prompting the user").option("--skip-doctor", "Skip doctor check").action((addonName, options) => {
|
|
10837
10100
|
withTelemetry("add", { cliOptions: options }, async () => {
|
|
10838
|
-
|
|
10101
|
+
logger25.intro(`Setting up your project for ${addonName}`), await add(addonName, options), await telemetry3("add", { addon: addonName, source: "cli" }), logger25.outro("Done!");
|
|
10839
10102
|
}).catch(handleCommandFailure);
|
|
10840
10103
|
});
|
|
10841
10104
|
command("remove <addon>").description("Remove an addon from your Storybook").addOption(
|
|
@@ -10844,7 +10107,7 @@ command("remove <addon>").description("Remove an addon from your Storybook").add
|
|
|
10844
10107
|
)
|
|
10845
10108
|
).option("-c, --config-dir <dir-name>", "Directory where to load Storybook configurations from").option("-s --skip-install", "Skip installing deps").action(
|
|
10846
10109
|
(addonName, options) => withTelemetry("remove", { cliOptions: options }, async () => {
|
|
10847
|
-
|
|
10110
|
+
logger25.intro(`Removing ${addonName} from your Storybook`);
|
|
10848
10111
|
let packageManager = JsPackageManagerFactory3.getPackageManager({
|
|
10849
10112
|
configDir: options.configDir,
|
|
10850
10113
|
force: options.packageManager
|
|
@@ -10853,7 +10116,7 @@ command("remove <addon>").description("Remove an addon from your Storybook").add
|
|
|
10853
10116
|
configDir: options.configDir,
|
|
10854
10117
|
packageManager,
|
|
10855
10118
|
skipInstall: options.skipInstall
|
|
10856
|
-
}), await telemetry3("remove", { addon: addonName, source: "cli" }),
|
|
10119
|
+
}), await telemetry3("remove", { addon: addonName, source: "cli" }), logger25.outro("Done!");
|
|
10857
10120
|
}).catch(handleCommandFailure(options.logfile))
|
|
10858
10121
|
);
|
|
10859
10122
|
command("upgrade").description(`Upgrade your Storybook packages to v${versions5.storybook}`).addOption(
|
|
@@ -10871,12 +10134,12 @@ command("upgrade").description(`Upgrade your Storybook packages to v${versions5.
|
|
|
10871
10134
|
"upgrade",
|
|
10872
10135
|
{ cliOptions: { ...options, configDir: options.configDir?.[0] } },
|
|
10873
10136
|
async () => {
|
|
10874
|
-
|
|
10137
|
+
logger25.intro(`Storybook upgrade - v${versions5.storybook}`), await upgrade(options), logger25.outro("Storybook upgrade completed!");
|
|
10875
10138
|
}
|
|
10876
10139
|
).catch(handleCommandFailure(options.logfile));
|
|
10877
10140
|
});
|
|
10878
10141
|
command("info").description("Prints debugging information about the local environment").action(async () => {
|
|
10879
|
-
|
|
10142
|
+
logger25.log(import_picocolors17.default.bold(`
|
|
10880
10143
|
Storybook Environment Info:`));
|
|
10881
10144
|
let activePackageManager = JsPackageManagerFactory3.getPackageManager().type.replace(/\d/, ""), output = await import_envinfo.default.run({
|
|
10882
10145
|
System: ["OS", "CPU", "Shell"],
|
|
@@ -10885,7 +10148,7 @@ Storybook Environment Info:`));
|
|
|
10885
10148
|
npmPackages: "{@storybook/*,*storybook*,sb,chromatic}",
|
|
10886
10149
|
npmGlobalPackages: "{@storybook/*,*storybook*,sb,chromatic}"
|
|
10887
10150
|
}), activePackageManagerLine = output.match(new RegExp(`${activePackageManager}:.*`, "i"));
|
|
10888
|
-
|
|
10151
|
+
logger25.log(
|
|
10889
10152
|
output.replace(
|
|
10890
10153
|
activePackageManagerLine,
|
|
10891
10154
|
import_picocolors17.default.bold(`${activePackageManagerLine} <----- active`)
|
|
@@ -10900,12 +10163,12 @@ command("migrate [migration]").description("Run a Storybook codemod migration on
|
|
|
10900
10163
|
'Rename suffix of matching files after codemod has been applied, e.g. ".js:.ts"'
|
|
10901
10164
|
).action((migration, options) => {
|
|
10902
10165
|
withTelemetry("migrate", { cliOptions: options }, async () => {
|
|
10903
|
-
|
|
10166
|
+
logger25.intro(`Running ${migration} migration`), await migrate(migration, options), logger25.outro("Migration completed");
|
|
10904
10167
|
}).catch(handleCommandFailure(options.logfile));
|
|
10905
10168
|
});
|
|
10906
10169
|
command("sandbox [filterValue]").alias("repro").description("Create a sandbox from a set of possible templates").option("-o --output <outDir>", "Define an output directory").option("--no-init", "Whether to download a template without an initialized Storybook", !1).action((filterValue, options) => {
|
|
10907
|
-
|
|
10908
|
-
|
|
10170
|
+
logger25.intro("Creating a Storybook sandbox..."), sandbox({ filterValue, ...options }).catch(handleCommandFailure).finally(() => {
|
|
10171
|
+
logger25.outro("Done!");
|
|
10909
10172
|
});
|
|
10910
10173
|
});
|
|
10911
10174
|
command("link <repo-url-or-directory>").description("Pull down a repro from a URL (or a local directory), link it, and run storybook").option("--local", "Link a local directory already in your file system").option("--no-start", "Start the storybook", !0).action(
|
|
@@ -10920,7 +10183,7 @@ command("automigrate [fixId]").description("Check storybook for incompatibilitie
|
|
|
10920
10183
|
"The renderer package for the framework Storybook is using."
|
|
10921
10184
|
).option("--skip-doctor", "Skip doctor check").option("--glob <pattern>", "Glob pattern for story files (for csf-factories codemod)").action(async (fixId, options) => {
|
|
10922
10185
|
withTelemetry("automigrate", { cliOptions: options }, async () => {
|
|
10923
|
-
|
|
10186
|
+
logger25.intro(fixId ? `Running ${fixId} automigration` : "Running automigrations"), await doAutomigrate({ fixId, ...options }), logger25.outro("Done");
|
|
10924
10187
|
}).catch(handleCommandFailure(options.logfile));
|
|
10925
10188
|
});
|
|
10926
10189
|
command("doctor").description("Check Storybook for known problems and provide suggestions or fixes").addOption(
|
|
@@ -10929,7 +10192,7 @@ command("doctor").description("Check Storybook for known problems and provide su
|
|
|
10929
10192
|
)
|
|
10930
10193
|
).option("-c, --config-dir <dir-name>", "Directory of Storybook configuration").action(async (options) => {
|
|
10931
10194
|
withTelemetry("doctor", { cliOptions: options }, async () => {
|
|
10932
|
-
|
|
10195
|
+
logger25.intro("Doctoring Storybook"), await doctor(options), logger25.outro("Done");
|
|
10933
10196
|
}).catch(handleCommandFailure(options.logfile));
|
|
10934
10197
|
});
|
|
10935
10198
|
var aiCommand = command("ai").description("AI agent helpers for Storybook").option(
|
|
@@ -10953,6 +10216,6 @@ program.on("command:*", ([invalidCmd]) => {
|
|
|
10953
10216
|
let errorMessage = ` Invalid command: ${import_picocolors17.default.bold(invalidCmd)}.
|
|
10954
10217
|
See --help for a list of available commands.`, suggestion = program.commands.map((cmd) => cmd.name()).find((cmd) => leven(cmd, invalidCmd) < 3);
|
|
10955
10218
|
suggestion && (errorMessage += `
|
|
10956
|
-
Did you mean ${import_picocolors17.default.yellow(suggestion)}?`),
|
|
10219
|
+
Did you mean ${import_picocolors17.default.yellow(suggestion)}?`), logger25.error(errorMessage), process.exit(1);
|
|
10957
10220
|
});
|
|
10958
10221
|
program.usage("<command> [options]").version(String(version)).parse(process.argv);
|