From 586c35880681d097ae90d96fa7946c9cb9f2568b Mon Sep 17 00:00:00 2001 From: Sean Monahan Date: Thu, 22 Sep 2022 14:38:43 -0700 Subject: [PATCH] stress test: add "build-fixture" command Adds a command to build test fixtures, allowing for easy fixture generation should we want alternates to the defaults. Provides default fixture generation with two variants for t-shirt sizes xs, s, m, l, and xl. Default fixtures are generated when running commands that may rely on fixtures existing. This commit also reworks the `ts-node` implementation a bit. Now the CLI app is a pure ESM application. This is supported by Node 16 but required some changes. In particular: 1. No more `require()` calls. 2. Script imports must have an extension. This is why there are `import foo from 'foo.js'` imports now. This is required because `random-seedable`, the node module we use for randomness, is a pure ESM module and since we do not transpile node_modules the simplest thing to do was go all-in on ESM for the CLI. --- apps/stress-test/package.json | 3 +- apps/stress-test/scripts/commands/build.ts | 11 +- .../scripts/commands/buildFixture.ts | 47 +++++ .../scripts/commands/buildTestConfig.ts | 6 +- apps/stress-test/scripts/commands/dev.ts | 12 +- .../scripts/commands/processResults.ts | 6 +- apps/stress-test/scripts/commands/run.ts | 13 +- .../stress-test/scripts/commands/runServer.ts | 4 +- .../scripts/commands/runTachometer.ts | 8 +- apps/stress-test/scripts/stressTest.ts | 18 +- .../scripts/utils/configureYargs.ts | 39 ++++- apps/stress-test/scripts/utils/fixtures.ts | 163 ++++++++++++++++++ apps/stress-test/scripts/utils/paths.ts | 6 +- apps/stress-test/scripts/utils/server.ts | 4 +- apps/stress-test/scripts/utils/tachometer.ts | 2 +- apps/stress-test/scripts/utils/types.ts | 7 + apps/stress-test/src/fixtures/.gitignore | 1 + .../src/shared/css/RandomSelector.ts | 2 +- .../src/shared/tree/RandomSelectorTreeNode.ts | 6 +- .../stress-test/src/shared/tree/RandomTree.ts | 4 +- apps/stress-test/tsconfig.scripts.json | 5 +- apps/stress-test/tsconfig.type.json | 5 +- .../{griffelConfig.js => griffelConfig.ts} | 33 ++-- .../webpack/{pageConfig.js => pageConfig.ts} | 47 ++--- .../{webpack.config.js => webpack.config.ts} | 45 ++--- 25 files changed, 371 insertions(+), 126 deletions(-) create mode 100644 apps/stress-test/scripts/commands/buildFixture.ts create mode 100644 apps/stress-test/scripts/utils/fixtures.ts create mode 100644 apps/stress-test/src/fixtures/.gitignore rename apps/stress-test/webpack/{griffelConfig.js => griffelConfig.ts} (64%) rename apps/stress-test/webpack/{pageConfig.js => pageConfig.ts} (56%) rename apps/stress-test/webpack/{webpack.config.js => webpack.config.ts} (62%) diff --git a/apps/stress-test/package.json b/apps/stress-test/package.json index 0f89ba9cd52ff7..7a78907517f3cc 100644 --- a/apps/stress-test/package.json +++ b/apps/stress-test/package.json @@ -3,9 +3,10 @@ "version": "1.0.0", "private": true, "main": "index.js", + "type": "module", "license": "MIT", "scripts": { - "stress-test": "ts-node --project tsconfig.scripts.json ./scripts/stressTest.ts", + "stress-test": "ts-node-esm --project tsconfig.scripts.json ./scripts/stressTest.ts", "type-check": "tsc -b tsconfig.type.json" }, "dependencies": { diff --git a/apps/stress-test/scripts/commands/build.ts b/apps/stress-test/scripts/commands/build.ts index 1fb0c3d3985a56..18f3c68dfe8f0e 100644 --- a/apps/stress-test/scripts/commands/build.ts +++ b/apps/stress-test/scripts/commands/build.ts @@ -3,10 +3,10 @@ import { CLIBuildOptions } from '../utils/types'; import { exec } from 'child_process'; import { promisify } from 'util'; -import configureYargs from '../utils/configureYargs'; -import * as webpack from 'webpack'; - -const webpackConfig = require('../../webpack/webpack.config'); +import configureYargs from '../utils/configureYargs.js'; +import webpack from 'webpack'; +import webpackConfig from '../../webpack/webpack.config.js'; +import { buildDefaultFixtures } from '../utils/fixtures.js'; const execAsync = promisify(exec); @@ -82,6 +82,8 @@ const api: yargs.CommandModule = { buildDeps: argv.buildDeps as boolean, }; + buildDefaultFixtures(); + run(args).then(() => { console.log('Build complete!'); }); @@ -89,4 +91,3 @@ const api: yargs.CommandModule = { }; export default api; -// export { api }; diff --git a/apps/stress-test/scripts/commands/buildFixture.ts b/apps/stress-test/scripts/commands/buildFixture.ts new file mode 100644 index 00000000000000..3562020b8b7de4 --- /dev/null +++ b/apps/stress-test/scripts/commands/buildFixture.ts @@ -0,0 +1,47 @@ +import * as yargs from 'yargs'; +import { CLIBuildFixtureOptions } from '../utils/types'; +import configureYargs from '../utils/configureYargs.js'; +import { buildTreeFixture, cleanFixtures, isReservedName, reservedNames } from '../utils/fixtures.js'; + +type BuildFixture = (options: CLIBuildFixtureOptions) => void; + +const command = 'build-fixture'; + +const buildFixture: BuildFixture = ({ type, name, options }) => { + if (type === 'tree') { + buildTreeFixture(name, options); + } +}; + +const api: yargs.CommandModule = { + command, + describe: 'Builds a test fixture.', + builder: y => { + return configureYargs(command, y); + }, + handler: argv => { + const { $0, _, ...options } = argv; + + const opts = options as CLIBuildFixtureOptions; + + if (opts.clean) { + cleanFixtures(); + } else { + if (!opts.name) { + throw new Error(`"name" is required.`); + } else if (!opts.options) { + throw new Error(`"options" is required.`); + } + + if (isReservedName(opts.name)) { + throw new Error( + `"${opts.name}" is a reserved name. Please using a name other than ${reservedNames.map(n => n + '*')}`, + ); + } + + buildFixture(opts); + } + }, +}; + +export default api; diff --git a/apps/stress-test/scripts/commands/buildTestConfig.ts b/apps/stress-test/scripts/commands/buildTestConfig.ts index 328db1a822b0b5..71dd499b51e414 100644 --- a/apps/stress-test/scripts/commands/buildTestConfig.ts +++ b/apps/stress-test/scripts/commands/buildTestConfig.ts @@ -1,11 +1,11 @@ import * as yargs from 'yargs'; import { CLIBuildTestConfigOptions, ConfigResult, TestOptions } from '../utils/types'; -import * as fs from 'fs-extra'; +import fs from 'fs-extra'; import * as path from 'path'; -import { getConfigDir, getResultsDir, ensureClean } from '../utils/paths'; -import configureYargs from '../utils/configureYargs'; +import { getConfigDir, getResultsDir, ensureClean } from '../utils/paths.js'; +import configureYargs from '../utils/configureYargs.js'; import * as querystring from 'querystring'; type BuildTestConfig = (options: CLIBuildTestConfigOptions) => ConfigResult[]; diff --git a/apps/stress-test/scripts/commands/dev.ts b/apps/stress-test/scripts/commands/dev.ts index 220cf0bba808dd..02c89ce854157f 100644 --- a/apps/stress-test/scripts/commands/dev.ts +++ b/apps/stress-test/scripts/commands/dev.ts @@ -1,11 +1,11 @@ import * as yargs from 'yargs'; import { CLIDevOptions } from '../utils/types'; -import * as webpack from 'webpack'; -import * as WebpackDevServer from 'webpack-dev-server'; - -import configureYargs from '../utils/configureYargs'; -const webpackConfig = require('../../webpack/webpack.config'); +import webpack from 'webpack'; +import WebpackDevServer from 'webpack-dev-server'; +import configureYargs from '../utils/configureYargs.js'; +import webpackConfig from '../../webpack/webpack.config.js'; +import { buildDefaultFixtures } from '../utils/fixtures.js'; const command = 'dev'; @@ -47,6 +47,8 @@ const api: yargs.CommandModule = { mode: argv.mode as CLIDevOptions['mode'], }; + buildDefaultFixtures(); + runServer(args); }, }; diff --git a/apps/stress-test/scripts/commands/processResults.ts b/apps/stress-test/scripts/commands/processResults.ts index 23f462feb2b712..b80b809d670f32 100644 --- a/apps/stress-test/scripts/commands/processResults.ts +++ b/apps/stress-test/scripts/commands/processResults.ts @@ -1,9 +1,9 @@ import * as yargs from 'yargs'; import { CLIProcessResultsOptions, ProcessedBrowserData, TachometerBenchmark } from '../utils/types'; -import * as fs from 'fs-extra'; +import fs from 'fs-extra'; import * as path from 'path'; -import configureYargs from '../utils/configureYargs'; -import { getResultsDir, readDirJson } from '../utils/paths'; +import configureYargs from '../utils/configureYargs.js'; +import { getResultsDir, readDirJson } from '../utils/paths.js'; const command = 'process-results'; diff --git a/apps/stress-test/scripts/commands/run.ts b/apps/stress-test/scripts/commands/run.ts index 46dbc621c440d7..2fc25713909b2c 100644 --- a/apps/stress-test/scripts/commands/run.ts +++ b/apps/stress-test/scripts/commands/run.ts @@ -1,10 +1,11 @@ import * as yargs from 'yargs'; import { CLIBuildTestConfigOptions, CLIRunOptions, CLIServerOptions, ConfigResult } from '../utils/types'; -import configureYargs from '../utils/configureYargs'; -import { startServer, stopServer } from '../utils/server'; -import runTachometer from '../utils/tachometer'; -import processResults from './processResults'; -import { buildTestConfig } from './buildTestConfig'; +import configureYargs from '../utils/configureYargs.js'; +import { startServer, stopServer } from '../utils/server.js'; +import runTachometer from '../utils/tachometer.js'; +import processResults from './processResults.js'; +import { buildTestConfig } from './buildTestConfig.js'; +import { buildDefaultFixtures } from '../utils/fixtures.js'; const command = 'run'; @@ -31,6 +32,8 @@ const api: yargs.CommandModule = { return configureYargs(command, y); }, handler: async argv => { + buildDefaultFixtures(); + const { $0, _, ...rest } = argv; const args = (rest as unknown) as CLIRunOptions; await handler(args); diff --git a/apps/stress-test/scripts/commands/runServer.ts b/apps/stress-test/scripts/commands/runServer.ts index ae73f350d1c421..6b3490487a1aa4 100644 --- a/apps/stress-test/scripts/commands/runServer.ts +++ b/apps/stress-test/scripts/commands/runServer.ts @@ -1,7 +1,7 @@ import * as yargs from 'yargs'; -import configureYargs from '../utils/configureYargs'; -import { startServer } from '../utils/server'; +import configureYargs from '../utils/configureYargs.js'; +import { startServer } from '../utils/server.js'; import { CLIServerOptions } from '../utils/types'; const command = 'serve'; diff --git a/apps/stress-test/scripts/commands/runTachometer.ts b/apps/stress-test/scripts/commands/runTachometer.ts index a56b1462a40411..516bcf25978cb9 100644 --- a/apps/stress-test/scripts/commands/runTachometer.ts +++ b/apps/stress-test/scripts/commands/runTachometer.ts @@ -1,11 +1,11 @@ import * as yargs from 'yargs'; import { CLITachometerOptions, ConfigResult } from '../utils/types'; -import * as fs from 'fs-extra'; +import fs from 'fs-extra'; import * as path from 'path'; -import configureYargs from '../utils/configureYargs'; -import { getConfigDir, getResultsDir, readDirJson } from '../utils/paths'; -import runTachometer from '../utils/tachometer'; +import configureYargs from '../utils/configureYargs.js'; +import { getConfigDir, getResultsDir, readDirJson } from '../utils/paths.js'; +import runTachometer from '../utils/tachometer.js'; const command = 'tachometer'; diff --git a/apps/stress-test/scripts/stressTest.ts b/apps/stress-test/scripts/stressTest.ts index 664b825176c0b4..716df4293ae609 100644 --- a/apps/stress-test/scripts/stressTest.ts +++ b/apps/stress-test/scripts/stressTest.ts @@ -1,11 +1,12 @@ -import * as yargs from 'yargs'; -import build from './commands/build'; -import buildTestConfig from './commands/buildTestConfig'; -import dev from './commands/dev'; -import processResults from './commands/processResults'; -import run from './commands/run'; -import runServer from './commands/runServer'; -import runTachometer from './commands/runTachometer'; +import yargs from 'yargs'; +import build from './commands/build.js'; +import buildTestConfig from './commands/buildTestConfig.js'; +import dev from './commands/dev.js'; +import processResults from './commands/processResults.js'; +import run from './commands/run.js'; +import runServer from './commands/runServer.js'; +import runTachometer from './commands/runTachometer.js'; +import buildFixture from './commands/buildFixture.js'; yargs .usage('Usage: $0 [options]') @@ -16,6 +17,7 @@ yargs .command(run) .command(runServer) .command(runTachometer) + .command(buildFixture) .demandCommand() .help() .parse(); diff --git a/apps/stress-test/scripts/utils/configureYargs.ts b/apps/stress-test/scripts/utils/configureYargs.ts index 177fd9a23e0cfe..f7947958443850 100644 --- a/apps/stress-test/scripts/utils/configureYargs.ts +++ b/apps/stress-test/scripts/utils/configureYargs.ts @@ -1,5 +1,5 @@ import * as yargs from 'yargs'; -import { getBrowsers } from './getBrowsers'; +import { getBrowsers } from './getBrowsers.js'; type YargsOptions = Record; type Configure = (y: yargs.Argv, options: YargsOptions) => void; @@ -79,6 +79,31 @@ const cliOptions = { describe: 'Open the dev server in a new browser window.', default: false, }, + type: { + describe: 'Type of fixture to build.', + default: 'tree', + }, + name: { + describe: 'Name of the fixture.', + }, + options: { + describe: 'Options for building the fixture. E.g., minBreadth=1 maxBreadth=20', + coerce: (arg: string[]) => { + return arg.reduce((map: { [key: string]: string }, current) => { + const [key, value] = current.split('='); + if (!key || !value) { + throw new Error(`Invalid test option. Got ${current}. Expected the form "key=value".`); + } + + map[key] = value; + return map; + }, {}); + }, + }, + clean: { + describe: 'Cleans fixtures.', + default: false, + }, }; const configure: Configure = (y, options) => { @@ -91,6 +116,7 @@ const configure: Configure = (y, options) => { case 'targets': case 'test-options': case 'renderers': + case 'options': _y = _y.array(option); break; @@ -107,6 +133,7 @@ const configure: Configure = (y, options) => { case 'verbose': case 'build-deps': case 'open': + case 'clean': _y = _y.boolean(option); break; @@ -117,6 +144,10 @@ const configure: Configure = (y, options) => { case 'mode': _y = _y.choices(option, ['production', 'development']); break; + + case 'type': + _y = _y.choices(option, ['tree']); + break; } }); }; @@ -209,6 +240,12 @@ const configureYargs: CongfigureYargs = (command, y) => { configure(y, { mode, open, 'griffel-mode': griffelMode }); break; } + + case 'build-fixture': { + const { type, name, options, clean } = cliOptions; + configure(y, { type, name, options, clean }); + break; + } } return y; diff --git a/apps/stress-test/scripts/utils/fixtures.ts b/apps/stress-test/scripts/utils/fixtures.ts new file mode 100644 index 00000000000000..c8feeb1f0a12a0 --- /dev/null +++ b/apps/stress-test/scripts/utils/fixtures.ts @@ -0,0 +1,163 @@ +import fs from 'fs-extra'; +import { join } from 'path'; +import { getFixturesDir, remove } from './paths.js'; +import { RandomTree } from '../../src/shared/tree/RandomTree.js'; +import { RandomSelectorTreeNode, selectorTreeCreator } from '../../src/shared/tree/RandomSelectorTreeNode.js'; +import glob from 'glob'; + +type BuildTreeFixture = (name: string, options: { [key: string]: string }) => void; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type TreeJsonReplacer = (key: string, value: any) => any; +type DefaultFixture = 'xs_1' | 'xs_2' | 's_1' | 's_2' | 'm_1' | 'm_2' | 'l_1' | 'l_2' | 'xl_1' | 'xl_2'; +type DefaultFixtureOptions = { + [fixtureName in DefaultFixture]: { + [option: string]: string; + }; +}; + +const defaultFixtures = ['xs_1', 'xs_2', 's_1', 's_2', 'm_1', 'm_2', 'l_1', 'l_2', 'xl_1', 'xl_2']; +const defaultFixtureOptions: DefaultFixtureOptions = { + // eslint-disable-next-line @typescript-eslint/naming-convention + xs_1: { + minBreadth: '1', + maxBreadth: '3', + minDepth: '1', + maxDepth: '3', + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + xs_2: { + minBreadth: '1', + maxBreadth: '3', + minDepth: '1', + maxDepth: '3', + seed: '4212021', + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + s_1: { + minBreadth: '2', + maxBreadth: '5', + minDepth: '2', + maxDepth: '5', + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + s_2: { + minBreadth: '2', + maxBreadth: '5', + minDepth: '2', + maxDepth: '5', + seed: '4212021', + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + m_1: { + minBreadth: '3', + maxBreadth: '8', + minDepth: '3', + maxDepth: '8', + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + m_2: { + minBreadth: '3', + maxBreadth: '8', + minDepth: '3', + maxDepth: '8', + seed: '4212021', + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + l_1: { + minBreadth: '5', + maxBreadth: '15', + minDepth: '4', + maxDepth: '15', + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + l_2: { + minBreadth: '5', + maxBreadth: '15', + minDepth: '4', + maxDepth: '15', + seed: '4212021', + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + xl_1: { + minBreadth: '10', + maxBreadth: '20', + minDepth: '10', + maxDepth: '20', + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + xl_2: { + minBreadth: '10', + maxBreadth: '20', + minDepth: '10', + maxDepth: '20', + seed: '4212021', + }, +}; + +export const reservedNames = ['xs_', 's_', 'm_', 'l_', 'xl_']; +export const isReservedName = (name: string): boolean => { + return reservedNames.some(reservedName => { + return name.startsWith(reservedName); + }); +}; + +const treeJsonReplace: TreeJsonReplacer = (key, value) => { + if (key === 'parent') { + return undefined; + } + + return value; +}; + +export const cleanFixtures = () => { + const files = glob.sync(join(getFixturesDir(), '**', '*.js')); + files.forEach(file => remove(file)); +}; + +export const buildTreeFixture: BuildTreeFixture = (name, options) => { + const selectors = [] as string[]; + const treeBuilder = new RandomTree(options); + const tree = treeBuilder.build(selectorTreeCreator(selectors)); + + const jsonTree = JSON.stringify(tree, treeJsonReplace, 2); + + const data = { + tree: JSON.parse(jsonTree), + selectors, + }; + + const js = `export default ${JSON.stringify(data, null, 2)};`; + + fs.writeFileSync(join(getFixturesDir(), `${name}.js`), js, { encoding: 'utf8' }); +}; + +export const buildDefaultFixtures = () => { + const fixtures = defaultFixtures.map(f => { + return { + name: f as DefaultFixture, + path: join(getFixturesDir(), `${f}.js`), + }; + }); + + const missingFixtures = [] as DefaultFixture[]; + fixtures.forEach(f => { + if (!fs.existsSync(f.path)) { + missingFixtures.push(f.name); + } + }); + + if (missingFixtures.length === 0) { + return; + } + + console.log(`Missing fixtures: ${missingFixtures}.`); + console.log('Generating...'); + + missingFixtures.forEach(missingFixture => { + console.log(`Generating fixture ${missingFixture}...`); + buildTreeFixture(missingFixture, defaultFixtureOptions[missingFixture]); + console.log(`Done!`); + }); + + console.log('All default fixtures generated!'); +}; diff --git a/apps/stress-test/scripts/utils/paths.ts b/apps/stress-test/scripts/utils/paths.ts index 4f51d31e5018c9..b3a1d5862fa128 100644 --- a/apps/stress-test/scripts/utils/paths.ts +++ b/apps/stress-test/scripts/utils/paths.ts @@ -1,4 +1,4 @@ -import * as fs from 'fs-extra'; +import fs from 'fs-extra'; import { join } from 'path'; export const getPackageRoot: () => string = () => { @@ -40,3 +40,7 @@ export const ensureClean: (path: string) => void = path => { remove(path); mkdirp(path); }; + +export const getFixturesDir: () => string = () => { + return join(getPackageRoot(), 'src', 'fixtures'); +}; diff --git a/apps/stress-test/scripts/utils/server.ts b/apps/stress-test/scripts/utils/server.ts index 33337ebcba93bf..f39d44f457a743 100644 --- a/apps/stress-test/scripts/utils/server.ts +++ b/apps/stress-test/scripts/utils/server.ts @@ -1,8 +1,8 @@ import { CLIServerOptions } from './types'; -import * as express from 'express'; +import express from 'express'; import { join } from 'path'; import { Server } from 'http'; -import { getPackageRoot } from './paths'; +import { getPackageRoot } from './paths.js'; const handleGracefulShutdown: (arg: unknown) => void = arg => { console.log('Shutting down...'); diff --git a/apps/stress-test/scripts/utils/tachometer.ts b/apps/stress-test/scripts/utils/tachometer.ts index 6cd3a925e066d6..c465709a70acf1 100644 --- a/apps/stress-test/scripts/utils/tachometer.ts +++ b/apps/stress-test/scripts/utils/tachometer.ts @@ -1,7 +1,7 @@ import { ConfigResult } from './types'; import { exec } from 'child_process'; import { promisify } from 'util'; -import { ensureClean } from './paths'; +import { ensureClean } from './paths.js'; const execAsync = promisify(exec); diff --git a/apps/stress-test/scripts/utils/types.ts b/apps/stress-test/scripts/utils/types.ts index 24edc00257f8c6..2343ce4f0c8a0f 100644 --- a/apps/stress-test/scripts/utils/types.ts +++ b/apps/stress-test/scripts/utils/types.ts @@ -1,3 +1,10 @@ +export type CLIBuildFixtureOptions = { + type: 'tree'; + name: string; + options: { [key: string]: string }; + clean: boolean; +}; + export type CLIBuildOptions = { griffelMode: GriffelMode; mode: WebpackMode; diff --git a/apps/stress-test/src/fixtures/.gitignore b/apps/stress-test/src/fixtures/.gitignore new file mode 100644 index 00000000000000..a6c7c2852d068f --- /dev/null +++ b/apps/stress-test/src/fixtures/.gitignore @@ -0,0 +1 @@ +*.js diff --git a/apps/stress-test/src/shared/css/RandomSelector.ts b/apps/stress-test/src/shared/css/RandomSelector.ts index caa8248bdcd67a..1a3e0b92665fd6 100644 --- a/apps/stress-test/src/shared/css/RandomSelector.ts +++ b/apps/stress-test/src/shared/css/RandomSelector.ts @@ -1,4 +1,4 @@ -import { random, Random } from '../utils/random'; +import { random, Random } from '../utils/random.js'; export const defaultSelectorTypes = [ 'class', diff --git a/apps/stress-test/src/shared/tree/RandomSelectorTreeNode.ts b/apps/stress-test/src/shared/tree/RandomSelectorTreeNode.ts index 28b0cb2f87c27f..89affde79593a0 100644 --- a/apps/stress-test/src/shared/tree/RandomSelectorTreeNode.ts +++ b/apps/stress-test/src/shared/tree/RandomSelectorTreeNode.ts @@ -1,6 +1,6 @@ -import { RandomSelector } from '../css/RandomSelector'; -import { TreeNode, TreeNodeCreateCallback } from './RandomTree'; -import { random } from '../utils/random'; +import { RandomSelector } from '../css/RandomSelector.js'; +import { TreeNode, TreeNodeCreateCallback } from './RandomTree.js'; +import { random } from '../utils/random.js'; export type Attribute = { key: string; diff --git a/apps/stress-test/src/shared/tree/RandomTree.ts b/apps/stress-test/src/shared/tree/RandomTree.ts index f41d024c1fb8e9..06d8705343f9b8 100644 --- a/apps/stress-test/src/shared/tree/RandomTree.ts +++ b/apps/stress-test/src/shared/tree/RandomTree.ts @@ -1,5 +1,5 @@ -import { random, Random } from '../utils/random'; -import { TestFixture } from '../utils/testUtils'; +import { random, Random } from '../utils/random.js'; +import { TestFixture } from '../utils/testUtils.js'; type TreeParams = { minDepth?: number; diff --git a/apps/stress-test/tsconfig.scripts.json b/apps/stress-test/tsconfig.scripts.json index 6ed5b82d76721d..aa733ecc6d8078 100644 --- a/apps/stress-test/tsconfig.scripts.json +++ b/apps/stress-test/tsconfig.scripts.json @@ -12,8 +12,9 @@ "experimentalDecorators": true, "types": ["environment", "node"], "moduleResolution": "node", - "module": "CommonJS" + "module": "ESNext", + "esModuleInterop": true }, - "include": ["src"], + "include": ["src", "scripts"], "exclude": ["node_modules"] } diff --git a/apps/stress-test/tsconfig.type.json b/apps/stress-test/tsconfig.type.json index 59fa84eca13865..6d2a4d4b82dc15 100644 --- a/apps/stress-test/tsconfig.type.json +++ b/apps/stress-test/tsconfig.type.json @@ -1,7 +1,10 @@ { "extends": "./tsconfig.json", "compilerOptions": { - "noEmit": true + "noEmit": true, + "moduleResolution": "node", + "module": "ESNext", + "esModuleInterop": true }, "include": ["src", "scenarios", "webpack", "scripts"] } diff --git a/apps/stress-test/webpack/griffelConfig.js b/apps/stress-test/webpack/griffelConfig.ts similarity index 64% rename from apps/stress-test/webpack/griffelConfig.js rename to apps/stress-test/webpack/griffelConfig.ts index ea070219094273..ef699e94b0a483 100644 --- a/apps/stress-test/webpack/griffelConfig.js +++ b/apps/stress-test/webpack/griffelConfig.ts @@ -1,14 +1,9 @@ -const { GriffelCSSExtractionPlugin } = require('@griffel/webpack-extraction-plugin'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +import { GriffelCSSExtractionPlugin } from '@griffel/webpack-extraction-plugin'; +import MiniCssExtractPlugin from 'mini-css-extract-plugin'; +import webpack from 'webpack'; +import { GriffelMode } from '../scripts/utils/types'; -/** - * @typedef {('runtime' | 'buildtime' | 'extraction')} GriffelMode - */ - -/** - * @type {import('webpack').RuleSetRule} - */ -const griffelWebpackLoader = { +const griffelWebpackLoader: webpack.RuleSetRule = { test: /\.(ts|tsx)$/, exclude: [/node_modules/, /\.wc\.(ts|tsx)?$/], use: { @@ -21,10 +16,7 @@ const griffelWebpackLoader = { }, }; -/** - * @type {import('webpack').RuleSetRule} - */ -const griffelExtractionLoader = { +const griffelExtractionLoader: webpack.RuleSetRule = { test: /\.(js|ts|tsx)$/, // Apply "exclude" only if your dependencies **do not use** Griffel // exclude: /node_modules/, @@ -43,12 +35,11 @@ const cssLoader = { * configure Griffel. * * NOTE: this function mutates the `config` object passed in to it. - * - * @param {import('webpack').Configuration} config - Webpack configuration object to modify. - * @param {GriffelMode} griffelMode - * @returns {import('webpack').Configuration} Modified Webpack configuration object. */ -const configureGriffel = (config, griffelMode) => { +const configureGriffel: (config: webpack.Configuration, griffelMode: GriffelMode) => webpack.Configuration = ( + config, + griffelMode, +) => { console.log(`Griffel running in ${griffelMode} mode.`); config.module = config.module || {}; @@ -69,6 +60,4 @@ const configureGriffel = (config, griffelMode) => { return config; }; -module.exports = { - configureGriffel, -}; +export { configureGriffel }; diff --git a/apps/stress-test/webpack/pageConfig.js b/apps/stress-test/webpack/pageConfig.ts similarity index 56% rename from apps/stress-test/webpack/pageConfig.js rename to apps/stress-test/webpack/pageConfig.ts index d8c0707a91b38e..5de1c7cd9cab9a 100644 --- a/apps/stress-test/webpack/pageConfig.js +++ b/apps/stress-test/webpack/pageConfig.ts @@ -1,5 +1,6 @@ -const glob = require('glob'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); +import glob from 'glob'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import webpack from 'webpack'; /** * Automatically configures Webpack to find pages so @@ -7,22 +8,18 @@ const HtmlWebpackPlugin = require('html-webpack-plugin'); * the Webpack config. */ -/** - * A page configuration object used to generate Webpack configuration. - * @typedef {Object} PageConfig - * @property {string} name - Name of the page. - * @property {string} path - Path the the index file for the page. This is a tsx (React) or wc.ts (Web Component) file. - * @property {string} template - HTML template for the page. - * @property {string} output - Path to the output file - */ +export type PageConfig = { + name: string; + path: string; + template: string; + output: string; +}; /** * Find all the source pages and map them to * config objects used to generate the Webpack config. - * - * @returns {PageConfig[]} List of page configuration objects. */ -const getPages = () => { +const getPages: () => PageConfig[] = () => { const extPattern = /\.(tsx|wc.ts)/; const pagePattern = './src/pages/**/*/index.?(tsx|wc.ts)'; @@ -48,15 +45,9 @@ const getPages = () => { /** * Take data from getPages() and generate Webpack * config's `entry`. - * - * @param {PageConfig[]} pages - List of page configuration objects. - * @returns {import('webpack').Entry} `entry` object for Webpack configuration. */ -const getEntry = pages => { - /** - * @type {Object.} - */ - const init = {}; +const getEntry: (pages: PageConfig[]) => webpack.Entry = pages => { + const init = {} as Record; return pages.reduce((config, page) => { config[page.name] = page.path; return config; @@ -66,11 +57,8 @@ const getEntry = pages => { /** * Take data from getPages() and generate * HTML plugins for the pages. - * - * @param {PageConfig[]} pages - List of page configuration objects. - * @returns {import('html-webpack-plugin')[]} List of HtmlWebpackPlugins for all pages. */ -const getHtmlPlugin = pages => { +const getHtmlPlugin: (pages: PageConfig[]) => HtmlWebpackPlugin[] = pages => { return pages.map(page => { return new HtmlWebpackPlugin({ inject: 'body', @@ -86,11 +74,8 @@ const getHtmlPlugin = pages => { * to automatically load pages. * * NOTE: this function mutates the `config` object passed in to it. - * - * @param {import('webpack').Configuration} config - Webpack configuration object to modify. - * @returns {import('webpack').Configuration} Modified Webpack configuration object. */ -const configurePages = config => { +const configurePages: (config: webpack.Configuration) => webpack.Configuration = config => { const pages = getPages(); config.entry = getEntry(pages); @@ -103,6 +88,4 @@ const configurePages = config => { return config; }; -module.exports = { - configurePages, -}; +export { configurePages }; diff --git a/apps/stress-test/webpack/webpack.config.js b/apps/stress-test/webpack/webpack.config.ts similarity index 62% rename from apps/stress-test/webpack/webpack.config.js rename to apps/stress-test/webpack/webpack.config.ts index 60836b410c637b..6c57826f433b2d 100644 --- a/apps/stress-test/webpack/webpack.config.js +++ b/apps/stress-test/webpack/webpack.config.ts @@ -1,29 +1,28 @@ -const path = require('path'); -const { CleanWebpackPlugin } = require('clean-webpack-plugin'); -const { TsconfigPathsPlugin } = require('tsconfig-paths-webpack-plugin'); -const { configurePages } = require('./pageConfig'); -const { configureGriffel } = require('./griffelConfig'); +import * as path from 'path'; +import { fileURLToPath } from 'url'; +import { CleanWebpackPlugin } from 'clean-webpack-plugin'; +import { TsconfigPathsPlugin } from 'tsconfig-paths-webpack-plugin'; +import { configurePages } from './pageConfig.js'; +import { configureGriffel } from './griffelConfig.js'; +import * as WebpackDevServer from 'webpack-dev-server'; +import { GriffelMode } from '../scripts/utils/types'; -/** - * @typedef {Object} Argv - * @property {('development' | 'production' | 'none')} mode - * @property {import('./griffelConfig.js').GriffelMode} griffelMode - */ +const __dirname = path.dirname(fileURLToPath(import.meta.url)); -/** - * @param {*} _env - * @param {Argv} argv - * @returns - */ -module.exports = (_env, argv) => { - console.log('env', _env); +type WebpackArgs = { + mode: 'production' | 'development' | 'none'; + griffelMode: GriffelMode; +}; + +type WebpackConfigurationCreator = ( + env: string | undefined, + argv: WebpackArgs, +) => WebpackDevServer.WebpackConfiguration; + +const createConfig: WebpackConfigurationCreator = (_env, argv) => { const isProd = argv.mode === 'production'; - /** @typedef {import('webpack-dev-server')} */ - /** - * @type {import('webpack').Configuration} - */ - let config = { + let config: WebpackDevServer.WebpackConfiguration = { mode: argv.mode, output: { filename: '[name].[contenthash].bundle.js', @@ -83,3 +82,5 @@ module.exports = (_env, argv) => { return config; }; + +export default createConfig;