diff --git a/package-lock.json b/package-lock.json index f5955c9d..368473e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,7 +61,7 @@ "lodash": "^4.17.21", "nx": "16.5.0", "nx-cloud": "16.0.5", - "prettier": "2.8.8", + "prettier": "3.0.0", "storybook": "^6.5.16", "type-fest": "4.0.0", "typescript": "5.1.6", @@ -20625,7 +20625,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", - "dev": true, "dependencies": { "minimatch": "^5.0.1" }, @@ -20637,7 +20636,6 @@ "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -25594,6 +25592,14 @@ "rimraf": "bin.js" } }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "engines": { + "node": ">=4" + } + }, "node_modules/mrmime": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", @@ -28388,14 +28394,14 @@ } }, "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz", + "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==", "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" @@ -28750,6 +28756,90 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, + "node_modules/publint": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/publint/-/publint-0.2.0.tgz", + "integrity": "sha512-h8lxdjhQjpDw+A4BgY4sE7Z4CU3x5tCGGpERVdKGDQmWMtr1P7kvptJS2P10HhmNnS7Yeny37zfQE5+xRZ6nig==", + "dependencies": { + "npm-packlist": "^5.1.3", + "picocolors": "^1.0.0", + "sade": "^1.8.1" + }, + "bin": { + "publint": "lib/cli.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://bjornlu.com/sponsor" + } + }, + "node_modules/publint/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/publint/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/publint/node_modules/npm-bundled": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz", + "integrity": "sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==", + "dependencies": { + "npm-normalize-package-bin": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/publint/node_modules/npm-normalize-package-bin": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", + "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/publint/node_modules/npm-packlist": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz", + "integrity": "sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==", + "dependencies": { + "glob": "^8.0.1", + "ignore-walk": "^5.0.1", + "npm-bundled": "^2.0.0", + "npm-normalize-package-bin": "^2.0.0" + }, + "bin": { + "npm-packlist": "bin/index.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -30616,6 +30706,17 @@ "tslib": "^2.1.0" } }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/safe-array-concat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", @@ -34036,6 +34137,11 @@ "node": ">=4" } }, + "node_modules/tsimportlib": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/tsimportlib/-/tsimportlib-0.0.5.tgz", + "integrity": "sha512-qWQv/C3YB4Pwj77Z2HlORfy5EsWHcSYt66VQlMM0xZiKXwtoe1SxfpzmHX62sdJgzU6esrBGtyRIlx6O2OFPrQ==" + }, "node_modules/tslib": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", @@ -37084,12 +37190,13 @@ "flat": "5.0.2", "fs-extra": "11.1.1", "lodash": "4.17.21", - "prettier": "^2" + "prettier": "^3", + "publint": "0.2.0", + "tsimportlib": "0.0.5" }, "devDependencies": { "@types/flat": "5.0.2", "@types/lodash": "4.14.195", - "@types/prettier": "2.7.3", "type-fest": "4.0.0", "typescript": "5.1.6" }, @@ -37583,7 +37690,7 @@ "node": ">= 16.16.0" }, "peerDependencies": { - "prettier": "^2" + "prettier": "^3" } }, "packages/semantic-release-config": { @@ -37610,12 +37717,11 @@ "glob": "^10.3.3", "jiti": "^1.19.1", "minimist": "^1.2.8", - "prettier": "^2", + "prettier": "^3.0.0", "prettier-package-json": "2.8.0" }, "devDependencies": { "@types/glob": "8.1.0", - "@types/prettier": "2.7.3", "@types/prettier-package-json": "2.3.0", "@types/semver": "7.5.0", "@types/string-similarity": "4.0.0", diff --git a/package.json b/package.json index 1ba8e082..9fda38d6 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "lodash": "^4.17.21", "nx": "16.5.0", "nx-cloud": "16.0.5", - "prettier": "2.8.8", + "prettier": "3.0.0", "storybook": "^6.5.16", "type-fest": "4.0.0", "typescript": "5.1.6", diff --git a/packages/eslint-config/src/rules/namingConvention.ts b/packages/eslint-config/src/rules/namingConvention.ts index 1b976fcc..e94eb22a 100644 --- a/packages/eslint-config/src/rules/namingConvention.ts +++ b/packages/eslint-config/src/rules/namingConvention.ts @@ -98,7 +98,7 @@ export const namingRules: Linter.RulesRecord = { }, }, { - selector: ['property'], + selector: ['property', 'parameterProperty'], format: ['camelCase', 'PascalCase', 'snake_case', 'UPPER_CASE'], leadingUnderscore: 'allowDouble', // double for __html }, @@ -109,7 +109,7 @@ export const namingRules: Linter.RulesRecord = { }, { selector: 'parameter', - format: ['camelCase'], + format: ['camelCase', 'PascalCase'], leadingUnderscore: 'allow', }, ], diff --git a/packages/eslint-config/src/rules/react.ts b/packages/eslint-config/src/rules/react.ts index e0297c5e..a18b1935 100644 --- a/packages/eslint-config/src/rules/react.ts +++ b/packages/eslint-config/src/rules/react.ts @@ -13,6 +13,12 @@ export const reactRules: Linter.RulesRecord = { 'react/prop-types': 'off', // see https://github.com/jsx-eslint/eslint-plugin-react/issues/3384#issuecomment-1236371796 'react/no-unknown-property': ['error', { ignore: ['css'] }], + 'react/no-unstable-nested-components': [ + 'error', + { + allowAsProps: true, + }, + ], // These cause typing conflicts 'react/require-default-props': ['off'], diff --git a/packages/eslint-plugin/src/shortestImport.ts b/packages/eslint-plugin/src/shortestImport.ts index 89e3557b..aeb850aa 100644 --- a/packages/eslint-plugin/src/shortestImport.ts +++ b/packages/eslint-plugin/src/shortestImport.ts @@ -53,19 +53,22 @@ export const shortestImport: TSESLint.RuleModule< .readdirSync(baseUrl, { withFileTypes: true, }) - .reduce((directoryMap, dirrent) => { - if (dirrent.isDirectory()) + .reduce( + (directoryMap, dirrent) => { + if (dirrent.isDirectory()) + return { + ...directoryMap, + [dirrent.name]: path.join(relativeBaseUrl, dirrent.name), + }; return { ...directoryMap, - [dirrent.name]: path.join(relativeBaseUrl, dirrent.name), + [dirrent.name.replace(/\.[^.]+$/gi, '')]: path + .join(relativeBaseUrl, dirrent.name) + .replace(/^\.\//gi, ''), }; - return { - ...directoryMap, - [dirrent.name.replace(/\.[^.]+$/gi, '')]: path - .join(relativeBaseUrl, dirrent.name) - .replace(/^\.\//gi, ''), - }; - }, {} as Record) + }, + {} as Record, + ) : {}; const compilerPaths = Object.entries(compilerOptions.paths ?? {}).reduce( (compilerPathsMap, [key, [value]]) => ({ diff --git a/packages/nx/package.json b/packages/nx/package.json index a7ab0391..7a21705b 100644 --- a/packages/nx/package.json +++ b/packages/nx/package.json @@ -32,12 +32,13 @@ "flat": "5.0.2", "fs-extra": "11.1.1", "lodash": "4.17.21", - "prettier": "^2" + "prettier": "^3", + "publint": "0.2.0", + "tsimportlib": "0.0.5" }, "devDependencies": { "@types/flat": "5.0.2", "@types/lodash": "4.14.195", - "@types/prettier": "2.7.3", "type-fest": "4.0.0", "typescript": "5.1.6" }, diff --git a/packages/nx/src/executors/build-lib/executor.ts b/packages/nx/src/executors/build-lib/executor.ts index e40b15d3..fccbce18 100644 --- a/packages/nx/src/executors/build-lib/executor.ts +++ b/packages/nx/src/executors/build-lib/executor.ts @@ -1,5 +1,6 @@ import { ExecutorContext } from '@nx/devkit'; import { buildPackage } from '@tablecheck/frontend-library'; +import { dynamicImport } from 'tsimportlib'; import { BuildLibExecutorSchema } from './schema.js'; @@ -7,9 +8,45 @@ export default async function runExecutor( options: BuildLibExecutorSchema, context: ExecutorContext, ) { + if (!context.projectName) { + throw new Error('Lib build must be run on a project'); + } const metadata = - context.projectsConfigurations?.projects[context.projectName || '.']; + context.projectsConfigurations?.projects[context.projectName]; + if (!metadata) { + throw new Error( + `Could not find project configuration for ${context.projectName}`, + ); + } + const isBuildSuccessful = await buildPackage({ + cwd: metadata.root, + ...options, + }); + + const { publint } = (await dynamicImport( + 'publint', + module, + // @ts-expect-error - this is a dynamic import + )) as typeof import('publint'); + + const { messages } = await publint({ + pkgDir: metadata.root, + /** + * Report warnings as errors. + */ + strict: true, + }); + return { - success: await buildPackage({ cwd: metadata!.root, ...options }), + success: isBuildSuccessful && messages.length === 0, + terminalOutput: messages + .map((message) => { + const { args, code, path, type } = message; + return `${type}: ${code} + - ${path.join('\n - ')} + + ${JSON.stringify(args, null, 2)}`; + }) + .join('\n'), }; } diff --git a/packages/nx/src/executors/quality/executor.ts b/packages/nx/src/executors/quality/executor.ts index 554e7f5d..ea324dd8 100644 --- a/packages/nx/src/executors/quality/executor.ts +++ b/packages/nx/src/executors/quality/executor.ts @@ -1,3 +1,5 @@ +import { execSync } from 'child_process'; + import { ExecutorContext } from '@nx/devkit'; import lintRun from '@nx/linter/src/executors/eslint/lint.impl.js'; @@ -39,6 +41,24 @@ export default async function runExecutor( }, context, ); + + try { + execSync( + `npx prettier ${[ + options.fix ? '-w' : '-c', + '--log-level warn', + '--no-error-on-unmatched-pattern', + '--ignore-unknown', + '--cache', + ].join(' ')} --log-level warn .`, + { + cwd: root, + stdio: 'inherit', + }, + ); + } catch (e) { + return { success: false }; + } return { success: lintResult.success && packageCheckResult.success }; } catch (e) { console.log(e as Error); diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index 94f2c5a2..b2a0c72f 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -10,7 +10,7 @@ "version": "1.0.0", "main": "./config.json", "peerDependencies": { - "prettier": "^2" + "prettier": "^3" }, "engines": { "node": ">= 16.16.0" diff --git a/packages/utils/package.json b/packages/utils/package.json index 12b51bbb..ebb581ef 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -31,12 +31,11 @@ "glob": "^10.3.3", "jiti": "^1.19.1", "minimist": "^1.2.8", - "prettier": "^2.8.8", + "prettier": "^3.0.0", "prettier-package-json": "2.8.0" }, "devDependencies": { "@types/glob": "8.1.0", - "@types/prettier": "2.7.3", "@types/prettier-package-json": "2.3.0", "@types/semver": "7.5.0", "@types/string-similarity": "4.0.0", diff --git a/packages/utils/src/prettier.ts b/packages/utils/src/prettier.ts index f27c4967..e480e15d 100644 --- a/packages/utils/src/prettier.ts +++ b/packages/utils/src/prettier.ts @@ -5,7 +5,7 @@ export async function outputPrettyFile(filePath: string, fileContent: string) { const prettierOptions = await prettier.resolveConfig(process.cwd()); fs.outputFileSync( filePath, - prettier.format(fileContent, { + await prettier.format(fileContent, { ...prettierOptions, filepath: filePath, }),