From 55a52b14d8390ebe2f0961d324a06b92c5f150c0 Mon Sep 17 00:00:00 2001 From: Arno V Date: Mon, 16 Sep 2024 14:15:21 -0400 Subject: [PATCH] chore: refactor individual components with common configuration (#641) --- configuration/tailwind.common.js | 9 ++ configuration/tsconfig.common.json | 80 +++--------- configuration/tsup.common.js | 12 ++ configuration/vite.common.js | 116 ++++++++++++++++++ .../vitest.setup.ts | 0 configuration/vitestconfig.common.ts | 29 +++++ packages/ui-anchor/tailwind.config.js | 9 +- packages/ui-anchor/tsconfig.json | 26 +--- packages/ui-anchor/tsconfig.node.json | 10 -- packages/ui-anchor/tsup.config.ts | 14 +-- packages/ui-anchor/vite.config.ts | 115 +---------------- packages/ui-anchor/vitest.config.js | 4 + packages/ui-anchor/vitest.config.ts | 28 ----- packages/ui-button/tailwind.config.js | 9 +- packages/ui-button/tsconfig.json | 26 +--- packages/ui-button/tsconfig.node.json | 10 -- packages/ui-button/tsup.config.ts | 14 +-- packages/ui-button/vite.config.ts | 115 +---------------- packages/ui-button/vitest.config.js | 4 + packages/ui-button/vitest.config.ts | 28 ----- packages/ui-button/vitest.setup.ts | 17 --- 21 files changed, 212 insertions(+), 463 deletions(-) create mode 100644 configuration/tailwind.common.js create mode 100644 configuration/tsup.common.js rename {packages/ui-anchor => configuration}/vitest.setup.ts (100%) create mode 100644 configuration/vitestconfig.common.ts delete mode 100644 packages/ui-anchor/tsconfig.node.json create mode 100644 packages/ui-anchor/vitest.config.js delete mode 100644 packages/ui-anchor/vitest.config.ts delete mode 100644 packages/ui-button/tsconfig.node.json create mode 100644 packages/ui-button/vitest.config.js delete mode 100644 packages/ui-button/vitest.config.ts delete mode 100644 packages/ui-button/vitest.setup.ts diff --git a/configuration/tailwind.common.js b/configuration/tailwind.common.js new file mode 100644 index 00000000..35428f8c --- /dev/null +++ b/configuration/tailwind.common.js @@ -0,0 +1,9 @@ +/** @type {import('tailwindcss').Config} */ + +import { twPlugin } from "@versini/ui-styles"; + +export const commonTailwindConfigForComponent = () => { + return twPlugin.merge({ + content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], + }); +}; diff --git a/configuration/tsconfig.common.json b/configuration/tsconfig.common.json index 9bba9850..d13b1e39 100644 --- a/configuration/tsconfig.common.json +++ b/configuration/tsconfig.common.json @@ -1,68 +1,24 @@ { - "$schema": "https://json.schemastore.org/tsconfig", - "ts-node": { - "swc": true - }, "compilerOptions": { - /** Allow JavaScript files to be imported inside your project, - * instead of just .ts and .tsx files. - */ - "allowJs": true, - /** - * Allow default imports from modules with no default export. - */ - "allowSyntheticDefaultImports": true, - /** - * Generate .d.ts files for every TypeScript or JavaScript file - * inside your project. - */ - "declaration": true, - /** - * Only output d.ts files and not JavaScript files. - */ - "emitDeclarationOnly": true, - /** - * Emit additional JavaScript to ease support for importing - * CommonJS modules. - */ - "esModuleInterop": false, - /** - * Ensure that each file can be safely transpiled without - * relying on other imports. - */ - "isolatedModules": true, - /** - * Specify a set of bundled library declaration files that - * describe the target runtime environment. - */ - "lib": ["ESNext"], - /** - * Specify what module code is generated. - */ + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], "module": "ESNext", - /** - * Specify the module resolution strategy: - * - 'node' for Node.js’ CommonJS implementation - * - 'node16' or 'nodenext' for Node.js’ ECMAScript Module Support - * from TypeScript 4.7 onwards - */ - "moduleResolution": "nodenext", - /** - * Enable importing .json files - */ - "resolveJsonModule": true, - /** - * Skip type checking of all declaration files (*.d.ts). - */ "skipLibCheck": true, - /** - * Enable all strict type checking options. - */ - "strict": false, - /** - * Set the JavaScript language version for emitted JavaScript - * and include compatible library declarations. - */ - "target": "ESNext" + "types": ["vitest/globals", "@testing-library/jest-dom"], + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true } } diff --git a/configuration/tsup.common.js b/configuration/tsup.common.js new file mode 100644 index 00000000..401c9275 --- /dev/null +++ b/configuration/tsup.common.js @@ -0,0 +1,12 @@ +import { defineConfig } from "tsup"; + +export const commonTsupConfig = defineConfig({ + format: "esm", + entry: { + index: "src/components/index.ts", + }, + outDir: "dist", + dts: { + only: true, + }, +}); diff --git a/configuration/vite.common.js b/configuration/vite.common.js index 18c8d5da..34a76226 100644 --- a/configuration/vite.common.js +++ b/configuration/vite.common.js @@ -1,3 +1,10 @@ +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +import fs from "fs-extra"; +import { glob } from "glob"; +import { defineConfig } from "vite"; + export const externalDependencies = [ "@floating-ui/react", "@tailwindcss/typography", @@ -8,3 +15,112 @@ export const externalDependencies = [ "react-dom/server", "tailwindcss", ]; + +export const commonViteConfigForComponent = ({ + globalComponentName, + globalLibraryName, +}) => { + const cwd = process.cwd(); + const packageJson = fs.readJSONSync(path.join(cwd, "package.json")); + const copyrightYear = new Date(Date.now()).getFullYear(); + const buildTime = new Date() + .toLocaleString("en-US", { + timeZone: "America/New_York", + timeZoneName: "short", + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + }) + .replace(/,/g, ""); + const banner = `/*! + ${packageJson.name} v${packageJson.version} + © ${copyrightYear} gizmette.com +*/ +try { + if (!window.${globalComponentName}) { + window.${globalComponentName} = { + version: "${packageJson.version}", + buildTime: "${buildTime}", + homepage: "${packageJson.homepage}", + license: "${packageJson.license}", + }; + } +} catch (error) { + // nothing to declare officer +} +`; + return defineConfig(({ mode }) => { + const isDev = mode === "development"; + /** + * Build a list of public files, which means all files in the + * src/components/ComponentName folders. + * Everything else will be moved to the chunk folder. + */ + const input = isDev + ? {} + : Object.fromEntries( + glob + .sync(path.join(cwd, "src/**/*.{ts,tsx}")) + .filter((file) => { + return file.match( + /src\/components\/[A-Z][a-zA-Z]*\/[A-Z][a-zA-Z]*\.tsx/, + ) + ? file + : null; + }) + .map((file) => { + return [ + // This remove `src/` as well as the file extension from each + // file, so e.g. src/nested/foo.js becomes nested/foo + path.relative( + path.join(cwd, "src"), + file.slice(0, file.length - path.extname(file).length), + ), + // This expands the relative paths to absolute paths, so e.g. + // src/nested/foo becomes /project/src/nested/foo.js + fileURLToPath(new URL(file, import.meta.url)), + ]; + }), + ); + + return { + build: { + copyPublicDir: false, + lib: { + entry: path.join(cwd, "src/components/index.ts"), + formats: ["es"], + name: globalLibraryName, + }, + rollupOptions: { + input: { + index: path.join(cwd, "src/components/index.ts"), + style: path.join(cwd, "src/style.ts"), + ...input, + }, + treeshake: "smallest", + external: externalDependencies, + output: { + compact: true, + minifyInternalExports: false, + assetFileNames: "style[extname]", + entryFileNames: "[name].js", + chunkFileNames: "chunks/[name].[hash].js", + banner: (module) => { + if (module?.facadeModuleId?.endsWith("src/components/index.ts")) { + return banner; + } + }, + }, + }, + }, + esbuild: { + supported: { + "top-level-await": true, + }, + }, + plugins: [], + }; + }); +}; diff --git a/packages/ui-anchor/vitest.setup.ts b/configuration/vitest.setup.ts similarity index 100% rename from packages/ui-anchor/vitest.setup.ts rename to configuration/vitest.setup.ts diff --git a/configuration/vitestconfig.common.ts b/configuration/vitestconfig.common.ts new file mode 100644 index 00000000..e29bfa2f --- /dev/null +++ b/configuration/vitestconfig.common.ts @@ -0,0 +1,29 @@ +/// + +import path from "node:path"; +import { defineConfig, mergeConfig } from "vitest/config"; + +export const commonVitestConfig = (viteConfig) => { + return defineConfig((configEnv) => + mergeConfig( + viteConfig(configEnv), + defineConfig({ + test: { + globals: true, + setupFiles: [path.join(__dirname, "./vitest.setup.ts")], + environment: "happy-dom", + coverage: { + include: ["src/**/*.ts", "src/**/*.tsx", "!src/style.ts"], + provider: "v8", + thresholds: { + statements: 100, + branches: 100, + functions: 100, + lines: 100, + }, + }, + }, + }), + ), + ); +}; diff --git a/packages/ui-anchor/tailwind.config.js b/packages/ui-anchor/tailwind.config.js index d9c6afd4..42ba260d 100644 --- a/packages/ui-anchor/tailwind.config.js +++ b/packages/ui-anchor/tailwind.config.js @@ -1,7 +1,2 @@ -/** @type {import('tailwindcss').Config} */ - -import { twPlugin } from "@versini/ui-styles"; - -export default twPlugin.merge({ - content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], -}); +import { commonTailwindConfigForComponent } from "../../configuration/tailwind.common"; +export default commonTailwindConfigForComponent(); diff --git a/packages/ui-anchor/tsconfig.json b/packages/ui-anchor/tsconfig.json index ffbdf148..652d144c 100644 --- a/packages/ui-anchor/tsconfig.json +++ b/packages/ui-anchor/tsconfig.json @@ -1,26 +1,4 @@ { - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - "types": ["vitest/globals", "@testing-library/jest-dom"], - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + "extends": "../../configuration/tsconfig.common.json", + "include": ["src"] } diff --git a/packages/ui-anchor/tsconfig.node.json b/packages/ui-anchor/tsconfig.node.json deleted file mode 100644 index f7d9f9ea..00000000 --- a/packages/ui-anchor/tsconfig.node.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true - }, - "include": ["./vite.config.ts", "./vitest.setup.ts"] -} diff --git a/packages/ui-anchor/tsup.config.ts b/packages/ui-anchor/tsup.config.ts index 30c94257..7490cbb5 100644 --- a/packages/ui-anchor/tsup.config.ts +++ b/packages/ui-anchor/tsup.config.ts @@ -1,12 +1,2 @@ -import { defineConfig } from "tsup"; - -export default defineConfig({ - format: "esm", - entry: { - index: "src/components/index.ts", - }, - outDir: "dist", - dts: { - only: true, - }, -}); +import { commonTsupConfig } from "../../configuration/tsup.common"; +export default commonTsupConfig; diff --git a/packages/ui-anchor/vite.config.ts b/packages/ui-anchor/vite.config.ts index 46751de1..52a6feff 100644 --- a/packages/ui-anchor/vite.config.ts +++ b/packages/ui-anchor/vite.config.ts @@ -1,113 +1,6 @@ -import path from "node:path"; -import { resolve } from "node:path"; -import { fileURLToPath } from "node:url"; +import { commonViteConfigForComponent } from "../../configuration/vite.common"; -import fs from "fs-extra"; -import { glob } from "glob"; -import { defineConfig } from "vite"; - -import { externalDependencies } from "../../configuration/vite.common"; - -const packageJson = fs.readJSONSync("package.json"); -const copyrightYear = new Date(Date.now()).getFullYear(); -const buildTime = new Date() - .toLocaleString("en-US", { - timeZone: "America/New_York", - timeZoneName: "short", - year: "numeric", - month: "2-digit", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - }) - .replace(/,/g, ""); -const banner = `/*! - ${packageJson.name} v${packageJson.version} - © ${copyrightYear} gizmette.com -*/ -try { - if (!window.__VERSINI_UI_ANCHOR__) { - window.__VERSINI_UI_ANCHOR__ = { - version: "${packageJson.version}", - buildTime: "${buildTime}", - homepage: "${packageJson.homepage}", - license: "${packageJson.license}", - }; - } -} catch (error) { - // nothing to declare officer -} -`; - -export default defineConfig(({ mode }) => { - const isDev = mode === "development"; - /** - * Build a list of public files, which means all files in the - * src/components/ComponentName folders. - * Everything else will be moved to the chunk folder. - */ - const input = isDev - ? {} - : Object.fromEntries( - glob - .sync("src/**/*.{ts,tsx}") - .filter((file) => { - return file.match( - /src\/components\/[A-Z][a-zA-Z]*\/[A-Z][a-zA-Z]*\.tsx/, - ) - ? file - : null; - }) - .map((file) => { - return [ - // This remove `src/` as well as the file extension from each - // file, so e.g. src/nested/foo.js becomes nested/foo - path.relative( - "src", - file.slice(0, file.length - path.extname(file).length), - ), - // This expands the relative paths to absolute paths, so e.g. - // src/nested/foo becomes /project/src/nested/foo.js - fileURLToPath(new URL(file, import.meta.url)), - ]; - }), - ); - - return { - build: { - copyPublicDir: false, - lib: { - entry: resolve(__dirname, "src/components/index.ts"), - formats: ["es"], - name: "UIAnchor", - }, - rollupOptions: { - input: { - index: resolve(__dirname, "src/components/index.ts"), - style: resolve(__dirname, "src/style.ts"), - ...input, - }, - treeshake: "smallest", - external: externalDependencies, - output: { - compact: true, - minifyInternalExports: false, - assetFileNames: "style[extname]", - entryFileNames: "[name].js", - chunkFileNames: "chunks/[name].[hash].js", - banner: (module) => { - if (module?.facadeModuleId?.endsWith("src/components/index.ts")) { - return banner; - } - }, - }, - }, - }, - esbuild: { - supported: { - "top-level-await": true, - }, - }, - plugins: [], - }; +export default commonViteConfigForComponent({ + globalComponentName: "__VERSINI_UI_ANCHOR__", + globalLibraryName: "UIAnchor", }); diff --git a/packages/ui-anchor/vitest.config.js b/packages/ui-anchor/vitest.config.js new file mode 100644 index 00000000..028e7ef7 --- /dev/null +++ b/packages/ui-anchor/vitest.config.js @@ -0,0 +1,4 @@ +import { commonVitestConfig } from "../../configuration/vitestconfig.common"; +import viteConfig from "./vite.config"; + +export default commonVitestConfig(viteConfig); diff --git a/packages/ui-anchor/vitest.config.ts b/packages/ui-anchor/vitest.config.ts deleted file mode 100644 index 10f38968..00000000 --- a/packages/ui-anchor/vitest.config.ts +++ /dev/null @@ -1,28 +0,0 @@ -/// - -import { defineConfig, mergeConfig } from "vitest/config"; - -import viteConfig from "./vite.config"; - -export default defineConfig((configEnv) => - mergeConfig( - viteConfig(configEnv), - defineConfig({ - test: { - globals: true, - setupFiles: ["./vitest.setup.ts"], - environment: "happy-dom", - coverage: { - include: ["src/**/*.ts", "src/**/*.tsx", "!src/style.ts"], - provider: "v8", - thresholds: { - statements: 100, - branches: 100, - functions: 100, - lines: 100, - }, - }, - }, - }), - ), -); diff --git a/packages/ui-button/tailwind.config.js b/packages/ui-button/tailwind.config.js index d9c6afd4..42ba260d 100644 --- a/packages/ui-button/tailwind.config.js +++ b/packages/ui-button/tailwind.config.js @@ -1,7 +1,2 @@ -/** @type {import('tailwindcss').Config} */ - -import { twPlugin } from "@versini/ui-styles"; - -export default twPlugin.merge({ - content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], -}); +import { commonTailwindConfigForComponent } from "../../configuration/tailwind.common"; +export default commonTailwindConfigForComponent(); diff --git a/packages/ui-button/tsconfig.json b/packages/ui-button/tsconfig.json index ffbdf148..652d144c 100644 --- a/packages/ui-button/tsconfig.json +++ b/packages/ui-button/tsconfig.json @@ -1,26 +1,4 @@ { - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - "types": ["vitest/globals", "@testing-library/jest-dom"], - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + "extends": "../../configuration/tsconfig.common.json", + "include": ["src"] } diff --git a/packages/ui-button/tsconfig.node.json b/packages/ui-button/tsconfig.node.json deleted file mode 100644 index f7d9f9ea..00000000 --- a/packages/ui-button/tsconfig.node.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true - }, - "include": ["./vite.config.ts", "./vitest.setup.ts"] -} diff --git a/packages/ui-button/tsup.config.ts b/packages/ui-button/tsup.config.ts index 30c94257..7490cbb5 100644 --- a/packages/ui-button/tsup.config.ts +++ b/packages/ui-button/tsup.config.ts @@ -1,12 +1,2 @@ -import { defineConfig } from "tsup"; - -export default defineConfig({ - format: "esm", - entry: { - index: "src/components/index.ts", - }, - outDir: "dist", - dts: { - only: true, - }, -}); +import { commonTsupConfig } from "../../configuration/tsup.common"; +export default commonTsupConfig; diff --git a/packages/ui-button/vite.config.ts b/packages/ui-button/vite.config.ts index dae033a7..601c0898 100644 --- a/packages/ui-button/vite.config.ts +++ b/packages/ui-button/vite.config.ts @@ -1,113 +1,6 @@ -import path from "node:path"; -import { resolve } from "node:path"; -import { fileURLToPath } from "node:url"; +import { commonViteConfigForComponent } from "../../configuration/vite.common"; -import fs from "fs-extra"; -import { glob } from "glob"; -import { defineConfig } from "vite"; - -import { externalDependencies } from "../../configuration/vite.common"; - -const packageJson = fs.readJSONSync("package.json"); -const copyrightYear = new Date(Date.now()).getFullYear(); -const buildTime = new Date() - .toLocaleString("en-US", { - timeZone: "America/New_York", - timeZoneName: "short", - year: "numeric", - month: "2-digit", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - }) - .replace(/,/g, ""); -const banner = `/*! - ${packageJson.name} v${packageJson.version} - © ${copyrightYear} gizmette.com -*/ -try { - if (!window.__VERSINI_UI_BUTTON__) { - window.__VERSINI_UI_BUTTON__ = { - version: "${packageJson.version}", - buildTime: "${buildTime}", - homepage: "${packageJson.homepage}", - license: "${packageJson.license}", - }; - } -} catch (error) { - // nothing to declare officer -} -`; - -export default defineConfig(({ mode }) => { - const isDev = mode === "development"; - /** - * Build a list of public files, which means all files in the - * src/components/ComponentName folders. - * Everything else will be moved to the chunk folder. - */ - const input = isDev - ? {} - : Object.fromEntries( - glob - .sync("src/**/*.{ts,tsx}") - .filter((file) => { - return file.match( - /src\/components\/[A-Z][a-zA-Z]*\/[A-Z][a-zA-Z]*\.tsx/, - ) - ? file - : null; - }) - .map((file) => { - return [ - // This remove `src/` as well as the file extension from each - // file, so e.g. src/nested/foo.js becomes nested/foo - path.relative( - "src", - file.slice(0, file.length - path.extname(file).length), - ), - // This expands the relative paths to absolute paths, so e.g. - // src/nested/foo becomes /project/src/nested/foo.js - fileURLToPath(new URL(file, import.meta.url)), - ]; - }), - ); - - return { - build: { - copyPublicDir: false, - lib: { - entry: resolve(__dirname, "src/components/index.ts"), - formats: ["es"], - name: "UIButton", - }, - rollupOptions: { - input: { - index: resolve(__dirname, "src/components/index.ts"), - style: resolve(__dirname, "src/style.ts"), - ...input, - }, - treeshake: "smallest", - external: externalDependencies, - output: { - compact: true, - minifyInternalExports: false, - assetFileNames: "style[extname]", - entryFileNames: "[name].js", - chunkFileNames: "chunks/[name].[hash].js", - banner: (module) => { - if (module?.facadeModuleId?.endsWith("src/components/index.ts")) { - return banner; - } - }, - }, - }, - }, - esbuild: { - supported: { - "top-level-await": true, - }, - }, - plugins: [], - }; +export default commonViteConfigForComponent({ + globalComponentName: "__VERSINI_UI_BUTTON__", + globalLibraryName: "UIButton", }); diff --git a/packages/ui-button/vitest.config.js b/packages/ui-button/vitest.config.js new file mode 100644 index 00000000..028e7ef7 --- /dev/null +++ b/packages/ui-button/vitest.config.js @@ -0,0 +1,4 @@ +import { commonVitestConfig } from "../../configuration/vitestconfig.common"; +import viteConfig from "./vite.config"; + +export default commonVitestConfig(viteConfig); diff --git a/packages/ui-button/vitest.config.ts b/packages/ui-button/vitest.config.ts deleted file mode 100644 index 10f38968..00000000 --- a/packages/ui-button/vitest.config.ts +++ /dev/null @@ -1,28 +0,0 @@ -/// - -import { defineConfig, mergeConfig } from "vitest/config"; - -import viteConfig from "./vite.config"; - -export default defineConfig((configEnv) => - mergeConfig( - viteConfig(configEnv), - defineConfig({ - test: { - globals: true, - setupFiles: ["./vitest.setup.ts"], - environment: "happy-dom", - coverage: { - include: ["src/**/*.ts", "src/**/*.tsx", "!src/style.ts"], - provider: "v8", - thresholds: { - statements: 100, - branches: 100, - functions: 100, - lines: 100, - }, - }, - }, - }), - ), -); diff --git a/packages/ui-button/vitest.setup.ts b/packages/ui-button/vitest.setup.ts deleted file mode 100644 index 1a4fd1d2..00000000 --- a/packages/ui-button/vitest.setup.ts +++ /dev/null @@ -1,17 +0,0 @@ -import "@testing-library/jest-dom/vitest"; - -import util from "node:util"; - -const originalConsoleError = console.error; -console.error = (...args: any) => { - const message = util.format(...args); - if ( - /(Warning: validateDOMNesting|Invalid prop|Failed prop type|React does not recognize|Unknown event handler property)/gi.test( - message, - ) - ) { - throw new Error(message); - } else { - originalConsoleError.apply(console, [...args]); - } -};