Skip to content

Commit

Permalink
Enforce front project structure through ESLINT (#7863)
Browse files Browse the repository at this point in the history
Fixes: #7329
  • Loading branch information
charlesBochet authored Oct 20, 2024
1 parent f801f3a commit eccf0bf
Show file tree
Hide file tree
Showing 260 changed files with 500 additions and 290 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

.nx/installation
.nx/cache
projectStructure.cache.json

.pnp.*
.yarn/*
Expand Down
2 changes: 1 addition & 1 deletion nx.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
"outputs": ["{projectRoot}/{options.output-dir}"],
"options": {
"cwd": "{projectRoot}",
"command": "storybook build",
"command": "VITE_DISABLE_ESLINT_CHECKER=true storybook build",
"output-dir": "storybook-static",
"config-dir": ".storybook"
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-prefer-arrow": "^1.2.3",
"eslint-plugin-prettier": "^5.1.2",
"eslint-plugin-project-structure": "^3.7.2",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.4",
Expand Down
9 changes: 8 additions & 1 deletion packages/twenty-front/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ module.exports = {
parserOptions: {
project: ['packages/twenty-front/tsconfig.{json,*.json}'],
},
rules: {},
plugins: ['project-structure'],
settings: {
'project-structure/folder-structure-config-path':
'packages/twenty-front/folderStructure.json',
},
rules: {
'project-structure/folder-structure': 'error',
},
},
],
};
81 changes: 81 additions & 0 deletions packages/twenty-front/folderStructure.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{
"$schema": "../../node_modules/eslint-plugin-project-structure/folderStructure.schema.json",
"regexParameters": {
"camelCase": "^[a-z]+([A-Za-z0-9]+)+"
},
"structure": [
{
"name": "packages",
"children": [
{
"name": "twenty-front",
"children": [
{ "name": "*", "children": [] },
{ "name": "*" },
{
"name": "src",
"children": [
{ "name": "*", "children": [] },
{ "name": "*" },
{
"name": "modules",
"children": [
{ "ruleId": "moduleFolderRule" },
{ "name": "types", "ruleId": "doNotCheckLeafFolderRule" }
]
}
]
}
]
}
]
}
],
"rules": {
"moduleFolderRule": {
"name": "^(?!utils$|hooks$|states$|types$|graphql$|components$|effect-components$|constants$|validation-schemas$|contexts$|scopes$|services$|errors$)[a-z][a-z0-9]**(?:-[a-z0-9]+)**$",
"folderRecursionLimit": 6,
"children": [
{ "ruleId": "moduleFolderRule" },
{ "name": "hooks", "ruleId": "hooksLeafFolderRule" },
{ "name": "utils", "ruleId": "utilsLeafFolderRule" },
{ "name": "states", "ruleId": "doNotCheckLeafFolderRule" },
{ "name": "types", "ruleId": "doNotCheckLeafFolderRule" },
{ "name": "graphql", "ruleId": "doNotCheckLeafFolderRule" },
{ "name": "components", "ruleId": "doNotCheckLeafFolderRule" },
{ "name": "effect-components", "ruleId": "doNotCheckLeafFolderRule" },
{ "name": "constants", "ruleId": "doNotCheckLeafFolderRule" },
{ "name": "validation-schemas", "ruleId": "doNotCheckLeafFolderRule" },
{ "name": "contexts", "ruleId": "doNotCheckLeafFolderRule" },
{ "name": "scopes", "ruleId": "doNotCheckLeafFolderRule" },
{ "name": "services", "ruleId": "doNotCheckLeafFolderRule" },
{ "name": "errors", "ruleId": "doNotCheckLeafFolderRule" }
]
},
"hooksLeafFolderRule": {
"folderRecursionLimit": 2,
"children": [
{ "name": "use{PascalCase}.(ts|tsx)" },
{
"name": "__tests__",
"children": [{ "name": "use{PascalCase}.test.(ts|tsx)" }]
},
{ "name": "internal", "ruleId": "hooksLeafFolderRule" }
]
},
"doNotCheckLeafFolderRule": {
"folderRecursionLimit": 1,
"children": [{ "name": "*" }, { "name": "*", "children": [] }]
},
"utilsLeafFolderRule": {
"folderRecursionLimit": 1,
"children": [
{ "name": "{camelCase}.ts" },
{
"name": "__tests__",
"children": [{ "name": "{camelCase}.test.ts" }]
}
]
}
}
}
4 changes: 2 additions & 2 deletions packages/twenty-front/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ const jestConfig: JestConfigWithTsJest = {
extensionsToTreatAsEsm: ['.ts', '.tsx'],
coverageThreshold: {
global: {
statements: 60,
statements: 59,
lines: 55,
functions: 50,
functions: 49,
},
},
collectCoverageFrom: ['<rootDir>/src/**/*.ts'],
Expand Down
4 changes: 3 additions & 1 deletion packages/twenty-front/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@
"reportUnusedDisableDirectives": "error"
},
"configurations": {
"ci": { "eslintConfig": "{projectRoot}/.eslintrc-ci.cjs" },
"ci": {
"eslintConfig": "{projectRoot}/.eslintrc-ci.cjs"
},
"fix": {}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { AppThemeProvider } from '@/ui/theme/components/AppThemeProvider';
import { isDefined } from '~/utils/isDefined';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';

import { AttachmentIcon } from '../files/components/AttachmentIcon';
import { AttachmentType } from '../files/types/Attachment';
import { getFileType } from '../files/utils/getFileType';
import { AttachmentIcon } from '../../files/components/AttachmentIcon';
import { AttachmentType } from '../../files/types/Attachment';
import { getFileType } from '../../files/utils/getFileType';

const StyledFileInput = styled.input`
display: none;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { BlockNoteSchema, defaultBlockSpecs } from '@blocknote/core';

import { FileBlock } from './FileBlock';
import { FileBlock } from '../components/FileBlock';

export const blockSchema = BlockNoteSchema.create({
export const BLOCK_SCHEMA = BlockNoteSchema.create({
blockSpecs: {
...defaultBlockSpecs,
file: FileBlock,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {

import { SuggestionItem } from '@/ui/input/editor/components/CustomSlashMenu';

import { blockSchema } from './schema';
import { BLOCK_SCHEMA } from '../constants/Schema';

const Icons: Record<string, IconComponent> = {
'Heading 1': IconH1,
Expand All @@ -35,7 +35,7 @@ const Icons: Record<string, IconComponent> = {
Emoji: IconMoodSmile,
};

export const getSlashMenu = (editor: typeof blockSchema.BlockNoteEditor) => {
export const getSlashMenu = (editor: typeof BLOCK_SCHEMA.BlockNoteEditor) => {
const items: SuggestionItem[] = [
...getDefaultReactSlashMenuItems(editor).map((x) => ({
...x,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { H3Title } from 'twenty-ui';
import { CalendarMonthCard } from '@/activities/calendar/components/CalendarMonthCard';
import { TIMELINE_CALENDAR_EVENTS_DEFAULT_PAGE_SIZE } from '@/activities/calendar/constants/Calendar';
import { CalendarContext } from '@/activities/calendar/contexts/CalendarContext';
import { getTimelineCalendarEventsFromCompanyId } from '@/activities/calendar/graphql/queries/getTimelineCalendarEventsFromCompanyId';
import { getTimelineCalendarEventsFromPersonId } from '@/activities/calendar/graphql/queries/getTimelineCalendarEventsFromPersonId';
import { useCalendarEvents } from '@/activities/calendar/hooks/useCalendarEvents';
import { getTimelineCalendarEventsFromCompanyId } from '@/activities/calendar/queries/getTimelineCalendarEventsFromCompanyId';
import { getTimelineCalendarEventsFromPersonId } from '@/activities/calendar/queries/getTimelineCalendarEventsFromPersonId';
import { CustomResolverFetchMoreLoader } from '@/activities/components/CustomResolverFetchMoreLoader';
import { SkeletonLoader } from '@/activities/components/SkeletonLoader';
import { useCustomResolver } from '@/activities/hooks/useCustomResolver';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { getOperationName } from '@apollo/client/utilities';
import { Meta, StoryObj } from '@storybook/react';
import { graphql, HttpResponse } from 'msw';
import { HttpResponse, graphql } from 'msw';
import { ComponentDecorator } from 'twenty-ui';

import { Calendar } from '@/activities/calendar/components/Calendar';
import { getTimelineCalendarEventsFromCompanyId } from '@/activities/calendar/queries/getTimelineCalendarEventsFromCompanyId';
import { getTimelineCalendarEventsFromCompanyId } from '@/activities/calendar/graphql/queries/getTimelineCalendarEventsFromCompanyId';
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { timelineCalendarEventParticipantFragment } from '@/activities/calendar/graphql/queries/fragments/timelineCalendarEventParticipantFragment';
import { gql } from '@apollo/client';

import { timelineCalendarEventParticipantFragment } from '@/activities/calendar/queries/fragments/timelineCalendarEventParticipantFragment';

export const timelineCalendarEventFragment = gql`
fragment TimelineCalendarEventFragment on TimelineCalendarEvent {
id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { timelineCalendarEventFragment } from '@/activities/calendar/graphql/queries/fragments/timelineCalendarEventFragment';
import { gql } from '@apollo/client';

import { timelineCalendarEventFragment } from '@/activities/calendar/queries/fragments/timelineCalendarEventFragment';

export const timelineCalendarEventWithTotalFragment = gql`
fragment TimelineCalendarEventsWithTotalFragment on TimelineCalendarEventsWithTotal {
totalNumberOfCalendarEvents
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { timelineCalendarEventWithTotalFragment } from '@/activities/calendar/graphql/queries/fragments/timelineCalendarEventWithTotalFragment';
import { gql } from '@apollo/client';

import { timelineCalendarEventWithTotalFragment } from '@/activities/calendar/queries/fragments/timelineCalendarEventWithTotalFragment';

export const getTimelineCalendarEventsFromCompanyId = gql`
query GetTimelineCalendarEventsFromCompanyId(
$companyId: UUID!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { timelineCalendarEventWithTotalFragment } from '@/activities/calendar/graphql/queries/fragments/timelineCalendarEventWithTotalFragment';
import { gql } from '@apollo/client';

import { timelineCalendarEventWithTotalFragment } from '@/activities/calendar/queries/fragments/timelineCalendarEventWithTotalFragment';

export const getTimelineCalendarEventsFromPersonId = gql`
query GetTimelineCalendarEventsFromPersonId(
$personId: UUID!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { Key } from 'ts-key-enum';
import { useDebouncedCallback } from 'use-debounce';
import { v4 } from 'uuid';

import { blockSchema } from '@/activities/blocks/schema';
import { useUpsertActivity } from '@/activities/hooks/useUpsertActivity';
import { activityBodyFamilyState } from '@/activities/states/activityBodyFamilyState';
import { activityTitleHasBeenSetFamilyState } from '@/activities/states/activityTitleHasBeenSetFamilyState';
Expand All @@ -27,6 +26,7 @@ import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';

import { getFileType } from '../files/utils/getFileType';

import { BLOCK_SCHEMA } from '@/activities/blocks/constants/Schema';
import { Note } from '@/activities/types/Note';
import { Task } from '@/activities/types/Task';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
Expand Down Expand Up @@ -287,7 +287,7 @@ export const RichTextEditor = ({
const editor = useCreateBlockNote({
initialContent: initialBody,
domAttributes: { editor: { class: 'editor' } },
schema: blockSchema,
schema: BLOCK_SCHEMA,
uploadFile: handleUploadAttachment,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { CustomResolverFetchMoreLoader } from '@/activities/components/CustomRes
import { SkeletonLoader } from '@/activities/components/SkeletonLoader';
import { EmailThreadPreview } from '@/activities/emails/components/EmailThreadPreview';
import { TIMELINE_THREADS_DEFAULT_PAGE_SIZE } from '@/activities/emails/constants/Messaging';
import { getTimelineThreadsFromCompanyId } from '@/activities/emails/queries/getTimelineThreadsFromCompanyId';
import { getTimelineThreadsFromPersonId } from '@/activities/emails/queries/getTimelineThreadsFromPersonId';
import { getTimelineThreadsFromCompanyId } from '@/activities/emails/graphql/queries/getTimelineThreadsFromCompanyId';
import { getTimelineThreadsFromPersonId } from '@/activities/emails/graphql/queries/getTimelineThreadsFromPersonId';
import { useCustomResolver } from '@/activities/hooks/useCustomResolver';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { gql } from '@apollo/client';

import { participantFragment } from '@/activities/emails/queries/fragments/participantFragment';
import { participantFragment } from '@/activities/emails/graphql/queries/fragments/participantFragment';

export const timelineThreadFragment = gql`
fragment TimelineThreadFragment on TimelineThread {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { timelineThreadFragment } from '@/activities/emails/graphql/queries/fragments/timelineThreadFragment';
import { gql } from '@apollo/client';

import { timelineThreadFragment } from '@/activities/emails/queries/fragments/timelineThreadFragment';

export const timelineThreadWithTotalFragment = gql`
fragment TimelineThreadsWithTotalFragment on TimelineThreadsWithTotal {
totalNumberOfThreads
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { timelineThreadWithTotalFragment } from '@/activities/emails/graphql/queries/fragments/timelineThreadWithTotalFragment';
import { gql } from '@apollo/client';

import { timelineThreadWithTotalFragment } from '@/activities/emails/queries/fragments/timelineThreadWithTotalFragment';

export const getTimelineThreadsFromCompanyId = gql`
query GetTimelineThreadsFromCompanyId(
$companyId: UUID!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { gql } from '@apollo/client';

import { timelineThreadWithTotalFragment } from '@/activities/emails/queries/fragments/timelineThreadWithTotalFragment';
import { timelineThreadWithTotalFragment } from '@/activities/emails/graphql/queries/fragments/timelineThreadWithTotalFragment';

export const getTimelineThreadsFromPersonId = gql`
query GetTimelineThreadsFromPersonId(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useRecoilValue } from 'recoil';

import { usePrepareFindManyActivitiesQuery } from '@/activities/hooks/usePrepareFindManyActivitiesQuery';
import { objectShowPageTargetableObjectState } from '@/activities/timelineActivities/states/objectShowPageTargetableObjectIdState';
import { objectShowPageTargetableObjectState } from '@/activities/timeline-activities/states/objectShowPageTargetableObjectIdState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { isDefined } from '~/utils/isDefined';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useCreateActivityInDB } from '@/activities/hooks/useCreateActivityInDB'
import { useRefreshShowPageFindManyActivitiesQueries } from '@/activities/hooks/useRefreshShowPageFindManyActivitiesQueries';
import { isActivityInCreateModeState } from '@/activities/states/isActivityInCreateModeState';
import { isUpsertingActivityInDBState } from '@/activities/states/isCreatingActivityInDBState';
import { objectShowPageTargetableObjectState } from '@/activities/timelineActivities/states/objectShowPageTargetableObjectIdState';
import { objectShowPageTargetableObjectState } from '@/activities/timeline-activities/states/objectShowPageTargetableObjectIdState';
import { Note } from '@/activities/types/Note';
import { Task } from '@/activities/types/Task';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useRecoilState } from 'recoil';

import { useActivities } from '@/activities/hooks/useActivities';
import { currentNotesQueryVariablesState } from '@/activities/notes/states/currentNotesQueryVariablesState';
import { FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY } from '@/activities/timelineActivities/constants/FindManyTimelineActivitiesOrderBy';
import { FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY } from '@/activities/timeline-activities/constants/FindManyTimelineActivitiesOrderBy';
import { Note } from '@/activities/types/Note';
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { PageAddButton } from '@/ui/layout/page/PageAddButton';
import { PageAddButton } from '@/ui/layout/page/components/PageAddButton';

export const PageAddTaskButton = () => {
const openCreateActivity = useOpenCreateActivityDrawer({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useActivities } from '@/activities/hooks/useActivities';
import { FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY } from '@/activities/timelineActivities/constants/FindManyTimelineActivitiesOrderBy';
import { FIND_MANY_TIMELINE_ACTIVITIES_ORDER_BY } from '@/activities/timeline-activities/constants/FindManyTimelineActivitiesOrderBy';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import { Task } from '@/activities/types/Task';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import styled from '@emotion/styled';
import { ReactElement } from 'react';

import { EventsGroup } from '@/activities/timelineActivities/components/EventsGroup';
import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity';
import { filterOutInvalidTimelineActivities } from '@/activities/timelineActivities/utils/filterOutInvalidTimelineActivities';
import { groupEventsByMonth } from '@/activities/timelineActivities/utils/groupEventsByMonth';
import { EventsGroup } from '@/activities/timeline-activities/components/EventsGroup';
import { TimelineActivity } from '@/activities/timeline-activities/types/TimelineActivity';
import { filterOutInvalidTimelineActivities } from '@/activities/timeline-activities/utils/filterOutInvalidTimelineActivities';
import { groupEventsByMonth } from '@/activities/timeline-activities/utils/groupEventsByMonth';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import styled from '@emotion/styled';
import { useContext } from 'react';
import { useRecoilValue } from 'recoil';

import { TimelineActivityContext } from '@/activities/timelineActivities/contexts/TimelineActivityContext';
import { TimelineActivityContext } from '@/activities/timeline-activities/contexts/TimelineActivityContext';

import { useLinkedObjectObjectMetadataItem } from '@/activities/timelineActivities/hooks/useLinkedObjectObjectMetadataItem';
import { EventIconDynamicComponent } from '@/activities/timelineActivities/rows/components/EventIconDynamicComponent';
import { EventRowDynamicComponent } from '@/activities/timelineActivities/rows/components/EventRowDynamicComponent';
import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity';
import { getTimelineActivityAuthorFullName } from '@/activities/timelineActivities/utils/getTimelineActivityAuthorFullName';
import { useLinkedObjectObjectMetadataItem } from '@/activities/timeline-activities/hooks/useLinkedObjectObjectMetadataItem';
import { EventIconDynamicComponent } from '@/activities/timeline-activities/rows/components/EventIconDynamicComponent';
import { EventRowDynamicComponent } from '@/activities/timeline-activities/rows/components/EventRowDynamicComponent';
import { TimelineActivity } from '@/activities/timeline-activities/types/TimelineActivity';
import { getTimelineActivityAuthorFullName } from '@/activities/timeline-activities/utils/getTimelineActivityAuthorFullName';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { beautifyPastDateRelativeToNow } from '~/utils/date-utils';
Expand Down
Loading

0 comments on commit eccf0bf

Please sign in to comment.