Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI: Typescript strict mode #22254

Merged
merged 43 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
1c2a717
Fix getVersionSpecifier
0916dhkim Apr 22, 2023
84a6952
Fix.check returns null
0916dhkim Apr 22, 2023
3f28ddd
Fix getStorybookData params
0916dhkim Apr 22, 2023
fe60f6c
Cast error to string
0916dhkim Apr 22, 2023
4eadf30
Fix automigrate webpack 5 type errors
0916dhkim Apr 22, 2023
008880f
Fix AutodocsTrueFrameworkRunOptions
0916dhkim Apr 22, 2023
edb293d
Fix dryRun in bare-mdx-stories-glob
0916dhkim Apr 22, 2023
7bdd65a
Fix dryRun in builder-vite
0916dhkim Apr 22, 2023
ffd71bd
Fix eslintPlugin.check
0916dhkim Apr 22, 2023
cb3a600
Fix mdx1to2.check return type
0916dhkim Apr 22, 2023
533d35c
Fix mdxgfm dryRun
0916dhkim Apr 22, 2023
c083c0d
Add optional chaning in missing-babelrc
0916dhkim Apr 22, 2023
15fcbb7
Handle unhandled semver failures
0916dhkim Apr 22, 2023
08428fe
Fix type errors in sb-scripts
0916dhkim Apr 22, 2023
55986a8
Remove strict: false in tsconfig.json
kasperpeulen Apr 26, 2023
5c8c2a6
Remove strictNullChecks
kasperpeulen Apr 26, 2023
6845a06
Install tiny-invariant
0916dhkim May 14, 2023
f27df86
Group programming
0916dhkim May 14, 2023
f516d10
More fixes
0916dhkim May 15, 2023
14c32d5
Fix SearchTuple
0916dhkim May 15, 2023
74da582
Fix dev.ts
0916dhkim May 15, 2023
2b454f2
Fix dirs.ts
0916dhkim May 15, 2023
75a868f
Fix generate.ts
0916dhkim May 15, 2023
70a5a6b
Fix ANGULAR
0916dhkim May 15, 2023
d2e39bd
Fix REACT_NATIVE
0916dhkim May 15, 2023
b554e0e
Fix baseGenerator.ts
0916dhkim May 15, 2023
75300e3
Fix initiate.ts
0916dhkim May 15, 2023
44131b2
Fix JsPackageManager.ts
0916dhkim May 15, 2023
abc7d48
Fix link.ts
0916dhkim May 15, 2023
ab83e54
Fix repro-generators
0916dhkim May 15, 2023
dfe520f
Fix sandbox.ts
0916dhkim May 15, 2023
7a8a80c
Fix upgrade.ts
0916dhkim May 15, 2023
3e8af28
Fix missing versions
0916dhkim May 15, 2023
fd769b4
Fix mdx-gfm type errors
0916dhkim May 20, 2023
b687df4
Extract coerceSemver helper
0916dhkim May 20, 2023
39009b5
Merge branch 'next' into pr/0916dhkim/22254
ndelangen Nov 28, 2023
8f0b100
fix
ndelangen Nov 28, 2023
96135bf
fixes
ndelangen Nov 28, 2023
6a8644b
regen lockfiles
ndelangen Nov 28, 2023
d531dde
fixes
ndelangen Nov 28, 2023
ba9f329
Merge branch 'next' into pr/0916dhkim/22254
ndelangen Nov 28, 2023
1edcc46
fix tests
ndelangen Nov 28, 2023
679cd26
fixes
ndelangen Nov 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/lib/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"simple-update-notifier": "^2.0.0",
"strip-json-comments": "^3.0.1",
"tempy": "^1.0.1",
"tiny-invariant": "^1.3.1",
"ts-dedent": "^2.0.0",
"util-deprecate": "^1.0.2"
},
Expand Down
6 changes: 3 additions & 3 deletions code/lib/cli/src/HandledError.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export class HandledError extends Error {
public handled = true;

constructor(messageOrError: string | Error) {
super(typeof messageOrError === 'string' ? messageOrError : messageOrError.message);
constructor(error: unknown) {
super(String(error));

if (typeof messageOrError !== 'string') this.cause = messageOrError;
if (typeof error !== 'string') this.cause = error;
}
}
11 changes: 10 additions & 1 deletion code/lib/cli/src/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ const postinstallAddon = async (addonName: string, options: PostinstallOptions)

const getVersionSpecifier = (addon: string) => {
const groups = /^(...*)@(.*)$/.exec(addon);
return groups ? [groups[1], groups[2]] : [addon, undefined];
if (groups) {
return [groups[0], groups[2]] as const;
}
return [addon, undefined] as const;
Comment on lines -40 to +43
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably would have just made more sense to add a tuple return-type to the getVersionSpecifier function definition.

};

const requireMain = (configDir: string) => {
Expand Down Expand Up @@ -79,6 +82,12 @@ export async function add(
const packageJson = await packageManager.retrievePackageJson();
const { mainConfig, configDir } = getStorybookInfo(packageJson);

if (typeof configDir === 'undefined') {
throw new Error(dedent`
Unable to find storybook config directory
`);
}

if (checkInstalled(addon, requireMain(configDir))) {
throw new Error(dedent`
Addon ${addon} is already installed; we skipped adding it to your ${mainConfig}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jest.mock('../../generators/ANGULAR/helpers', () => ({
}));

describe('is Nx project', () => {
// @ts-expect-error (Type 'null' is not comparable)
const packageManager = {
getPackageVersion: () => {
return null;
Expand Down
6 changes: 2 additions & 4 deletions code/lib/cli/src/automigrate/fixes/autodocs-true.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import chalk from 'chalk';
import { dedent } from 'ts-dedent';

import type { StorybookConfigRaw } from '@storybook/types';

import type { Fix } from '../types';
import { updateMainConfig } from '../helpers/mainConfigFile';

const logger = console;

interface AutodocsTrueFrameworkRunOptions {
value?: StorybookConfigRaw['docs']['autodocs'];
value?: boolean | 'tag';
}

/**
Expand Down Expand Up @@ -83,7 +81,7 @@ export const autodocsTrue: Fix<AutodocsTrueFrameworkRunOptions> = {
async run({ result: { value }, dryRun, mainConfigPath }) {
logger.info(`✅ Setting 'docs.autodocs' to true in main.js`);
if (!dryRun) {
await updateMainConfig({ mainConfigPath, dryRun }, async (main) => {
await updateMainConfig({ mainConfigPath, dryRun: !!dryRun }, async (main) => {
main.removeField(['docs', 'docsPage']);
main.setFieldValue(['docs', 'autodocs'], value ?? true);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export const bareMdxStoriesGlob: Fix<BareMdxStoriesGlobRunOptions> = {
${JSON.stringify(nextStoriesEntries, null, 2)}`);

if (!dryRun) {
await updateMainConfig({ mainConfigPath, dryRun }, async (main) => {
await updateMainConfig({ mainConfigPath, dryRun: !!dryRun }, async (main) => {
main.setFieldValue(['stories'], nextStoriesEntries);
});
}
Expand Down
2 changes: 1 addition & 1 deletion code/lib/cli/src/automigrate/fixes/builder-vite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const builderVite: Fix<BuilderViteOptions> = {

logger.info(`✅ Updating main.js to use vite builder`);
if (!dryRun) {
await updateMainConfig({ dryRun, mainConfigPath }, async (main) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mainConfigPath is declared as optional in RunOptions here

mainConfigPath?: string;

but updateMainConfig expects non-null string. What would be a good fix here?

await updateMainConfig({ dryRun: !!dryRun, mainConfigPath }, async (main) => {
const updatedBuilder =
typeof builder === 'string'
? '@storybook/builder-vite'
Expand Down
1 change: 1 addition & 0 deletions code/lib/cli/src/automigrate/fixes/cra5.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ describe('cra5 fix', () => {
});
});
describe('no cra dependency', () => {
// @ts-expect-error (Type 'null' is not comparable)
const packageManager = {
getPackageVersion: () => {
return null;
Expand Down
10 changes: 6 additions & 4 deletions code/lib/cli/src/automigrate/fixes/eslint-plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ describe('eslint-plugin fix', () => {
checkEslint({
packageJson,
})
).resolves.toMatchObject({
unsupportedExtension: undefined,
});
).rejects.toThrowErrorMatchingInlineSnapshot(
`"warn: Unable to find .eslintrc config file, skipping"`
);
});

it('when .eslintrc is using unsupported extension', async () => {
Expand All @@ -104,7 +104,9 @@ describe('eslint-plugin fix', () => {
packageJson,
eslintExtension: 'yml',
})
).resolves.toMatchObject({ unsupportedExtension: 'yml' });
).rejects.toThrowErrorMatchingInlineSnapshot(
`"warn: Unable to find .eslintrc config file, skipping"`
);
});
});
});
Expand Down
8 changes: 4 additions & 4 deletions code/lib/cli/src/automigrate/fixes/eslint-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ export const eslintPlugin: Fix<EslintPluginRunOptions> = {
return null;
}

let eslintFile;
let unsupportedExtension;
let eslintFile: string | null = null;
let unsupportedExtension: string | undefined;
try {
eslintFile = findEslintFile();
} catch (err) {
unsupportedExtension = err.message;
unsupportedExtension = String(err);
}

if (!eslintFile && !unsupportedExtension) {
if (!eslintFile || !unsupportedExtension) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure this is meant to be || here. Let me know if this is a mistake.

logger.warn('Unable to find .eslintrc config file, skipping');
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion code/lib/cli/src/automigrate/fixes/mdx-1-to-2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const mdx1to2: Fix<Mdx1to2Options> = {

async check() {
const storiesMdxFiles = await globby('./!(node_modules)**/*.(story|stories).mdx');
return storiesMdxFiles.length ? { storiesMdxFiles } : undefined;
return storiesMdxFiles.length ? { storiesMdxFiles } : null;
},

prompt({ storiesMdxFiles }) {
Expand Down
10 changes: 9 additions & 1 deletion code/lib/cli/src/automigrate/fixes/mdx-gfm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export const mdxgfm: Fix<Options> = {

let pattern;

if (typeof configDir === 'undefined') {
return false;
}

if (typeof item === 'string') {
pattern = slash(join(configDir, item));
} else if (typeof item === 'object') {
Expand All @@ -41,6 +45,10 @@ export const mdxgfm: Fix<Options> = {
pattern = slash(join(configDir, directory, files));
}

if (!pattern) {
return false;
}

const files = await glob(pattern, commonGlobOptions(pattern));

return files.some((f) => f.endsWith('.mdx'));
Expand Down Expand Up @@ -94,7 +102,7 @@ export const mdxgfm: Fix<Options> = {
[`@storybook/addon-mdx-gfm@${versionToInstall}`]
);

await updateMainConfig({ mainConfigPath, dryRun }, async (main) => {
await updateMainConfig({ mainConfigPath, dryRun: !!dryRun }, async (main) => {
logger.info(`✅ Adding "@storybook/addon-mdx-gfm" addon`);
if (!dryRun) {
main.appendValueToArray(['addons'], '@storybook/addon-mdx-gfm');
Expand Down
2 changes: 1 addition & 1 deletion code/lib/cli/src/automigrate/fixes/missing-babelrc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe('missing-babelrc fix', () => {
afterEach(jest.restoreAllMocks);

it('skips when storybook version < 7.0.0', async () => {
await expect(check({ storybookVersion: '6.3.2' })).resolves.toBeNull();
await expect(check({ storybookVersion: '6.3.2', main: {} })).resolves.toBeNull();
});

it('skips when babelrc config is present', async () => {
Expand Down
2 changes: 1 addition & 1 deletion code/lib/cli/src/automigrate/fixes/missing-babelrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const missingBabelRc: Fix<MissingBabelRcOptions> = {
filename: '__fake__.js', // somehow needed to detect .babelrc.* files
});

if (!config.config && !config.babelrc && !packageJson.babel) {
if (!config?.config && !config?.babelrc && !packageJson.babel) {
return { needsBabelRc: true };
}
}
Expand Down
1 change: 1 addition & 0 deletions code/lib/cli/src/automigrate/fixes/new-frameworks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const checkNewFrameworks = async ({
storybookVersion,
rendererPackage,
configDir: '',
mainConfigPath: ' ',
});
};

Expand Down
18 changes: 13 additions & 5 deletions code/lib/cli/src/automigrate/fixes/new-frameworks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import semver from 'semver';
import { frameworkPackages, rendererPackages } from '@storybook/core-common';

import type { Preset } from '@storybook/types';
import invariant from 'tiny-invariant';
import type { Fix } from '../types';
import { getStorybookVersionSpecifier } from '../../helpers';
import {
Expand All @@ -26,13 +27,13 @@ interface NewFrameworkRunOptions {
dependenciesToRemove: string[];
hasFrameworkInMainConfig: boolean;
frameworkPackage: string;
metaFramework: string;
metaFramework: string | undefined;
renderer: string;
addonsToRemove: string[];
frameworkOptions: Record<string, any>;
rendererOptions: Record<string, any>;
addonOptions: Record<string, any>;
builderConfig: string | Record<string, any>;
builderConfig: string | Record<string, any> | undefined;
builderInfo: {
name: string;
options: Record<string, any>;
Expand Down Expand Up @@ -69,13 +70,17 @@ export const newFrameworks: Fix<NewFrameworkRunOptions> = {
return null;
}

if (typeof configDir === 'undefined') {
return null;
}

const packageJson = await packageManager.retrievePackageJson();

const frameworkPackageName = getFrameworkPackageName(mainConfig);

const rendererPackageName =
rendererPackage ??
(await getRendererPackageNameFromFramework(frameworkPackageName)) ??
(await getRendererPackageNameFromFramework(frameworkPackageName as string)) ??
(await detectRenderer(packageJson));

let hasFrameworkInMainConfig = !!frameworkPackageName;
Expand Down Expand Up @@ -220,7 +225,9 @@ export const newFrameworks: Fix<NewFrameworkRunOptions> = {
`);
}

return {
invariant(mainConfigPath, 'Missing main config path.');

const result: Awaited<ReturnType<Fix<NewFrameworkRunOptions>['check']>> = {
mainConfigPath,
dependenciesToAdd,
dependenciesToRemove,
Expand All @@ -239,6 +246,7 @@ export const newFrameworks: Fix<NewFrameworkRunOptions> = {
builderConfig,
metaFramework,
};
return result;
},

prompt({
Expand Down Expand Up @@ -453,7 +461,7 @@ export const newFrameworks: Fix<NewFrameworkRunOptions> = {
}
}

await updateMainConfig({ mainConfigPath, dryRun }, async (main) => {
await updateMainConfig({ mainConfigPath, dryRun: !!dryRun }, async (main) => {
logger.info(`✅ Updating main.js`);

logger.info(`✅ Updating "framework" field`);
Expand Down
13 changes: 9 additions & 4 deletions code/lib/cli/src/automigrate/fixes/sb-scripts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import chalk from 'chalk';
import { dedent } from 'ts-dedent';
import semver from 'semver';
import type { PackageJson } from '@storybook/types';
import type { Fix } from '../types';
import type { PackageJsonWithDepsAndDevDeps } from '../../js-package-manager';

Expand All @@ -18,10 +19,14 @@ const logger = console;
* that do contain the actual sb binary, and not something like "npm run start-storybook"
* which could actually be a custom script even though the name matches the legacy binary name
*/
export const getStorybookScripts = (allScripts: Record<string, string>) => {
export const getStorybookScripts = (allScripts: NonNullable<PackageJson['scripts']>) => {
return Object.keys(allScripts).reduce((acc, key) => {
const currentScript = allScripts[key];
if (currentScript == null) {
return acc;
}
let isStorybookScript = false;
const allWordsFromScript = allScripts[key].split(' ');
const allWordsFromScript = currentScript.split(' ');
const newScript = allWordsFromScript
.map((currentWord, index) => {
const previousWord = allWordsFromScript[index - 1];
Expand Down Expand Up @@ -51,7 +56,7 @@ export const getStorybookScripts = (allScripts: Record<string, string>) => {

if (isStorybookScript) {
acc[key] = {
before: allScripts[key],
before: currentScript,
after: newScript,
};
}
Expand Down Expand Up @@ -90,7 +95,7 @@ export const sbScripts: Fix<SbScriptsRunOptions> = {
prompt({ storybookVersion, storybookScripts }) {
const sbFormatted = chalk.cyan(`Storybook ${storybookVersion}`);

const newScriptsMessage = Object.keys(storybookScripts).reduce((acc, scriptKey) => {
const newScriptsMessage = Object.keys(storybookScripts).reduce((acc: string[], scriptKey) => {
acc.push(
[
chalk.bold(scriptKey),
Expand Down
1 change: 1 addition & 0 deletions code/lib/cli/src/automigrate/fixes/vue3.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ describe('vue3 fix', () => {
});
describe('no vue dependency', () => {
it('should no-op', async () => {
// @ts-expect-error (Type 'null' is not comparable)
const packageManager = {
getPackageVersion: (packageName) => {
return null;
Expand Down
1 change: 1 addition & 0 deletions code/lib/cli/src/automigrate/fixes/webpack5.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ describe('webpack5 fix', () => {
});
});
describe('no webpack dependency', () => {
// @ts-expect-error (Type 'null' is not comparable)
const packageManager = {
getPackageVersion: () => {
return null;
Expand Down
8 changes: 4 additions & 4 deletions code/lib/cli/src/automigrate/fixes/webpack5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { updateMainConfig } from '../helpers/mainConfigFile';
const logger = console;

interface Webpack5RunOptions {
webpackVersion: string;
webpackVersion: string | null;
storybookVersion: string;
}

Expand All @@ -22,7 +22,7 @@ interface Webpack5RunOptions {
* - Add core.builder = 'webpack5' to main.js
* - Add 'webpack5' as a project dependency
*/
export const webpack5: Fix<Webpack5RunOptions> = {
export const webpack5 = {
id: 'webpack5',

async check({ configDir, packageManager, mainConfig, storybookVersion }) {
Expand Down Expand Up @@ -75,9 +75,9 @@ export const webpack5: Fix<Webpack5RunOptions> = {

logger.info('✅ Setting `core.builder` to `@storybook/builder-webpack5` in main.js');
if (!dryRun) {
await updateMainConfig({ mainConfigPath, dryRun }, async (main) => {
await updateMainConfig({ mainConfigPath, dryRun: !!dryRun }, async (main) => {
main.setFieldValue(['core', 'builder'], '@storybook/builder-webpack5');
});
}
},
};
} satisfies Fix<Webpack5RunOptions>;
Loading