diff --git a/bin-src/init.ts b/bin-src/init.ts index a8571b597..5668b6f61 100644 --- a/bin-src/init.ts +++ b/bin-src/init.ts @@ -73,10 +73,10 @@ export const installArchiveDependencies = async ( packageJson: PackageJson, testFramework: TestFrameworkType ) => { - const defaultInstallArgs = ['-D', 'chromatic', `@chromatic-com/${testFramework}`]; + const defaultInstallArguments = ['-D', 'chromatic', `@chromatic-com/${testFramework}`]; const sbPackages = getStorybookPackages(packageJson); - const installArgs = [...defaultInstallArgs, ...sbPackages]; - const installCommand = await getPackageManagerInstallCommand(installArgs); + const installArguments = [...defaultInstallArguments, ...sbPackages]; + const installCommand = await getPackageManagerInstallCommand(installArguments); await execaCommand(installCommand); }; diff --git a/bin-src/trace.test.ts b/bin-src/trace.test.ts index 7a269f6c9..9f1269f5d 100644 --- a/bin-src/trace.test.ts +++ b/bin-src/trace.test.ts @@ -2,9 +2,9 @@ import { execSync } from 'child_process'; import { describe, expect, it } from 'vitest'; import { - baseDirNote, - rootDirNote, - storybookDirNote, + baseDirectoryNote, + rootDirectoryNote, + storybookDirectoryNote, traceSuggestions, } from '../node-src/ui/messages/info/tracedAffectedFiles'; @@ -17,7 +17,7 @@ describe('Test trace script from package.json', () => { const output = execSync(`yarn ${scriptName}`).toString().trim(); // Verify that the output does not contain the expanded output - expect(output).not.toContain(rootDirNote); + expect(output).not.toContain(rootDirectoryNote); }); it('outputs directory info when -m expanded is passed', () => { const scriptName = @@ -30,9 +30,9 @@ describe('Test trace script from package.json', () => { const expandedFileModule = `node-src/ui/messages/errors/invalidReportPath.ts`; // Add your assertions based on the expected output or behavior of the script - expect(output).toContain(rootDirNote); - expect(output).toContain(baseDirNote); - expect(output).toContain(storybookDirNote); + expect(output).toContain(rootDirectoryNote); + expect(output).toContain(baseDirectoryNote); + expect(output).toContain(storybookDirectoryNote); expect(output).toContain(traceSuggestions); expect(output).toContain(expandedStoryModule); expect(output).toContain(expandedFileModule); diff --git a/bin-src/trim-stats-file.ts b/bin-src/trim-stats-file.ts index 24863b941..523543cf6 100644 --- a/bin-src/trim-stats-file.ts +++ b/bin-src/trim-stats-file.ts @@ -2,7 +2,7 @@ import { outputFile } from 'fs-extra'; import { readStatsFile } from '../node-src/tasks/read-stats-file'; -const dedupe = (arr: T[]) => [...new Set(arr)]; +const dedupe = (array: T[]) => [...new Set(array)]; const isUserCode = ({ name, moduleName = name }: { name?: string; moduleName?: string }) => moduleName && !moduleName.startsWith('(webpack)') && diff --git a/eslint.config.mjs b/eslint.config.mjs index 1a104ff12..a99fb272d 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -123,7 +123,10 @@ export default [ str: true, args: true, docsUrl: true, + fn: true, + pkg: true, }, + ignore: [/.*e2e.*/, /\w+[Dd]ocs\w*/], }, ], 'unicorn/catch-error-name': [ diff --git a/isChromatic.js b/isChromatic.js index c2567af7b..621640371 100644 --- a/isChromatic.js +++ b/isChromatic.js @@ -1,7 +1,7 @@ /* eslint-env browser */ -module.exports = function isChromatic(windowArg) { - const windowToCheck = windowArg || (typeof window !== 'undefined' && window); +module.exports = function isChromatic(windowArgument) { + const windowToCheck = windowArgument || (typeof window !== 'undefined' && window); return !!( windowToCheck && (/Chromatic/.test(windowToCheck.navigator.userAgent) || diff --git a/isChromatic.mjs b/isChromatic.mjs index b6d0309d1..2ca61ee41 100644 --- a/isChromatic.mjs +++ b/isChromatic.mjs @@ -1,7 +1,7 @@ /* eslint-env browser */ -export default function isChromatic(windowArg) { - const windowToCheck = windowArg || (typeof window !== 'undefined' && window); +export default function isChromatic(windowArgument) { + const windowToCheck = windowArgument || (typeof window !== 'undefined' && window); return !!( windowToCheck && (/Chromatic/.test(windowToCheck.navigator.userAgent) || diff --git a/node-src/git/generateGitRepository.ts b/node-src/git/generateGitRepository.ts index 446d55ab3..aaafeaf58 100644 --- a/node-src/git/generateGitRepository.ts +++ b/node-src/git/generateGitRepository.ts @@ -24,22 +24,22 @@ async function generateCommit( .map((parentName) => parentName && commitMap[parentName].hash); const randomBranchName = `temp-${Math.random().toString().slice(2)}`; - const commitEnv = `GIT_COMMITTER_DATE='${nextDate()}'`; + const commitEnvironment = `GIT_COMMITTER_DATE='${nextDate()}'`; // No parent, check out nothing if (parentCommits.length === 0) { await runGit(`git checkout --orphan ${randomBranchName}`); - await runGit(`${commitEnv} git commit -m ${name} --allow-empty`); + await runGit(`${commitEnvironment} git commit -m ${name} --allow-empty`); } else { // Check out the first parent await runGit(`git checkout ${parentCommits[0]}`); // If more parents, create merge commit await (parentCommits.length > 1 - ? runGit(`${commitEnv} git merge -m ${name} ${parentCommits.slice(1).join(' ')}`) - : runGit(`${commitEnv} git commit -m ${name} --allow-empty`)); + ? runGit(`${commitEnvironment} git merge -m ${name} ${parentCommits.slice(1).join(' ')}`) + : runGit(`${commitEnvironment} git commit -m ${name} --allow-empty`)); } - const gitShowStr = await runGit(`git show --format=%H,%ct`); - const [hash, committedAt] = gitShowStr.stdout.trim().split(','); + const gitShowString = await runGit(`git show --format=%H,%ct`); + const [hash, committedAt] = gitShowString.stdout.trim().split(','); return { hash, committedAt: Number.parseInt(committedAt, 10) }; } diff --git a/node-src/git/getCommitAndBranch.test.ts b/node-src/git/getCommitAndBranch.test.ts index 50c5b7be1..67b9ec284 100644 --- a/node-src/git/getCommitAndBranch.test.ts +++ b/node-src/git/getCommitAndBranch.test.ts @@ -17,9 +17,9 @@ const mergeQueueBranchMatch = vi.mocked(git.mergeQueueBranchMatch); const log = { info: vi.fn(), warn: vi.fn(), debug: vi.fn() }; -const processEnv = process.env; +const processEnvironment = process.env; beforeEach(() => { - process.env = { ...processEnv }; + process.env = { ...processEnvironment }; envCi.mockReturnValue({}); getBranch.mockResolvedValue('main'); getCommit.mockResolvedValue({ diff --git a/node-src/git/getCommitAndBranch.ts b/node-src/git/getCommitAndBranch.ts index 713ad3a9b..edb273b55 100644 --- a/node-src/git/getCommitAndBranch.ts +++ b/node-src/git/getCommitAndBranch.ts @@ -56,7 +56,7 @@ export default async function getCommitAndBranch( } = process.env; const { isCi, service, prBranch, branch: ciBranch, commit: ciCommit, slug: ciSlug } = envCi(); - const isFromEnvVariable = CHROMATIC_SHA && CHROMATIC_BRANCH; // Our GitHub Action also sets these + const isFromEnvironmentVariable = CHROMATIC_SHA && CHROMATIC_BRANCH; // Our GitHub Action also sets these const isTravisPrBuild = TRAVIS_EVENT_TYPE === 'pull_request'; const isGitHubAction = GITHUB_ACTIONS === 'true'; const isGitHubPrBuild = GITHUB_EVENT_NAME === 'pull_request'; @@ -70,7 +70,7 @@ export default async function getCommitAndBranch( } } - if (isFromEnvVariable) { + if (isFromEnvironmentVariable) { commit = await getCommit(CHROMATIC_SHA).catch((err) => { log.warn(noCommitDetails({ sha: CHROMATIC_SHA, env: 'CHROMATIC_SHA' })); log.debug(err); @@ -156,7 +156,7 @@ export default async function getCommitAndBranch( !!process.env.GITHUB_REPOSITORY; // Strip off any `origin/` prefix that's added sometimes. - if (!branchName && !isFromEnvVariable && ORIGIN_PREFIX_REGEXP.test(branch)) { + if (!branchName && !isFromEnvironmentVariable && ORIGIN_PREFIX_REGEXP.test(branch)) { log.warn(`Ignoring 'origin/' prefix in branch name.`); branch = branch.replace(ORIGIN_PREFIX_REGEXP, ''); } diff --git a/node-src/git/git.ts b/node-src/git/git.ts index 06a0313e4..43728381f 100644 --- a/node-src/git/git.ts +++ b/node-src/git/git.ts @@ -1,7 +1,7 @@ import { execaCommand } from 'execa'; import { EOL } from 'os'; import pLimit from 'p-limit'; -import { file as tmpFile } from 'tmp-promise'; +import { file as temporaryFile } from 'tmp-promise'; import { Context } from '../types'; import gitNoCommits from '../ui/messages/errors/gitNoCommits'; @@ -88,13 +88,13 @@ export async function getBranch() { try { // Git v1.8 and above // Throws when in detached HEAD state - const ref = await execGitCommand('git symbolic-ref HEAD'); - return ref.replace(/^refs\/heads\//, ''); // strip the "refs/heads/" prefix + const reference = await execGitCommand('git symbolic-ref HEAD'); + return reference.replace(/^refs\/heads\//, ''); // strip the "refs/heads/" prefix } catch { // Git v1.7 and above // Yields 'HEAD' when in detached HEAD state - const ref = await execGitCommand('git rev-parse --abbrev-ref HEAD'); - return ref.replace(/^heads\//, ''); // strip the "heads/" prefix that's sometimes present + const reference = await execGitCommand('git rev-parse --abbrev-ref HEAD'); + return reference.replace(/^heads\//, ''); // strip the "heads/" prefix that's sometimes present } } } @@ -230,8 +230,8 @@ export async function getUpdateMessage() { * @param {string} headRef Name of the head branch * @param {string} baseRef Name of the base branch */ -export async function findMergeBase(headRef: string, baseRef: string) { - const result = await execGitCommand(`git merge-base --all ${headRef} ${baseRef}`); +export async function findMergeBase(headReference: string, baseReference: string) { + const result = await execGitCommand(`git merge-base --all ${headReference} ${baseReference}`); const mergeBases = result.split(newline).filter((line) => line && !line.startsWith('warning: ')); if (mergeBases.length === 0) return undefined; if (mergeBases.length === 1) return mergeBases[0]; @@ -244,21 +244,25 @@ export async function findMergeBase(headRef: string, baseRef: string) { return name.replace(/~\d+$/, ''); // Drop the potential suffix }) ); - const baseRefIndex = branchNames.indexOf(baseRef); - return mergeBases[baseRefIndex] || mergeBases[0]; + const baseReferenceIndex = branchNames.indexOf(baseReference); + return mergeBases[baseReferenceIndex] || mergeBases[0]; } -export async function checkout(ref: string) { - return execGitCommand(`git checkout ${ref}`); +export async function checkout(reference: string) { + return execGitCommand(`git checkout ${reference}`); } const fileCache = {}; const limitConcurrency = pLimit(10); -export async function checkoutFile({ log }: Pick, ref: string, fileName: string) { - const pathspec = `${ref}:${fileName}`; +export async function checkoutFile( + { log }: Pick, + reference: string, + fileName: string +) { + const pathspec = `${reference}:${fileName}`; if (!fileCache[pathspec]) { fileCache[pathspec] = limitConcurrency(async () => { - const { path: targetFileName } = await tmpFile({ + const { path: targetFileName } = await temporaryFile({ postfix: `-${fileName.replaceAll('/', '--')}`, }); log.debug(`Checking out file ${pathspec} at ${targetFileName}`); diff --git a/node-src/index.test.ts b/node-src/index.test.ts index 8ad6fc790..6d3e2cd50 100644 --- a/node-src/index.test.ts +++ b/node-src/index.test.ts @@ -11,8 +11,8 @@ import { getGitInfo, runAll } from '.'; import * as git from './git/git'; import { DNSResolveAgent } from './io/getDNSResolveAgent'; import * as checkPackageJson from './lib/checkPackageJson'; -import getEnv from './lib/getEnv'; -import parseArgs from './lib/parseArgs'; +import getEnvironment from './lib/getEnvironment'; +import parseArguments from './lib/parseArguments'; import TestLogger from './lib/testLogger'; import { uploadFiles } from './lib/uploadFiles'; import { writeChromaticDiagnostics } from './lib/writeChromaticDiagnostics'; @@ -342,9 +342,9 @@ vi.mock('./lib/uploadFiles'); vi.mock('./lib/spawn', () => ({ default: () => Promise.resolve('https://npm.example.com') })); -let processEnv; +let processEnvironment; beforeEach(() => { - processEnv = process.env; + processEnvironment = process.env; process.env = { DISABLE_LOGGING: 'true', CHROMATIC_APP_CODE: undefined, @@ -361,14 +361,14 @@ beforeEach(() => { getSlug.mockResolvedValue('user/repo'); }); afterEach(() => { - process.env = processEnv; + process.env = processEnvironment; }); const getContext = (argv: string[]): Context & { testLogger: TestLogger } => { const testLogger = new TestLogger(); return { title: '', - env: getEnv(), + env: getEnvironment(), log: testLogger, testLogger, sessionId: ':sessionId', @@ -384,7 +384,7 @@ const getContext = (argv: string[]): Context & { testLogger: TestLogger } => { packagePath: '', statsPath: 'preview-stats.json', options: {}, - ...parseArgs(argv), + ...parseArguments(argv), } as any; }; diff --git a/node-src/index.ts b/node-src/index.ts index 77256efee..774285d44 100644 --- a/node-src/index.ts +++ b/node-src/index.ts @@ -19,12 +19,12 @@ import checkPackageJson from './lib/checkPackageJson'; import { isE2EBuild } from './lib/e2e'; import { emailHash } from './lib/emailHash'; import { getConfiguration } from './lib/getConfiguration'; -import getEnv from './lib/getEnv'; +import getEnvironment from './lib/getEnvironment'; import getOptions from './lib/getOptions'; import { createLogger } from './lib/log'; import LoggingRenderer from './lib/LoggingRenderer'; import NonTTYRenderer from './lib/NonTTYRenderer'; -import parseArgs from './lib/parseArgs'; +import parseArguments from './lib/parseArguments'; import { exitCodes, setExitCode } from './lib/setExitCode'; import { uploadMetadataFiles } from './lib/uploadMetadataFiles'; import { rewriteErrorMessage } from './lib/utils'; @@ -96,22 +96,26 @@ export async function run({ flags?: Flags; options?: Partial; }): Promise { - const { sessionId = uuid(), env = getEnv(), log = createLogger() } = extraOptions || {}; + const { + sessionId = uuid(), + env: environment = getEnvironment(), + log = createLogger(), + } = extraOptions || {}; - const pkgInfo = await readPkgUp({ cwd: process.cwd() }); - if (!pkgInfo) { + const packageInfo = await readPkgUp({ cwd: process.cwd() }); + if (!packageInfo) { log.error(noPackageJson()); process.exit(253); } - const { path: packagePath, packageJson } = pkgInfo; + const { path: packagePath, packageJson } = packageInfo; const ctx: InitialContext = { - ...parseArgs(argv), + ...parseArguments(argv), ...(flags && { flags }), ...(extraOptions && { extraOptions }), packagePath, packageJson, - env, + env: environment, log, sessionId, }; @@ -142,12 +146,12 @@ export async function runAll(ctx: InitialContext) { ctx.log.info(intro(ctx)); ctx.log.info(''); - const onError = (e: Error | Error[]) => { + const onError = (err: Error | Error[]) => { ctx.log.info(''); - ctx.log.error(fatalError(ctx, [e].flat())); + ctx.log.error(fatalError(ctx, [err].flat())); ctx.extraOptions?.experimental_onTaskError?.(ctx, { - formattedError: fatalError(ctx, [e].flat()), - originalError: e, + formattedError: fatalError(ctx, [err].flat()), + originalError: err, }); setExitCode(ctx, exitCodes.INVALID_OPTIONS, true); }; @@ -289,7 +293,7 @@ export async function getGitInfo(): Promise { const commitInfo = await getCommit(); const userEmail = await getUserEmail(); const userEmailHash = emailHash(userEmail); - const repositoryRootDir = await getRepositoryRoot(); + const repositoryRootDirectory = await getRepositoryRoot(); const [ownerName, repoName, ...rest] = slug ? slug.split('/') : []; const isValidSlug = !!ownerName && !!repoName && rest.length === 0; @@ -302,7 +306,7 @@ export async function getGitInfo(): Promise { uncommittedHash, userEmail, userEmailHash, - repositoryRootDir, + repositoryRootDir: repositoryRootDirectory, }; } diff --git a/node-src/io/GraphQLClient.ts b/node-src/io/GraphQLClient.ts index b2a49caa5..11186d3dc 100644 --- a/node-src/io/GraphQLClient.ts +++ b/node-src/io/GraphQLClient.ts @@ -47,7 +47,7 @@ export default class GraphQLClient { }, { retries } ) - .then((res) => res.json() as any) + .then((result) => result.json() as any) .catch(bail); if (!errors) return data; diff --git a/node-src/io/HTTPClient.ts b/node-src/io/HTTPClient.ts index 9484318bf..91976a1bd 100644 --- a/node-src/io/HTTPClient.ts +++ b/node-src/io/HTTPClient.ts @@ -10,8 +10,8 @@ import getProxyAgent from './getProxyAgent'; export class HTTPClientError extends Error { response: Response; - constructor(fetchResponse: Response, message?: string, ...params: any[]) { - super(...params); + constructor(fetchResponse: Response, message?: string, ...parameters: any[]) { + super(...parameters); // Maintains proper stack trace for where our error was thrown (only available on V8) if (Error.captureStackTrace) { @@ -57,8 +57,9 @@ export default class HTTPClient { this.retries = retries; } - async fetch(url: string, options: RequestInit = {}, opts: HTTPClientFetchOptions = {}) { - let agent = options.agent || getProxyAgent({ env: this.env, log: this.log }, url, opts.proxy); + async fetch(url: string, options: RequestInit = {}, options_: HTTPClientFetchOptions = {}) { + let agent = + options.agent || getProxyAgent({ env: this.env, log: this.log }, url, options_.proxy); if (this.env.CHROMATIC_DNS_SERVERS.length > 0) { this.log.debug(`Using custom DNS servers: ${this.env.CHROMATIC_DNS_SERVERS.join(', ')}`); @@ -67,7 +68,7 @@ export default class HTTPClient { } // The user can override retries and set it to 0 - const retries = opts.retries === undefined ? this.retries : opts.retries; + const retries = options_.retries === undefined ? this.retries : options_.retries; const onRetry = (err, n) => { this.log.debug({ url, err }, `Fetch failed; retrying ${n}/${retries}`); // node-fetch includes ENOTFOUND in the message, but undici (native fetch in ts-node) doesn't. @@ -85,25 +86,25 @@ export default class HTTPClient { return retry( async () => { const headers = { ...this.headers, ...options.headers }; - const res = await fetch(url, { ...options, agent, headers }); - if (!res.ok) { - const error = new HTTPClientError(res); + const result = await fetch(url, { ...options, agent, headers }); + if (!result.ok) { + const error = new HTTPClientError(result); // You can only call text() or json() once, so if we are going to handle it outside of here.. - if (!opts.noLogErrorBody) { - const body = await res.text(); + if (!options_.noLogErrorBody) { + const body = await result.text(); this.log.debug(error.message); this.log.debug(body); } throw error; } - return res; + return result; }, { retries, onRetry } ); } async fetchBuffer(url, options) { - const res = await this.fetch(url, options); - return res.buffer(); + const result = await this.fetch(url, options); + return result.buffer(); } } diff --git a/node-src/lib/checkForUpdates.ts b/node-src/lib/checkForUpdates.ts index 6d820af59..18c055036 100644 --- a/node-src/lib/checkForUpdates.ts +++ b/node-src/lib/checkForUpdates.ts @@ -30,13 +30,13 @@ export default async function checkForUpdates(ctx: Context) { } const pkgUrl = new URL(ctx.pkg.name, registryUrl).href; - const res = await withTimeout(ctx.http.fetch(pkgUrl), 5000); // If not fetched within 5 seconds, nevermind. - const { 'dist-tags': distTags = {} } = (await res.json()) as any; - if (!semver.valid(distTags.latest)) { + const result = await withTimeout(ctx.http.fetch(pkgUrl), 5000); // If not fetched within 5 seconds, nevermind. + const { 'dist-tags': distributionTags = {} } = (await result.json()) as any; + if (!semver.valid(distributionTags.latest)) { ctx.log.warn(`Invalid dist-tag 'latest' returned from registry; skipping update check`); return; } - latestVersion = distTags.latest; + latestVersion = distributionTags.latest; } catch (err) { ctx.log.warn(`Could not retrieve package info from registry; skipping update check`); ctx.log.warn(err); diff --git a/node-src/lib/checkStorybookBaseDir.test.ts b/node-src/lib/checkStorybookBaseDirectory.test.ts similarity index 64% rename from node-src/lib/checkStorybookBaseDir.test.ts rename to node-src/lib/checkStorybookBaseDirectory.test.ts index 19815240b..4e163a3a3 100644 --- a/node-src/lib/checkStorybookBaseDir.test.ts +++ b/node-src/lib/checkStorybookBaseDirectory.test.ts @@ -2,7 +2,7 @@ import path from 'path'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import * as git from '../git/git'; -import { checkStorybookBaseDir } from './checkStorybookBaseDir'; +import { checkStorybookBaseDirectory } from './checkStorybookBaseDirectory'; import { exitCodes } from './setExitCode'; import TestLogger from './testLogger'; @@ -17,9 +17,9 @@ afterEach(() => { getRepositoryRoot.mockReset(); }); -const getContext: any = (storybookBaseDir?: string) => ({ +const getContext: any = (storybookBaseDirectory?: string) => ({ log: new TestLogger(), - options: { storybookBaseDir }, + options: { storybookBaseDir: storybookBaseDirectory }, }); describe('checkStorybookBaseDir', () => { @@ -34,7 +34,7 @@ describe('checkStorybookBaseDir', () => { }, ], }; - await expect(checkStorybookBaseDir(ctx, statsWithJsModule)).resolves.toBeUndefined(); + await expect(checkStorybookBaseDirectory(ctx, statsWithJsModule)).resolves.toBeUndefined(); const statsWithJsxModule = { modules: [ @@ -44,7 +44,7 @@ describe('checkStorybookBaseDir', () => { }, ], }; - await expect(checkStorybookBaseDir(ctx, statsWithJsxModule)).resolves.toBeUndefined(); + await expect(checkStorybookBaseDirectory(ctx, statsWithJsxModule)).resolves.toBeUndefined(); const statsWithTsModule = { modules: [ @@ -54,7 +54,7 @@ describe('checkStorybookBaseDir', () => { }, ], }; - await expect(checkStorybookBaseDir(ctx, statsWithTsModule)).resolves.toBeUndefined(); + await expect(checkStorybookBaseDirectory(ctx, statsWithTsModule)).resolves.toBeUndefined(); const statsWithTsxModule = { modules: [ @@ -64,7 +64,7 @@ describe('checkStorybookBaseDir', () => { }, ], }; - await expect(checkStorybookBaseDir(ctx, statsWithTsxModule)).resolves.toBeUndefined(); + await expect(checkStorybookBaseDirectory(ctx, statsWithTsxModule)).resolves.toBeUndefined(); }); it('should throw an error if none of the js(x)/ts(x) modules in stats exist at the path prepended by the storybookBaseDir', async () => { @@ -77,13 +77,15 @@ describe('checkStorybookBaseDir', () => { ], }; - const ctxWithBaseDir = getContext('wrong'); - await expect(() => checkStorybookBaseDir(ctxWithBaseDir, stats)).rejects.toThrow(); - expect(ctxWithBaseDir.exitCode).toBe(exitCodes.INVALID_OPTIONS); + const ctxWithBaseDirectory = getContext('wrong'); + await expect(() => checkStorybookBaseDirectory(ctxWithBaseDirectory, stats)).rejects.toThrow(); + expect(ctxWithBaseDirectory.exitCode).toBe(exitCodes.INVALID_OPTIONS); - const ctxWithoutBaseDir = getContext(); - await expect(() => checkStorybookBaseDir(ctxWithoutBaseDir, stats)).rejects.toThrow(); - expect(ctxWithoutBaseDir.exitCode).toBe(exitCodes.INVALID_OPTIONS); + const ctxWithoutBaseDirectory = getContext(); + await expect(() => + checkStorybookBaseDirectory(ctxWithoutBaseDirectory, stats) + ).rejects.toThrow(); + expect(ctxWithoutBaseDirectory.exitCode).toBe(exitCodes.INVALID_OPTIONS); }); it('should not consider modules in node_modules as valid files to match', async () => { @@ -97,7 +99,7 @@ describe('checkStorybookBaseDir', () => { ], }; - await expect(() => checkStorybookBaseDir(ctx, stats)).rejects.toThrow(); + await expect(() => checkStorybookBaseDirectory(ctx, stats)).rejects.toThrow(); }); it('should assume current working directory if no storybookBaseDir is specified', async () => { @@ -112,9 +114,9 @@ describe('checkStorybookBaseDir', () => { }; getRepositoryRoot.mockResolvedValueOnce(process.cwd()); - await expect(checkStorybookBaseDir(ctx, stats)).resolves.toBeUndefined(); + await expect(checkStorybookBaseDirectory(ctx, stats)).resolves.toBeUndefined(); getRepositoryRoot.mockResolvedValueOnce(path.resolve(process.cwd(), '..')); - await expect(checkStorybookBaseDir(ctx, stats)).resolves.toBeUndefined(); + await expect(checkStorybookBaseDirectory(ctx, stats)).resolves.toBeUndefined(); }); }); diff --git a/node-src/lib/checkStorybookBaseDir.ts b/node-src/lib/checkStorybookBaseDirectory.ts similarity index 75% rename from node-src/lib/checkStorybookBaseDir.ts rename to node-src/lib/checkStorybookBaseDirectory.ts index 64cd314a5..b650c9c87 100644 --- a/node-src/lib/checkStorybookBaseDir.ts +++ b/node-src/lib/checkStorybookBaseDirectory.ts @@ -4,14 +4,15 @@ import path from 'path'; import { getRepositoryRoot } from '../git/git'; import { Context, Stats } from '../types'; -import { invalidStorybookBaseDir } from '../ui/messages/errors/invalidStorybookBaseDir'; +import { invalidStorybookBaseDirectory } from '../ui/messages/errors/invalidStorybookBaseDirectory'; import { exitCodes, setExitCode } from './setExitCode'; -export async function checkStorybookBaseDir(ctx: Context, stats: Stats) { +export async function checkStorybookBaseDirectory(ctx: Context, stats: Stats) { const repositoryRoot = await getRepositoryRoot(); // Assume CWD if no storybookBaseDir is provided - const { storybookBaseDir = path.relative(repositoryRoot, '') } = ctx.options; + const { storybookBaseDir: storybookBaseDirectory = path.relative(repositoryRoot, '') } = + ctx.options; // Find all js(x)/ts(x) files in stats that are not in node_modules const sourceModuleFiles = stats.modules.filter( @@ -26,7 +27,7 @@ export async function checkStorybookBaseDir(ctx: Context, stats: Stats) { await Promise.any( sourceModuleFiles.map((file) => { return limitConcurrency(() => { - const absolutePath = path.join(repositoryRoot, storybookBaseDir, file.name); + const absolutePath = path.join(repositoryRoot, storybookBaseDirectory, file.name); return new Promise((resolve, reject) => fs.access(absolutePath, (err) => { if (err) { @@ -41,8 +42,8 @@ export async function checkStorybookBaseDir(ctx: Context, stats: Stats) { }) ); } catch { - ctx.log.debug(`Invalid storybookBaseDir: ${storybookBaseDir}`); + ctx.log.debug(`Invalid storybookBaseDir: ${storybookBaseDirectory}`); setExitCode(ctx, exitCodes.INVALID_OPTIONS, true); - throw new Error(invalidStorybookBaseDir()); + throw new Error(invalidStorybookBaseDirectory()); } } diff --git a/node-src/lib/compress.ts b/node-src/lib/compress.ts index 8b7b889a5..fdd34884f 100644 --- a/node-src/lib/compress.ts +++ b/node-src/lib/compress.ts @@ -1,17 +1,17 @@ import archiver from 'archiver'; import { createReadStream, createWriteStream } from 'fs'; -import { file as tempFile } from 'tmp-promise'; +import { file as temporaryFile } from 'tmp-promise'; import { Context, FileDesc } from '../types'; export default async function makeZipFile(ctx: Context, files: FileDesc[]) { const archive = archiver('zip', { zlib: { level: 9 } }); - const tmp = await tempFile({ postfix: '.zip' }); - const sink = createWriteStream(undefined, { fd: tmp.fd }); + const temporary = await temporaryFile({ postfix: '.zip' }); + const sink = createWriteStream(undefined, { fd: temporary.fd }); return new Promise<{ path: string; size: number }>((resolve, reject) => { sink.on('close', () => { - resolve({ path: tmp.path, size: archive.pointer() }); + resolve({ path: temporary.path, size: archive.pointer() }); }); // 'warning' messages contain non-blocking errors diff --git a/node-src/lib/e2e.ts b/node-src/lib/e2e.ts index 22713cc10..4748ed877 100644 --- a/node-src/lib/e2e.ts +++ b/node-src/lib/e2e.ts @@ -7,8 +7,8 @@ import { exitCodes, setExitCode } from './setExitCode'; export const buildBinName = 'build-archive-storybook'; -const quote = (arg: string) => - !arg.startsWith('--') && arg.includes(' ') ? JSON.stringify(arg) : arg; +const quote = (argument: string) => + !argument.startsWith('--') && argument.includes(' ') ? JSON.stringify(argument) : argument; // ni doesn't currently have a "exec" command (equivalent to `npm exec`). // It has a "download & exec" command (equivalent to `npx`). diff --git a/node-src/lib/findChangedDependencies.ts b/node-src/lib/findChangedDependencies.ts index bfddf104b..288e8e82e 100644 --- a/node-src/lib/findChangedDependencies.ts +++ b/node-src/lib/findChangedDependencies.ts @@ -103,12 +103,12 @@ export const findChangedDependencies = async (ctx: Context) => { // A change means either the version number is different or the dependency was added/removed. // If a manifest or lockfile is missing on the baseline, this throws and we'll end up bailing. await Promise.all( - commits.map(async (ref) => { + commits.map(async (reference) => { const baselineChanges = await compareBaseline(ctx, headDependencies, { - ref, + ref: reference, rootPath, - manifestPath: await checkoutFile(ctx, ref, manifestPath), - lockfilePath: await checkoutFile(ctx, ref, lockfilePath), + manifestPath: await checkoutFile(ctx, reference, manifestPath), + lockfilePath: await checkoutFile(ctx, reference, lockfilePath), }); for (const change of baselineChanges) { changedDependencyNames.add(change); diff --git a/node-src/lib/findChangedPackageFiles.ts b/node-src/lib/findChangedPackageFiles.ts index 3cf7667f3..fe1bbe930 100644 --- a/node-src/lib/findChangedPackageFiles.ts +++ b/node-src/lib/findChangedPackageFiles.ts @@ -20,8 +20,8 @@ const isEqual = (left: unknown = {}, right: unknown = {}) => { } // depends on always having consistent ordering of keys - for (const [i, [keyA, valueA]] of entriesA.entries()) { - const [keyB, valueB] = entriesB[i]; + for (const [index, [keyA, valueA]] of entriesA.entries()) { + const [keyB, valueB] = entriesB[index]; // values might be objects, so recursively compare if (keyA !== keyB || !isEqual(valueA, valueB)) { diff --git a/node-src/lib/getDependencies.ts b/node-src/lib/getDependencies.ts index 7b50bcb90..63340dec9 100644 --- a/node-src/lib/getDependencies.ts +++ b/node-src/lib/getDependencies.ts @@ -8,6 +8,7 @@ export const getDependencies = async ( rootPath, manifestPath, lockfilePath, + // eslint-disable-next-line unicorn/prevent-abbreviations includeDev = true, strictOutOfSync = false, }: { diff --git a/node-src/lib/getDependentStoryFiles.test.ts b/node-src/lib/getDependentStoryFiles.test.ts index ed24ce2ad..55fe8f790 100644 --- a/node-src/lib/getDependentStoryFiles.test.ts +++ b/node-src/lib/getDependentStoryFiles.test.ts @@ -51,8 +51,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -72,8 +72,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -93,8 +93,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext({ storybookBaseDir: 'path/to/project' }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.js': ['path/to/project/src/foo.stories.js'], }); }); @@ -114,8 +114,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -135,8 +135,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -156,8 +156,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -185,8 +185,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -211,8 +211,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -243,8 +243,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.ts': ['src/foo.stories.ts'], }); }); @@ -265,8 +265,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js', 'src/foo.js'], }); }); @@ -292,14 +292,14 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles( + const result = await getDependentStoryFiles( ctx, { modules }, statsPath, changedFiles, changedDependencies ); - expect(res).toEqual({ + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -324,8 +324,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext({ storybookBaseDir: 'services/webapp' }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.js': ['services/webapp/src/foo.stories.js'], }); }); @@ -353,8 +353,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ '/path/to/project/src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -383,8 +383,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext({ storybookBaseDir: 'packages/storybook' }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ '/path/to/project/packages/webapp/src/foo.stories.js': ['packages/webapp/src/foo.stories.js'], }); }); @@ -419,8 +419,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({ + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); expect(ctx.turboSnap.bailReason).toBeUndefined(); @@ -447,7 +447,7 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext(); - const res = await getDependentStoryFiles( + const result = await getDependentStoryFiles( ctx, { modules }, statsPath, @@ -455,7 +455,7 @@ describe('getDependentStoryFiles', () => { changedDependencies ); expect(ctx.turboSnap.bailReason).toBeUndefined(); - expect(res).toEqual({ + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -480,9 +480,9 @@ describe('getDependentStoryFiles', () => { // signifying the package.json file had dependency changes git: { ...rawContext.git, changedPackageManifests: ['src/package.json'] }, }; - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); expect(ctx.turboSnap.bailReason).toBeUndefined(); - expect(res).toEqual({ + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -502,8 +502,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext({ configDir: 'path/to/storybook-config' }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toBeUndefined(); + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toBeUndefined(); expect(ctx.turboSnap.bailReason).toEqual({ changedStorybookFiles: ['path/to/storybook-config/file.js'], }); @@ -529,8 +529,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext({ configDir: 'path/to/storybook-config' }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toBeUndefined(); + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toBeUndefined(); expect(ctx.turboSnap.bailReason).toEqual({ changedStorybookFiles: ['path/to/storybook-config/file.js'], }); @@ -557,8 +557,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext({ configDir: 'path/to/storybook-config' }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toBeUndefined(); + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toBeUndefined(); expect(ctx.turboSnap.bailReason).toEqual({ changedStorybookFiles: ['path/to/storybook-config/file.js', 'src/styles.js'], }); @@ -584,8 +584,8 @@ describe('getDependentStoryFiles', () => { }, ]; const ctx = getContext({ staticDir: ['path/to/statics'] }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toBeUndefined(); + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toBeUndefined(); expect(ctx.turboSnap.bailReason).toEqual({ changedStaticFiles: ['path/to/statics/image.png'], }); @@ -663,8 +663,8 @@ describe('getDependentStoryFiles', () => { staticDir: ['public'], untraced: ['**/stories/**'], }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({}); + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({}); }); it('ignores untraced files', async () => { @@ -695,8 +695,8 @@ describe('getDependentStoryFiles', () => { staticDir: ['path/to/statics'], untraced: ['**/foo.js'], }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); - expect(res).toEqual({}); + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + expect(result).toEqual({}); }); it('does not bail on untraced global files', async () => { @@ -731,9 +731,9 @@ describe('getDependentStoryFiles', () => { const ctx = getContext({ untraced: ['**/(package**.json|yarn.lock)'], }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); expect(ctx.turboSnap.bailReason).toBeUndefined(); - expect(res).toEqual({ + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -780,9 +780,9 @@ describe('getDependentStoryFiles', () => { const ctx = getContext({ untraced: ['**/decorator.jsx'], }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); expect(ctx.turboSnap.bailReason).toBeUndefined(); - expect(res).toEqual({ + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); @@ -837,9 +837,9 @@ describe('getDependentStoryFiles', () => { configDir: 'path/to/storybook-config', untraced: ['**/decorator.jsx'], }); - const res = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); + const result = await getDependentStoryFiles(ctx, { modules }, statsPath, changedFiles); expect(ctx.turboSnap.bailReason).toBeUndefined(); - expect(res).toEqual({ + expect(result).toEqual({ './src/foo.stories.js': ['src/foo.stories.js'], }); }); diff --git a/node-src/lib/getDependentStoryFiles.ts b/node-src/lib/getDependentStoryFiles.ts index 1b984b2cb..218ea2ed6 100644 --- a/node-src/lib/getDependentStoryFiles.ts +++ b/node-src/lib/getDependentStoryFiles.ts @@ -22,10 +22,10 @@ const LOCKFILES = [ const INTERNALS = [/\/webpack\/runtime\//, /^\(webpack\)/]; const isPackageLockFile = (name: string) => LOCKFILES.some((re) => re.test(name)); -const isUserModule = (mod: Module | Reason) => - (mod as Module).id !== undefined && - (mod as Module).id !== null && - !INTERNALS.some((re) => re.test((mod as Module).name || (mod as Reason).moduleName)); +const isUserModule = (module_: Module | Reason) => + (module_ as Module).id !== undefined && + (module_ as Module).id !== null && + !INTERNALS.some((re) => re.test((module_ as Module).name || (module_ as Reason).moduleName)); // Replaces Windows-style backslash path separators with POSIX-style forward slashes, because the // Webpack stats use forward slashes in the `name` and `moduleName` fields. Note `changedFiles` @@ -47,11 +47,11 @@ const getPackageName = (modulePath: string) => { * The result is a relative POSIX path compatible with `git diff --name-only`. * Virtual paths (e.g. Vite) are returned as-is. */ -export function normalizePath(posixPath: string, rootPath: string, baseDir = '') { +export function normalizePath(posixPath: string, rootPath: string, baseDirectory = '') { if (!posixPath || posixPath.startsWith('/virtual:')) return posixPath; return path.posix.isAbsolute(posixPath) ? path.posix.relative(rootPath, posixPath) - : path.posix.join(baseDir, posixPath); + : path.posix.join(baseDirectory, posixPath); } /** @@ -68,34 +68,41 @@ export async function getDependentStoryFiles( changedFiles: string[], changedDependencies: string[] = [] ) { - const { configDir = '.storybook', staticDir = [], viewLayer } = ctx.storybook || {}; + const { + configDir: configDirectory = '.storybook', + staticDir: staticDirectory = [], + viewLayer, + } = ctx.storybook || {}; const { storybookBuildDir, storybookBaseDir, - storybookConfigDir = configDir, + // eslint-disable-next-line unicorn/prevent-abbreviations + storybookConfigDir = configDirectory, untraced = [], } = ctx.options; const rootPath = await getRepositoryRoot(); // e.g. `/path/to/project` (always absolute posix) - const baseDir = storybookBaseDir ? posix(storybookBaseDir) : path.posix.relative(rootPath, ''); + const baseDirectory = storybookBaseDir + ? posix(storybookBaseDir) + : path.posix.relative(rootPath, ''); // Convert a "webpack path" (relative to storybookBaseDir) to a "git path" (relative to repository root) // e.g. `./src/file.js` => `path/to/storybook/src/file.js` const normalize = (posixPath: FilePath): NormalizedName => { const CSF_REGEX = /\s+(sync|lazy)\s+/g; const URL_PARAM_REGEX = /(\?.*)/g; - const newPath = normalizePath(posixPath, rootPath, baseDir); + const newPath = normalizePath(posixPath, rootPath, baseDirectory); // Trim query params such as `?ngResource` which are sometimes present return URL_PARAM_REGEX.test(newPath) && !CSF_REGEX.test(newPath) ? newPath.replaceAll(URL_PARAM_REGEX, '') : newPath; }; - const storybookDir = normalize(posix(storybookConfigDir)); - const staticDirs = staticDir.map((dir: string) => normalize(posix(dir))); + const storybookDirectory = normalize(posix(storybookConfigDir)); + const staticDirectories = staticDirectory.map((directory: string) => normalize(posix(directory))); - ctx.log.debug('BASE Directory:', baseDir); - ctx.log.debug('Storybook CONFIG Directory:', storybookDir); + ctx.log.debug('BASE Directory:', baseDirectory); + ctx.log.debug('Storybook CONFIG Directory:', storybookDirectory); // NOTE: this only works with `main:stories` -- if stories are imported from files in `.storybook/preview.js` // we'll need a different approach to figure out CSF files (maybe the user should pass a glob?). @@ -123,13 +130,13 @@ export async function getDependentStoryFiles( const csfGlobsByName = new Set(); stats.modules - .filter((mod) => isUserModule(mod)) - .map((mod) => { - const normalizedName = normalize(mod.name); - modulesByName.set(normalizedName, mod); - namesById.set(mod.id, normalizedName); + .filter((module_) => isUserModule(module_)) + .map((module_) => { + const normalizedName = normalize(module_.name); + modulesByName.set(normalizedName, module_); + namesById.set(module_.id, normalizedName); - const packageName = getPackageName(mod.name); + const packageName = getPackageName(module_.name); if (packageName) { // Track all modules from any node_modules directory by their package name, so we can mark // all those files "changed" if a dependency (version) changes, while still being able to @@ -138,18 +145,18 @@ export async function getDependentStoryFiles( nodeModules.get(packageName).push(normalizedName); } - if (mod.modules) { - for (const m of mod.modules) { - modulesByName.set(normalize(m.name), mod); + if (module_.modules) { + for (const m of module_.modules) { + modulesByName.set(normalize(m.name), module_); } } - const normalizedReasons = mod.reasons + const normalizedReasons = module_.reasons .map((reason) => normalize(reason.moduleName)) .filter((reasonName) => reasonName && reasonName !== normalizedName); - reasonsById.set(mod.id, normalizedReasons); + reasonsById.set(module_.id, normalizedReasons); - if (reasonsById.get(mod.id).some((reason) => storiesEntryFiles.has(reason))) { + if (reasonsById.get(module_.id).some((reason) => storiesEntryFiles.has(reason))) { csfGlobsByName.add(normalizedName); } }); @@ -159,18 +166,27 @@ export async function getDependentStoryFiles( // does not use configDir in the entry file path so there's no fix to recommend there. const storiesEntryRegExp = /^(.+\/)?generated-stories-entry\.js$/; const foundEntry = stats.modules.find( - (mod) => storiesEntryRegExp.test(mod.name) && !storiesEntryFiles.has(normalize(mod.name)) + (module_) => + storiesEntryRegExp.test(module_.name) && !storiesEntryFiles.has(normalize(module_.name)) ); const entryFile = foundEntry && normalize(foundEntry.name); - ctx.log.error(noCSFGlobs({ statsPath, storybookDir, storybookBuildDir, entryFile, viewLayer })); + ctx.log.error( + noCSFGlobs({ + statsPath, + storybookDir: storybookDirectory, + storybookBuildDir, + entryFile, + viewLayer, + }) + ); throw new Error('Did not find any CSF globs in preview-stats.json'); } const isCsfGlob = (name: NormalizedName) => csfGlobsByName.has(name); const isStorybookFile = (name: string) => - name && name.startsWith(`${storybookDir}/`) && !storiesEntryFiles.has(name); + name && name.startsWith(`${storybookDirectory}/`) && !storiesEntryFiles.has(name); const isStaticFile = (name: string) => - staticDirs.some((dir) => name && name.startsWith(`${dir}/`)); + staticDirectories.some((directory) => name && name.startsWith(`${directory}/`)); ctx.untracedFiles = []; function untrace(filepath: string) { @@ -182,10 +198,12 @@ export async function getDependentStoryFiles( } function files(moduleName: string) { - const mod = modulesByName.get(moduleName); - if (!mod) return [moduleName]; + const module_ = modulesByName.get(moduleName); + if (!module_) return [moduleName]; // Normalize module names, if there are any - return mod.modules?.length ? mod.modules.map((m) => normalize(m.name)) : [normalize(mod.name)]; + return module_.modules?.length + ? module_.modules.map((m) => normalize(m.name)) + : [normalize(module_.name)]; } const tracedFiles = [ @@ -200,9 +218,9 @@ export async function getDependentStoryFiles( ctx.turboSnap = { rootPath, - baseDir, - storybookDir, - staticDirs, + baseDir: baseDirectory, + storybookDir: storybookDirectory, + staticDirs: staticDirectories, globs: [...csfGlobsByName], modules: [...modulesByName.keys()], tracedFiles, diff --git a/node-src/lib/getEnv.ts b/node-src/lib/getEnvironment.ts similarity index 97% rename from node-src/lib/getEnv.ts rename to node-src/lib/getEnvironment.ts index cfb0b3385..6d86dab21 100644 --- a/node-src/lib/getEnv.ts +++ b/node-src/lib/getEnvironment.ts @@ -1,4 +1,4 @@ -export interface Env { +export interface Environment { CHROMATIC_DNS_FAILOVER_SERVERS: string[]; CHROMATIC_DNS_SERVERS: string[]; CHROMATIC_HASH_CONCURRENCY: number; @@ -51,7 +51,7 @@ const CHROMATIC_PROJECT_TOKEN = process.env.CHROMATIC_APP_CODE || // backwards compatibility process.env.CHROMA_APP_CODE; // backwards compatibility -export default function getEnv(): Env { +export default function getEnvironment(): Environment { return { CHROMATIC_DNS_FAILOVER_SERVERS: CHROMATIC_DNS_FAILOVER_SERVERS.split(',') .map((ip) => ip.trim()) diff --git a/node-src/lib/getFileHashes.ts b/node-src/lib/getFileHashes.ts index d025cd911..3f3968757 100644 --- a/node-src/lib/getFileHashes.ts +++ b/node-src/lib/getFileHashes.ts @@ -10,17 +10,17 @@ const hashFile = (buffer: Buffer, path: string, xxhash: XXHashAPI): Promise { const done = (fd: number, getResult: () => bigint) => { let result: bigint = undefined; - close(fd, (closeErr) => { - if (closeErr) reject(closeErr); + close(fd, (closeError) => { + if (closeError) reject(closeError); else resolve(result.toString(16).padStart(16, '0')); }); result = getResult(); }; const readIncremental = (fd: number, hash: XXHash) => { - read(fd, buffer, undefined, BUFFER_SIZE, -1, (readErr, bytesRead) => { - if (readErr) { - return close(fd, () => reject(readErr)); + read(fd, buffer, undefined, BUFFER_SIZE, -1, (readError, bytesRead) => { + if (readError) { + return close(fd, () => reject(readError)); } if (bytesRead === BUFFER_SIZE) { hash.update(buffer); @@ -32,13 +32,13 @@ const hashFile = (buffer: Buffer, path: string, xxhash: XXHashAPI): Promise { - if (openErr) { - return reject(openErr); + open(path, 'r', (openError, fd) => { + if (openError) { + return reject(openError); } - read(fd, buffer, undefined, BUFFER_SIZE, -1, (readErr, bytesRead) => { - if (readErr) { - return close(fd, () => reject(readErr)); + read(fd, buffer, undefined, BUFFER_SIZE, -1, (readError, bytesRead) => { + if (readError) { + return close(fd, () => reject(readError)); } if (bytesRead < BUFFER_SIZE) { // Do a single hash if the whole file fits into the buffer. @@ -54,7 +54,7 @@ const hashFile = (buffer: Buffer, path: string, xxhash: XXHashAPI): Promise { +export const getFileHashes = async (files: string[], directory: string, concurrency: number) => { // Limit the number of concurrent file reads and hashing operations. const limit = pLimit(concurrency); const xxhash = await xxHashWasm(); @@ -64,7 +64,7 @@ export const getFileHashes = async (files: string[], dir: string, concurrency: n const hashes = await Promise.all( buffers.map(([buffer, file]) => - limit(async () => [file, await hashFile(buffer, path.join(dir, file), xxhash)] as const) + limit(async () => [file, await hashFile(buffer, path.join(directory, file), xxhash)] as const) ) ); diff --git a/node-src/lib/getOptions.test.ts b/node-src/lib/getOptions.test.ts index 960c02ac2..96a3cf888 100644 --- a/node-src/lib/getOptions.test.ts +++ b/node-src/lib/getOptions.test.ts @@ -2,21 +2,21 @@ import chalk from 'chalk'; import { describe, expect, it, vi } from 'vitest'; import { Context } from '../types'; -import getEnv from './getEnv'; +import getEnvironment from './getEnvironment'; import getOptions from './getOptions'; import getStorybookConfiguration from './getStorybookConfiguration'; -import parseArgs from './parseArgs'; +import parseArguments from './parseArguments'; import TestLogger from './testLogger'; // Make sure we don't print any colors so we can match against plain strings chalk.level = 0; -vi.mock('./getEnv', () => ({ +vi.mock('./getEnvironment', () => ({ default: () => ({ CHROMATIC_PROJECT_TOKEN: 'env-code' }), })); const getContext = (argv: string[]): Context => { - const env = getEnv(); + const environment = getEnvironment(); const log = new TestLogger(); const packageJson = { scripts: { @@ -26,7 +26,7 @@ const getContext = (argv: string[]): Context => { otherBuildStorybook: 'build-storybook', }, }; - return { env, log, packageJson, ...parseArgs(argv) } as any; + return { env: environment, log, packageJson, ...parseArguments(argv) } as any; }; describe('getOptions', () => { diff --git a/node-src/lib/getOptions.ts b/node-src/lib/getOptions.ts index a11bc7611..b485aacb0 100644 --- a/node-src/lib/getOptions.ts +++ b/node-src/lib/getOptions.ts @@ -94,7 +94,9 @@ export default function getOptions({ uploadMetadata: undefined, }; - const [patchHeadRef, patchBaseRef] = (flags.patchBuild || '').split('...').filter(Boolean); + const [patchHeadReference, patchBaseReference] = (flags.patchBuild || '') + .split('...') + .filter(Boolean); const [branchName, branchOwner] = (flags.branchName || '').split(':').reverse(); const [repositoryOwner, repositoryName, ...rest] = flags.repositorySlug?.split('/') || []; @@ -149,8 +151,8 @@ export default function getOptions({ ownerName: branchOwner || repositoryOwner, repositorySlug: flags.repositorySlug, branchName, - patchHeadRef, - patchBaseRef, + patchHeadRef: patchHeadReference, + patchBaseRef: patchBaseReference, uploadMetadata: flags.uploadMetadata, }); @@ -210,15 +212,17 @@ export default function getOptions({ let { buildScriptName } = options; // We can only have one of these arguments - const singularOpts = { + const singularOptions = { storybookBuildDir: '--storybook-build-dir', playwright: '--playwright', cypress: '--cypress', }; - const foundSingularOpts = Object.keys(singularOpts).filter((name) => !!options[name]); + const foundSingularOptions = Object.keys(singularOptions).filter((name) => !!options[name]); - if (foundSingularOpts.length > 1) { - throw new Error(invalidSingularOptions(foundSingularOpts.map((key) => singularOpts[key]))); + if (foundSingularOptions.length > 1) { + throw new Error( + invalidSingularOptions(foundSingularOptions.map((key) => singularOptions[key])) + ); } if (options.onlyChanged && options.onlyStoryFiles) { diff --git a/node-src/lib/getStorybookMetadata.ts b/node-src/lib/getStorybookMetadata.ts index 928450cf0..9925a2b15 100644 --- a/node-src/lib/getStorybookMetadata.ts +++ b/node-src/lib/getStorybookMetadata.ts @@ -32,6 +32,7 @@ const findDependency = ( ]; const getDependencyInfo = ({ packageJson, log }, dependencyMap: Record) => { + // eslint-disable-next-line unicorn/prevent-abbreviations const [dep, devDep, peerDep] = findDependency(packageJson, (key) => dependencyMap[key]); const [pkg, version] = dep || devDep || peerDep || []; const dependency = viewLayers[pkg]; @@ -201,26 +202,26 @@ export const findBuilder = async (mainConfig, v7) => { }; export const findStorybookConfigFile = async (ctx: Context, pattern: RegExp) => { - const configDir = ctx.options.storybookConfigDir ?? '.storybook'; - const files = await readdir(configDir); + const configDirectory = ctx.options.storybookConfigDir ?? '.storybook'; + const files = await readdir(configDirectory); const configFile = files.find((file) => pattern.test(file)); - return configFile && path.join(configDir, configFile); + return configFile && path.join(configDirectory, configFile); }; export const getStorybookMetadata = async (ctx: Context) => { - const configDir = ctx.options.storybookConfigDir ?? '.storybook'; + const configDirectory = ctx.options.storybookConfigDir ?? '.storybook'; const r = typeof __non_webpack_require__ === 'undefined' ? require : __non_webpack_require__; let mainConfig; let v7 = false; try { - mainConfig = await r(path.resolve(configDir, 'main')); - ctx.log.debug({ configDir, mainConfig }); + mainConfig = await r(path.resolve(configDirectory, 'main')); + ctx.log.debug({ configDirectory, mainConfig }); } catch (err) { ctx.log.debug({ storybookV6error: err }); try { mainConfig = await readConfig(await findStorybookConfigFile(ctx, /^main\.[jt]sx?$/)); - ctx.log.debug({ configDir, mainConfig }); + ctx.log.debug({ configDirectory, mainConfig }); v7 = true; } catch (err) { ctx.log.debug({ storybookV7error: err }); diff --git a/node-src/lib/log.ts b/node-src/lib/log.ts index 9e370a074..45d436f0b 100644 --- a/node-src/lib/log.ts +++ b/node-src/lib/log.ts @@ -16,13 +16,17 @@ process.on('unhandledRejection', handleRejection); // Omits any JSON metadata, returning only the message string const logInteractive = (args: any[]): string[] => - args.map((arg) => (arg && arg.message) || arg).filter((arg) => typeof arg === 'string'); + args + .map((argument) => (argument && argument.message) || argument) + .filter((argument) => typeof argument === 'string'); // Strips ANSI codes from messages and stringifies metadata to JSON const logVerbose = (type: string, args: any[]) => { const stringify = - type === 'error' ? (e: any) => JSON.stringify(errorSerializer(e)) : JSON.stringify; - return args.map((arg) => (typeof arg === 'string' ? stripAnsi(arg) : stringify(arg))); + type === 'error' ? (err: any) => JSON.stringify(errorSerializer(err)) : JSON.stringify; + return args.map((argument) => + typeof argument === 'string' ? stripAnsi(argument) : stringify(argument) + ); }; const withTime = (messages: string[], color = false) => { @@ -31,21 +35,21 @@ const withTime = (messages: string[], color = false) => { if (color) time = chalk.dim(time); return [ time + ' ', - ...messages.map((msg) => - typeof msg === 'string' ? msg.replaceAll('\n', `\n `) : msg + ...messages.map((message) => + typeof message === 'string' ? message.replaceAll('\n', `\n `) : message ), ]; }; type LogType = 'error' | 'warn' | 'info' | 'debug'; -type LogFn = (...args: any[]) => void; +type LogFunction = (...args: any[]) => void; export interface Logger { - error: LogFn; - warn: LogFn; - info: LogFn; - log: LogFn; - file: LogFn; - debug: LogFn; + error: LogFunction; + warn: LogFunction; + info: LogFunction; + log: LogFunction; + file: LogFunction; + debug: LogFunction; queue: () => void; flush: () => void; getLevel: () => keyof typeof LOG_LEVELS; @@ -63,7 +67,7 @@ const fileLogger = { this.append = () => {}; this.queue = []; }, - initialize(path: string, onError: LogFn) { + initialize(path: string, onError: LogFunction) { rm(path, { force: true }, (err) => { if (err) { this.disable(); @@ -72,7 +76,9 @@ const fileLogger = { const stream = createWriteStream(path, { flags: 'a' }); this.append = (...messages: string[]) => { stream?.write( - messages.reduce((acc, msg) => acc + msg + (msg === '\n' ? '' : ' '), '').trim() + '\n' + messages + .reduce((result, message) => result + message + (message === '\n' ? '' : ' '), '') + .trim() + '\n' ); }; this.append(...this.queue); diff --git a/node-src/lib/logSerializers.ts b/node-src/lib/logSerializers.ts index 9f448ce17..a3bdb81c8 100644 --- a/node-src/lib/logSerializers.ts +++ b/node-src/lib/logSerializers.ts @@ -13,14 +13,14 @@ function responseSerializer({ status, statusText, headers, url, _raw }: Response // We *don't* want to log the envPairs key -- this is added by node and includes // all of our environment variables! See https://github.com/chromaui/chromatic/issues/1993 // Note it is added to both err.envPairs *and* err.options.envPairs :facepalm: -function stripEnvPairs(err: any) { +function stripEnvironmentPairs(err: any) { // @ts-expect-error Ignore the _ property - const { envPairs, options: { envPairs: _, ...options } = {}, ...sanitizedErr } = err; - return { sanitizedErr, ...(err.options && { options }) }; + const { envPairs, options: { envPairs: _, ...options } = {}, ...sanitizedError } = err; + return { sanitizedErr: sanitizedError, ...(err.options && { options }) }; } export const errorSerializer = (err: any) => ({ - ...stripEnvPairs(err), + ...stripEnvironmentPairs(err), // Serialize the response part of err with the response serializer ...(err.response && { response: responseSerializer(err.response) }), }); diff --git a/node-src/lib/parseArgs.ts b/node-src/lib/parseArguments.ts similarity index 99% rename from node-src/lib/parseArgs.ts rename to node-src/lib/parseArguments.ts index ef23e02bb..44657b76f 100644 --- a/node-src/lib/parseArgs.ts +++ b/node-src/lib/parseArguments.ts @@ -3,7 +3,7 @@ import meow from 'meow'; import pkg from '../../package.json'; import { Flags } from '../types'; -export default function parseArgs(argv: string[]) { +export default function parseArguments(argv: string[]) { const { input, flags, help } = meow( ` Chromatic CLI diff --git a/node-src/lib/promises.ts b/node-src/lib/promises.ts index 0852f9fdb..6de10cb35 100644 --- a/node-src/lib/promises.ts +++ b/node-src/lib/promises.ts @@ -5,7 +5,7 @@ const invert = (promise: Promise) => new Promise((resolve, reject) => promise.then(reject, resolve)); export const raceFulfilled = (promises: Promise[]): Promise => - invert(Promise.all(promises.map((promise) => invert(promise))).then((arr) => arr[0])); + invert(Promise.all(promises.map((promise) => invert(promise))).then((promises) => promises[0])); export const timeout = (ms: number) => new Promise((_, rej) => { diff --git a/node-src/lib/tasks.ts b/node-src/lib/tasks.ts index d764d533c..3def15366 100644 --- a/node-src/lib/tasks.ts +++ b/node-src/lib/tasks.ts @@ -4,7 +4,7 @@ import pluralize from 'pluralize'; import { Context, Task, TaskName } from '../types'; -type ValueFn = string | ((ctx: Context, task: Task) => string); +type ValueFunction = string | ((ctx: Context, task: Task) => string); type TaskInput = Omit, 'task'> & { name: TaskName; @@ -35,20 +35,21 @@ export const createTask = ({ ...config, }); -export const setTitle = (title: ValueFn, subtitle: ValueFn) => (ctx: Context, task: Task) => { - const ttl = typeof title === 'function' ? title(ctx, task) : title; - const sub = typeof subtitle === 'function' ? subtitle(ctx, task) : subtitle; - task.title = sub ? `${ttl}\n${chalk.dim(` → ${sub}`)}` : ttl; -}; +export const setTitle = + (title: ValueFunction, subtitle: ValueFunction) => (ctx: Context, task: Task) => { + const ttl = typeof title === 'function' ? title(ctx, task) : title; + const sub = typeof subtitle === 'function' ? subtitle(ctx, task) : subtitle; + task.title = sub ? `${ttl}\n${chalk.dim(` → ${sub}`)}` : ttl; + }; -export const setOutput = (output: ValueFn) => (ctx: Context, task: Task) => { +export const setOutput = (output: ValueFunction) => (ctx: Context, task: Task) => { task.output = typeof output === 'function' ? output(ctx, task) : output; }; export const transitionTo = - (stateFn: (ctx: Context) => Task, last = false) => + (stateFunction: (ctx: Context) => Task, last = false) => (ctx: Context, task: Task) => { - const { title, output } = stateFn(ctx); + const { title, output } = stateFunction(ctx); setTitle(title, last ? output : undefined)(ctx, task); if (!last && output) setOutput(output)(ctx, task); }; diff --git a/node-src/lib/upload.ts b/node-src/lib/upload.ts index 57230ac20..eb3a0ddbf 100644 --- a/node-src/lib/upload.ts +++ b/node-src/lib/upload.ts @@ -239,6 +239,6 @@ export async function uploadMetadata(ctx: Context, files: FileDesc[]) { } if (uploadMetadata.userErrors.length > 0) { - uploadMetadata.userErrors.map((e) => ctx.log.warn(e.message)); + uploadMetadata.userErrors.map((err) => ctx.log.warn(err.message)); } } diff --git a/node-src/lib/uploadZip.ts b/node-src/lib/uploadZip.ts index b27f1617a..f62dbb3b9 100644 --- a/node-src/lib/uploadZip.ts +++ b/node-src/lib/uploadZip.ts @@ -33,14 +33,14 @@ export async function uploadZip( } formData.append('file', blob); - const res = await ctx.http.fetch( + const result = await ctx.http.fetch( formAction, { body: formData, method: 'POST', signal }, { retries: 0 } // already retrying the whole operation ); - if (!res.ok) { - ctx.log.debug(`Uploading ${localPath} failed: %O`, res); + if (!result.ok) { + ctx.log.debug(`Uploading ${localPath} failed: %O`, result); throw new Error(localPath); } ctx.log.debug(`Uploaded ${filePath} (${filesize(contentLength)})`); diff --git a/node-src/lib/utils.ts b/node-src/lib/utils.ts index 6bd215df4..d9d43a091 100644 --- a/node-src/lib/utils.ts +++ b/node-src/lib/utils.ts @@ -3,19 +3,19 @@ import picomatch, { Matcher } from 'picomatch'; export const lcfirst = (str: string) => `${str.charAt(0).toLowerCase()}${str.slice(1)}`; export const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); -export const tick = async (times: number, interval: number, fn: (i: number) => any) => { - for (let i = 0; i < times; i += 1) { +export const tick = async (times: number, interval: number, function_: (index: number) => any) => { + for (let index = 0; index < times; index += 1) { await delay(interval); - fn(i); + function_(index); } }; export const throttle = (fn: (...args: any[]) => void, wait: number) => { - let prev = 0; + let previous = 0; return (...args: any[]) => { const now = Date.now(); - if (now - prev >= wait) { - prev = now; + if (now - previous >= wait) { + previous = now; fn(...args); } }; @@ -30,8 +30,8 @@ export const progressBar = (percentage: number, size = 20) => { }; export const activityBar = (n = 0, size = 20) => { const track = repeat(size, ' '); - const i = n % ((size - 1) * 2); - track[i >= size ? (size - 1) * 2 - i : i] = '*'; + const index = n % ((size - 1) * 2); + track[index >= size ? (size - 1) * 2 - index : index] = '*'; return `[${track.join('')}]`; }; @@ -65,7 +65,8 @@ export const isPackageMetadataFile = (filePath: string) => export const redact = (value: T, ...fields: string[]): T => { if (value === null || typeof value !== 'object') return value; if (Array.isArray(value)) return value.map((item) => redact(item, ...fields)) as T; - const obj = { ...value }; - for (const key in obj) obj[key] = fields.includes(key) ? undefined : redact(obj[key], ...fields); - return obj; + const object = { ...value }; + for (const key in object) + object[key] = fields.includes(key) ? undefined : redact(object[key], ...fields); + return object; }; diff --git a/node-src/lib/waitForSentinel.ts b/node-src/lib/waitForSentinel.ts index d13fbe14e..a48fb86df 100644 --- a/node-src/lib/waitForSentinel.ts +++ b/node-src/lib/waitForSentinel.ts @@ -19,8 +19,12 @@ export async function waitForSentinel(ctx: Context, { name, url }: { name: strin } try { - const res = await ctx.http.fetch(url, { signal }, { retries: 0, noLogErrorBody: true }); - const result = await res.text(); + const response = await ctx.http.fetch( + url, + { signal }, + { retries: 0, noLogErrorBody: true } + ); + const result = await response.text(); if (result !== SENTINEL_SUCCESS_VALUE) { ctx.log.debug(`Sentinel file '${name}' not OK, got '${result}'.`); return bail(new Error(`Sentinel file '${name}' not OK.`)); diff --git a/node-src/tasks/build.test.ts b/node-src/tasks/build.test.ts index 24204e26a..bb2676ddd 100644 --- a/node-src/tasks/build.test.ts +++ b/node-src/tasks/build.test.ts @@ -4,7 +4,7 @@ import { getCliCommand as getCliCommandDefault } from '@antfu/ni'; import { execaCommand } from 'execa'; import { describe, expect, it, vi } from 'vitest'; -import { buildStorybook, setBuildCommand, setSourceDir } from './build'; +import { buildStorybook, setBuildCommand, setSourceDirectory } from './build'; vi.mock('execa'); vi.mock('@antfu/ni'); @@ -19,25 +19,25 @@ beforeEach(() => { describe('setSourceDir', () => { it('sets a random temp directory path on the context', async () => { const ctx = { options: {}, storybook: { version: '5.0.0' } } as any; - await setSourceDir(ctx); + await setSourceDirectory(ctx); expect(ctx.sourceDir).toMatch(/chromatic-/); }); it('falls back to the default output dir for older Storybooks', async () => { const ctx = { options: {}, storybook: { version: '4.0.0' } } as any; - await setSourceDir(ctx); + await setSourceDirectory(ctx); expect(ctx.sourceDir).toBe('storybook-static'); }); it('uses the outputDir option if provided', async () => { const ctx = { options: { outputDir: 'storybook-out' }, storybook: { version: '5.0.0' } } as any; - await setSourceDir(ctx); + await setSourceDirectory(ctx); expect(ctx.sourceDir).toBe('storybook-out'); }); it('uses the outputDir option if provided, even for older Storybooks', async () => { const ctx = { options: { outputDir: 'storybook-out' }, storybook: { version: '4.0.0' } } as any; - await setSourceDir(ctx); + await setSourceDirectory(ctx); expect(ctx.sourceDir).toBe('storybook-out'); }); }); diff --git a/node-src/tasks/build.ts b/node-src/tasks/build.ts index 5e4e72f45..36b115e84 100644 --- a/node-src/tasks/build.ts +++ b/node-src/tasks/build.ts @@ -15,15 +15,15 @@ import e2eBuildFailed from '../ui/messages/errors/e2eBuildFailed'; import missingDependency from '../ui/messages/errors/missingDependency'; import { failed, initial, pending, skipped, success } from '../ui/tasks/build'; -export const setSourceDir = async (ctx: Context) => { +export const setSourceDirectory = async (ctx: Context) => { if (ctx.options.outputDir) { ctx.sourceDir = ctx.options.outputDir; } else if (ctx.storybook && ctx.storybook.version && semver.lt(ctx.storybook.version, '5.0.0')) { // Storybook v4 doesn't support absolute paths like tmp.dir would yield ctx.sourceDir = 'storybook-static'; } else { - const tmpDir = await tmp.dir({ unsafeCleanup: true, prefix: `chromatic-` }); - ctx.sourceDir = tmpDir.path; + const temporaryDirectory = await tmp.dir({ unsafeCleanup: true, prefix: `chromatic-` }); + ctx.sourceDir = temporaryDirectory.path; } }; @@ -75,7 +75,7 @@ function isE2EBuildCommandNotFoundError(errorMessage: string) { function e2eBuildErrorMessage( err, - workingDir: string, + workingDirectory: string, ctx: Context ): { exitCode: number; message: string } { const flag = ctx.options.playwright ? 'playwright' : 'cypress'; @@ -88,7 +88,7 @@ function e2eBuildErrorMessage( const dependencyName = `@chromatic-com/${flag}`; return { exitCode: exitCodes.MISSING_DEPENDENCY, - message: missingDependency({ dependencyName, flag, workingDir }), + message: missingDependency({ dependencyName, flag, workingDir: workingDirectory }), }; } @@ -157,7 +157,7 @@ export default createTask({ return false; }, steps: [ - setSourceDir, + setSourceDirectory, setBuildCommand, transitionTo(pending), startActivity, diff --git a/node-src/tasks/initialize.test.ts b/node-src/tasks/initialize.test.ts index 2b6fdeeff..4227d0c78 100644 --- a/node-src/tasks/initialize.test.ts +++ b/node-src/tasks/initialize.test.ts @@ -14,12 +14,12 @@ const getCliCommand = vi.mocked(getCliCommandDefault); process.env.GERRIT_BRANCH = 'foo/bar'; process.env.TRAVIS_EVENT_TYPE = 'pull_request'; -const env = { ENVIRONMENT_WHITELIST: [/^GERRIT/, /^TRAVIS/] }; +const environment = { ENVIRONMENT_WHITELIST: [/^GERRIT/, /^TRAVIS/] }; const log = { info: vi.fn(), warn: vi.fn(), debug: vi.fn() }; describe('setEnvironment', () => { it('sets the environment info on context', async () => { - const ctx = { env, log } as any; + const ctx = { env: environment, log } as any; await setEnvironment(ctx); expect(ctx.environment).toMatchObject({ GERRIT_BRANCH: 'foo/bar', @@ -94,7 +94,7 @@ describe('setRuntimeMetadata', () => { describe('announceBuild', () => { const defaultContext = { - env, + env: environment, log, options: {}, environment: ':environment', diff --git a/node-src/tasks/snapshot.test.ts b/node-src/tasks/snapshot.test.ts index 15b25d663..48e5aeac4 100644 --- a/node-src/tasks/snapshot.test.ts +++ b/node-src/tasks/snapshot.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it, vi } from 'vitest'; import { takeSnapshots } from './snapshot'; -const env = { CHROMATIC_POLL_INTERVAL: 0, CHROMATIC_OUTPUT_INTERVAL: 0 }; +const environment = { CHROMATIC_POLL_INTERVAL: 0, CHROMATIC_OUTPUT_INTERVAL: 0 }; const log = { error: vi.fn(), info: vi.fn() }; const matchesBranch = () => false; @@ -17,7 +17,7 @@ describe('takeSnapshots', () => { }; const ctx = { client, - env, + env: environment, git: { matchesBranch }, log, options: {}, @@ -45,7 +45,7 @@ describe('takeSnapshots', () => { const build = { app: { repository: { provider: 'github' } }, number: 1, features: {} }; const ctx = { client, - env, + env: environment, git: { matchesBranch }, log, options: {}, @@ -68,7 +68,7 @@ describe('takeSnapshots', () => { const build = { app: { repository: { provider: 'github' } }, number: 1, features: {} }; const ctx = { client, - env, + env: environment, git: { matchesBranch }, log, options: {}, @@ -91,7 +91,7 @@ describe('takeSnapshots', () => { const build = { app: { repository: { provider: 'github' } }, number: 1, features: {} }; const ctx = { client, - env, + env: environment, git: { matchesBranch }, log, options: {}, @@ -121,7 +121,7 @@ describe('takeSnapshots', () => { }; const ctx = { client, - env, + env: environment, git: { matchesBranch }, log, options: { experimental_onTaskProgress: vi.fn() }, diff --git a/node-src/tasks/upload.test.ts b/node-src/tasks/upload.test.ts index e336a113f..8758ebaba 100644 --- a/node-src/tasks/upload.test.ts +++ b/node-src/tasks/upload.test.ts @@ -5,7 +5,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { default as compress } from '../lib/compress'; import { findChangedDependencies as findChangedDep } from '../lib/findChangedDependencies'; -import { findChangedPackageFiles as findChangedPkg } from '../lib/findChangedPackageFiles'; +import { findChangedPackageFiles as findChangedPackage } from '../lib/findChangedPackageFiles'; import { getDependentStoryFiles as getDepStoryFiles } from '../lib/getDependentStoryFiles'; import { exitCodes } from '../lib/setExitCode'; import { @@ -51,7 +51,7 @@ vi.mock('../lib/getFileHashes', () => ({ const makeZipFile = vi.mocked(compress); const findChangedDependencies = vi.mocked(findChangedDep); -const findChangedPackageFiles = vi.mocked(findChangedPkg); +const findChangedPackageFiles = vi.mocked(findChangedPackage); const getDependentStoryFiles = vi.mocked(getDepStoryFiles); const accessMock = vi.mocked(access); const createReadStreamMock = vi.mocked(createReadStream); @@ -59,7 +59,7 @@ const readdirSyncMock = vi.mocked(readdirSync); const readFileSyncMock = vi.mocked(readFileSync); const statSyncMock = vi.mocked(statSync); -const env = { CHROMATIC_RETRIES: 2, CHROMATIC_OUTPUT_INTERVAL: 0 }; +const environment = { CHROMATIC_RETRIES: 2, CHROMATIC_OUTPUT_INTERVAL: 0 }; const log = { info: vi.fn(), warn: vi.fn(), debug: vi.fn(), error: vi.fn() }; const http = { fetch: vi.fn() }; @@ -72,7 +72,7 @@ describe('validateFiles', () => { readdirSyncMock.mockReturnValue(['iframe.html', 'index.html'] as any); statSyncMock.mockReturnValue({ isDirectory: () => false, size: 42 } as any); - const ctx = { env, log, http, sourceDir: '/static/' } as any; + const ctx = { env: environment, log, http, sourceDir: '/static/' } as any; await validateFiles(ctx); expect(ctx.fileInfo).toEqual( @@ -91,7 +91,7 @@ describe('validateFiles', () => { readdirSyncMock.mockReturnValue(['iframe.html'] as any); statSyncMock.mockReturnValue({ isDirectory: () => false, size: 42 } as any); - const ctx = { env, log, http, sourceDir: '/static/' } as any; + const ctx = { env: environment, log, http, sourceDir: '/static/' } as any; await expect(validateFiles(ctx)).rejects.toThrow('Invalid Storybook build at /static/'); }); @@ -99,7 +99,7 @@ describe('validateFiles', () => { readdirSyncMock.mockReturnValue(['index.html'] as any); statSyncMock.mockReturnValue({ isDirectory: () => false, size: 42 } as any); - const ctx = { env, log, http, sourceDir: '/static/' } as any; + const ctx = { env: environment, log, http, sourceDir: '/static/' } as any; await expect(validateFiles(ctx)).rejects.toThrow('Invalid Storybook build at /static/'); }); @@ -117,7 +117,7 @@ describe('validateFiles', () => { return { isDirectory: () => false, size: 42 } as any; }); - const ctx = { env, log, http, sourceDir: '.' } as any; + const ctx = { env: environment, log, http, sourceDir: '.' } as any; await validateFiles(ctx); expect(ctx.fileInfo).toEqual( @@ -140,7 +140,7 @@ describe('validateFiles', () => { readFileSyncMock.mockReturnValue('info => Output directory: /var/storybook-static'); const ctx = { - env, + env: environment, log, http, sourceDir: '/static/', @@ -181,7 +181,7 @@ describe('traceChangedFiles', () => { getDependentStoryFiles.mockResolvedValue(deps); const ctx = { - env, + env: environment, log, http, options: {}, @@ -210,7 +210,7 @@ describe('traceChangedFiles', () => { getDependentStoryFiles.mockResolvedValue(deps); const ctx = { - env, + env: environment, log, http, options: {}, @@ -235,7 +235,7 @@ describe('traceChangedFiles', () => { getDependentStoryFiles.mockResolvedValue(deps); const ctx = { - env, + env: environment, log, http, options: {}, @@ -257,7 +257,7 @@ describe('traceChangedFiles', () => { const packageMetadataChanges = [{ changedFiles: ['./package.json'], commit: 'abcdef' }]; const ctx = { - env, + env: environment, log, http, options: {}, @@ -283,7 +283,7 @@ describe('traceChangedFiles', () => { ); const ctx = { - env, + env: environment, log, http, options: { storybookBaseDir: '/wrong' }, @@ -304,7 +304,7 @@ describe('traceChangedFiles', () => { const packageMetadataChanges = [{ changedFiles: ['./package.json'], commit: 'abcdef' }]; const ctx = { - env, + env: environment, log, http, options: {}, @@ -332,7 +332,7 @@ describe('calculateFileHashes', () => { total: 84, }; const ctx = { - env, + env: environment, log, http, sourceDir: '/static/', @@ -389,7 +389,7 @@ describe('uploadStorybook', () => { }; const ctx = { client, - env, + env: environment, log, http, sourceDir: '/static/', @@ -458,7 +458,7 @@ describe('uploadStorybook', () => { }; const ctx = { client, - env, + env: environment, log, http, sourceDir: '/static/', @@ -497,10 +497,10 @@ describe('uploadStorybook', () => { uploadBuild: { info: { sentinelUrls: [], - targets: Array.from({ length: 1000 }, (_, i) => ({ + targets: Array.from({ length: 1000 }, (_, index) => ({ contentType: 'application/javascript', - filePath: `${i}.js`, - formAction: `https://s3.amazonaws.com/presigned?${i}.js`, + filePath: `${index}.js`, + formAction: `https://s3.amazonaws.com/presigned?${index}.js`, formFields: {}, })), }, @@ -528,13 +528,16 @@ describe('uploadStorybook', () => { http.fetch.mockReturnValue({ ok: true }); const fileInfo = { - lengths: Array.from({ length: 1001 }, (_, i) => ({ knownAs: `${i}.js`, contentLength: i })), - paths: Array.from({ length: 1001 }, (_, i) => `${i}.js`), - total: Array.from({ length: 1001 }, (_, i) => i).reduce((a, v) => a + v), + lengths: Array.from({ length: 1001 }, (_, index) => ({ + knownAs: `${index}.js`, + contentLength: index, + })), + paths: Array.from({ length: 1001 }, (_, index) => `${index}.js`), + total: Array.from({ length: 1001 }, (_, index) => index).reduce((a, v) => a + v), }; const ctx = { client, - env, + env: environment, log, http, sourceDir: '/static/', @@ -547,10 +550,10 @@ describe('uploadStorybook', () => { expect(client.runQuery).toHaveBeenCalledTimes(2); expect(client.runQuery).toHaveBeenCalledWith(expect.stringMatching(/UploadBuildMutation/), { buildId: '1', - files: Array.from({ length: 1000 }, (_, i) => ({ + files: Array.from({ length: 1000 }, (_, index) => ({ contentHash: undefined, - contentLength: i, - filePath: `${i}.js`, + contentLength: index, + filePath: `${index}.js`, })), }); expect(client.runQuery).toHaveBeenCalledWith(expect.stringMatching(/UploadBuildMutation/), { @@ -616,7 +619,7 @@ describe('uploadStorybook', () => { }; const ctx = { client, - env, + env: environment, log, http, sourceDir: '/static/', @@ -695,7 +698,7 @@ describe('uploadStorybook', () => { }; const ctx = { client, - env, + env: environment, log, http, sourceDir: '/static/', @@ -738,10 +741,10 @@ describe('uploadStorybook', () => { uploadBuild: { info: { sentinelUrls: [], - targets: Array.from({ length: 1000 }, (_, i) => ({ + targets: Array.from({ length: 1000 }, (_, target) => ({ contentType: 'application/javascript', - filePath: `${i}.js`, - formAction: `https://s3.amazonaws.com/presigned?${i}.js`, + filePath: `${target}.js`, + formAction: `https://s3.amazonaws.com/presigned?${target}.js`, formFields: {}, })), zipTarget: { @@ -777,13 +780,16 @@ describe('uploadStorybook', () => { http.fetch.mockReturnValue({ ok: true, text: () => Promise.resolve('OK') }); const fileInfo = { - lengths: Array.from({ length: 1001 }, (_, i) => ({ knownAs: `${i}.js`, contentLength: i })), - paths: Array.from({ length: 1001 }, (_, i) => `${i}.js`), - total: Array.from({ length: 1001 }, (_, i) => i).reduce((a, v) => a + v), + lengths: Array.from({ length: 1001 }, (_, index) => ({ + knownAs: `${index}.js`, + contentLength: index, + })), + paths: Array.from({ length: 1001 }, (_, index) => `${index}.js`), + total: Array.from({ length: 1001 }, (_, index) => index).reduce((a, v) => a + v), }; const ctx = { client, - env, + env: environment, log, http, sourceDir: '/static/', @@ -825,7 +831,7 @@ describe('waitForSentinels', () => { ]; const ctx = { client, - env, + env: environment, log, http, options: {}, diff --git a/node-src/tasks/upload.ts b/node-src/tasks/upload.ts index 92024b609..b5d33faf0 100644 --- a/node-src/tasks/upload.ts +++ b/node-src/tasks/upload.ts @@ -3,7 +3,7 @@ import path from 'path'; import semver from 'semver'; import slash from 'slash'; -import { checkStorybookBaseDir } from '../lib/checkStorybookBaseDir'; +import { checkStorybookBaseDirectory } from '../lib/checkStorybookBaseDirectory'; import { findChangedDependencies } from '../lib/findChangedDependencies'; import { findChangedPackageFiles } from '../lib/findChangedPackageFiles'; import { getDependentStoryFiles } from '../lib/getDependentStoryFiles'; @@ -15,7 +15,7 @@ import { waitForSentinel } from '../lib/waitForSentinel'; import { Context, FileDesc, Task } from '../types'; import missingStatsFile from '../ui/messages/errors/missingStatsFile'; import bailFile from '../ui/messages/warnings/bailFile'; -import deviatingOutputDir from '../ui/messages/warnings/deviatingOutputDir'; +import deviatingOutputDirectory from '../ui/messages/warnings/deviatingOutputDirectory'; import { bailed, dryRun, @@ -44,43 +44,46 @@ const SPECIAL_CHARS_REGEXP = /([$()*+?[\]^])/g; // Get all paths in rootDir, starting at dirname. // We don't want the paths to include rootDir -- so if rootDir = storybook-static, // paths will be like iframe.html rather than storybook-static/iframe.html -function getPathsInDir(ctx: Context, rootDir: string, dirname = '.'): PathSpec[] { +function getPathsInDirectory(ctx: Context, rootDirectory: string, dirname = '.'): PathSpec[] { // .chromatic is a special directory reserved for internal use and should not be uploaded if (dirname === '.chromatic') { return []; } try { - return readdirSync(path.join(rootDir, dirname)).flatMap((p: string) => { + return readdirSync(path.join(rootDirectory, dirname)).flatMap((p: string) => { const pathname = path.join(dirname, p); - const stats = statSync(path.join(rootDir, pathname)); + const stats = statSync(path.join(rootDirectory, pathname)); return stats.isDirectory() - ? getPathsInDir(ctx, rootDir, pathname) + ? getPathsInDirectory(ctx, rootDirectory, pathname) : [{ pathname, contentLength: stats.size }]; }); } catch (err) { ctx.log.debug(err); - throw new Error(invalid({ sourceDir: rootDir } as any, err).output); + throw new Error(invalid({ sourceDir: rootDirectory } as any, err).output); } } -function getOutputDir(buildLog: string) { +function getOutputDirectory(buildLog: string) { const outputString = 'Output directory: '; const outputIndex = buildLog.lastIndexOf(outputString); if (outputIndex === -1) return undefined; const remainingLog = buildLog.slice(outputIndex + outputString.length); const newlineIndex = remainingLog.indexOf('\n'); - const outputDir = newlineIndex === -1 ? remainingLog : remainingLog.slice(0, newlineIndex); - return outputDir.trim(); + const outputDirectory = newlineIndex === -1 ? remainingLog : remainingLog.slice(0, newlineIndex); + return outputDirectory.trim(); } -function getFileInfo(ctx: Context, sourceDir: string) { - const lengths = getPathsInDir(ctx, sourceDir).map((o) => ({ ...o, knownAs: slash(o.pathname) })); +function getFileInfo(ctx: Context, sourceDirectory: string) { + const lengths = getPathsInDirectory(ctx, sourceDirectory).map((o) => ({ + ...o, + knownAs: slash(o.pathname), + })); const total = lengths.map(({ contentLength }) => contentLength).reduce((a, b) => a + b, 0); const paths: string[] = []; let statsPath: string; for (const { knownAs } of lengths) { - if (knownAs.endsWith('preview-stats.json')) statsPath = path.join(sourceDir, knownAs); + if (knownAs.endsWith('preview-stats.json')) statsPath = path.join(sourceDirectory, knownAs); else if (!knownAs.endsWith('manager-stats.json')) paths.push(knownAs); } return { lengths, paths, statsPath, total }; @@ -95,10 +98,10 @@ export const validateFiles = async (ctx: Context) => { if (!isValidStorybook(ctx.fileInfo) && ctx.buildLogFile) { try { const buildLog = readFileSync(ctx.buildLogFile, 'utf8'); - const outputDir = getOutputDir(buildLog); - if (outputDir && outputDir !== ctx.sourceDir) { - ctx.log.warn(deviatingOutputDir(ctx, outputDir)); - ctx.sourceDir = outputDir; + const outputDirectory = getOutputDirectory(buildLog); + if (outputDirectory && outputDirectory !== ctx.sourceDir) { + ctx.log.warn(deviatingOutputDirectory(ctx, outputDirectory)); + ctx.sourceDir = outputDirectory; ctx.fileInfo = getFileInfo(ctx, ctx.sourceDir); } } catch (err) { @@ -161,7 +164,7 @@ export const traceChangedFiles = async (ctx: Context, task: Task) => { const stats = await readStatsFile(statsPath); - await checkStorybookBaseDir(ctx, stats); + await checkStorybookBaseDirectory(ctx, stats); const onlyStoryFiles = await getDependentStoryFiles( ctx, diff --git a/node-src/tasks/verify.test.ts b/node-src/tasks/verify.test.ts index 9cbe66cee..120967c96 100644 --- a/node-src/tasks/verify.test.ts +++ b/node-src/tasks/verify.test.ts @@ -3,7 +3,7 @@ import { describe, expect, it, vi } from 'vitest'; import { exitCodes } from '../lib/setExitCode'; import { publishBuild, verifyBuild } from './verify'; -const env = { +const environment = { CHROMATIC_POLL_INTERVAL: 10, CHROMATIC_UPGRADE_TIMEOUT: 100, STORYBOOK_VERIFY_TIMEOUT: 20, @@ -19,7 +19,7 @@ describe('publishBuild', () => { client.runQuery.mockReturnValue({ publishBuild: publishedBuild }); const ctx = { - env, + env: environment, log, http, client, @@ -43,7 +43,7 @@ describe('publishBuild', () => { describe('verifyBuild', () => { const defaultContext = { - env, + env: environment, log, options: {}, environment: ':environment', diff --git a/node-src/types.ts b/node-src/types.ts index dc6af7740..16099eb28 100644 --- a/node-src/types.ts +++ b/node-src/types.ts @@ -2,7 +2,7 @@ import { InitialContext } from '.'; import GraphQLClient from './io/GraphQLClient'; import HTTPClient from './io/HTTPClient'; import type { Configuration } from './lib/getConfiguration'; -import { Env } from './lib/getEnv'; +import { Environment } from './lib/getEnvironment'; import { Logger } from './lib/log'; export interface Flags { @@ -140,7 +140,7 @@ export interface Options extends Configuration { sessionId?: string; /** Environment variables */ - env?: Env; + env?: Environment; skipUpdateCheck: Flags['skipUpdateCheck']; } @@ -159,7 +159,7 @@ export type TaskName = | 'restoreWorkspace'; export interface Context { - env: Env; + env: Environment; log: Logger; pkg: { name: string; diff --git a/node-src/ui/components/task.stories.ts b/node-src/ui/components/task.stories.ts index b59bca408..b89530508 100644 --- a/node-src/ui/components/task.stories.ts +++ b/node-src/ui/components/task.stories.ts @@ -4,19 +4,22 @@ export default { title: 'CLI/Components/Task', }; -const arr = ['Line one', 'Line two']; -const str = ` +const outputArray = ['Line one', 'Line two']; +const outputString = ` Line one Line two `; export const Initial = () => - task({ status: 'initial', title: 'Waiting for task to start', output: arr }); -export const Pending = () => task({ status: 'pending', title: 'Task in progress', output: arr }); -export const Skipped = () => task({ status: 'skipped', title: 'Task skipped', output: arr }); + task({ status: 'initial', title: 'Waiting for task to start', output: outputArray }); +export const Pending = () => + task({ status: 'pending', title: 'Task in progress', output: outputArray }); +export const Skipped = () => + task({ status: 'skipped', title: 'Task skipped', output: outputArray }); export const Success = () => - task({ status: 'success', title: 'Successfully completed task', output: str }); + task({ status: 'success', title: 'Successfully completed task', output: outputString }); export const Warning = () => - task({ status: 'warning', title: 'Be aware this is a warning', output: str }); -export const Info = () => task({ status: 'info', title: "Here's some info", output: str }); -export const Error = () => task({ status: 'error', title: 'Something went wrong', output: str }); + task({ status: 'warning', title: 'Be aware this is a warning', output: outputString }); +export const Info = () => task({ status: 'info', title: "Here's some info", output: outputString }); +export const Error = () => + task({ status: 'error', title: 'Something went wrong', output: outputString }); diff --git a/node-src/ui/messages/errors/invalidConfigurationFile.ts b/node-src/ui/messages/errors/invalidConfigurationFile.ts index a4ecd3c6b..d117c7926 100644 --- a/node-src/ui/messages/errors/invalidConfigurationFile.ts +++ b/node-src/ui/messages/errors/invalidConfigurationFile.ts @@ -11,11 +11,11 @@ export const invalidConfigurationFile = (configFile: string, err: ZodError) => { ${error} Configuration file {bold ${configFile}} was invalid, please check the allowed keys. ${ formErrors.length > 0 - ? `\n${formErrors.map((msg) => chalk`- {bold ${msg}}`).join('\n ')}\n\n` + ? `\n${formErrors.map((message) => chalk`- {bold ${message}}`).join('\n ')}\n\n` : '' } ${Object.entries(fieldErrors) - .map(([field, msg]) => chalk`- {bold ${field}}: ${msg}`) + .map(([field, message]) => chalk`- {bold ${field}}: ${message}`) .join('\n ')} `); }; diff --git a/node-src/ui/messages/errors/invalidStorybookBaseDir.stories.ts b/node-src/ui/messages/errors/invalidStorybookBaseDir.stories.ts deleted file mode 100644 index 2de572b68..000000000 --- a/node-src/ui/messages/errors/invalidStorybookBaseDir.stories.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { invalidStorybookBaseDir } from './invalidStorybookBaseDir'; - -export default { - title: 'CLI/Messages/Errors', -}; - -export const InvalidStorybookBaseDir = () => invalidStorybookBaseDir(); diff --git a/node-src/ui/messages/errors/invalidStorybookBaseDirectory.stories.ts b/node-src/ui/messages/errors/invalidStorybookBaseDirectory.stories.ts new file mode 100644 index 000000000..21d1e145c --- /dev/null +++ b/node-src/ui/messages/errors/invalidStorybookBaseDirectory.stories.ts @@ -0,0 +1,7 @@ +import { invalidStorybookBaseDirectory } from './invalidStorybookBaseDirectory'; + +export default { + title: 'CLI/Messages/Errors', +}; + +export const InvalidStorybookBaseDirectory = () => invalidStorybookBaseDirectory(); diff --git a/node-src/ui/messages/errors/invalidStorybookBaseDir.ts b/node-src/ui/messages/errors/invalidStorybookBaseDirectory.ts similarity index 90% rename from node-src/ui/messages/errors/invalidStorybookBaseDir.ts rename to node-src/ui/messages/errors/invalidStorybookBaseDirectory.ts index a08ff519a..4d3120e77 100644 --- a/node-src/ui/messages/errors/invalidStorybookBaseDir.ts +++ b/node-src/ui/messages/errors/invalidStorybookBaseDirectory.ts @@ -3,7 +3,7 @@ import { dedent } from 'ts-dedent'; import { error } from '../../components/icons'; -export const invalidStorybookBaseDir = () => +export const invalidStorybookBaseDirectory = () => dedent(chalk` ${error} TurboSnap disabled until base directory is set correctly The base directory allows TurboSnap to trace files. diff --git a/node-src/ui/messages/errors/noViewLayerPackage.ts b/node-src/ui/messages/errors/noViewLayerPackage.ts index 52e2ea8c4..905e38f76 100644 --- a/node-src/ui/messages/errors/noViewLayerPackage.ts +++ b/node-src/ui/messages/errors/noViewLayerPackage.ts @@ -3,9 +3,9 @@ import { dedent } from 'ts-dedent'; import { error } from '../../components/icons'; -export default (pkg: string) => +export default (packageName: string) => dedent(chalk` ${error} {bold Storybook package not installed} - Could not find {bold ${pkg}} in {bold node_modules}. + Could not find {bold ${packageName}} in {bold node_modules}. Most likely, you forgot to run {bold npm install} or {bold yarn} before running Chromatic. `); diff --git a/node-src/ui/messages/info/tracedAffectedFiles.ts b/node-src/ui/messages/info/tracedAffectedFiles.ts index 32001ee36..5dfdf4dbc 100644 --- a/node-src/ui/messages/info/tracedAffectedFiles.ts +++ b/node-src/ui/messages/info/tracedAffectedFiles.ts @@ -17,9 +17,9 @@ const printFilePath = (filepath: string, basedir: string, expanded: boolean) => .join('/'); }; -export const rootDirNote = `The root directory of your project:`; -export const baseDirNote = `The base directory (The relative path from the root to the storybook config root):`; -export const storybookDirNote = `The storybook directory (The directory can either be at the root or in a sub-directory):`; +export const rootDirectoryNote = `The root directory of your project:`; +export const baseDirectoryNote = `The base directory (The relative path from the root to the storybook config root):`; +export const storybookDirectoryNote = `The storybook directory (The directory can either be at the root or in a sub-directory):`; export const traceSuggestions = `If you are having trouble with tracing, please check the following:\n 1. Make sure you have the correct root path, base path, and storybook path.\n 2. Make sure you have the correct storybook config file.\n @@ -44,7 +44,7 @@ export default ( ) => { const flag = ctx.log === (console as any) ? '--mode (-m)' : '--trace-changed'; const basedir = ctx.options.storybookBaseDir || '.'; - const storybookConfigDir = ctx.options.storybookConfigDir || '.storybook'; + const storybookConfigDirectory = ctx.options.storybookConfigDir || '.storybook'; const expanded = ctx.options.traceChanged === 'expanded'; const printPath = (filepath: string) => printFilePath(filepath, basedir, expanded); @@ -55,9 +55,9 @@ export default ( if (expanded) { const bailReason = ctx.turboSnap?.bailReason ? `${ctx.turboSnap.bailReason}\n\n` : ''; - const rootPath = `${chalk.magenta(rootDirNote)} ${ctx.turboSnap.rootPath}\n\n`; - const basePath = `${chalk.magenta(baseDirNote)} ${basedir}\n\n`; - const storybookPath = `${chalk.magenta(storybookDirNote)} ${storybookConfigDir}\n\n`; + const rootPath = `${chalk.magenta(rootDirectoryNote)} ${ctx.turboSnap.rootPath}\n\n`; + const basePath = `${chalk.magenta(baseDirectoryNote)} ${basedir}\n\n`; + const storybookPath = `${chalk.magenta(storybookDirectoryNote)} ${storybookConfigDirectory}\n\n`; const untracedNotice = ctx.untracedFiles && ctx.untracedFiles.length > 0 ? `${chalk.magenta( diff --git a/node-src/ui/messages/warnings/deviatingOutputDir.stories.ts b/node-src/ui/messages/warnings/deviatingOutputDir.stories.ts deleted file mode 100644 index de7f574d3..000000000 --- a/node-src/ui/messages/warnings/deviatingOutputDir.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import deviatingOutputDir from './deviatingOutputDir'; - -export default { - title: 'CLI/Messages/Warnings', -}; - -const withCustomScript = { scripts: { 'build:storybook': './run-storybook-build' } }; -const withChainedScript = { scripts: { 'build:storybook': 'build-storybook && true' } }; -const withNpmRunScript = { scripts: { 'build:storybook': 'npm run build-storybook' } }; - -const ctx = { - sourceDir: '/var/folders/h3/ff9kk23958l99z2qbzfjdlxc0000gn/T/chromatic-20036LMP9FAlLEjpu', - options: { buildScriptName: 'build:storybook' }, -}; - -const outputDir = '/users/me/project/storybook-static'; - -export const DeviatingOutputDir = () => - deviatingOutputDir({ ...ctx, packageJson: withCustomScript } as any, outputDir); - -export const DeviatingOutputDirChained = () => - deviatingOutputDir({ ...ctx, packageJson: withChainedScript } as any, outputDir); - -export const DeviatingOutputDirNpmRun = () => - deviatingOutputDir({ ...ctx, packageJson: withNpmRunScript } as any, outputDir); diff --git a/node-src/ui/messages/warnings/deviatingOutputDirectory.stories.ts b/node-src/ui/messages/warnings/deviatingOutputDirectory.stories.ts new file mode 100644 index 000000000..9a457b211 --- /dev/null +++ b/node-src/ui/messages/warnings/deviatingOutputDirectory.stories.ts @@ -0,0 +1,25 @@ +import deviatingOutputDirectory from './deviatingOutputDirectory'; + +export default { + title: 'CLI/Messages/Warnings', +}; + +const withCustomScript = { scripts: { 'build:storybook': './run-storybook-build' } }; +const withChainedScript = { scripts: { 'build:storybook': 'build-storybook && true' } }; +const withNpmRunScript = { scripts: { 'build:storybook': 'npm run build-storybook' } }; + +const ctx = { + sourceDir: '/var/folders/h3/ff9kk23958l99z2qbzfjdlxc0000gn/T/chromatic-20036LMP9FAlLEjpu', + options: { buildScriptName: 'build:storybook' }, +}; + +const outputDirectory = '/users/me/project/storybook-static'; + +export const DeviatingOutputDirectory = () => + deviatingOutputDirectory({ ...ctx, packageJson: withCustomScript } as any, outputDirectory); + +export const DeviatingOutputDirectoryChained = () => + deviatingOutputDirectory({ ...ctx, packageJson: withChainedScript } as any, outputDirectory); + +export const DeviatingOutputDirectoryNpmRun = () => + deviatingOutputDirectory({ ...ctx, packageJson: withNpmRunScript } as any, outputDirectory); diff --git a/node-src/ui/messages/warnings/deviatingOutputDir.ts b/node-src/ui/messages/warnings/deviatingOutputDirectory.ts similarity index 94% rename from node-src/ui/messages/warnings/deviatingOutputDir.ts rename to node-src/ui/messages/warnings/deviatingOutputDirectory.ts index c15b56bbe..99405d2bb 100644 --- a/node-src/ui/messages/warnings/deviatingOutputDir.ts +++ b/node-src/ui/messages/warnings/deviatingOutputDirectory.ts @@ -26,7 +26,7 @@ const getHint = (buildScriptName: string, buildScript: string) => { export default ( { sourceDir, options, packageJson }: Pick, - outputDir: string + outputDirectory: string ) => { const { buildScriptName } = options; const buildScript = packageJson.scripts && packageJson.scripts[buildScriptName]; @@ -34,7 +34,7 @@ export default ( return dedent(chalk` ${warning} {bold Unexpected build directory} The CLI tried to build your Storybook at {bold ${sourceDir}} - but instead it was built at {bold ${outputDir}} + but instead it was built at {bold ${outputDirectory}} Make sure your {bold "${buildScriptName}"} script forwards the {bold --output-dir (-o)} flag to the {bold build-storybook} CLI. ${getHint(buildScriptName, buildScript)} diff --git a/node-src/ui/messages/warnings/noCommitDetails.ts b/node-src/ui/messages/warnings/noCommitDetails.ts index 7d3463a26..bd5208e33 100644 --- a/node-src/ui/messages/warnings/noCommitDetails.ts +++ b/node-src/ui/messages/warnings/noCommitDetails.ts @@ -4,18 +4,18 @@ import { dedent } from 'ts-dedent'; import { info, warning } from '../../components/icons'; import link from '../../components/link'; -interface BranchRef { +interface BranchReference { ref: string; sha: string; env: string; } -interface CommitRef { +interface CommitReference { ref?: never; sha: string; env?: string; } -export default ({ ref, sha, env }: BranchRef | CommitRef) => { +export default ({ ref, sha, env }: BranchReference | CommitReference) => { if (ref) { return dedent(chalk` ${warning} {bold Branch '${ref}' does not exist} diff --git a/node-src/ui/tasks/auth.stories.ts b/node-src/ui/tasks/auth.stories.ts index 5c0aba42d..a7224ab50 100644 --- a/node-src/ui/tasks/auth.stories.ts +++ b/node-src/ui/tasks/auth.stories.ts @@ -3,13 +3,13 @@ import { authenticated, authenticating, initial, invalidToken } from './auth'; export default { title: 'CLI/Tasks/Auth', - decorators: [(storyFn: any) => task(storyFn())], + decorators: [(storyFunction: any) => task(storyFunction())], }; -const env = { CHROMATIC_INDEX_URL: 'https://index.chromatic.com' }; +const environment = { CHROMATIC_INDEX_URL: 'https://index.chromatic.com' }; const options = { projectToken: '3cm6b49xnld' }; export const Initial = () => initial; -export const Authenticating = () => authenticating({ env } as any); -export const Authenticated = () => authenticated({ env, options } as any); -export const InvalidToken = () => invalidToken({ env, options } as any); +export const Authenticating = () => authenticating({ env: environment } as any); +export const Authenticated = () => authenticated({ env: environment, options } as any); +export const InvalidToken = () => invalidToken({ env: environment, options } as any); diff --git a/node-src/ui/tasks/auth.ts b/node-src/ui/tasks/auth.ts index 721cf585a..1f3c32008 100644 --- a/node-src/ui/tasks/auth.ts +++ b/node-src/ui/tasks/auth.ts @@ -2,7 +2,7 @@ import { Context } from '../../types'; const mask = (secret: string) => '*'.repeat(secret.length - 4) + secret.slice(-4); -const env = (indexUrl: string) => { +const environment = (indexUrl: string) => { if (indexUrl.includes('dev')) return ' [dev]'; if (indexUrl.includes('staging')) return ' [staging]'; return ''; @@ -15,13 +15,13 @@ export const initial = { export const authenticating = (ctx: Context) => ({ status: 'pending', - title: `Authenticating with Chromatic${env(ctx.env.CHROMATIC_INDEX_URL)}`, + title: `Authenticating with Chromatic${environment(ctx.env.CHROMATIC_INDEX_URL)}`, output: `Connecting to ${ctx.env.CHROMATIC_INDEX_URL}`, }); export const authenticated = (ctx: Context) => ({ status: 'success', - title: `Authenticated with Chromatic${env(ctx.env.CHROMATIC_INDEX_URL)}`, + title: `Authenticated with Chromatic${environment(ctx.env.CHROMATIC_INDEX_URL)}`, output: ctx.options.projectToken ? `Using project token '${mask(ctx.options.projectToken)}'` : `Using project ID '${ctx.options.projectId}' and user token`, @@ -29,6 +29,6 @@ export const authenticated = (ctx: Context) => ({ export const invalidToken = (ctx: Context) => ({ status: 'error', - title: `Failed to authenticate with Chromatic${env(ctx.env.CHROMATIC_INDEX_URL)}`, + title: `Failed to authenticate with Chromatic${environment(ctx.env.CHROMATIC_INDEX_URL)}`, output: `Invalid project token '${ctx.options.projectToken}'`, }); diff --git a/node-src/ui/tasks/build.stories.ts b/node-src/ui/tasks/build.stories.ts index 3d6e7d5d6..e3cff9206 100644 --- a/node-src/ui/tasks/build.stories.ts +++ b/node-src/ui/tasks/build.stories.ts @@ -3,7 +3,7 @@ import { failed, initial, pending, skipped, success } from './build'; export default { title: 'CLI/Tasks/Build', - decorators: [(storyFn) => task(storyFn())], + decorators: [(storyFunction) => task(storyFunction())], }; const buildCommand = 'yarn run build-storybook -o storybook-static'; diff --git a/node-src/ui/tasks/gitInfo.stories.ts b/node-src/ui/tasks/gitInfo.stories.ts index 31332884e..318933d39 100644 --- a/node-src/ui/tasks/gitInfo.stories.ts +++ b/node-src/ui/tasks/gitInfo.stories.ts @@ -11,7 +11,7 @@ import { export default { title: 'CLI/Tasks/GitInfo', - decorators: [(storyFn) => task(storyFn())], + decorators: [(storyFunction) => task(storyFunction())], }; const git = { commit: 'a32af7e265aa08e4a16d', branch: 'feat/new-ui', parentCommits: ['a', 'b'] }; diff --git a/node-src/ui/tasks/initialize.stories.ts b/node-src/ui/tasks/initialize.stories.ts index 123873ba3..7265552ec 100644 --- a/node-src/ui/tasks/initialize.stories.ts +++ b/node-src/ui/tasks/initialize.stories.ts @@ -3,7 +3,7 @@ import { initial, pending, success } from './initialize'; export default { title: 'CLI/Tasks/Initialize', - decorators: [(storyFn: any) => task(storyFn())], + decorators: [(storyFunction: any) => task(storyFunction())], }; const announcedBuild = { diff --git a/node-src/ui/tasks/prepareWorkspace.stories.ts b/node-src/ui/tasks/prepareWorkspace.stories.ts index 5b56d8044..fcb1636d2 100644 --- a/node-src/ui/tasks/prepareWorkspace.stories.ts +++ b/node-src/ui/tasks/prepareWorkspace.stories.ts @@ -10,7 +10,7 @@ import { export default { title: 'CLI/Tasks/PrepareWorkspace', - decorators: [(storyFn: any) => task(storyFn())], + decorators: [(storyFunction: any) => task(storyFunction())], }; const options = { diff --git a/node-src/ui/tasks/report.stories.ts b/node-src/ui/tasks/report.stories.ts index dba29e99b..28de5148c 100644 --- a/node-src/ui/tasks/report.stories.ts +++ b/node-src/ui/tasks/report.stories.ts @@ -3,7 +3,7 @@ import { initial, pending, success } from './report'; export default { title: 'CLI/Tasks/Report', - decorators: [(storyFn: any) => task(storyFn())], + decorators: [(storyFunction: any) => task(storyFunction())], }; export const Initial = () => initial; diff --git a/node-src/ui/tasks/restoreWorkspace.stories.ts b/node-src/ui/tasks/restoreWorkspace.stories.ts index 50f1e2e4a..bd708c77c 100644 --- a/node-src/ui/tasks/restoreWorkspace.stories.ts +++ b/node-src/ui/tasks/restoreWorkspace.stories.ts @@ -3,7 +3,7 @@ import { initial, pending, success } from './restoreWorkspace'; export default { title: 'CLI/Tasks/RestoreWorkspace', - decorators: [(storyFn: any) => task(storyFn())], + decorators: [(storyFunction: any) => task(storyFunction())], }; export const Initial = () => initial; diff --git a/node-src/ui/tasks/snapshot.stories.ts b/node-src/ui/tasks/snapshot.stories.ts index a82807541..0ef65bea9 100644 --- a/node-src/ui/tasks/snapshot.stories.ts +++ b/node-src/ui/tasks/snapshot.stories.ts @@ -14,7 +14,7 @@ import { export default { title: 'CLI/Tasks/Snapshot', - decorators: [(storyFn) => task(storyFn())], + decorators: [(storyFunction) => task(storyFunction())], }; const build = { diff --git a/node-src/ui/tasks/storybookInfo.stories.ts b/node-src/ui/tasks/storybookInfo.stories.ts index 6aa8a4f15..b2a8a97a2 100644 --- a/node-src/ui/tasks/storybookInfo.stories.ts +++ b/node-src/ui/tasks/storybookInfo.stories.ts @@ -3,7 +3,7 @@ import { initial, pending, success } from './storybookInfo'; export default { title: 'CLI/Tasks/StorybookInfo', - decorators: [(storyFn: any) => task(storyFn())], + decorators: [(storyFunction: any) => task(storyFunction())], }; const storybook = { diff --git a/node-src/ui/tasks/upload.stories.ts b/node-src/ui/tasks/upload.stories.ts index 4433e4c40..7f435f66e 100644 --- a/node-src/ui/tasks/upload.stories.ts +++ b/node-src/ui/tasks/upload.stories.ts @@ -17,7 +17,7 @@ import { export default { title: 'CLI/Tasks/Upload', - decorators: [(storyFn: any) => task(storyFn())], + decorators: [(storyFunction: any) => task(storyFunction())], }; export const Initial = () => initial; diff --git a/node-src/ui/tasks/verify.stories.ts b/node-src/ui/tasks/verify.stories.ts index b7bfd4ea2..114b42a51 100644 --- a/node-src/ui/tasks/verify.stories.ts +++ b/node-src/ui/tasks/verify.stories.ts @@ -14,7 +14,7 @@ import { export default { title: 'CLI/Tasks/Verify', - decorators: [(storyFn: any) => task(storyFn())], + decorators: [(storyFunction: any) => task(storyFunction())], }; const build = { diff --git a/node-src/ui/workflows/uploadBuild.stories.ts b/node-src/ui/workflows/uploadBuild.stories.ts index 7de4a691a..f8e778973 100644 --- a/node-src/ui/workflows/uploadBuild.stories.ts +++ b/node-src/ui/workflows/uploadBuild.stories.ts @@ -12,11 +12,11 @@ import * as storybookInfo from '../tasks/storybookInfo.stories'; import * as upload from '../tasks/upload.stories'; import * as verify from '../tasks/verify.stories'; -const steps = (...arr) => arr.map((step) => task(step())).join('\n'); +const steps = (...steps) => steps.map((step) => task(step())).join('\n'); export default { title: 'CLI/Workflows/UploadBuild', - decorators: [(storyFn) => storyFn().join('\n\n')], + decorators: [(storyFunction) => storyFunction().join('\n\n')], }; export const Initial = () => [