@elliemae/pui-cli 9.0.0-next.3 → 9.0.0-next.30

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 (122) hide show
  1. package/dist/cjs/commands/lint.js +26 -7
  2. package/dist/cjs/commands/start.js +1 -1
  3. package/dist/cjs/commands/storybook.js +2 -2
  4. package/dist/cjs/commands/test.js +49 -22
  5. package/dist/cjs/commands/utils.js +30 -1
  6. package/dist/cjs/index.js +3 -1
  7. package/dist/cjs/lint-config/eslint/common.cjs +3 -2
  8. package/dist/cjs/lint-config/eslint/typescript/common.cjs +3 -3
  9. package/dist/cjs/lint-config/stylelint.config.cjs +14 -13
  10. package/dist/cjs/monorepo/delete-merged-tags.js +1 -1
  11. package/dist/cjs/monorepo/set-registry-version.js +1 -1
  12. package/dist/cjs/monorepo/set-workspace-version.js +1 -1
  13. package/dist/cjs/server/csp.js +2 -1
  14. package/dist/cjs/server/index.js +5 -0
  15. package/dist/cjs/server/utils.js +11 -4
  16. package/dist/cjs/server/wsServer.js +129 -0
  17. package/dist/cjs/testing/ExtendedJSDomEnv.cjs +27 -0
  18. package/dist/cjs/testing/extended/axe-core/getMessageAndPass.js +37 -0
  19. package/dist/cjs/testing/extended/axe-core/index.js +24 -0
  20. package/dist/cjs/testing/extended/axe-core/reporter.js +51 -0
  21. package/dist/cjs/testing/extended/axe-core/shouldIgnoreNodeViolation.js +31 -0
  22. package/dist/cjs/testing/extended/axe-core/toHaveNoViolations.js +43 -0
  23. package/dist/cjs/testing/jest.config.cjs +5 -2
  24. package/dist/cjs/testing/jest.polyfills.cjs +28 -0
  25. package/dist/cjs/testing/setup-test-env.js +0 -2
  26. package/dist/cjs/testing/setup-tests.js +25 -4
  27. package/dist/cjs/testing/vitest.config.js +8 -8
  28. package/dist/cjs/transpile/esbuild.js +1 -1
  29. package/dist/cjs/update-notifier.js +1 -1
  30. package/dist/cjs/utils.js +1 -1
  31. package/dist/cjs/webpack/helpers.js +18 -6
  32. package/dist/cjs/webpack/webpack.base.babel.js +7 -4
  33. package/dist/cjs/webpack/webpack.dev.babel.js +14 -3
  34. package/dist/cjs/webpack/webpack.lib.base.babel.js +13 -5
  35. package/dist/cjs/webpack/webpack.lib.dev.babel.js +5 -11
  36. package/dist/cjs/webpack/webpack.lib.prod.babel.js +4 -5
  37. package/dist/cjs/webpack/webpack.prod.babel.js +3 -2
  38. package/dist/cjs/webpack/webpack.storybook.js +10 -11
  39. package/dist/esm/commands/lint.js +27 -7
  40. package/dist/esm/commands/start.js +1 -1
  41. package/dist/esm/commands/storybook.js +2 -2
  42. package/dist/esm/commands/test.js +49 -22
  43. package/dist/esm/commands/utils.js +30 -1
  44. package/dist/esm/index.js +3 -1
  45. package/dist/esm/lint-config/eslint/common.cjs +3 -2
  46. package/dist/esm/lint-config/eslint/typescript/common.cjs +3 -3
  47. package/dist/esm/lint-config/stylelint.config.cjs +14 -13
  48. package/dist/esm/monorepo/delete-merged-tags.js +1 -1
  49. package/dist/esm/monorepo/set-registry-version.js +1 -1
  50. package/dist/esm/monorepo/set-workspace-version.js +1 -1
  51. package/dist/esm/server/csp.js +2 -1
  52. package/dist/esm/server/index.js +6 -1
  53. package/dist/esm/server/utils.js +11 -4
  54. package/dist/esm/server/wsServer.js +99 -0
  55. package/dist/esm/testing/ExtendedJSDomEnv.cjs +27 -0
  56. package/dist/esm/testing/extended/axe-core/getMessageAndPass.js +17 -0
  57. package/dist/esm/testing/extended/axe-core/index.js +4 -0
  58. package/dist/esm/testing/extended/axe-core/reporter.js +31 -0
  59. package/dist/esm/testing/extended/axe-core/shouldIgnoreNodeViolation.js +11 -0
  60. package/dist/esm/testing/extended/axe-core/toHaveNoViolations.js +23 -0
  61. package/dist/esm/testing/jest.config.cjs +5 -2
  62. package/dist/esm/testing/jest.polyfills.cjs +28 -0
  63. package/dist/esm/testing/setup-test-env.js +0 -2
  64. package/dist/esm/testing/setup-tests.js +25 -4
  65. package/dist/esm/testing/vitest.config.js +8 -8
  66. package/dist/esm/transpile/esbuild.js +1 -1
  67. package/dist/esm/update-notifier.js +1 -1
  68. package/dist/esm/utils.js +1 -1
  69. package/dist/esm/webpack/helpers.js +18 -6
  70. package/dist/esm/webpack/webpack.base.babel.js +7 -4
  71. package/dist/esm/webpack/webpack.dev.babel.js +14 -3
  72. package/dist/esm/webpack/webpack.lib.base.babel.js +13 -5
  73. package/dist/esm/webpack/webpack.lib.dev.babel.js +6 -12
  74. package/dist/esm/webpack/webpack.lib.prod.babel.js +9 -6
  75. package/dist/esm/webpack/webpack.prod.babel.js +3 -2
  76. package/dist/esm/webpack/webpack.storybook.js +11 -12
  77. package/dist/types/babel.config.d.cts +7 -7
  78. package/dist/types/commands/build.d.ts +2 -2
  79. package/dist/types/commands/codemod.d.ts +2 -2
  80. package/dist/types/commands/lint.d.ts +3 -2
  81. package/dist/types/commands/pack.d.ts +2 -2
  82. package/dist/types/commands/start.d.ts +2 -2
  83. package/dist/types/commands/storybook.d.ts +2 -2
  84. package/dist/types/commands/test.d.ts +4 -2
  85. package/dist/types/commands/tscheck.d.ts +2 -2
  86. package/dist/types/commands/utils.d.ts +23 -1
  87. package/dist/types/commands/version.d.ts +2 -2
  88. package/dist/types/commands/vitest.d.ts +2 -2
  89. package/dist/types/index.d.ts +1 -0
  90. package/dist/types/lint-config/commitlint.config.d.cts +1 -1
  91. package/dist/types/lint-config/eslint/common.d.cts +18 -12
  92. package/dist/types/lint-config/eslint/non-react.d.cts +8 -1
  93. package/dist/types/lint-config/eslint/react.d.cts +8 -1
  94. package/dist/types/lint-config/eslint/typescript/common.d.cts +6 -6
  95. package/dist/types/lint-config/eslint/typescript/non-react.d.cts +9 -2
  96. package/dist/types/lint-config/eslint/typescript/react.d.cts +9 -2
  97. package/dist/types/lint-config/lint-staged.config.d.ts +3 -3
  98. package/dist/types/lint-config/prettier.config.d.cts +6 -6
  99. package/dist/types/lint-config/stylelint.config.d.cts +6 -6
  100. package/dist/types/release.config.d.cts +2 -2
  101. package/dist/types/server/csp.d.ts +2 -2
  102. package/dist/types/server/utils.d.ts +1 -0
  103. package/dist/types/server/wsServer.d.ts +13 -0
  104. package/dist/types/testing/ExtendedJSDomEnv.d.cts +5 -0
  105. package/dist/types/testing/extended/axe-core/getMessageAndPass.d.ts +8 -0
  106. package/dist/types/testing/extended/axe-core/index.d.ts +1 -0
  107. package/dist/types/testing/extended/axe-core/reporter.d.ts +2 -0
  108. package/dist/types/testing/extended/axe-core/shouldIgnoreNodeViolation.d.ts +2 -0
  109. package/dist/types/testing/extended/axe-core/toHaveNoViolations.d.ts +12 -0
  110. package/dist/types/testing/jest.config.d.cts +25 -22
  111. package/dist/types/testing/jest.node.config.d.cts +3 -0
  112. package/dist/types/testing/jest.polyfills.d.cts +1 -0
  113. package/dist/types/testing/mocks/axios.d.ts +7 -7
  114. package/dist/types/testing/mocks/pui-diagnostics.d.ts +13 -13
  115. package/dist/types/testing/vitest.config.d.ts +1 -1
  116. package/dist/types/tests/basic.test.d.ts +0 -0
  117. package/dist/types/transpile/esbuild.d.ts +3 -3
  118. package/dist/types/typedoc.d.cts +3 -3
  119. package/dist/types/webpack/helpers.d.ts +4 -1
  120. package/dist/types/webpack/webpack.storybook.d.ts +0 -1
  121. package/nx.json +97 -0
  122. package/package.json +163 -150
@@ -1,14 +1,24 @@
1
1
  import path from "node:path";
2
+ import { inspect } from "node:util";
2
3
  import yargs from "yargs";
3
4
  import {
4
5
  exec,
6
+ logInfo,
5
7
  logError,
6
8
  logSuccess,
7
9
  getCIEnv,
8
10
  isTypeScriptEnabled
9
11
  } from "./utils.js";
10
- const lintCSS = async (fix = false) => {
11
- const fixIssues = fix ? "--fix" : "";
12
+ const lintCSS = async (args) => {
13
+ const fixIssues = args.fix ? "--fix" : "";
14
+ if (args.debug) {
15
+ const configPath = path.join(process.cwd(), "stylelint.config.cjs");
16
+ const config = await import(configPath);
17
+ logInfo("stylelint version:");
18
+ await exec(`stylelint ./{lib,app}/**/*.{js,jsx,ts,tsx} --version`);
19
+ logInfo("stylelint config:");
20
+ logInfo(inspect(config, { depth: null }));
21
+ }
12
22
  await exec(
13
23
  `stylelint ./{lib,app}/**/*.{js,jsx,ts,tsx} ${fixIssues} ${!getCIEnv() ? "--color" : "--no-color"} --allow-empty-input --config ${path.join(
14
24
  process.cwd(),
@@ -16,10 +26,11 @@ const lintCSS = async (fix = false) => {
16
26
  )}`
17
27
  );
18
28
  };
19
- const lintJS = async (fix = false) => {
20
- const fixIssues = fix ? "--fix" : "";
29
+ const lintJS = async (args) => {
30
+ const fixIssues = args.fix ? "--fix" : "";
31
+ const debugFlags = args.debug ? "--env-info --debug" : "";
21
32
  await exec(
22
- `eslint ${!getCIEnv() ? "--color" : "--no-color"} ${fixIssues} .`
33
+ `eslint ${!getCIEnv() ? "--color" : "--no-color"} ${fixIssues} ${debugFlags} .`
23
34
  );
24
35
  };
25
36
  const cmdArgs = {
@@ -37,6 +48,11 @@ const cmdArgs = {
37
48
  boolean: true,
38
49
  alias: "fix",
39
50
  default: false
51
+ },
52
+ debug: {
53
+ boolean: true,
54
+ alias: "debug",
55
+ default: false
40
56
  }
41
57
  };
42
58
  const lintCmd = {
@@ -46,10 +62,12 @@ const lintCmd = {
46
62
  await exec("tsc --noEmit --emitDeclarationOnly false");
47
63
  try {
48
64
  await exec("rimraf ./reports/eslint.json");
49
- await lintJS(argv.fix);
65
+ await lintJS({ ...argv });
50
66
  logSuccess("JS linting completed");
51
67
  } catch (err) {
52
68
  logError("JS linting failed");
69
+ if (argv.debug)
70
+ logError(err);
53
71
  yargs().exit(-1, err);
54
72
  return;
55
73
  }
@@ -57,10 +75,12 @@ const lintCmd = {
57
75
  if (argv.css) {
58
76
  try {
59
77
  await exec("rimraf ./reports/stylelint.json");
60
- await lintCSS(argv.fix);
78
+ await lintCSS({ ...argv });
61
79
  logSuccess("CSS linting completed");
62
80
  } catch (err) {
63
81
  logError("CSS linting failed");
82
+ if (argv.debug)
83
+ logError(err);
64
84
  yargs().exit(-1, err);
65
85
  }
66
86
  }
@@ -5,7 +5,7 @@ import { exec, logError, logSuccess, isApp } from "./utils.js";
5
5
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
6
  const startProdServer = async () => {
7
7
  await exec(
8
- `cross-env NODE_ENV=production ts-node --esm ${path.resolve(
8
+ `cross-env NODE_ENV=production tsx ${path.resolve(
9
9
  __dirname,
10
10
  "../server/index.js"
11
11
  )} --color always`
@@ -3,12 +3,12 @@ import { exec, logInfo, logError, logSuccess } from "./utils.js";
3
3
  const buildStoryBook = async (outputDir = "demo", isDoc = false) => {
4
4
  const additionalParams = isDoc ? `--docs -o ${outputDir}/docs` : `-o ${outputDir}`;
5
5
  await exec(
6
- `cross-env NODE_ENV=production build-storybook --quiet ${additionalParams}`
6
+ `cross-env NODE_ENV=production storybook build --quiet ${additionalParams}`
7
7
  );
8
8
  };
9
9
  const startStoryBook = async (isDoc = false) => {
10
10
  await exec(
11
- `cross-env NODE_ENV=development STORYBOOK_BUILD=true start-storybook ${isDoc ? "--docs" : ""} -p 11000 --quiet`
11
+ `cross-env STORYBOOK_BUILD=true storybook dev ${isDoc ? "--docs" : ""} -p 11000 --quiet`
12
12
  );
13
13
  };
14
14
  const cmdArgs = {
@@ -1,13 +1,5 @@
1
1
  import yargs from "yargs";
2
2
  import { exec, logError, logSuccess, getCIEnv } from "./utils.js";
3
- const test = async (commandOptions) => {
4
- await exec(`cross-env NODE_ENV=test jest ${commandOptions}`);
5
- };
6
- const debugTest = async () => {
7
- await exec(
8
- `node --inspect-brk ./node_modules/jest-cli/bin/jest.js --runInBand --watch`
9
- );
10
- };
11
3
  const cmdArgs = {
12
4
  fix: {
13
5
  boolean: true,
@@ -38,24 +30,59 @@ const cmdArgs = {
38
30
  boolean: true,
39
31
  alias: "s",
40
32
  default: false
33
+ },
34
+ coverage: {
35
+ string: true,
36
+ // we want to support "CI" | "false" | "true"
37
+ default: "true"
38
+ },
39
+ maxWorkers: {
40
+ string: true,
41
+ default: "50%"
41
42
  }
42
43
  };
44
+ const getJestFlags = (argv) => {
45
+ const flagsArray = [argv.maxWorkers];
46
+ const isCi = getCIEnv();
47
+ switch (`${argv.coverage}`) {
48
+ case "CI":
49
+ if (isCi) {
50
+ flagsArray.push("--coverage");
51
+ }
52
+ break;
53
+ case "false":
54
+ break;
55
+ case "true":
56
+ default:
57
+ flagsArray.push("--coverage");
58
+ break;
59
+ }
60
+ if (argv.fix)
61
+ flagsArray.push("-u");
62
+ else if (argv.watch)
63
+ flagsArray.push("--watchAll");
64
+ if (argv.passWithNoTests)
65
+ flagsArray.push("--passWithNoTests");
66
+ if (argv.findReleatedTests)
67
+ flagsArray.push("--bail --findRelatedTests");
68
+ if (argv.silent)
69
+ flagsArray.push("--silent");
70
+ if (isCi)
71
+ flagsArray.push("--ci --no-colors");
72
+ return flagsArray.join(" ");
73
+ };
74
+ const test = async (argv) => {
75
+ const jestFlags = getJestFlags(argv);
76
+ await exec(`cross-env NODE_ENV=test jest ${jestFlags}`);
77
+ };
78
+ const debugTest = async () => {
79
+ await exec(
80
+ `node --inspect-brk ./node_modules/jest-cli/bin/jest.js --runInBand --watch`
81
+ );
82
+ };
43
83
  const testCmd = {
44
84
  // eslint-disable-next-line max-statements
45
85
  handler: async (argv) => {
46
- let commandOptions = "--coverage --maxWorkers=50%";
47
- if (argv.fix)
48
- commandOptions = "-u";
49
- else if (argv.watch)
50
- commandOptions = "--watchAll";
51
- if (getCIEnv())
52
- commandOptions += " --ci --no-colors";
53
- if (argv.passWithNoTests)
54
- commandOptions += " --passWithNoTests";
55
- if (argv.findReleatedTests)
56
- commandOptions += " --bail --findRelatedTests";
57
- if (argv.silent)
58
- commandOptions += " --silent";
59
86
  try {
60
87
  if (getCIEnv()) {
61
88
  await exec("rimraf ./reports");
@@ -63,7 +90,7 @@ const testCmd = {
63
90
  if (argv.debug) {
64
91
  await debugTest();
65
92
  } else {
66
- await test(commandOptions);
93
+ await test(argv);
67
94
  }
68
95
  logSuccess("Unit test execution completed");
69
96
  } catch (err) {
@@ -31,6 +31,7 @@ const browsersMapping = {
31
31
  };
32
32
  const exec = async (command, options = { stdio: "inherit" }) => execaCommand(command, options);
33
33
  const logInfo = console.log;
34
+ const logWarning = (...args) => console.log(chalk.yellow(...args));
34
35
  const logSuccess = (...args) => console.log(chalk.green(...args));
35
36
  const logError = console.error;
36
37
  const readPackageLock = async () => {
@@ -52,7 +53,7 @@ const getSupportedBrowsers = async () => {
52
53
  return browserVersions.reduce((acc, nameVersion) => {
53
54
  const [name, version] = nameVersion.split(" ");
54
55
  const versionRange = version.split("-");
55
- acc[browsersMapping[name]] = versionRange && versionRange[0] || version;
56
+ acc[browsersMapping[name]] = versionRange?.[0] ?? version;
56
57
  return acc;
57
58
  }, {});
58
59
  };
@@ -176,15 +177,43 @@ const isPathExist = async (pathToCheck) => {
176
177
  const isApp = async () => isPathExist(path.join(process.cwd(), "app"));
177
178
  const getCIEnv = () => process.env.CI === "true";
178
179
  const isTypeScriptEnabled = () => fs.existsSync(path.join(process.cwd(), "tsconfig.json"));
180
+ const getUnspecifiedOptions = (options, command) => {
181
+ const rawArgs = process.argv.slice(2);
182
+ const rawArgsMap = /* @__PURE__ */ new Map();
183
+ rawArgs.forEach((arg) => {
184
+ const [key, value] = arg.split("=");
185
+ const keyWithoutPrefix = key.replace(/^-{1,2}/, "");
186
+ rawArgsMap.set(keyWithoutPrefix, value || true);
187
+ });
188
+ const expectedOptionsMap = /* @__PURE__ */ new Map();
189
+ Object.entries(options).forEach(([key, value]) => {
190
+ expectedOptionsMap.set(key, value);
191
+ if (value.alias)
192
+ expectedOptionsMap.set(value.alias, value);
193
+ });
194
+ const unspecifiedOptions = {};
195
+ rawArgsMap.forEach((value, key) => {
196
+ if (key === command)
197
+ return;
198
+ if (key === "")
199
+ return;
200
+ if (!expectedOptionsMap.has(key)) {
201
+ unspecifiedOptions[key] = value;
202
+ }
203
+ });
204
+ return unspecifiedOptions;
205
+ };
179
206
  export {
180
207
  copyBuildAssetsToVersionedFolder,
181
208
  exec,
182
209
  getCIEnv,
210
+ getUnspecifiedOptions,
183
211
  isApp,
184
212
  isPathExist,
185
213
  isTypeScriptEnabled,
186
214
  logError,
187
215
  logInfo,
188
216
  logSuccess,
217
+ logWarning,
189
218
  writeAppInfo
190
219
  };
package/dist/esm/index.js CHANGED
@@ -9,6 +9,7 @@ import { vitestConfig } from "./testing/vitest.config.js";
9
9
  import { jestNodeConfig } from "./testing/jest.node.config.cjs";
10
10
  import { lintStagedConfig } from "./lint-config/lint-staged.config.js";
11
11
  import { loadRoutes } from "./server/appRoutes.js";
12
+ import { webpackFinal } from "./webpack/webpack.storybook.js";
12
13
  export {
13
14
  babelConfig,
14
15
  commitlintConfig,
@@ -20,5 +21,6 @@ export {
20
21
  loadRoutes,
21
22
  prettierConfig,
22
23
  stylelintConfig,
23
- vitestConfig
24
+ vitestConfig,
25
+ webpackFinal
24
26
  };
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable max-lines */
2
- const prettierOptions = require("../prettier.config.cjs");
2
+ const { prettierConfig } = require("../prettier.config.cjs");
3
3
  // const webpackConfig = require('../../webpack/webpack.prod.babel');
4
4
 
5
5
  exports.baseExtends = [
@@ -26,7 +26,7 @@ exports.baseOverrides = [
26
26
  ];
27
27
 
28
28
  const baseRules = {
29
- "prettier/prettier": ["error", prettierOptions],
29
+ "prettier/prettier": ["error", prettierConfig],
30
30
  "arrow-body-style": [2, "as-needed"],
31
31
  "class-methods-use-this": 0,
32
32
  "import/imports-first": 0,
@@ -152,6 +152,7 @@ exports.baseConfig = {
152
152
  },
153
153
  ignorePatterns: [
154
154
  "/build/**/*",
155
+ "/node_modules/**/*",
155
156
  "/dist/**/*",
156
157
  "/reports/**/*",
157
158
  "/coverage/**/*",
@@ -1,9 +1,9 @@
1
1
  const { baseExtends, basePlugins } = require('../common.cjs');
2
2
 
3
3
  exports.tsBaseExtends = [
4
- 'plugin:@typescript-eslint/recommended',
5
4
  'plugin:import/typescript',
6
- 'plugin:@typescript-eslint/recommended-requiring-type-checking',
5
+ 'plugin:@typescript-eslint/recommended-type-checked',
6
+ 'plugin:@typescript-eslint/stylistic-type-checked',
7
7
  ].concat(baseExtends);
8
8
 
9
9
  exports.tsBaseRules = {
@@ -34,7 +34,7 @@ exports.tsBaseConfig = {
34
34
  plugins: ['@typescript-eslint'].concat(basePlugins),
35
35
  parserOptions: {
36
36
  tsconfigRootDir: process.cwd(),
37
- project: 'tsconfig.json',
37
+ project: true,
38
38
  },
39
39
  settings: {
40
40
  'import/resolver': {
@@ -1,19 +1,20 @@
1
1
  exports.stylelintConfig = {
2
2
  ignoreFiles: [
3
- '/dist/**/*',
4
- '/coverage/**/*',
5
- '/build/**/*',
6
- '/reports/**/*',
7
- '/temp/**/*',
8
- '/docs/**/*',
9
- '/demo/**/*',
10
- '/node_modules/**/*',
11
- '/vendor/**/*',
3
+ "/dist/**/*",
4
+ "/coverage/**/*",
5
+ "/build/**/*",
6
+ "/reports/**/*",
7
+ "/temp/**/*",
8
+ "/docs/**/*",
9
+ "/demo/**/*",
10
+ "/node_modules/**/*",
11
+ "/vendor/**/*",
12
12
  ],
13
- customSyntax: '@stylelint/postcss-css-in-js',
13
+ customSyntax: "@stylelint/postcss-css-in-js",
14
+ // customSyntax: "postcss-styled-components", // '@stylelint/postcss-css-in-js' is deprecated, this may be a replacement?
14
15
  extends: [
15
- 'stylelint-config-recommended',
16
- 'stylelint-config-styled-components',
16
+ "stylelint-config-recommended",
17
+ "stylelint-config-styled-components",
17
18
  ],
18
- rules: { 'selector-type-no-unknown': null, 'function-no-unknown': null },
19
+ rules: { "selector-type-no-unknown": null, "function-no-unknown": null },
19
20
  };
@@ -3,7 +3,7 @@ const cwd = process.cwd();
3
3
  const execaOptions = { cwd, stdio: "inherit" };
4
4
  const semVerRegEx = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
5
5
  const isSemVersion = (tagName) => semVerRegEx.test(tagName);
6
- const branchName = (process.env.BRANCH_NAME || "master").toLowerCase();
6
+ const branchName = (process.env.BRANCH_NAME ?? "master").toLowerCase();
7
7
  const branchTags = {
8
8
  master: /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/,
9
9
  next: /^v.*-next\.(0|[1-9]\d*)/,
@@ -2,7 +2,7 @@ import { readFile, writeFile } from "node:fs/promises";
2
2
  import fg from "fast-glob";
3
3
  import normalizePath from "normalize-path";
4
4
  import { findMonoRepoRoot } from "./utils.js";
5
- const monorepoRoot = normalizePath(findMonoRepoRoot() || "");
5
+ const monorepoRoot = normalizePath(findMonoRepoRoot() ?? "");
6
6
  const setRegistryVersion = async () => {
7
7
  const files = await fg([
8
8
  `${monorepoRoot}/libs/*/package.json`,
@@ -2,7 +2,7 @@ import { readFile, writeFile } from "node:fs/promises";
2
2
  import fg from "fast-glob";
3
3
  import normalizePath from "normalize-path";
4
4
  import { findMonoRepoRoot } from "./utils.js";
5
- const monorepoRoot = normalizePath(findMonoRepoRoot() || "");
5
+ const monorepoRoot = normalizePath(findMonoRepoRoot() ?? "");
6
6
  const setWorkspaceVersion = async () => {
7
7
  const files = await fg([
8
8
  `${monorepoRoot}/libs/*/package.json`,
@@ -1,12 +1,13 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import crypto from "crypto";
3
4
  import express from "express";
4
5
  import cspPolicy from "helmet-csp";
5
- import crypto from "crypto";
6
6
  const CSP_REPORT_URI = "/diagnostics/v1/csp";
7
7
  const sources = [
8
8
  "'self'",
9
9
  "http://localhost:*",
10
+ "ws://localhost:*",
10
11
  "*.elliemae.io",
11
12
  "*.elliemae.com",
12
13
  "*.elliservices.com",
@@ -4,8 +4,9 @@ import {
4
4
  setupDefaultMiddlewares,
5
5
  setupAdditionalMiddlewars
6
6
  } from "./middlewares.js";
7
- import { port, host } from "./utils.js";
7
+ import { port, wsPort, host } from "./utils.js";
8
8
  import { loadRoutes } from "./appRoutes.js";
9
+ import { createWSServer } from "./wsServer.js";
9
10
  (async function startServer() {
10
11
  const app = express();
11
12
  setupDefaultMiddlewares(app);
@@ -17,4 +18,8 @@ import { loadRoutes } from "./appRoutes.js";
17
18
  logger.error(err);
18
19
  process.exit(1);
19
20
  });
21
+ const { wsServer } = await createWSServer({
22
+ port: wsPort
23
+ });
24
+ app.locals.wsServer = wsServer;
20
25
  })();
@@ -1,13 +1,20 @@
1
1
  import minimist from "minimist";
2
- const argv = minimist(process.argv.slice(2));
2
+ const argv = minimist(
3
+ process.argv.slice(2)
4
+ );
3
5
  const getCWD = () => process.cwd();
4
6
  const port = parseInt(
5
- argv.port || process.env.port || process.env.PORT || "3000",
7
+ argv.port ?? process.env.port ?? process.env.PORT ?? "3000",
8
+ 10
9
+ );
10
+ const host = argv.host ?? process.env.HOST ?? "localhost";
11
+ const wsPort = parseInt(
12
+ argv.wsport ?? process.env.wsport ?? process.env.WSPORT ?? "5000",
6
13
  10
7
14
  );
8
- const host = argv.host || process.env.HOST || "localhost";
9
15
  export {
10
16
  getCWD,
11
17
  host,
12
- port
18
+ port,
19
+ wsPort
13
20
  };
@@ -0,0 +1,99 @@
1
+ import http from "node:http";
2
+ import * as wsLib from "ws";
3
+ const PING_INTERVAL = 3e4;
4
+ const DEFAULT_PORT = 5001;
5
+ const onSocketError = (err) => {
6
+ console.error(err);
7
+ };
8
+ const authenticate = (token, cb) => {
9
+ if (!token)
10
+ cb(4401);
11
+ else
12
+ cb();
13
+ };
14
+ const getAuthToken = (protocols) => {
15
+ const authProtocol = protocols.find(
16
+ (protocol) => protocol.startsWith("auth--")
17
+ );
18
+ if (!authProtocol)
19
+ return "";
20
+ return authProtocol.split("--")[1]?.trim?.();
21
+ };
22
+ const createWSServer = ({
23
+ port = DEFAULT_PORT,
24
+ pingInterval = PING_INTERVAL,
25
+ onOpen
26
+ }) => {
27
+ let isAlive = false;
28
+ const heartbeat = () => {
29
+ isAlive = true;
30
+ };
31
+ const httpServer = http.createServer();
32
+ const wsServer = new wsLib.WebSocketServer({ noServer: true });
33
+ httpServer.on("upgrade", (req, socket, head) => {
34
+ socket.on("error", onSocketError);
35
+ wsServer.handleUpgrade(req, socket, head, (ws) => {
36
+ const protocols = req.headers["sec-websocket-protocol"]?.split(",");
37
+ if (!protocols) {
38
+ console.error("no protocols");
39
+ ws.close(4401, "unauthorized");
40
+ socket.destroy();
41
+ socket.removeListener("error", onSocketError);
42
+ return;
43
+ }
44
+ authenticate(getAuthToken(protocols) || "", (errCode) => {
45
+ if (errCode) {
46
+ switch (errCode) {
47
+ case 4401:
48
+ ws.close(errCode, "unauthorized");
49
+ break;
50
+ default:
51
+ ws.close(4400, "Unknown error");
52
+ break;
53
+ }
54
+ socket.destroy();
55
+ socket.removeListener("error", onSocketError);
56
+ } else {
57
+ socket.removeListener("error", onSocketError);
58
+ wsServer.emit("connection", ws, req);
59
+ }
60
+ });
61
+ });
62
+ });
63
+ wsServer.on("connection", (ws) => {
64
+ isAlive = true;
65
+ ws.on("error", console.error);
66
+ ws.on("pong", () => {
67
+ heartbeat();
68
+ });
69
+ ws.on("message", (message) => {
70
+ console.log(
71
+ "message from client:",
72
+ JSON.parse(message)
73
+ );
74
+ ws.send(JSON.stringify(JSON.parse(message)));
75
+ });
76
+ console.log("client connected");
77
+ onOpen?.(ws);
78
+ });
79
+ const interval = setInterval(() => {
80
+ wsServer.clients.forEach((ws) => {
81
+ if (isAlive === false)
82
+ ws.terminate();
83
+ isAlive = false;
84
+ ws.ping();
85
+ });
86
+ }, pingInterval);
87
+ wsServer.on("close", function close() {
88
+ clearInterval(interval);
89
+ });
90
+ return new Promise((resolve) => {
91
+ httpServer.listen(port, () => {
92
+ console.log(`Websocket server listening on port ${port}`);
93
+ return resolve({ httpServer, wsServer });
94
+ });
95
+ });
96
+ };
97
+ export {
98
+ createWSServer
99
+ };
@@ -0,0 +1,27 @@
1
+ const { TestEnvironment } = require('jest-environment-jsdom');
2
+
3
+ // ICE platform is meant to be run on node > 18
4
+ // "jest-environment-jsdom": "~29.6.3" is instead meant to support node >16
5
+ // features that are supported since node 17 & 18 are not supported in jsdom env
6
+ // the limitation is not relevant for us since we are already running on node 18 anyway,
7
+ // this "ExtendedJSDomEnv" is an extension of the
8
+ // jest.config.cjs
9
+ // {
10
+ // ...
11
+ // testEnvironment: 'jsdom'
12
+ // ...
13
+ // }
14
+ // that actually uses node 18 features that are not supported in "jest-environment-jsdom": "~29.6.3"
15
+
16
+ // https://github.com/facebook/jest/blob/v29.4.3/website/versioned_docs/version-29.4/Configuration.md#testenvironment-string
17
+ class FixJSDOMEnvironment extends TestEnvironment {
18
+ constructor(...args) {
19
+ super(...args);
20
+
21
+ // From here on we are using "node" (currently running version of it) to polyfill jsdom this.global
22
+
23
+ // FIXME https://github.com/jsdom/jsdom/issues/3363
24
+ if (structuredClone) this.global.structuredClone = structuredClone;
25
+ }
26
+ }
27
+ module.exports = FixJSDOMEnvironment;
@@ -0,0 +1,17 @@
1
+ import { matcherHint } from "jest-matcher-utils";
2
+ import { reporter } from "./reporter.js";
3
+ const getMessageAndPass = (violations) => {
4
+ const formatedViolations = reporter(violations);
5
+ const pass = formatedViolations.length === 0;
6
+ if (pass)
7
+ return { message: () => "", pass };
8
+ return {
9
+ message: () => `${matcherHint(".toHaveNoViolations")}
10
+
11
+ ${formatedViolations}`,
12
+ pass
13
+ };
14
+ };
15
+ export {
16
+ getMessageAndPass
17
+ };
@@ -0,0 +1,4 @@
1
+ import { toHaveNoViolations } from "./toHaveNoViolations.js";
2
+ export {
3
+ toHaveNoViolations
4
+ };
@@ -0,0 +1,31 @@
1
+ import { printReceived } from "jest-matcher-utils";
2
+ const colorYellow = (arg) => `\x1B[93m ${arg ?? ""} \x1B[0m`;
3
+ const colorGrey = (arg) => `\x1B[90m ${arg ?? ""} \x1B[0m`;
4
+ const colorBlue = (arg) => `\x1B[34m ${arg ?? ""} \x1B[0m`;
5
+ const reporter = (violToFormat) => {
6
+ if (violToFormat.length === 0)
7
+ return "";
8
+ const lineBreak = "\n\n";
9
+ const horizontalLine = "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500";
10
+ return violToFormat.map((violation) => {
11
+ const errorBody = violation.nodes.map((node) => {
12
+ const selector = node.target.join(", ");
13
+ const expectedText = `Expected the HTML found at $('${selector}') to have no violations:${lineBreak}`;
14
+ let violationHelpUrl = "";
15
+ if (violation.helpUrl)
16
+ violationHelpUrl = `You can find more information on this issue here:
17
+ ${colorBlue(
18
+ violation.helpUrl
19
+ )}`;
20
+ return `${expectedText + colorGrey(node.html) + lineBreak}Received:${lineBreak}${printReceived(
21
+ `${violation.help} (${violation.id})`
22
+ )}${lineBreak}${colorYellow(
23
+ node.failureSummary
24
+ )}${lineBreak}${violationHelpUrl}`;
25
+ }).join(lineBreak);
26
+ return errorBody;
27
+ }).join(lineBreak + horizontalLine + lineBreak);
28
+ };
29
+ export {
30
+ reporter
31
+ };
@@ -0,0 +1,11 @@
1
+ const dataAttributeRegexp = /(data-[\S]*)=["']([\S]*)["']/gm;
2
+ const shouldIgnoreNodeViolation = (node, violation) => [...node.html.matchAll(dataAttributeRegexp)].map(([fullMatch, dataKey, dataValue]) => ({
3
+ fullMatch,
4
+ dataKey,
5
+ dataValue
6
+ })).some(
7
+ ({ dataKey, dataValue }) => dataKey === `data-axe-ignore-${violation.id}` && dataValue === "true"
8
+ );
9
+ export {
10
+ shouldIgnoreNodeViolation
11
+ };
@@ -0,0 +1,23 @@
1
+ import { getMessageAndPass } from "./getMessageAndPass.js";
2
+ import { shouldIgnoreNodeViolation } from "./shouldIgnoreNodeViolation.js";
3
+ const toHaveNoViolations = {
4
+ toHaveNoViolations(results) {
5
+ const { violations } = results;
6
+ const finalViolations = [];
7
+ violations.forEach((violation) => {
8
+ const { nodes } = violation;
9
+ const newNodes = [];
10
+ nodes.forEach((node) => {
11
+ if (!shouldIgnoreNodeViolation(node, violation))
12
+ newNodes.push(node);
13
+ });
14
+ if (newNodes.length > 0) {
15
+ finalViolations.push({ ...violation, nodes: newNodes });
16
+ }
17
+ });
18
+ return { actual: violations, ...getMessageAndPass(finalViolations) };
19
+ }
20
+ };
21
+ export {
22
+ toHaveNoViolations
23
+ };