@elliemae/pui-cli 9.0.0-next.68 → 9.0.0-next.69

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.
@@ -3,6 +3,7 @@ import { existsSync } from "node:fs";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import globals from "globals";
5
5
  import eslint from "@eslint/js";
6
+ import { defineConfig } from "eslint/config";
6
7
  import { FlatCompat } from "@eslint/eslintrc";
7
8
  import { includeIgnoreFile } from "@eslint/compat";
8
9
  import tseslint from "typescript-eslint";
@@ -23,210 +24,201 @@ const gitignorePath = path.resolve(process.cwd(), ".gitignore");
23
24
  const compat = new FlatCompat({
24
25
  baseDirectory: __dirname
25
26
  });
26
- const ignores = {
27
- ignores: [
28
- "build/*",
29
- "**/node_modules/",
30
- "dist/*",
31
- "reports/*",
32
- "allure-report/*",
33
- "public/*",
34
- "webroot/*",
35
- "cdn/*",
36
- ".tmp/*",
37
- "coverage/*",
38
- "demo/*",
39
- "docs/*",
40
- "temp/*",
41
- "**/vendor/*.js",
42
- ".docusaurus/*",
43
- ".scannerwork/*",
44
- ".DS_Store/*",
45
- ".nx/*",
46
- ".idea/*",
47
- "*.tgz",
48
- "npm-debug.log",
49
- "stats.json",
50
- "!.storybook"
51
- ]
52
- };
53
- const options = {
54
- languageOptions: {
55
- ecmaVersion: "latest",
56
- sourceType: "module",
57
- globals: {
58
- ...globals.builtin,
59
- ...globals.browser,
60
- ...globals.es2021,
61
- ...globals.nodeBuiltin,
62
- ...globals.node,
63
- ...globals.serviceworker,
64
- ...globals.jest,
65
- ...globals.commonjs,
66
- browser: true,
67
- $: true
68
- },
69
- parserOptions: {
70
- ecmaVersion: "latest",
71
- sourceType: "module",
72
- ecmaFeatures: {
73
- jsx: true
74
- },
75
- project: true,
76
- projectService: true,
77
- tsconfigRootDir: process.cwd()
78
- }
79
- },
80
- settings: {
81
- react: {
82
- version: "detect",
83
- pragma: "React"
84
- },
85
- jest: {
86
- version: "detect"
87
- },
88
- "import-x/parsers": {
89
- espree: [".js", ".cjs", ".mjs", ".jsx"]
90
- },
91
- // "import-x/resolver": {
92
- // node: {
93
- // extensions: [".js", ".jsx", ".ts", ".tsx"],
94
- // },
95
- // typescript: true,
96
- // },
97
- "import/resolver-next": [
98
- createTypeScriptImportResolver({
99
- alwaysTryTypes: true
100
- })
101
- ]
102
- }
103
- };
104
- const e2eTestConfig = {
105
- files: ["**/*.func.spec.{js,ts}", "**/*.visual.spec.{js,ts}"],
106
- extends: [wdioConfig["flat/recommended"]],
107
- rules: {
108
- "jest/valid-expect": "off"
109
- }
110
- };
111
- const jestConfig = {
112
- files: ["**/*.test.{js,jsx,ts,tsx}", "**/testing/**/*.{js,jsx,ts,tsx}"],
113
- extends: [
114
- jest.configs["flat/recommended"],
115
- jest.configs["flat/style"],
116
- testingLibraryConfig.configs["flat/dom"],
117
- testingLibraryConfig.configs["flat/react"]
118
- ]
119
- };
120
- const sbConfig = {
121
- files: ["**/*.stories.{js,jsx,ts,tsx,mdx}"],
122
- extends: [storybookConfig.configs["flat/recommended"]]
123
- };
124
- const jsRulesConfig = {
125
- rules: {
126
- complexity: ["error", { max: 10 }],
127
- "import-x/no-named-as-default-member": "off",
128
- "import-x/no-named-as-default": "off",
129
- "import-x/no-unresolved": [
130
- "error",
131
- { caseSensitive: true, caseSensitiveStrict: true }
132
- ],
133
- "import-x/extensions": [
134
- "error",
135
- "never",
136
- {
137
- json: "ignorePackages",
138
- js: "ignorePackages"
139
- }
140
- ],
141
- "max-depth": ["error", { max: 4 }],
142
- "max-nested-callbacks": ["error", { max: 3 }],
143
- "max-params": ["error", { max: 3 }],
144
- "max-statements": ["error", { max: 20 }],
145
- "no-console": "warn",
146
- "no-param-reassign": ["error", { props: false }],
147
- "no-unused-vars": "off",
148
- "prefer-template": "error"
149
- }
150
- };
151
- const tsConfig = {
152
- ignores: ["**/*.{js,jsx,mjs,cjs,mdx,md}"],
153
- extends: [
154
- tseslint.configs.recommendedTypeChecked,
155
- tseslint.configs.stylisticTypeChecked
156
- ],
157
- rules: {
158
- "@typescript-eslint/no-unused-vars": [
159
- "error",
160
- {
161
- args: "all",
162
- argsIgnorePattern: "^_",
163
- caughtErrors: "all",
164
- caughtErrorsIgnorePattern: "^_",
165
- destructuredArrayIgnorePattern: "^_",
166
- varsIgnorePattern: "^_",
167
- ignoreRestSiblings: true
168
- }
169
- ],
170
- "@typescript-eslint/unbound-method": [
171
- "error",
172
- {
173
- ignoreStatic: true
174
- }
175
- ]
176
- }
177
- };
178
- const reactConfig = {
179
- files: ["**/*.{jsx,tsx}"],
180
- extends: [
181
- reactPlugin.configs.flat.recommended,
182
- reactPlugin.configs.flat["jsx-runtime"],
183
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
184
- jsxA11yConfig.flatConfigs.recommended,
185
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment
186
- ...compat.extends("plugin:redux-saga/recommended")
187
- ],
188
- languageOptions: {
189
- ...reactPlugin.configs.flat.recommended.languageOptions
190
- },
191
- plugins: {
192
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
193
- "react-hooks": reactHookPlugin
194
- },
195
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
196
- rules: {
197
- "react/prop-types": ["error", { skipUndeclared: true }],
198
- "react/display-name": "off",
199
- "react/function-component-definition": [
200
- 2,
201
- { namedComponents: "arrow-function" }
202
- ],
203
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
204
- ...reactHookPlugin.configs.recommended.rules
205
- }
206
- };
207
27
  const gitignoreExists = existsSync(gitignorePath);
208
- const tseslintConfigArgs = [ignores];
28
+ let gitIgnoreConfig = {};
209
29
  if (gitignoreExists) {
210
- tseslintConfigArgs.push(includeIgnoreFile(gitignorePath));
30
+ gitIgnoreConfig = includeIgnoreFile(gitignorePath) ?? {};
211
31
  }
212
- tseslintConfigArgs.push(
32
+ const config = defineConfig([
33
+ gitIgnoreConfig,
34
+ {
35
+ ignores: [
36
+ "build/*",
37
+ "**/node_modules/",
38
+ "dist/*",
39
+ "reports/*",
40
+ "allure-report/*",
41
+ "public/*",
42
+ "webroot/*",
43
+ "cdn/*",
44
+ ".tmp/*",
45
+ "coverage/*",
46
+ "demo/*",
47
+ "docs/*",
48
+ "temp/*",
49
+ "**/vendor/*.js",
50
+ ".docusaurus/*",
51
+ ".scannerwork/*",
52
+ ".DS_Store/*",
53
+ ".nx/*",
54
+ ".idea/*",
55
+ "*.tgz",
56
+ "npm-debug.log",
57
+ "stats.json",
58
+ "!.storybook"
59
+ ]
60
+ },
213
61
  {
214
62
  ignores: ["**/*.stories.mdx"],
215
63
  extends: [mdx.flat]
216
64
  },
217
65
  eslint.configs.recommended,
218
- tsConfig,
66
+ {
67
+ ignores: ["**/*.{js,jsx,mjs,cjs,mdx,md}"],
68
+ extends: [
69
+ tseslint.configs.recommendedTypeChecked,
70
+ tseslint.configs.stylisticTypeChecked
71
+ ],
72
+ rules: {
73
+ "@typescript-eslint/no-unused-vars": [
74
+ "error",
75
+ {
76
+ args: "all",
77
+ argsIgnorePattern: "^_",
78
+ caughtErrors: "all",
79
+ caughtErrorsIgnorePattern: "^_",
80
+ destructuredArrayIgnorePattern: "^_",
81
+ varsIgnorePattern: "^_",
82
+ ignoreRestSiblings: true
83
+ }
84
+ ],
85
+ "@typescript-eslint/unbound-method": [
86
+ "error",
87
+ {
88
+ ignoreStatic: true
89
+ }
90
+ ]
91
+ }
92
+ },
219
93
  eslintPluginImportX.flatConfigs.recommended,
220
94
  eslintPluginImportX.flatConfigs.typescript,
221
- jestConfig,
95
+ {
96
+ files: ["**/*.test.{js,jsx,ts,tsx}", "**/testing/**/*.{js,jsx,ts,tsx}"],
97
+ ...jest.configs["flat/recommended"],
98
+ ...jest.configs["flat/style"],
99
+ ...testingLibraryConfig.configs["flat/dom"],
100
+ ...testingLibraryConfig.configs["flat/react"]
101
+ },
222
102
  prettierRecommended,
223
- reactConfig,
224
- e2eTestConfig,
225
- sbConfig,
226
- jsRulesConfig,
227
- options
228
- );
229
- const config = tseslint.config(...tseslintConfigArgs);
103
+ {
104
+ files: ["**/*.{jsx,tsx}"],
105
+ ...reactPlugin.configs.flat.recommended,
106
+ ...reactPlugin.configs.flat["jsx-runtime"],
107
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
108
+ ...jsxA11yConfig.flatConfigs.recommended,
109
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
110
+ ...compat.extends("plugin:redux-saga/recommended"),
111
+ languageOptions: {
112
+ ...reactPlugin.configs.flat.recommended.languageOptions
113
+ },
114
+ plugins: {
115
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
116
+ "react-hooks": reactHookPlugin
117
+ },
118
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
119
+ rules: {
120
+ "react/prop-types": ["error", { skipUndeclared: true }],
121
+ "react/display-name": "off",
122
+ "react/function-component-definition": [
123
+ 2,
124
+ { namedComponents: "arrow-function" }
125
+ ],
126
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
127
+ ...reactHookPlugin.configs.recommended.rules
128
+ }
129
+ },
130
+ {
131
+ files: ["**/*.func.spec.{js,ts}", "**/*.visual.spec.{js,ts}"],
132
+ extends: [wdioConfig["flat/recommended"]],
133
+ rules: {
134
+ "jest/valid-expect": "off"
135
+ }
136
+ },
137
+ {
138
+ files: ["**/*.stories.{js,jsx,ts,tsx,mdx}"],
139
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
140
+ // @ts-ignore
141
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
142
+ extends: [storybookConfig.configs["flat/recommended"]]
143
+ },
144
+ {
145
+ rules: {
146
+ complexity: ["error", { max: 10 }],
147
+ "import-x/no-named-as-default-member": "off",
148
+ "import-x/no-named-as-default": "off",
149
+ "import-x/no-unresolved": [
150
+ "error",
151
+ { caseSensitive: true, caseSensitiveStrict: true }
152
+ ],
153
+ "import-x/extensions": [
154
+ "error",
155
+ "never",
156
+ {
157
+ json: "ignorePackages",
158
+ js: "ignorePackages"
159
+ }
160
+ ],
161
+ "max-depth": ["error", { max: 4 }],
162
+ "max-nested-callbacks": ["error", { max: 3 }],
163
+ "max-params": ["error", { max: 3 }],
164
+ "max-statements": ["error", { max: 20 }],
165
+ "no-console": "warn",
166
+ "no-param-reassign": ["error", { props: false }],
167
+ "no-unused-vars": "off",
168
+ "prefer-template": "error"
169
+ }
170
+ },
171
+ {
172
+ languageOptions: {
173
+ ecmaVersion: "latest",
174
+ sourceType: "module",
175
+ globals: {
176
+ ...globals.builtin,
177
+ ...globals.browser,
178
+ ...globals.es2021,
179
+ ...globals.nodeBuiltin,
180
+ ...globals.node,
181
+ ...globals.serviceworker,
182
+ ...globals.jest,
183
+ ...globals.commonjs,
184
+ browser: true,
185
+ $: true
186
+ },
187
+ parserOptions: {
188
+ ecmaVersion: "latest",
189
+ sourceType: "module",
190
+ ecmaFeatures: {
191
+ jsx: true
192
+ },
193
+ projectService: true,
194
+ tsconfigRootDir: process.cwd()
195
+ }
196
+ },
197
+ settings: {
198
+ react: {
199
+ version: "detect",
200
+ pragma: "React"
201
+ },
202
+ jest: {
203
+ version: "detect"
204
+ },
205
+ "import-x/parsers": {
206
+ espree: [".js", ".cjs", ".mjs", ".jsx"]
207
+ },
208
+ // "import-x/resolver": {
209
+ // node: {
210
+ // extensions: [".js", ".jsx", ".ts", ".tsx"],
211
+ // },
212
+ // typescript: true,
213
+ // },
214
+ "import/resolver-next": [
215
+ createTypeScriptImportResolver({
216
+ alwaysTryTypes: true
217
+ })
218
+ ]
219
+ }
220
+ }
221
+ ]);
230
222
  export {
231
223
  config
232
224
  };
@@ -30,7 +30,9 @@ const loadRoutes = async (app) => {
30
30
  const routeFileURL = pathToFileURL(routeFile).href;
31
31
  const { default: init } = await import(routeFileURL);
32
32
  try {
33
- if (typeof init === "function") init(app);
33
+ if (typeof init === "function") {
34
+ await init(app);
35
+ }
34
36
  } catch (err) {
35
37
  console.error(
36
38
  `unable to load routes from ${routeFile}. ${err.message}`
@@ -21,18 +21,22 @@ const sendFileWithCSPNonce = ({
21
21
  res,
22
22
  fileSystem = fs
23
23
  }) => {
24
- fileSystem.readFile(path.resolve(buildPath, page), "utf8", (err, html) => {
25
- if (err) {
26
- res.sendStatus(404);
27
- } else {
28
- res.set("Content-Type", "text/html");
29
- res.set("Reporting-Endpoints", `csp-report-uri="${CSP_REPORT_URI}"`);
30
- res.set(
31
- "Permissions-Policy",
32
- "geolocation=(), camera=(), microphone=(), interest-cohort=()"
33
- );
34
- res.send(html.replace(nonceRegex, res.locals.cspNonce));
35
- }
24
+ return new Promise((resolve) => {
25
+ fileSystem.readFile(path.resolve(buildPath, page), "utf8", (err, html) => {
26
+ const r = res;
27
+ if (err) {
28
+ r.sendStatus(404);
29
+ } else {
30
+ r.set("Content-Type", "text/html");
31
+ r.set("Reporting-Endpoints", `csp-report-uri="${CSP_REPORT_URI}"`);
32
+ r.set(
33
+ "Permissions-Policy",
34
+ "geolocation=(), camera=(), microphone=(), interest-cohort=()"
35
+ );
36
+ r.send(html.replace(nonceRegex, r.locals.cspNonce ?? ""));
37
+ }
38
+ resolve();
39
+ });
36
40
  });
37
41
  };
38
42
  const getScriptSrc = () => {
@@ -12,19 +12,28 @@ import { isHttps } from "../utils.js";
12
12
  import { loadRoutes } from "./appRoutes.js";
13
13
  import { createWSServer } from "./wsServer.js";
14
14
  void (async function startServer() {
15
- const app = express();
16
- setupDefaultMiddlewares(app);
17
- await loadRoutes(app);
18
- setupAdditionalMiddlewars(app);
19
- const server = isHttps() ? https.createServer(getCertOptions(), app) : http.createServer(app);
20
- server.listen(port, host, () => {
21
- logger.appStarted(port.toString(), host || "localhost");
22
- }).on("error", (err) => {
15
+ try {
16
+ const app = express();
17
+ setupDefaultMiddlewares(app);
18
+ await loadRoutes(app);
19
+ setupAdditionalMiddlewars(app);
20
+ const server = isHttps() ? https.createServer(getCertOptions(), app) : http.createServer(app);
21
+ server.listen(port, host, () => {
22
+ logger.appStarted(port.toString(), host || "localhost");
23
+ }).on("error", (err) => {
24
+ logger.error(err);
25
+ process.exit(1);
26
+ });
27
+ const { wsServer } = await createWSServer({
28
+ port: wsPort
29
+ });
30
+ app.locals.wsServer = wsServer;
31
+ } catch (err) {
23
32
  logger.error(err);
24
33
  process.exit(1);
25
- });
26
- const { wsServer } = await createWSServer({
27
- port: wsPort
28
- });
29
- app.locals.wsServer = wsServer;
34
+ }
30
35
  })();
36
+ process.on("unhandledRejection", (reason) => {
37
+ logger.error(reason);
38
+ process.exit(1);
39
+ });
@@ -2,12 +2,12 @@ import express from "express";
2
2
  import cors from "cors";
3
3
  import compression from "compression";
4
4
  import expressStaticGzip from "express-static-gzip";
5
- import pinoLogger from "pino-http";
5
+ import { pinoHttp } from "pino-http";
6
6
  import { csp, sendFileWithCSPNonce } from "./csp.js";
7
7
  import { getPaths } from "../webpack/helpers.js";
8
8
  const paths = getPaths();
9
9
  const setupDefaultMiddlewares = (app) => {
10
- const pino = pinoLogger({
10
+ const pino = pinoHttp({
11
11
  transport: {
12
12
  target: "pino-pretty",
13
13
  options: {
@@ -27,8 +27,8 @@ const setupDefaultMiddlewares = (app) => {
27
27
  const setupAdditionalMiddlewars = (app, options = {}) => {
28
28
  const { buildPath = paths.buildPath, basePath = paths.basePath } = options;
29
29
  app.use(compression());
30
- app.get(basePath, (_req, res) => {
31
- sendFileWithCSPNonce({ buildPath, res });
30
+ app.get(basePath, async (_req, res) => {
31
+ await sendFileWithCSPNonce({ buildPath, res });
32
32
  });
33
33
  app.use(
34
34
  basePath,
@@ -39,10 +39,13 @@ const setupAdditionalMiddlewars = (app, options = {}) => {
39
39
  })
40
40
  );
41
41
  app.use(expressStaticGzip("cdn", {}));
42
- app.get(
43
- "*",
44
- (_req, res) => sendFileWithCSPNonce({ buildPath, res })
45
- );
42
+ app.get("*", async (_req, res) => {
43
+ await sendFileWithCSPNonce({ buildPath, res });
44
+ });
45
+ app.use(function(err, _req, res, _next) {
46
+ console.error("Express error:", err);
47
+ res.status(500).send("Internal Server Error");
48
+ });
46
49
  return app;
47
50
  };
48
51
  export {
@@ -1,2 +1,2 @@
1
- import { config } from './lib/lint-config/eslint.config';
1
+ import { config } from './lib/lint-config/eslint.config.js';
2
2
  export default config;
@@ -1,3 +1,3 @@
1
- export type { TSESLint } from "@typescript-eslint/utils";
2
- declare const config: import("@typescript-eslint/utils/dist/ts-eslint").FlatConfig.ConfigArray;
1
+ import { Linter } from "eslint";
2
+ declare const config: Linter.Config<Linter.RulesRecord>[];
3
3
  export { config };
@@ -7,6 +7,6 @@ interface CSPConfig {
7
7
  res: Response<unknown, Record<string, unknown>>;
8
8
  fileSystem?: typeof fs;
9
9
  }
10
- export declare const sendFileWithCSPNonce: ({ buildPath, page, nonceRegex, res, fileSystem, }: CSPConfig) => void;
10
+ export declare const sendFileWithCSPNonce: ({ buildPath, page, nonceRegex, res, fileSystem, }: CSPConfig) => Promise<void>;
11
11
  export declare const csp: (app: Application) => void;
12
12
  export {};