@elliemae/pui-cli 6.0.0-beta.9 → 6.0.0
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.
- package/README.md +8 -0
- package/lib/cli-commands/build.js +11 -5
- package/lib/cli-commands/pack.js +18 -78
- package/lib/cli-commands/test.js +1 -12
- package/lib/cli-commands/tsc.js +103 -0
- package/lib/cli-commands/utils.js +9 -4
- package/lib/cli-commands/vitest.js +66 -0
- package/lib/cli.js +2 -0
- package/lib/index.js +2 -0
- package/lib/lint/eslint/common.js +16 -8
- package/lib/lint/eslint/typescript/common.js +6 -1
- package/lib/lint/eslint/typescript/non-react.js +1 -1
- package/lib/lint/eslint/typescript/react.js +6 -1
- package/lib/lint/lint-staged.config.js +8 -1
- package/lib/lint/stylelint.config.js +0 -1
- package/lib/pui-config/index.js +18 -0
- package/lib/server/index.js +0 -7
- package/lib/server/middlewares/addDevMiddlewares.js +2 -2
- package/lib/server/middlewares/addProdMiddlewares.js +10 -3
- package/lib/testing/jest.config.js +16 -7
- package/lib/testing/jest.node.config.js +6 -0
- package/lib/testing/mocks/matchMedia.js +12 -6
- package/lib/testing/mocks/pui-app-loader.js +1 -3
- package/lib/testing/mocks/pui-diagnostics.js +27 -35
- package/lib/testing/mocks/pui-user-monitoring.js +3 -5
- package/lib/testing/mocks/retry-axios.js +3 -5
- package/lib/testing/mocks/webpack-hmr.js +1 -0
- package/lib/testing/resolver.js +47 -0
- package/lib/testing/setup-react-env.js +3 -0
- package/lib/testing/setup-tests.js +28 -4
- package/lib/testing/vitest.config.ts +16 -0
- package/lib/testing/vitest.setup.ts +0 -0
- package/lib/transpile/.swcrc +11 -0
- package/lib/transpile/esbuild.js +110 -0
- package/lib/transpile/react-shim.js +2 -0
- package/lib/transpile/swcrc.config.js +13 -0
- package/lib/typescript/tsc-files/index.js +66 -0
- package/lib/typescript/tsc-files/utils.js +16 -0
- package/lib/webpack/helpers.js +44 -3
- package/lib/webpack/webpack.base.babel.js +44 -71
- package/lib/webpack/webpack.dev.babel.js +16 -10
- package/lib/webpack/webpack.lib.base.babel.js +31 -46
- package/lib/webpack/webpack.lib.dev.babel.js +2 -3
- package/lib/webpack/webpack.lib.prod.babel.js +5 -11
- package/lib/webpack/webpack.prod.babel.js +29 -24
- package/lib/webpack/webpack.storybook.js +16 -88
- package/package.json +114 -122
- package/lib/esbuild.js +0 -44
- 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
|
|
24
|
-
|
|
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: {
|
package/lib/cli-commands/pack.js
CHANGED
|
@@ -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
|
|
12
|
-
logInfo('
|
|
13
|
-
await exec('tsc');
|
|
14
|
-
|
|
15
|
-
}
|
|
7
|
+
const compileTypeScript = async () => {
|
|
8
|
+
logInfo('Generating types...');
|
|
9
|
+
await exec('tsc --emitDeclarationOnly');
|
|
10
|
+
logInfo('Types generation completed...');
|
|
11
|
+
};
|
|
16
12
|
|
|
17
|
-
async
|
|
18
|
-
logInfo('
|
|
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
|
-
|
|
23
|
-
|
|
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
|
|
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('
|
|
64
|
-
|
|
65
|
-
|
|
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
|
|
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',
|
package/lib/cli-commands/test.js
CHANGED
|
@@ -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 (
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
@@ -5,6 +5,7 @@ const stylelintConfig = require('./lint/stylelint.config');
|
|
|
5
5
|
const prettierConfig = require('./lint/prettier.config');
|
|
6
6
|
const commitlintConfig = require('./lint/commitlint.config');
|
|
7
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':
|
|
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
|
-
'
|
|
45
|
+
'never',
|
|
40
46
|
{
|
|
41
|
-
|
|
42
|
-
|
|
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', '.
|
|
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: [
|
|
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}': [
|
|
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',
|
|
@@ -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;
|
package/lib/server/index.js
CHANGED
|
@@ -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
|
|
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(
|
|
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(
|
|
21
|
-
|
|
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
|
};
|