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

Build: Migrate @storybook/scripts to strict-ts #23818

Merged
merged 11 commits into from
Aug 16, 2023
5 changes: 5 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ jobs:
command: |
cd scripts
yarn get-template --check
- run:
name: Type check
command: |
cd scripts
yarn check
- run:
name: Run tests
command: |
Expand Down
2 changes: 1 addition & 1 deletion scripts/event-log-collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ server.post('/event-log', (req, res) => {
res.end('OK');
});

server.get('/event-log', (req, res) => {
server.get('/event-log', (_req, res) => {
console.log(`Sending ${events.length} events`);
res.json(events);
});
Expand Down
2 changes: 2 additions & 0 deletions scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "7.0.0-alpha.16",
"private": true,
"scripts": {
"check": "./prepare/check-scripts.ts",
"docs:prettier:check": "cd ../docs && prettier --check ./snippets",
"docs:prettier:write": "cd ../docs && prettier --write ./snippets",
"get-report-message": "ts-node --swc ./get-report-message.ts",
Expand Down Expand Up @@ -175,6 +176,7 @@
"slash": "^3.0.0",
"sort-package-json": "^2.0.0",
"tempy": "^1.0.0",
"tiny-invariant": "^1.3.1",
"trash": "^7.0.0",
"ts-dedent": "^2.0.0",
"ts-node": "^10.9.1",
Expand Down
75 changes: 75 additions & 0 deletions scripts/prepare/check-scripts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env ./node_modules/.bin/ts-node-script

import { join } from 'path';
import * as ts from 'typescript';

const run = async ({ cwd }: { cwd: string }) => {
const { options, fileNames } = getTSFilesAndConfig('tsconfig.json');
const { program, host } = getTSProgramAndHost(fileNames, options);

const tsDiagnostics = getTSDiagnostics(program, cwd, host);
if (tsDiagnostics.length > 0) {
console.log(tsDiagnostics);
process.exit(1);
} else {
console.log('no type errors');
}

// TODO, add more package checks here, like:
// - check for missing dependencies/peerDependencies
// - check for unused exports

console.log('done');
};

run({ cwd: process.cwd() }).catch((err: unknown) => {
// We can't let the stack try to print, it crashes in a way that sets the exit code to 0.
// Seems to have something to do with running JSON.parse() on binary / base64 encoded sourcemaps
// in @cspotcode/source-map-support
if (err instanceof Error) {
console.error(err.message);
}
process.exit(1);
});

function getTSDiagnostics(program: ts.Program, cwd: string, host: ts.CompilerHost): any {
return ts.formatDiagnosticsWithColorAndContext(
ts.getPreEmitDiagnostics(program).filter((d) => d.file.fileName.startsWith(cwd)),
host
);
}

function getTSProgramAndHost(fileNames: string[], options: ts.CompilerOptions) {
const program = ts.createProgram({
rootNames: fileNames,
options: {
module: ts.ModuleKind.CommonJS,
...options,
declaration: false,
noEmit: true,
},
});

const host = ts.createCompilerHost(program.getCompilerOptions());
return { program, host };
}

function getTSFilesAndConfig(tsconfigPath: string) {
const content = ts.readJsonConfigFile(tsconfigPath, ts.sys.readFile);
return ts.parseJsonSourceFileConfigFileContent(
content,
{
useCaseSensitiveFileNames: true,
readDirectory: ts.sys.readDirectory,
fileExists: ts.sys.fileExists,
readFile: ts.sys.readFile,
},
process.cwd(),
{
noEmit: true,
outDir: join(process.cwd(), 'types'),
target: ts.ScriptTarget.ES2022,
declaration: false,
}
);
}
3 changes: 2 additions & 1 deletion scripts/prepare/esm-bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import { exec } from '../utils/exec';
/* TYPES */

type BundlerConfig = {
entries: string[];
browserEntries: string[];
nodeEntries: string[];
externals: string[];
pre: string;
post: string;
Expand Down
5 changes: 4 additions & 1 deletion scripts/release/pick-patches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ora from 'ora';
import { setOutput } from '@actions/core';
import { git } from './utils/git-client';
import { getUnpickedPRs } from './utils/github-client';
import invariant from 'tiny-invariant';

program.name('pick-patches').description('Cherry pick patch PRs back to main');

Expand Down Expand Up @@ -57,15 +58,17 @@ export const run = async (_: unknown) => {
await git.raw(['cherry-pick', '-m', '1', '--keep-redundant-commits', '-x', pr.mergeCommit]);
prSpinner.succeed(`Picked: ${formatPR(pr)}`);
} catch (pickError) {
invariant(pickError instanceof Error);
prSpinner.fail(`Failed to automatically pick: ${formatPR(pr)}`);
logger.error(pickError.message);
const abort = ora(`Aborting cherry pick for merge commit: ${pr.mergeCommit}`).start();
try {
await git.raw(['cherry-pick', '--abort']);
abort.stop();
} catch (abortError) {
invariant(abortError instanceof Error);
abort.warn(`Failed to abort cherry pick (${pr.mergeCommit})`);
logger.error(pickError.message);
logger.error(abortError.message);
}
failedCherryPicks.push(pr.mergeCommit);
prSpinner.info(
Expand Down
2 changes: 1 addition & 1 deletion scripts/release/utils/get-github-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ function makeQuery(repos: ReposWithCommitsAndPRsToFetch) {
// getReleaseLine will be called a large number of times but it'll be called at the same time
// so instead of doing a bunch of network requests, we can do a single one.
const GHDataLoader = new DataLoader(
async (requests: RequestData[]) => {
async (requests: readonly RequestData[]) => {
if (!process.env.GH_TOKEN) {
throw new Error(
'Please create a GitHub personal access token at https://github.com/settings/tokens/new with `read:user` and `repo:status` permissions and add it as the GH_TOKEN environment variable'
Expand Down
4 changes: 1 addition & 3 deletions scripts/release/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,10 @@ const bumpVersionSources = async (currentVersion: string, nextVersion: string) =

const bumpAllPackageJsons = async ({
packages,
currentVersion,
nextVersion,
verbose,
}: {
packages: Workspace[];
currentVersion: string;
nextVersion: string;
verbose?: boolean;
}) => {
Expand Down Expand Up @@ -279,7 +277,7 @@ export const run = async (options: unknown) => {

await bumpCodeVersion(nextVersion);
await bumpVersionSources(currentVersion, nextVersion);
await bumpAllPackageJsons({ packages, currentVersion, nextVersion, verbose });
await bumpAllPackageJsons({ packages, nextVersion, verbose });

console.log(`⬆️ Updating lock file with ${chalk.blue('yarn install --mode=update-lockfile')}`);
await execaCommand(`yarn install --mode=update-lockfile`, {
Expand Down
6 changes: 5 additions & 1 deletion scripts/sandbox/utils/git.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import fetch from 'node-fetch';
import invariant from 'tiny-invariant';

import { execaCommand } from '../../utils/exec';
// eslint-disable-next-line import/no-cycle
import { logger } from '../publish';
Expand Down Expand Up @@ -27,9 +29,9 @@ const getTheLastCommitHashThatUpdatedTheSandboxRepo = async (branch: string) =>
`Could not find the last commit hash in the following commit message: "${latestCommitMessage}".\nDid someone manually push to the sandboxes repo?`
);
}

return lastCommitHash;
} catch (error) {
invariant(error instanceof Error);
if (!error.message.includes('Did someone manually push to the sandboxes repo')) {
logger.error(
`⚠️ Error getting latest commit message of ${owner}/${repo} on branch ${branch}: ${error.message}`
Expand Down Expand Up @@ -84,6 +86,7 @@ export async function commitAllToGit({ cwd, branch }: { cwd: string; branch: str
].join('\n');
gitCommitCommand = `git commit -m "${commitTitle}" -m "${commitBody}"`;
} catch (err) {
invariant(err instanceof Error);
logger.log(
`⚠️ Falling back to a simpler commit message because of an error while trying to get the previous commit hash: ${err.message}`
);
Expand All @@ -95,6 +98,7 @@ export async function commitAllToGit({ cwd, branch }: { cwd: string; branch: str
cwd,
});
} catch (e) {
invariant(e instanceof Error);
if (e.message.includes('nothing to commit')) {
logger.log(
`🤷 Git found no changes between previous versions so there is nothing to commit. Skipping publish!`
Expand Down
27 changes: 12 additions & 15 deletions scripts/sandbox/utils/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,17 @@ export async function getTemplatesData(branch: string) {
>
>;

const templatesData = Object.keys(sandboxTemplates).reduce<TemplatesData>(
(acc, curr: keyof typeof sandboxTemplates) => {
const [dirName, templateName] = curr.split('/');
const groupName =
dirName === 'cra' ? 'CRA' : dirName.slice(0, 1).toUpperCase() + dirName.slice(1);
const generatorData = sandboxTemplates[curr];
acc[groupName] = acc[groupName] || {};
acc[groupName][templateName] = {
...generatorData,
stackblitzUrl: getStackblitzUrl(curr, branch),
};
return acc;
},
{}
);
const templatesData = Object.keys(sandboxTemplates).reduce<TemplatesData>((acc, curr) => {
const [dirName, templateName] = curr.split('/');
const groupName =
dirName === 'cra' ? 'CRA' : dirName.slice(0, 1).toUpperCase() + dirName.slice(1);
const generatorData = sandboxTemplates[curr as keyof typeof sandboxTemplates];
acc[groupName] = acc[groupName] || {};
acc[groupName][templateName] = {
...generatorData,
stackblitzUrl: getStackblitzUrl(curr, branch),
};
return acc;
}, {});
return templatesData;
}
5 changes: 4 additions & 1 deletion scripts/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
} from '../code/lib/cli/src/sandbox-templates';

import { version } from '../code/package.json';
import invariant from 'tiny-invariant';

const sandboxDir = process.env.SANDBOX_ROOT || SANDBOX_DIRECTORY;

Expand Down Expand Up @@ -73,7 +74,7 @@ export type Task = {
/**
* Is this task already "ready", and potentially not required?
*/
ready: (details: TemplateDetails, options: PassedOptionValues) => MaybePromise<boolean>;
ready: (details: TemplateDetails, options?: PassedOptionValues) => MaybePromise<boolean>;
/**
* Run the task
*/
Expand Down Expand Up @@ -320,6 +321,7 @@ async function runTask(task: Task, details: TemplateDetails, optionValues: Passe

return controller;
} catch (err) {
invariant(err instanceof Error);
const hasJunitFile = await pathExists(junitFilename);
// If there's a non-test related error (junit report has not been reported already), we report the general failure in a junit report
if (junitFilename && !hasJunitFile) {
Expand Down Expand Up @@ -466,6 +468,7 @@ async function run() {
});
if (controller) controllers.push(controller);
} catch (err) {
invariant(err instanceof Error);
logger.error(`Error running task ${getTaskKey(task)}:`);
// If it is the last task, we don't need to log the full trace
if (task === finalTask) {
Expand Down
3 changes: 1 addition & 2 deletions scripts/tasks/sandbox-parts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,7 @@ export const addStories: Task['run'] = async (
// Ensure that we match the right stories in the stories directory
updateStoriesField(
mainConfig,
(await detectLanguage(packageManager)) === SupportedLanguage.JAVASCRIPT,
disableDocs
(await detectLanguage(packageManager)) === SupportedLanguage.JAVASCRIPT
);

const isCoreRenderer =
Expand Down
2 changes: 2 additions & 0 deletions scripts/ts-to-ts49.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as recast from 'recast';
import type Babel from '@babel/core';
import type { File } from '@babel/types';
import * as t from '@babel/types';
import invariant from 'tiny-invariant';

const files = glob.sync('**/*.ts.mdx', {
absolute: true,
Expand Down Expand Up @@ -74,6 +75,7 @@ for (const [, file] of files.entries()) {
console.log('changed', file);
}
} catch (e) {
invariant(e instanceof Error);
console.error(e.message);
}
}
Expand Down
4 changes: 2 additions & 2 deletions scripts/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
"moduleResolution": "Node",
"target": "ES2020",
"module": "CommonJS",
"skipLibCheck": false,
"skipLibCheck": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"isolatedModules": true,
"strictBindCallApply": true,
"lib": ["dom", "esnext"],
"types": ["node", "jest"],
"strict": false,
"strict": true,
"strictNullChecks": false,
"forceConsistentCasingInFileNames": true,
"noUnusedLocals": true,
Expand Down
2 changes: 1 addition & 1 deletion scripts/utils/exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const exec = async (
}
}
} catch (err) {
if (!err.killed) {
if (!(typeof err === 'object' && 'killed' in err && err.killed)) {
logger.error(chalk.red(`An error occurred while executing: \`${command}\``));
logger.log(`${errorMessage}\n`);
}
Expand Down
13 changes: 0 additions & 13 deletions scripts/utils/options.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { describe, expect, it } from '@jest/globals';
import { createCommand } from 'commander';

import type { MaybeOptionValues, OptionValues } from './options';
import { areOptionsSatisfied, createOptions, getCommand, getOptions } from './options';

const allOptions = createOptions({
Expand Down Expand Up @@ -35,17 +34,6 @@ const allOptions = createOptions({
},
});

// TS "tests"
// deepscan-disable-next-line
function test(mv: MaybeOptionValues<typeof allOptions>, v: OptionValues<typeof allOptions>) {
console.log(mv.first, mv.second, mv.third, mv.fourth, mv.fifth, mv.sixth);
// @ts-expect-error as it's not allowed
console.log(mv.seventh);
console.log(v.first, v.second, v.third, v.fourth, v.fifth, v.sixth);
// @ts-expect-error as it's not allowed
console.log(v.seventh);
}

Comment on lines -38 to -48
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 don't really think it makes a lot of sense to keep this "test" but if it were really important to prevent these particular cases from being changed this could be wrapped in a trivial test to silence compiler warnings, e.g.

describe('TS "tests"', () => {
  it('MaybeOptionValues and OptionValues type test', () => {
    // deepscan-disable-next-line
    function test(mv: MaybeOptionValues<typeof allOptions>, v: OptionValues<typeof allOptions>) {
      console.log(mv.first, mv.second, mv.third, mv.fourth, mv.fifth, mv.sixth);
      // @ts-expect-error as it's not allowed
      console.log(mv.seventh);
      console.log(v.first, v.second, v.third, v.fourth, v.fifth, v.sixth);
      // @ts-expect-error as it's not allowed
      console.log(v.seventh);
    }
    expect(test).toBeDefined();
  });
});

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this test matters that much indeed, so I'm just gonna merge it thanks!

describe('getOptions', () => {
it('deals with boolean options', () => {
expect(getOptions(createCommand(), allOptions, ['command', 'name', '--first'])).toMatchObject({
Expand All @@ -71,7 +59,6 @@ describe('getOptions', () => {
});

it('deals with string options', () => {
const r = getOptions(createCommand(), allOptions, ['command', 'name', '--third', 'one']);
expect(
getOptions(createCommand(), allOptions, ['command', 'name', '--third', 'one'])
).toMatchObject({
Expand Down
8 changes: 8 additions & 0 deletions scripts/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3033,6 +3033,7 @@ __metadata:
slash: ^3.0.0
sort-package-json: ^2.0.0
tempy: ^1.0.0
tiny-invariant: ^1.3.1
trash: ^7.0.0
ts-dedent: ^2.0.0
ts-loader: ^9.4.2
Expand Down Expand Up @@ -15618,6 +15619,13 @@ __metadata:
languageName: node
linkType: hard

"tiny-invariant@npm:^1.3.1":
version: 1.3.1
resolution: "tiny-invariant@npm:1.3.1"
checksum: 5b87c1d52847d9452b60d0dcb77011b459044e0361ca8253bfe7b43d6288106e12af926adb709a6fc28900e3864349b91dad9a4ac93c39aa15f360b26c2ff4db
languageName: node
linkType: hard

"tmp@npm:~0.2.1":
version: 0.2.1
resolution: "tmp@npm:0.2.1"
Expand Down