@elliemae/pui-cli 6.0.0-beta.7 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +8 -0
  2. package/lib/cli-commands/build.js +11 -5
  3. package/lib/cli-commands/pack.js +18 -78
  4. package/lib/cli-commands/test.js +1 -12
  5. package/lib/cli-commands/tsc.js +103 -0
  6. package/lib/cli-commands/utils.js +9 -4
  7. package/lib/cli-commands/vitest.js +66 -0
  8. package/lib/cli.js +2 -0
  9. package/lib/index.js +3 -1
  10. package/lib/lint/eslint/common.js +16 -8
  11. package/lib/lint/eslint/typescript/common.js +6 -1
  12. package/lib/lint/eslint/typescript/non-react.js +1 -1
  13. package/lib/lint/eslint/typescript/react.js +6 -1
  14. package/lib/lint/lint-staged.config.js +8 -1
  15. package/lib/lint/stylelint.config.js +0 -1
  16. package/lib/pui-config/index.js +18 -0
  17. package/lib/server/index.js +0 -7
  18. package/lib/server/middlewares/addDevMiddlewares.js +2 -2
  19. package/lib/server/middlewares/addProdMiddlewares.js +10 -3
  20. package/lib/testing/jest.config.js +18 -8
  21. package/lib/testing/jest.node.config.js +8 -0
  22. package/lib/testing/mocks/matchMedia.js +12 -6
  23. package/lib/testing/mocks/pui-app-loader.js +1 -3
  24. package/lib/testing/mocks/pui-diagnostics.js +27 -35
  25. package/lib/testing/mocks/pui-user-monitoring.js +3 -5
  26. package/lib/testing/mocks/retry-axios.js +3 -5
  27. package/lib/testing/mocks/svg.js +5 -3
  28. package/lib/testing/mocks/webpack-hmr.js +1 -0
  29. package/lib/testing/resolver.js +47 -0
  30. package/lib/testing/setup-react-env.js +3 -0
  31. package/lib/testing/setup-tests.js +28 -4
  32. package/lib/testing/vitest.config.ts +16 -0
  33. package/lib/testing/vitest.setup.ts +0 -0
  34. package/lib/transpile/.swcrc +11 -0
  35. package/lib/transpile/esbuild.js +110 -0
  36. package/lib/transpile/react-shim.js +2 -0
  37. package/lib/transpile/swcrc.config.js +13 -0
  38. package/lib/typescript/tsc-files/index.js +66 -0
  39. package/lib/typescript/tsc-files/utils.js +16 -0
  40. package/lib/webpack/helpers.js +44 -3
  41. package/lib/webpack/webpack.base.babel.js +47 -81
  42. package/lib/webpack/webpack.dev.babel.js +16 -10
  43. package/lib/webpack/webpack.lib.base.babel.js +33 -55
  44. package/lib/webpack/webpack.lib.dev.babel.js +2 -3
  45. package/lib/webpack/webpack.lib.prod.babel.js +5 -11
  46. package/lib/webpack/webpack.prod.babel.js +29 -24
  47. package/lib/webpack/webpack.storybook.js +19 -98
  48. package/package.json +116 -124
  49. package/lib/esbuild.js +0 -44
  50. package/lib/testing/setup-styled-components-tests.js +0 -1
package/README.md CHANGED
@@ -22,6 +22,14 @@
22
22
 
23
23
  ## Migration Guide
24
24
 
25
+ ### v5 to v6
26
+
27
+ [ChangeLog](https://confluence.elliemae.io/display/FEAE/CLI+ChangeLog)
28
+
29
+ ### v4 to v5
30
+
31
+ For most users this upgrade doesn't break functionality. If it does, please reach out to ui-platform-chat channel for assistance
32
+
25
33
  ### v3 to v4
26
34
 
27
35
  Version 4 has breaking changes that impacts only libraries (e.g: app sdk, app widgets etc) not applications
@@ -6,11 +6,11 @@ const {
6
6
  logSuccess,
7
7
  writeAppInfo,
8
8
  } = require('./utils');
9
+ const { esBuild, TARGETS } = require('../transpile/esbuild');
9
10
 
10
11
  const { name } = require('../../package.json');
11
12
 
12
13
  async function buildWebApp() {
13
- logInfo('Build in progress...');
14
14
  await exec(`rimraf ./build`);
15
15
  await exec(
16
16
  `cross-env NODE_ENV=production webpack --config node_modules/${name}/lib/webpack/webpack.prod.babel.js --color`,
@@ -20,13 +20,19 @@ async function buildWebApp() {
20
20
 
21
21
  async function buildService() {
22
22
  await exec('rimraf ./build');
23
- await exec(
24
- `cross-env NODE_ENV=production MODULE_EXTENSIONS=true TARGET_ENV=node babel --extensions '.ts,.js' --config-file ./babel.config.cjs --out-dir ./build --copy-files --no-copy-ignored --ignore '**/*.test.ts','**/*.test.js','**/*.spec.ts','**/*.test.js' ./app`,
25
- );
23
+ await esBuild({
24
+ srcdir: './app',
25
+ outdir: 'build',
26
+ esmOnly: true,
27
+ target: TARGETS.node,
28
+ injectReactShim: false,
29
+ skipNestedPackageJSON: true,
30
+ });
26
31
  }
27
32
 
28
33
  async function handler({ service = false }) {
29
34
  try {
35
+ logInfo('Build in progress...');
30
36
  if (service) await buildService();
31
37
  else await buildWebApp();
32
38
  logSuccess('Build completed');
@@ -38,7 +44,7 @@ async function handler({ service = false }) {
38
44
 
39
45
  exports.command = 'build';
40
46
 
41
- exports.describe = 'builds application';
47
+ exports.describe = 'builds front end application or NodeJS service';
42
48
 
43
49
  exports.builder = {
44
50
  service: {
@@ -1,58 +1,24 @@
1
- /* eslint-disable max-lines */
2
1
  const { exit } = require('yargs');
3
- const path = require('path');
4
- const { writeFile, readFile } = require('fs/promises');
5
2
  const { exec, logInfo, logError, logSuccess } = require('./utils');
6
3
  const { isTypeScriptEnabled } = require('../typescript/util');
7
- const { esBuild } = require('../esbuild');
8
-
4
+ const { esBuild } = require('../transpile/esbuild');
9
5
  const { name } = require('../../package.json');
10
6
 
11
- async function compileTypeScript() {
12
- logInfo('Compiling typescript files...');
13
- await exec('tsc');
14
- await exec('tsc-alias');
15
- }
7
+ const compileTypeScript = async () => {
8
+ logInfo('Generating types...');
9
+ await exec('tsc --emitDeclarationOnly');
10
+ logInfo('Types generation completed...');
11
+ };
16
12
 
17
- async function webBuild(productionBuild) {
18
- logInfo('Compiling source files for browser environment...');
13
+ const webBuild = async (productionBuild) => {
14
+ logInfo('Building source files for browser environment...');
19
15
  const devCmd = `node_modules/${name}/lib/webpack/webpack.lib.dev.babel.js --color`;
20
16
  const prodCmd = `node_modules/${name}/lib/webpack/webpack.lib.prod.babel.js --color`;
21
- await exec(
22
- `cross-env NODE_ENV=production webpack --config ${
23
- productionBuild ? prodCmd : devCmd
24
- }`,
25
- );
26
- }
27
-
28
- async function getSideEffects() {
29
- const data = await readFile(path.join(process.cwd(), './package.json'));
30
- const packageJSON = JSON.parse(data);
31
- return packageJSON?.sideEffects || false;
32
- }
33
-
34
- async function createPackageJson(file, commonJS, sideEffects) {
35
- const packageJSON = JSON.stringify({
36
- type: commonJS ? 'commonjs' : 'module',
37
- sideEffects,
38
- });
39
- await writeFile(file, packageJSON);
40
- }
41
-
42
- async function nodeBuild({ srcPath, commonJS, emitModuleType }) {
43
- const outDir = `./dist/${commonJS ? 'cjs' : 'es'}`;
44
- await esBuild({ srcPath, commonJS });
45
- if (emitModuleType) {
46
- const sideEffects = await getSideEffects();
47
- await createPackageJson(
48
- path.join(process.cwd(), outDir, 'package.json'),
49
- commonJS,
50
- sideEffects,
51
- );
52
- }
53
- }
17
+ await exec(`webpack --config ${productionBuild ? prodCmd : devCmd}`);
18
+ logInfo('Building source files for browser environment completed...');
19
+ };
54
20
 
55
- async function pack({ production, target, module, srcPath, emitModuleType }) {
21
+ const pack = async ({ production, target, srcPath }) => {
56
22
  logInfo('Build in-progress...');
57
23
  await exec('rimraf ./dist');
58
24
  if (isTypeScriptEnabled()) {
@@ -60,28 +26,13 @@ async function pack({ production, target, module, srcPath, emitModuleType }) {
60
26
  }
61
27
  if (target !== 'node') await webBuild(production);
62
28
  if (target !== 'web') {
63
- logInfo('Compiling source files for nodejs environment');
64
- if (module !== 'es') {
65
- logInfo('output format: commonjs');
66
- await nodeBuild({
67
- srcPath,
68
- commonJS: true,
69
- emitModuleType,
70
- target,
71
- });
72
- }
73
- if (module !== 'cjs') {
74
- logInfo('output format: es');
75
- await nodeBuild({
76
- srcPath,
77
- commonJS: false,
78
- emitModuleType,
79
- });
80
- }
29
+ logInfo('Building source files for nodejs environment...');
30
+ await esBuild({ srcdir: srcPath });
31
+ logInfo('Building source files for nodejs environment completed.');
81
32
  }
82
- }
33
+ };
83
34
 
84
- async function handler(argv) {
35
+ const handler = async (argv) => {
85
36
  try {
86
37
  await pack(argv);
87
38
  logSuccess('Build completed');
@@ -89,7 +40,7 @@ async function handler(argv) {
89
40
  logError('Build failed', err);
90
41
  exit(-1, err);
91
42
  }
92
- }
43
+ };
93
44
 
94
45
  exports.command = 'pack';
95
46
 
@@ -107,17 +58,6 @@ exports.builder = {
107
58
  description:
108
59
  'target environment where this library will be used. allowed values are web, node. by default libraries will be compiled for both web and nodejs environments',
109
60
  },
110
- module: {
111
- type: 'string',
112
- description:
113
- 'specify the format in which the library to be compiled. es - es module format, cjs - commonjs module format. by default libraries will be compiled in both es and cjs format ',
114
- },
115
- emitModuleType: {
116
- type: 'boolean',
117
- default: true,
118
- description:
119
- 'creates type attribute in the package.json and sets its value to commonjs or module based on module cli argument. default: true',
120
- },
121
61
  srcPath: {
122
62
  type: 'string',
123
63
  default: './lib',
@@ -1,6 +1,5 @@
1
1
  const { exit } = require('yargs');
2
2
  const { exec, logError, logSuccess } = require('./utils');
3
- const { lintCSS, lintJS } = require('./lint');
4
3
 
5
4
  const { CI = false } = process.env;
6
5
 
@@ -19,17 +18,7 @@ async function handler(argv) {
19
18
  if (argv.r) commandOptions += ' --bail --findRelatedTests';
20
19
  if (argv.s) commandOptions += ' --silent';
21
20
  try {
22
- if (!CI) {
23
- try {
24
- await lintJS();
25
- await lintCSS();
26
- logSuccess('Linting completed');
27
- } catch (err) {
28
- logError('Linting failed');
29
- exit(-1, err);
30
- return -1;
31
- }
32
- } else {
21
+ if (CI) {
33
22
  await exec('rimraf ./reports');
34
23
  }
35
24
 
@@ -0,0 +1,103 @@
1
+ const { exit } = require('yargs');
2
+ const { dirname, join } = require('path');
3
+ const { spawnSync } = require('child_process');
4
+ const fs = require('fs');
5
+ const { logInfo, logError } = require('./utils');
6
+
7
+ const randomChars = () => Math.random().toString(36).slice(2);
8
+
9
+ const resolveFromModule = (moduleName, ...paths) => {
10
+ const modulePath = dirname(require.resolve(`${moduleName}/package.json`));
11
+ return join(modulePath, ...paths);
12
+ };
13
+
14
+ const resolveFromRoot = (...paths) => join(process.cwd(), ...paths);
15
+
16
+ const validateTypescript = async () => {
17
+ const args = process.argv.slice(2);
18
+ const argsProjectIndex = args.findIndex((arg) =>
19
+ ['-p', '--project'].includes(arg),
20
+ );
21
+ const argsProjectValue =
22
+ argsProjectIndex !== -1 ? args[argsProjectIndex + 1] : undefined;
23
+
24
+ const files = args.filter((file) => /\.(ts|tsx)$/.test(file));
25
+ if (files.length === 0) {
26
+ process.exit(0);
27
+ }
28
+
29
+ const remainingArgsToForward = args
30
+ .slice()
31
+ .filter((arg) => !files.includes(arg));
32
+
33
+ if (argsProjectIndex !== -1) {
34
+ remainingArgsToForward.splice(argsProjectIndex, 2);
35
+ }
36
+
37
+ // Load existing config
38
+ const tsconfigPath = argsProjectValue || resolveFromRoot('tsconfig.json');
39
+ const tsconfigContent = fs.readFileSync(tsconfigPath).toString();
40
+ // Use 'eval' to read the JSON as regular JavaScript syntax so that comments are allowed
41
+ // eslint-disable-next-line prefer-const
42
+ let tsconfig = {};
43
+ // eslint-disable-next-line no-eval
44
+ eval(`tsconfig = ${tsconfigContent}`);
45
+
46
+ // Write a temp config file
47
+ const tmpTsconfigPath = resolveFromRoot(`tsconfig.${randomChars()}.json`);
48
+ const tmpTsconfig = {
49
+ ...tsconfig,
50
+ compilerOptions: {
51
+ ...tsconfig.compilerOptions,
52
+ skipLibCheck: true,
53
+ },
54
+ files,
55
+ include: ['shared/typings'],
56
+ };
57
+ fs.writeFileSync(tmpTsconfigPath, JSON.stringify(tmpTsconfig, null, 2));
58
+
59
+ // Type-check our files
60
+ const { status } = spawnSync(
61
+ resolveFromModule(
62
+ 'typescript',
63
+ `../.bin/tsc${process.platform === 'win32' ? '.cmd' : ''}`,
64
+ ),
65
+ ['-p', tmpTsconfigPath, ...remainingArgsToForward],
66
+ { stdio: 'inherit' },
67
+ );
68
+
69
+ // Delete temp config file
70
+ fs.unlinkSync(tmpTsconfigPath);
71
+
72
+ process.exit(status);
73
+ };
74
+
75
+ async function handler(argv) {
76
+ try {
77
+ await validateTypescript(argv.p);
78
+ logInfo('Typescript validation started');
79
+ } catch (err) {
80
+ logError('Typescript validation failed', err);
81
+ exit(-1, err);
82
+ }
83
+ }
84
+
85
+ exports.command = 'tsc [options]';
86
+
87
+ exports.describe = 'validate typescript code';
88
+
89
+ exports.builder = {
90
+ project: {
91
+ alias: 'p',
92
+ type: 'boolean',
93
+ default: false,
94
+ },
95
+ docs: {
96
+ type: 'boolean',
97
+ default: false,
98
+ },
99
+ };
100
+
101
+ exports.handler = handler;
102
+
103
+ exports.validateTypescript = validateTypescript;
@@ -24,10 +24,15 @@ exports.logSuccess = (...args) => console.log(chalk.green(...args));
24
24
  exports.logError = console.error;
25
25
 
26
26
  const readPackageLock = async () => {
27
- const appPkgLockFile = path.join(process.cwd(), 'package-lock.json');
28
- const pkgLockJSON = await readFile(appPkgLockFile, 'utf8');
29
- const { dependencies } = JSON.parse(pkgLockJSON);
30
- return (moduleName) => dependencies[moduleName]?.version || '';
27
+ try {
28
+ const appPkgLockFile = path.join(process.cwd(), 'package-lock.json');
29
+ const pkgLockJSON = await readFile(appPkgLockFile, 'utf8');
30
+ const { dependencies } = JSON.parse(pkgLockJSON);
31
+ return (moduleName) => dependencies[moduleName]?.version || '';
32
+ } catch (err) {
33
+ console.warn('Package lock file not found');
34
+ return () => '';
35
+ }
31
36
  };
32
37
 
33
38
  const getSupportedBrowsers = async () => {
@@ -0,0 +1,66 @@
1
+ const { exit } = require('yargs');
2
+ const path = require('path');
3
+ const { exec, logError, logSuccess } = require('./utils');
4
+
5
+ const { CI = false } = process.env;
6
+
7
+ const configPath = path.resolve(__dirname, '../testing/vitest.config.ts');
8
+
9
+ async function test(commandOptions) {
10
+ await exec(
11
+ `cross-env FORCE_COLOR=true vitest --config ${configPath} ${commandOptions}`,
12
+ );
13
+ }
14
+
15
+ // eslint-disable-next-line max-statements
16
+ async function handler(argv) {
17
+ let commandOptions = '--coverage';
18
+ if (argv.fix) commandOptions = '-u';
19
+ else if (argv.watch) commandOptions = '--watch';
20
+ if (argv.p) commandOptions += ' --passWithNoTests';
21
+ if (argv.r) commandOptions += ' --related';
22
+ if (argv.s) commandOptions += ' --silent';
23
+ try {
24
+ if (CI) {
25
+ await exec('rimraf ./reports');
26
+ }
27
+
28
+ // eslint-disable-next-line jest/valid-title, jest/no-disabled-tests, jest/expect-expect
29
+ await test(commandOptions);
30
+ logSuccess('Unit test execution completed');
31
+ } catch (err) {
32
+ logError('Unit test execution failed', err);
33
+ exit(-1, err);
34
+ return -1;
35
+ }
36
+ return 0;
37
+ }
38
+
39
+ exports.command = 'vitest [options]';
40
+
41
+ exports.describe = 'unit tests application code using vitest';
42
+
43
+ exports.builder = {
44
+ fix: {
45
+ alias: 'f',
46
+ type: 'boolean',
47
+ },
48
+ watch: {
49
+ alias: 'w',
50
+ type: 'boolean',
51
+ },
52
+ passWithNoTests: {
53
+ alias: 'p',
54
+ type: 'boolean',
55
+ },
56
+ related: {
57
+ alias: 'r',
58
+ type: 'boolean',
59
+ },
60
+ silent: {
61
+ alias: 's',
62
+ type: 'boolean',
63
+ },
64
+ };
65
+
66
+ exports.handler = handler;
package/lib/cli.js CHANGED
@@ -12,6 +12,7 @@ const lintCmd = require('./cli-commands/lint');
12
12
  const gendocCmd = require('./cli-commands/gendoc');
13
13
  const codemodCmd = require('./cli-commands/codemod');
14
14
  const storybookCmd = require('./cli-commands/storybook');
15
+ const vitestCmd = require('./cli-commands/vitest');
15
16
 
16
17
  envConfig();
17
18
  process.env.PATH +=
@@ -25,5 +26,6 @@ yargs.command(lintCmd).help().argv;
25
26
  yargs.command(gendocCmd).help().argv;
26
27
  yargs.command(codemodCmd).help().argv;
27
28
  yargs.command(storybookCmd).help().argv;
29
+ yargs.command(vitestCmd).help().argv;
28
30
 
29
31
  notifyUpdates();
package/lib/index.js CHANGED
@@ -4,7 +4,8 @@ const { esReactConfig } = require('./lint/eslint/react');
4
4
  const stylelintConfig = require('./lint/stylelint.config');
5
5
  const prettierConfig = require('./lint/prettier.config');
6
6
  const commitlintConfig = require('./lint/commitlint.config');
7
- const jestConfig = require('./testing/jest.config');
7
+ const { jestConfig } = require('./testing/jest.config');
8
+ const { jestNodeConfig } = require('./testing/jest.node.config');
8
9
  const jsdocConfig = require('./docgen/jsdoc.config');
9
10
  const lintStagedConfig = require('./lint/lint-staged.config');
10
11
  const { loadRoutes } = require('./server/util');
@@ -17,6 +18,7 @@ module.exports = {
17
18
  prettierConfig,
18
19
  commitlintConfig,
19
20
  jestConfig,
21
+ jestNodeConfig,
20
22
  jsdocConfig,
21
23
  lintStagedConfig,
22
24
  loadRoutes,
@@ -4,14 +4,17 @@ const webpackConfig = require('../../webpack/webpack.prod.babel');
4
4
 
5
5
  exports.baseExtends = [
6
6
  'plugin:eslint-comments/recommended',
7
+ 'plugin:import/recommended',
7
8
  'plugin:prettier/recommended',
8
9
  'plugin:jest/recommended',
9
10
  'plugin:jsdoc/recommended',
10
11
  'plugin:wdio/recommended',
11
12
  'plugin:testing-library/dom',
13
+ 'plugin:storybook/recommended',
12
14
  ];
13
15
 
14
- const basePlugins = ['testing-library', 'jest', 'jsdoc', 'wdio'];
16
+ const basePlugins = ['testing-library', 'jest', 'jsdoc', 'wdio', 'import'];
17
+ exports.basePlugins = basePlugins;
15
18
 
16
19
  exports.baseOverrides = [
17
20
  {
@@ -31,17 +34,18 @@ const baseRules = {
31
34
  'import/no-dynamic-require': 0,
32
35
  'import/no-extraneous-dependencies': 0,
33
36
  'import/no-named-as-default': 0,
34
- 'import/no-unresolved': 0, // ToDo: set this to error once this issue is resolved https://github.com/import-js/eslint-plugin-import/issues/1868
37
+ 'import/no-unresolved': [
38
+ 2,
39
+ { caseSensitive: true, caseSensitiveStrict: true },
40
+ ], // Tip: https://github.com/import-js/eslint-plugin-import/issues/1868
35
41
  'import/no-webpack-loader-syntax': 0,
36
42
  'import/prefer-default-export': 0,
37
43
  'import/extensions': [
38
44
  2,
39
- 'ignorePackages',
45
+ 'never',
40
46
  {
41
- js: 'never',
42
- jsx: 'never',
43
- ts: 'never',
44
- tsx: 'never',
47
+ json: 'ignorePackages',
48
+ js: 'ignorePackages',
45
49
  },
46
50
  ],
47
51
  indent: [
@@ -104,7 +108,11 @@ const reactRules = {
104
108
  'react/react-in-jsx-scope': 0,
105
109
  'react/jsx-filename-extension': [
106
110
  1,
107
- { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
111
+ { extensions: ['.js', '.jsx', '.tsx', '.mdx'] },
112
+ ],
113
+ 'react/function-component-definition': [
114
+ 2,
115
+ { namedComponents: 'arrow-function' },
108
116
  ],
109
117
  'redux-saga/no-yield-in-race': 2,
110
118
  'redux-saga/yield-effects': 2,
@@ -1,7 +1,8 @@
1
- const { baseExtends } = require('../common');
1
+ const { baseExtends, basePlugins } = require('../common');
2
2
 
3
3
  exports.tsBaseExtends = [
4
4
  'plugin:@typescript-eslint/recommended',
5
+ 'plugin:import/typescript',
5
6
  'plugin:@typescript-eslint/recommended-requiring-type-checking',
6
7
  ].concat(baseExtends);
7
8
 
@@ -24,6 +25,7 @@ exports.tsBaseRules = {
24
25
  exports.tsBaseConfig = {
25
26
  files: ['*.ts', '*.tsx'],
26
27
  parser: '@typescript-eslint/parser',
28
+ plugins: ['@typescript-eslint'].concat(basePlugins),
27
29
  parserOptions: {
28
30
  tsconfigRootDir: process.cwd(),
29
31
  project: 'tsconfig.json',
@@ -34,5 +36,8 @@ exports.tsBaseConfig = {
34
36
  alwaysTryTypes: true,
35
37
  },
36
38
  },
39
+ 'import/parsers': {
40
+ '@typescript-eslint/parser': ['.ts', '.tsx'],
41
+ },
37
42
  },
38
43
  };
@@ -4,7 +4,7 @@ const { tsBaseExtends, tsBaseRules, tsBaseConfig } = require('./common');
4
4
 
5
5
  exports.tsConfig = {
6
6
  ...tsBaseConfig,
7
- extends: ['airbnb-typescript/base'].concat(tsBaseExtends),
7
+ extends: ['airbnb-base', 'airbnb-typescript/base'].concat(tsBaseExtends),
8
8
  rules: {
9
9
  ...baseRules,
10
10
  ...tsBaseRules,
@@ -4,7 +4,12 @@ const { tsBaseExtends, tsBaseRules, tsBaseConfig } = require('./common');
4
4
 
5
5
  exports.tsReactConfig = {
6
6
  ...tsBaseConfig,
7
- extends: ['airbnb-typescript'].concat(tsBaseExtends),
7
+ extends: [
8
+ 'airbnb',
9
+ 'airbnb/hooks',
10
+ 'plugin:redux-saga/recommended',
11
+ 'airbnb-typescript',
12
+ ].concat(tsBaseExtends),
8
13
  rules: {
9
14
  ...baseRules,
10
15
  ...tsBaseRules,
@@ -1,5 +1,12 @@
1
+ const path = require('path');
2
+
1
3
  module.exports = {
2
- '*.{ts,tsx}': ['tsc-files --noEmit --emitDeclarationOnly false'],
4
+ '*.{ts,tsx}': [
5
+ `node ${path.resolve(
6
+ __dirname,
7
+ '../typescript/tsc-files/index.js',
8
+ )} --noEmit --emitDeclarationOnly false`,
9
+ ],
3
10
  '*.{js,ts,jsx,tsx}': [
4
11
  'npm run lint:fix',
5
12
  'npm run test:staged',
@@ -1,6 +1,5 @@
1
1
  module.exports = {
2
2
  customSyntax: '@stylelint/postcss-css-in-js',
3
- plugins: [],
4
3
  extends: [
5
4
  'stylelint-config-recommended',
6
5
  'stylelint-config-styled-components',
@@ -0,0 +1,18 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+ const { merge } = require('lodash');
4
+
5
+ const baseConfig = {
6
+ esBuild: {
7
+ target: 'es2020',
8
+ },
9
+ };
10
+
11
+ const getPUIConfig = () => {
12
+ const configPath = path.resolve(process.cwd(), './pui.config.js');
13
+ if (!fs.existsSync(configPath)) return baseConfig;
14
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
15
+ return merge(baseConfig, config);
16
+ };
17
+
18
+ exports.getPUIConfig = getPUIConfig;
@@ -60,13 +60,6 @@ const customHost = argv.host || process.env.HOST;
60
60
  const host = customHost || null; // Let http.Server use its default IPv6/4 host
61
61
  const prettyHost = customHost || 'localhost';
62
62
 
63
- // use the gzipped bundle
64
- app.get('*.js', (req, res, next) => {
65
- req.url += '.gz';
66
- res.set('Content-Encoding', 'gzip');
67
- next();
68
- });
69
-
70
63
  // Start your app.
71
64
  app.listen(port, host, async (err) => {
72
65
  if (err) {
@@ -1,5 +1,5 @@
1
1
  const webpack = require('webpack');
2
- const express = require('express');
2
+ const expressStaticGzip = require('express-static-gzip');
3
3
  const webpackDevMiddleware = require('webpack-dev-middleware');
4
4
  const webpackHotMiddleware = require('webpack-hot-middleware');
5
5
  const { sendFileWithCSPNonce } = require('../csp');
@@ -25,7 +25,7 @@ module.exports = function addDevMiddlewares(app, webpackConfig) {
25
25
  heartbeat: 10 * 1000,
26
26
  }),
27
27
  );
28
- app.use(express.static('cdn'));
28
+ app.use(expressStaticGzip('cdn'));
29
29
 
30
30
  const { outputFileSystem } = (middleware || {}).context || {};
31
31
 
@@ -1,6 +1,6 @@
1
1
  const path = require('path');
2
- const express = require('express');
3
2
  const compression = require('compression');
3
+ const expressStaticGzip = require('express-static-gzip');
4
4
  const { sendFileWithCSPNonce } = require('../csp');
5
5
 
6
6
  module.exports = function addProdMiddlewares(app, options) {
@@ -17,8 +17,15 @@ module.exports = function addProdMiddlewares(app, options) {
17
17
  sendFileWithCSPNonce({ outputPath, res });
18
18
  });
19
19
 
20
- app.use(publicPath, express.static(outputPath, { index: false }));
21
- app.use(express.static('cdn'));
20
+ app.use(
21
+ publicPath,
22
+ expressStaticGzip(outputPath, {
23
+ index: false,
24
+ enableBrotli: true,
25
+ orderPreference: ['br'],
26
+ }),
27
+ );
28
+ app.use(expressStaticGzip('cdn'));
22
29
 
23
30
  app.get('*', (req, res) => sendFileWithCSPNonce({ outputPath, res }));
24
31
  };