UNPKG

create-nextjs-storybook

Version:

Install embedded Storybook route into a NextJS project

174 lines (172 loc) 6.46 kB
import { dedent } from 'ts-dedent'; import { findUpSync } from 'find-up'; import { existsSync, readFileSync } from 'node:fs'; import { join } from 'node:path'; import semver from 'semver'; import { createLogStream } from '../createLogStream.js'; import { JsPackageManager } from './JsPackageManager.js'; import { parsePackageData } from './util.js'; const YARN1_ERROR_REGEX = /^error\s(.*)$/gm; export class Yarn1Proxy extends JsPackageManager { type = 'yarn1'; installArgs; getInstallArgs() { if (!this.installArgs) { this.installArgs = ['--ignore-workspace-root-check']; } return this.installArgs; } async initPackageJson() { await this.executeCommand({ command: 'yarn', args: ['init', '-y'] }); } getRunStorybookCommand() { return 'yarn storybook'; } getRunCommand(command) { return `yarn ${command}`; } runPackageCommandSync(command, args, cwd, stdio) { return this.executeCommandSync({ command: `yarn`, args: [command, ...args], cwd, stdio }); } async runPackageCommand(command, args, cwd) { return this.executeCommand({ command: `yarn`, args: [command, ...args], cwd }); } async getPackageJSON(packageName, basePath = this.cwd) { const packageJsonPath = await findUpSync((dir) => { const possiblePath = join(dir, 'node_modules', packageName, 'package.json'); return existsSync(possiblePath) ? possiblePath : undefined; }, { cwd: basePath }); if (!packageJsonPath) { return null; } return JSON.parse(readFileSync(packageJsonPath, 'utf-8')); } async getPackageVersion(packageName, basePath = this.cwd) { const packageJson = await this.getPackageJSON(packageName, basePath); return packageJson ? semver.coerce(packageJson.version)?.version ?? null : null; } async findInstallations(pattern) { const commandResult = await this.executeCommand({ command: 'yarn', args: ['list', '--pattern', pattern.map((p) => `"${p}"`).join(' '), '--recursive', '--json'], env: { FORCE_COLOR: 'false', }, }); try { const parsedOutput = JSON.parse(commandResult); return this.mapDependencies(parsedOutput); } catch (e) { return undefined; } } getResolutions(packageJson, versions) { return { resolutions: { ...packageJson.resolutions, ...versions, }, }; } async runInstall() { await this.executeCommand({ command: 'yarn', args: ['install', ...this.getInstallArgs()], stdio: 'inherit', }); } async runAddDeps(dependencies, installAsDevDependencies) { let args = [...dependencies]; if (installAsDevDependencies) { args = ['-D', ...args]; } const { logStream, readLogFile, moveLogFile, removeLogFile } = await createLogStream(); try { await this.executeCommand({ command: 'yarn', args: ['add', ...this.getInstallArgs(), ...args], stdio: process.env.CI ? 'inherit' : ['ignore', logStream, logStream], }); } catch (err) { const stdout = await readLogFile(); const errorMessage = this.parseErrorFromLogs(stdout); await moveLogFile(); throw new Error(dedent `${errorMessage} Please check the logfile generated at ./storybook.log for troubleshooting and try again.`); } await removeLogFile(); } async runRemoveDeps(dependencies) { const args = [...dependencies]; await this.executeCommand({ command: 'yarn', args: ['remove', ...this.getInstallArgs(), ...args], stdio: 'inherit', }); } async runGetVersions(packageName, fetchAllVersions) { const args = [fetchAllVersions ? 'versions' : 'version', '--json']; const commandResult = await this.executeCommand({ command: 'yarn', args: ['info', packageName, ...args], }); try { const parsedOutput = JSON.parse(commandResult); if (parsedOutput.type === 'inspect') { return parsedOutput.data; } throw new Error(`Unable to find versions of ${packageName} using yarn`); } catch (e) { throw new Error(`Unable to find versions of ${packageName} using yarn`); } } mapDependencies(input) { if (input.type === 'tree') { const { trees } = input.data; const acc = {}; const existingVersions = {}; const duplicatedDependencies = {}; const recurse = (tree) => { const { children } = tree; const { name, value } = parsePackageData(tree.name); if (!name || !name.includes('storybook')) return; if (!existingVersions[name]?.includes(value.version)) { if (acc[name]) { acc[name].push(value); } else { acc[name] = [value]; } existingVersions[name] = [...(existingVersions[name] || []), value.version]; if (existingVersions[name].length > 1) { duplicatedDependencies[name] = existingVersions[name]; } } children.forEach(recurse); }; trees.forEach(recurse); return { dependencies: acc, duplicatedDependencies, infoCommand: 'yarn why', dedupeCommand: 'yarn dedupe', }; } throw new Error('Something went wrong while parsing yarn output'); } parseErrorFromLogs(logs) { let finalMessage = 'YARN1 error'; const match = logs.match(YARN1_ERROR_REGEX); if (match) { const errorMessage = match[0]?.replace(/^error\s(.*)$/, '$1'); if (errorMessage) { finalMessage = `${finalMessage}: ${errorMessage}`; } } return finalMessage.trim(); } }