chore: upgrade Nx to v18.1.3 (#4706)

Split from https://github.com/twentyhq/twenty/pull/4518

- Upgrades dependencies and applies automatic config migrations with the
command: `npx nx migrate nx` (see
https://nx.dev/nx-api/nx/documents/migrate)
- Fixes lint errors after upgrading `@typescript-eslint`

Note: it was not possible (for now) to migrate Nx to the latest stable
version (v18.2.1) because it upgrades Typescript to v5.4.3, which seems
to cause a bug on install when Yarn tries to apply its native patches.
Might be a bug on the Yarn side.
This commit is contained in:
Thaïs 2024-04-01 13:16:50 +02:00 committed by GitHub
parent 5d07b6347e
commit a3e5cf37b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 592 additions and 678 deletions

View File

@ -74,6 +74,7 @@ module.exports = {
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-unused-vars': [
'warn',
{
@ -87,6 +88,10 @@ module.exports = {
'error',
{ prefer: 'no-type-imports' },
],
'@typescript-eslint/no-empty-interface': [
'error',
{ allowSingleExtends: true },
],
},
},
{
@ -99,7 +104,15 @@ module.exports = {
env: {
jest: true,
},
rules: {},
rules: {
'@typescript-eslint/no-non-null-assertion': 'off',
},
},
{
files: ['*.stories.@(ts|tsx|js|jsx)'],
rules: {
'@typescript-eslint/no-non-null-assertion': 'off',
},
},
{
files: ['**/constants/*.ts', '**/*.constants.ts'],

View File

@ -67,7 +67,7 @@ jobs:
- name: Install Playwright
run: cd packages/twenty-front && npx playwright install
- name: Build Storybook
run: yarn nx storybook:pages:build --quiet twenty-front
run: yarn nx storybook:pages:build twenty-front --quiet
- name: Run storybook tests
run: |
cd packages/twenty-front && npx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \
@ -107,7 +107,7 @@ jobs:
- name: Install Playwright
run: cd packages/twenty-front && npx playwright install
- name: Build Storybook
run: yarn nx storybook:modules:build --quiet twenty-front
run: yarn nx storybook:modules:build twenty-front --quiet
- name: Run storybook tests
run: |
cd packages/twenty-front && npx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \

View File

@ -1,7 +1,7 @@
"use strict";
// This file should be committed to your repository! It wraps Nx and ensures
// that your local installation matches nx.json.
// See: https://nx.dev/more-concepts/nx-and-the-wrapper for more info.
// See: https://nx.dev/recipes/installation/install-non-javascript for more info.
@ -11,9 +11,12 @@ const fs = require('fs');
const path = require('path');
const cp = require('child_process');
const installationPath = path.join(__dirname, 'installation', 'package.json');
function matchesCurrentNxInstall(nxJsonInstallation) {
function matchesCurrentNxInstall(currentInstallation, nxJsonInstallation) {
if (!currentInstallation.devDependencies ||
!Object.keys(currentInstallation.devDependencies).length) {
return false;
}
try {
const currentInstallation = require(installationPath);
if (currentInstallation.devDependencies['nx'] !==
nxJsonInstallation.version ||
require(path.join(path.dirname(installationPath), 'node_modules', 'nx', 'package.json')).version !== nxJsonInstallation.version) {
@ -35,30 +38,58 @@ function ensureDir(p) {
fs.mkdirSync(p, { recursive: true });
}
}
function getCurrentInstallation() {
try {
return require(installationPath);
}
catch {
return {
name: 'nx-installation',
version: '0.0.0',
devDependencies: {},
};
}
}
function performInstallation(currentInstallation, nxJson) {
fs.writeFileSync(installationPath, JSON.stringify({
name: 'nx-installation',
devDependencies: {
nx: nxJson.installation.version,
...nxJson.installation.plugins,
},
}));
try {
cp.execSync('npm i', {
cwd: path.dirname(installationPath),
stdio: 'inherit',
});
}
catch (e) {
// revert possible changes to the current installation
fs.writeFileSync(installationPath, JSON.stringify(currentInstallation));
// rethrow
throw e;
}
}
function ensureUpToDateInstallation() {
const nxJsonPath = path.join(__dirname, '..', 'nx.json');
let nxJson;
try {
nxJson = require(nxJsonPath);
if (!nxJson.installation) {
console.error('[NX]: The "installation" entry in the "nx.json" file is required when running the nx wrapper. See https://nx.dev/recipes/installation/install-non-javascript');
process.exit(1);
}
}
catch {
console.error('[NX]: nx.json is required when running the nx wrapper. See https://nx.dev/more-concepts/nx-and-the-wrapper');
console.error('[NX]: The "nx.json" file is required when running the nx wrapper. See https://nx.dev/recipes/installation/install-non-javascript');
process.exit(1);
}
try {
ensureDir(path.join(__dirname, 'installation'));
if (!matchesCurrentNxInstall(nxJson.installation)) {
fs.writeFileSync(installationPath, JSON.stringify({
name: 'nx-installation',
devDependencies: {
nx: nxJson.installation.version,
...nxJson.installation.plugins,
},
}));
cp.execSync('npm i', {
cwd: path.dirname(installationPath),
stdio: 'inherit',
});
const currentInstallation = getCurrentInstallation();
if (!matchesCurrentNxInstall(currentInstallation, nxJson.installation)) {
performInstallation(currentInstallation, nxJson);
}
}
catch (e) {

17
nx.json
View File

@ -32,16 +32,17 @@
}
}
},
"@nx/vite:test": {
"@nx/eslint:lint": {
"cache": true,
"inputs": ["default", "^default"]
"inputs": [
"default",
"{workspaceRoot}/.eslintrc.js",
"{workspaceRoot}/tools/eslint-rules/**/*"
]
}
},
"installation": {
"version": "17.2.8"
},
"affected": {
"defaultBase": "main"
"version": "18.1.3"
},
"generators": {
"@nx/react": {
@ -70,5 +71,7 @@
"cacheableOperations": ["build-storybook"]
}
}
}
},
"useInferencePlugins": false,
"defaultBase": "main"
}

View File

@ -193,14 +193,14 @@
"@nestjs/cli": "^9.0.0",
"@nestjs/schematics": "^9.0.0",
"@nestjs/testing": "^9.0.0",
"@nx/eslint": "17.2.8",
"@nx/eslint-plugin": "17.2.8",
"@nx/jest": "17.2.8",
"@nx/js": "17.2.8",
"@nx/react": "17.2.8",
"@nx/storybook": "^17.2.8",
"@nx/vite": "17.2.8",
"@nx/web": "17.2.8",
"@nx/eslint": "18.1.3",
"@nx/eslint-plugin": "18.1.3",
"@nx/jest": "18.1.3",
"@nx/js": "18.1.3",
"@nx/react": "18.1.3",
"@nx/storybook": "18.1.3",
"@nx/vite": "18.1.3",
"@nx/web": "18.1.3",
"@storybook/addon-actions": "^7.6.3",
"@storybook/addon-coverage": "^1.0.0",
"@storybook/addon-essentials": "^7.6.7",
@ -217,7 +217,7 @@
"@storybook/test-runner": "^0.16.0",
"@storybook/testing-library": "^0.2.2",
"@stylistic/eslint-plugin": "^1.5.0",
"@swc-node/register": "~1.6.7",
"@swc-node/register": "1.8.0",
"@swc/core": "~1.3.100",
"@swc/helpers": "~0.5.2",
"@testing-library/jest-dom": "^6.1.5",
@ -245,7 +245,7 @@
"@types/lodash.upperfirst": "^4.3.7",
"@types/luxon": "^3.3.0",
"@types/ms": "^0.7.31",
"@types/node": "^20.10.6",
"@types/node": "18.19.26",
"@types/passport-google-oauth20": "^2.0.11",
"@types/passport-jwt": "^3.0.8",
"@types/react": "^18.2.39",
@ -254,12 +254,12 @@
"@types/scroll-into-view": "^1.16.0",
"@types/supertest": "^2.0.11",
"@types/uuid": "^9.0.2",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/eslint-plugin": "6.21.0",
"@typescript-eslint/experimental-utils": "^5.62.0",
"@typescript-eslint/parser": "^6.10.0",
"@typescript-eslint/utils": "^6.9.1",
"@typescript-eslint/parser": "6.21.0",
"@typescript-eslint/utils": "6.21.0",
"@vitejs/plugin-react-swc": "^3.5.0",
"@vitest/ui": "~0.34.6",
"@vitest/ui": "1.4.0",
"chromatic": "^6.18.0",
"concurrently": "^8.2.2",
"cross-var": "^1.1.0",
@ -288,7 +288,7 @@
"jsdom": "~22.1.0",
"msw": "^2.0.11",
"msw-storybook-addon": "2.0.0--canary.122.b3ed3b1.0",
"nx": "17.2.8",
"nx": "18.1.3",
"playwright": "^1.40.1",
"prettier": "^3.1.1",
"raw-loader": "^4.0.2",
@ -307,7 +307,7 @@
"vite-plugin-checker": "^0.6.2",
"vite-plugin-dts": "~2.3.0",
"vite-plugin-svgr": "^4.2.0",
"vitest": "~0.34.6"
"vitest": "1.4.0"
},
"engines": {
"node": "^18.17.1",

View File

@ -31,7 +31,9 @@ import { App } from './App';
import './index.css';
import 'react-loading-skeleton/dist/skeleton.css';
const root = ReactDOM.createRoot(document.getElementById('root')!);
const root = ReactDOM.createRoot(
document.getElementById('root') ?? document.body,
);
root.render(
<RecoilRoot>

View File

@ -30,7 +30,9 @@ export const loggerLink = (getSchemaName: (operation: Operation) => string) =>
const operationType = (operation.query.definitions[0] as any).operation;
const headers = operation.getContext().headers;
const [queryName, query] = parseQuery(operation.query.loc!.source.body);
const [queryName, query] = parseQuery(
operation.query.loc?.source.body ?? '',
);
if (operationType === 'subscription') {
const date = new Date().toLocaleTimeString();

View File

@ -108,7 +108,8 @@ export const useAuth = () => {
.filter(
({ workspace }) => workspace !== null && workspace !== undefined,
)
.map((validWorkspace) => validWorkspace.workspace!);
.map((validWorkspace) => validWorkspace.workspace)
.filter(isDefined);
setWorkspaces(validWorkspaces);
}

View File

@ -53,7 +53,7 @@ export const RecordDetailSectionHeader = ({
<StyledTitleLabel>{title}</StyledTitleLabel>
{link && <StyledLink to={link.to}>{link.label}</StyledLink>}
</StyledTitle>
{hideRightAdornmentOnMouseLeave && !isHovered! ? null : rightAdornment}
{hideRightAdornmentOnMouseLeave && !isHovered ? null : rightAdornment}
</StyledHeader>
);
};

View File

@ -6,8 +6,8 @@ import { beautifyDateDiff } from '~/utils/date-utils';
export const formatExpiration = (
expiresAt: string | null,
withExpiresMention: boolean = false,
short: boolean = true,
withExpiresMention = false,
short = true,
) => {
if (isNonEmptyString(expiresAt)) {
const dateDiff = beautifyDateDiff(expiresAt, undefined, short);

View File

@ -103,7 +103,7 @@ export const MultiWorkspaceDropdownButton = ({
{workspaces.map((workspace) => (
<MenuItemSelectAvatar
key={workspace.id}
text={workspace.displayName!}
text={workspace.displayName ?? ''}
avatar={
<StyledLogo
logo={

View File

@ -5,9 +5,10 @@ import { useSetRecoilState } from 'recoil';
import { currentUserState } from '@/auth/states/currentUserState';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { Workspaces, workspacesState } from '@/auth/states/workspaces';
import { workspacesState } from '@/auth/states/workspaces';
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
import { User } from '~/generated/graphql';
import { isDefined } from '~/utils/isDefined';
export const UserProvider = ({ children }: React.PropsWithChildren) => {
@ -21,32 +22,34 @@ export const UserProvider = ({ children }: React.PropsWithChildren) => {
currentWorkspaceMemberState,
);
const { loading: queryLoading, data: queryData } = useQuery(GET_CURRENT_USER);
const { loading: queryLoading, data: queryData } = useQuery<{
currentUser: User;
}>(GET_CURRENT_USER);
useEffect(() => {
if (!queryLoading) {
setIsLoading(false);
}
if (isDefined(queryData?.currentUser)) {
setCurrentUser(queryData.currentUser);
setCurrentWorkspace(queryData.currentUser.defaultWorkspace);
}
if (isDefined(queryData?.currentUser?.workspaceMember)) {
const workspaceMember = queryData.currentUser.workspaceMember;
if (!isDefined(queryData?.currentUser)) return;
setCurrentUser(queryData.currentUser);
setCurrentWorkspace(queryData.currentUser.defaultWorkspace);
const { workspaceMember, workspaces: userWorkspaces } =
queryData.currentUser;
if (isDefined(workspaceMember)) {
setCurrentWorkspaceMember({
...workspaceMember,
colorScheme: (workspaceMember.colorScheme as ColorScheme) ?? 'Light',
});
}
if (isDefined(queryData?.currentUser?.workspaces)) {
const validWorkspaces = queryData.currentUser.workspaces.filter(
(obj: any) => obj.workspace !== null && obj.workspace !== undefined,
);
const workspaces: Workspaces[] = [];
validWorkspaces.forEach((validWorkspace: any) => {
const workspace = validWorkspace.workspace! as Workspaces;
workspaces.push(workspace);
});
if (isDefined(userWorkspaces)) {
const workspaces = userWorkspaces
.map(({ workspace }) => workspace)
.filter(isDefined);
setWorkspaces(workspaces);
}

View File

@ -116,7 +116,7 @@ export const hasDatePassed = (date: Date | string | number) => {
export const beautifyDateDiff = (
date: string,
dateToCompareWith?: string,
short: boolean = false,
short = false,
) => {
const dateDiff = DateTime.fromISO(date).diff(
dateToCompareWith ? DateTime.fromISO(dateToCompareWith) : DateTime.now(),

View File

@ -33,7 +33,7 @@
},
"devDependencies": {
"@nestjs/cli": "10.3.0",
"@nx/js": "17.2.8",
"@nx/js": "18.1.3",
"@types/lodash.differencewith": "^4.5.9",
"@types/lodash.isempty": "^4.4.7",
"@types/lodash.isequal": "^4.5.8",

View File

@ -5,24 +5,17 @@
"targets": {
"lint": {
"executor": "@nx/eslint:lint",
"outputs": [
"{options.outputFile}"
],
"options": {
"lintFilePatterns": [
"tools/eslint-rules/**/*.ts"
],
"lintFilePatterns": ["{projectRoot}/**/*.ts"],
"fix": true
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": [
"{workspaceRoot}/coverage/{projectRoot}"
],
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "tools/eslint-rules/jest.config.ts"
}
}
}
}
}

1066
yarn.lock

File diff suppressed because it is too large Load Diff