diff --git a/.eslintrc.js b/.eslintrc.js index d7ba8189..79240d46 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -37,6 +37,13 @@ module.exports = { }, ], curly: 'error', + 'import/order': [ + 'error', + { + groups: [['external', 'builtin']], + 'newlines-between': 'always', + }, + ], 'jsx-a11y/anchor-is-valid': 'off', 'no-console': 'error', 'no-switch-statements/no-switch': 'error', @@ -78,14 +85,6 @@ module.exports = { html: true, }, ], - 'sort-imports': [ - 'error', - { - ignoreCase: true, - allowSeparatedGroups: true, - memberSyntaxSortOrder: ['none', 'all', 'single', 'multiple'], - }, - ], 'sort-keys': 'error', 'sort-vars': 'error', }, diff --git a/package.json b/package.json index 3f71bcd3..003d12f9 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "eslint": "^7.15.0", "eslint-config-next": "13.5.6", "eslint-config-prettier": "^8.3.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-next": "^0.0.0", "eslint-plugin-no-switch-statements": "^1.0.0", diff --git a/webapp/src/RepoGit.ts b/webapp/src/RepoGit.ts index 66601ade..d633becb 100644 --- a/webapp/src/RepoGit.ts +++ b/webapp/src/RepoGit.ts @@ -1,14 +1,15 @@ -import { Cache } from '@/Cache'; import fs from 'fs'; import fsp from 'fs/promises'; +import { Octokit } from '@octokit/rest'; +import path from 'path'; +import { stringify } from 'yaml'; + +import { Cache } from '@/Cache'; import { IGit } from '@/utils/git/IGit'; import { LyraConfig } from '@/utils/lyraConfig'; -import { Octokit } from '@octokit/rest'; import packageJson from '../package.json'; -import path from 'path'; import { ServerProjectConfig } from '@/utils/serverConfig'; import { SimpleGitWrapper } from '@/utils/git/SimpleGitWrapper'; -import { stringify } from 'yaml'; import { unflattenObject } from '@/utils/unflattenObject'; import { debug, info, warn } from '@/utils/log'; import { WriteLanguageFileError, WriteLanguageFileErrors } from '@/errors'; diff --git a/webapp/src/app/api/messages/[projectName]/route.ts b/webapp/src/app/api/messages/[projectName]/route.ts index abc4e68b..a796a289 100644 --- a/webapp/src/app/api/messages/[projectName]/route.ts +++ b/webapp/src/app/api/messages/[projectName]/route.ts @@ -1,3 +1,5 @@ +import { NextRequest, NextResponse } from 'next/server'; + import MessageAdapterFactory from '@/utils/adapters/MessageAdapterFactory'; import { RepoGit } from '@/RepoGit'; import { ServerConfig } from '@/utils/serverConfig'; @@ -6,7 +8,6 @@ import { ProjectNameNotFoundError, ProjectPathNotFoundError, } from '@/errors'; -import { NextRequest, NextResponse } from 'next/server'; export async function GET( req: NextRequest, diff --git a/webapp/src/app/api/projects/route.ts b/webapp/src/app/api/projects/route.ts index e332fbfa..3a5c3919 100644 --- a/webapp/src/app/api/projects/route.ts +++ b/webapp/src/app/api/projects/route.ts @@ -1,4 +1,5 @@ import { NextResponse } from 'next/server'; + import { ServerConfig } from '@/utils/serverConfig'; import { ServerConfigReadingError } from '@/errors'; import { type ProjectItem, type ProjectsResponse } from '@/types'; diff --git a/webapp/src/app/api/pull-request/[projectName]/route.ts b/webapp/src/app/api/pull-request/[projectName]/route.ts index 172c220e..928e9326 100644 --- a/webapp/src/app/api/pull-request/[projectName]/route.ts +++ b/webapp/src/app/api/pull-request/[projectName]/route.ts @@ -1,6 +1,7 @@ +import { NextRequest, NextResponse } from 'next/server'; + import { ProjectNameNotFoundError } from '@/errors'; import { RepoGit } from '@/RepoGit'; -import { NextRequest, NextResponse } from 'next/server'; import { ServerConfig, ServerProjectConfig } from '@/utils/serverConfig'; /** used to prevent multiple requests from running at the same time */ diff --git a/webapp/src/app/api/translations/[projectName]/[languageName]/[messageId]/route.ts b/webapp/src/app/api/translations/[projectName]/[languageName]/[messageId]/route.ts index d067158f..5f232b2f 100644 --- a/webapp/src/app/api/translations/[projectName]/[languageName]/[messageId]/route.ts +++ b/webapp/src/app/api/translations/[projectName]/[languageName]/[messageId]/route.ts @@ -1,3 +1,5 @@ +import { NextRequest, NextResponse } from 'next/server'; + import { Cache } from '@/Cache'; import { RepoGit } from '@/RepoGit'; import { ServerConfig } from '@/utils/serverConfig'; @@ -8,7 +10,6 @@ import { ProjectNameNotFoundError, ProjectPathNotFoundError, } from '@/errors'; -import { NextRequest, NextResponse } from 'next/server'; export async function PUT( req: NextRequest, diff --git a/webapp/src/app/api/translations/[projectName]/[languageName]/route.ts b/webapp/src/app/api/translations/[projectName]/[languageName]/route.ts index 7124b1e9..871388ef 100644 --- a/webapp/src/app/api/translations/[projectName]/[languageName]/route.ts +++ b/webapp/src/app/api/translations/[projectName]/[languageName]/route.ts @@ -1,10 +1,11 @@ +import { NextRequest, NextResponse } from 'next/server'; + import { Cache } from '@/Cache'; import { LanguageNotFound, LanguageNotSupported, ProjectNameNotFoundError, } from '@/errors'; -import { NextRequest, NextResponse } from 'next/server'; export async function GET( req: NextRequest, // keep this here even if unused diff --git a/webapp/src/app/projects/[projectName]/[languageName]/page.tsx b/webapp/src/app/projects/[projectName]/[languageName]/page.tsx index 15aeb800..1aeaa244 100644 --- a/webapp/src/app/projects/[projectName]/[languageName]/page.tsx +++ b/webapp/src/app/projects/[projectName]/[languageName]/page.tsx @@ -1,10 +1,11 @@ 'use client'; +import { Box, Button, Input, Link, Typography } from '@mui/joy'; +import { useEffect, useMemo, useState } from 'react'; + import { type MessageData } from '@/utils/adapters'; import MessageForm from '@/components/MessageForm'; import { SafeRecord } from '@/utils/types'; -import { Box, Button, Input, Link, Typography } from '@mui/joy'; -import { useEffect, useMemo, useState } from 'react'; export default function Home(context: { params: { languageName: string; projectName: string }; diff --git a/webapp/src/app/projects/[projectName]/page.tsx b/webapp/src/app/projects/[projectName]/page.tsx index 26365a1e..24c30d71 100644 --- a/webapp/src/app/projects/[projectName]/page.tsx +++ b/webapp/src/app/projects/[projectName]/page.tsx @@ -1,7 +1,8 @@ -import { Cache } from '@/Cache'; -import MessageAdapterFactory from '@/utils/adapters/MessageAdapterFactory'; import { NextPage } from 'next'; import { notFound } from 'next/navigation'; + +import { Cache } from '@/Cache'; +import MessageAdapterFactory from '@/utils/adapters/MessageAdapterFactory'; import ProjectDashboard from '@/components/ProjectDashboard'; import { RepoGit } from '@/RepoGit'; import { ServerConfig } from '@/utils/serverConfig'; diff --git a/webapp/src/app/projects/page.tsx b/webapp/src/app/projects/page.tsx index 2018b32b..f77d9044 100644 --- a/webapp/src/app/projects/page.tsx +++ b/webapp/src/app/projects/page.tsx @@ -1,8 +1,9 @@ 'use client'; -import { type ProjectsResponse } from '@/types'; import { useEffect, useState } from 'react'; +import { type ProjectsResponse } from '@/types'; + export default function Home() { const [projectsResponse, setProjectsResponse] = useState({ projects: [], diff --git a/webapp/src/components/HomeDashboard.tsx b/webapp/src/components/HomeDashboard.tsx index 5c57d13c..6745df06 100644 --- a/webapp/src/components/HomeDashboard.tsx +++ b/webapp/src/components/HomeDashboard.tsx @@ -1,6 +1,7 @@ -import { CardGrid } from '@/components/CardGrid'; import { FC } from 'react'; import { Box, Typography } from '@mui/joy'; + +import { CardGrid } from '@/components/CardGrid'; import ProjectCard, { ProjectCardProps } from '@/components/ProjectCard'; type HomeDashboardProps = { diff --git a/webapp/src/components/MessageForm.tsx b/webapp/src/components/MessageForm.tsx index f1944828..a7edaea2 100644 --- a/webapp/src/components/MessageForm.tsx +++ b/webapp/src/components/MessageForm.tsx @@ -1,4 +1,3 @@ -import { type MessageData } from '@/utils/adapters'; import { Box, Button, @@ -10,6 +9,8 @@ import { } from '@mui/joy'; import { FC, useEffect, useState } from 'react'; +import { type MessageData } from '@/utils/adapters'; + type Props = { message: MessageData; // eslint-disable-next-line no-unused-vars diff --git a/webapp/src/components/ProjectDashboard.tsx b/webapp/src/components/ProjectDashboard.tsx index 9a344cbd..7d1bd812 100644 --- a/webapp/src/components/ProjectDashboard.tsx +++ b/webapp/src/components/ProjectDashboard.tsx @@ -1,9 +1,10 @@ 'use client'; -import { CardGrid } from '@/components/CardGrid'; import { FC } from 'react'; import Link from 'next/link'; import { Box, Typography, useTheme } from '@mui/joy'; + +import { CardGrid } from '@/components/CardGrid'; import LanguageCard, { LanguageCardProps } from '@/components/LanguageCard'; type ProjectDashboardProps = { diff --git a/webapp/src/store/ProjectStore.spec.ts b/webapp/src/store/ProjectStore.spec.ts index 526dcab3..c18c12ee 100644 --- a/webapp/src/store/ProjectStore.spec.ts +++ b/webapp/src/store/ProjectStore.spec.ts @@ -1,5 +1,6 @@ -import { ProjectStore } from './ProjectStore'; import { describe, expect, it } from '@jest/globals'; + +import { ProjectStore } from './ProjectStore'; import { LanguageNotFound, MessageNotFound } from '@/errors'; describe('ProjectStore', () => { diff --git a/webapp/src/store/Store.spec.ts b/webapp/src/store/Store.spec.ts index 9e880bbc..9c1c21d4 100644 --- a/webapp/src/store/Store.spec.ts +++ b/webapp/src/store/Store.spec.ts @@ -1,6 +1,7 @@ +import { describe, expect, it } from '@jest/globals'; + import { ProjectStore } from '@/store/ProjectStore'; import { Store } from './Store'; -import { describe, expect, it } from '@jest/globals'; describe('Store', () => { describe('getProjectStore()', () => { diff --git a/webapp/src/utils/adapters/TsMessageAdapter.spec.ts b/webapp/src/utils/adapters/TsMessageAdapter.spec.ts index c331d9d8..49b053bd 100644 --- a/webapp/src/utils/adapters/TsMessageAdapter.spec.ts +++ b/webapp/src/utils/adapters/TsMessageAdapter.spec.ts @@ -1,8 +1,9 @@ -import { type MessageData } from '.'; import mock from 'mock-fs'; -import TsMessageAdapter from './TsMessageAdapter'; import { afterEach, describe, expect, it } from '@jest/globals'; +import { type MessageData } from '.'; +import TsMessageAdapter from './TsMessageAdapter'; + describe('TsMessageAdapter', () => { afterEach(() => { mock.restore(); diff --git a/webapp/src/utils/adapters/TsMessageAdapter.ts b/webapp/src/utils/adapters/TsMessageAdapter.ts index 284a5f6e..e3d5a16b 100644 --- a/webapp/src/utils/adapters/TsMessageAdapter.ts +++ b/webapp/src/utils/adapters/TsMessageAdapter.ts @@ -1,5 +1,6 @@ import fs from 'fs/promises'; import path from 'path'; + import readTypedMessages from '../readTypedMessages'; import { IMessageAdapter, type MessageData } from '.'; diff --git a/webapp/src/utils/adapters/YamlMessageAdapter.spec.ts b/webapp/src/utils/adapters/YamlMessageAdapter.spec.ts index 0ff8b75e..ebcc8e56 100644 --- a/webapp/src/utils/adapters/YamlMessageAdapter.spec.ts +++ b/webapp/src/utils/adapters/YamlMessageAdapter.spec.ts @@ -1,8 +1,9 @@ -import { type MessageData } from '.'; import mock from 'mock-fs'; -import YamlMessageAdapter from './YamlMessageAdapter'; import { afterEach, describe, expect, it } from '@jest/globals'; +import { type MessageData } from '.'; +import YamlMessageAdapter from './YamlMessageAdapter'; + describe('YamlMessageAdapter', () => { describe('getMessages()', () => { afterEach(() => { diff --git a/webapp/src/utils/adapters/YamlMessageAdapter.ts b/webapp/src/utils/adapters/YamlMessageAdapter.ts index db4a065b..5f176ac8 100644 --- a/webapp/src/utils/adapters/YamlMessageAdapter.ts +++ b/webapp/src/utils/adapters/YamlMessageAdapter.ts @@ -1,7 +1,8 @@ -import flattenObject from '../flattenObject'; import fs from 'fs/promises'; import { parse } from 'yaml'; import path from 'path'; + +import flattenObject from '../flattenObject'; import { IMessageAdapter, type MessageData } from '.'; export default class YamlMessageAdapter implements IMessageAdapter { diff --git a/webapp/src/utils/adapters/YamlTranslationAdapter.spec.ts b/webapp/src/utils/adapters/YamlTranslationAdapter.spec.ts index 08689b38..8540582e 100644 --- a/webapp/src/utils/adapters/YamlTranslationAdapter.spec.ts +++ b/webapp/src/utils/adapters/YamlTranslationAdapter.spec.ts @@ -1,7 +1,8 @@ import mock from 'mock-fs'; -import YamlTranslationAdapter from './YamlTranslationAdapter'; import { afterEach, describe, expect, it } from '@jest/globals'; +import YamlTranslationAdapter from './YamlTranslationAdapter'; + describe('YamlTranslationAdapter', () => { describe('getTranslations()', () => { afterEach(() => { diff --git a/webapp/src/utils/adapters/YamlTranslationAdapter.ts b/webapp/src/utils/adapters/YamlTranslationAdapter.ts index f7336923..e44ea013 100644 --- a/webapp/src/utils/adapters/YamlTranslationAdapter.ts +++ b/webapp/src/utils/adapters/YamlTranslationAdapter.ts @@ -1,7 +1,8 @@ -import flattenObject from '../flattenObject'; import fs from 'fs/promises'; import { parse } from 'yaml'; import path from 'path'; + +import flattenObject from '../flattenObject'; import { ITranslationAdapter, type TranslationMap } from '.'; export default class YamlTranslationAdapter implements ITranslationAdapter { diff --git a/webapp/src/utils/flattenObject.spec.ts b/webapp/src/utils/flattenObject.spec.ts index 0340fade..c68960b3 100644 --- a/webapp/src/utils/flattenObject.spec.ts +++ b/webapp/src/utils/flattenObject.spec.ts @@ -1,6 +1,7 @@ -import flattenObject from './flattenObject'; import { describe, expect, it } from '@jest/globals'; +import flattenObject from './flattenObject'; + describe('flattenObject()', () => { it('returns empty object for empty obj', () => { const actual = flattenObject({}); diff --git a/webapp/src/utils/git/SimpleGitWrapper.ts b/webapp/src/utils/git/SimpleGitWrapper.ts index 68ca36f0..f9149909 100644 --- a/webapp/src/utils/git/SimpleGitWrapper.ts +++ b/webapp/src/utils/git/SimpleGitWrapper.ts @@ -1,6 +1,7 @@ -import { IGit } from './IGit'; import { simpleGit, SimpleGit, SimpleGitOptions } from 'simple-git'; +import { IGit } from './IGit'; + export class SimpleGitWrapper implements IGit { private readonly git: SimpleGit; diff --git a/webapp/src/utils/lyraConfig.spec.ts b/webapp/src/utils/lyraConfig.spec.ts index bf164f5b..610522e6 100644 --- a/webapp/src/utils/lyraConfig.spec.ts +++ b/webapp/src/utils/lyraConfig.spec.ts @@ -1,5 +1,6 @@ import mock from 'mock-fs'; import { afterEach, describe, expect, it } from '@jest/globals'; + import { LyraConfig, MessageKind } from './lyraConfig'; import { LyraConfigReadingError, ProjectPathNotFoundError } from '@/errors'; diff --git a/webapp/src/utils/lyraConfig.ts b/webapp/src/utils/lyraConfig.ts index 9fcd1169..4532c5f4 100644 --- a/webapp/src/utils/lyraConfig.ts +++ b/webapp/src/utils/lyraConfig.ts @@ -2,6 +2,7 @@ import fs from 'fs/promises'; import { parse } from 'yaml'; import path from 'path'; import { z } from 'zod'; + import { LyraConfigReadingError, ProjectPathNotFoundError } from '@/errors'; export enum MessageKind { diff --git a/webapp/src/utils/readTypedMessages.ts b/webapp/src/utils/readTypedMessages.ts index 0ff68f7f..5b54b13c 100644 --- a/webapp/src/utils/readTypedMessages.ts +++ b/webapp/src/utils/readTypedMessages.ts @@ -1,6 +1,7 @@ -import { type MessageData } from './adapters'; import ts from 'typescript'; +import { type MessageData } from './adapters'; + export default function readTypedMessages(fileName: string): MessageData[] { const host = ts.createIncrementalCompilerHost( {}, diff --git a/webapp/src/utils/serverConfig.spec.ts b/webapp/src/utils/serverConfig.spec.ts index 8e1f79ff..11d37114 100644 --- a/webapp/src/utils/serverConfig.spec.ts +++ b/webapp/src/utils/serverConfig.spec.ts @@ -1,6 +1,7 @@ import mock from 'mock-fs'; -import { ServerConfig } from './serverConfig'; import { afterEach, describe, expect, it } from '@jest/globals'; + +import { ServerConfig } from './serverConfig'; import { ProjectNameNotFoundError, ServerConfigReadingError } from '@/errors'; describe('ServerConfig', () => { diff --git a/webapp/src/utils/serverConfig.ts b/webapp/src/utils/serverConfig.ts index 8182b2ca..314cc4c9 100644 --- a/webapp/src/utils/serverConfig.ts +++ b/webapp/src/utils/serverConfig.ts @@ -2,6 +2,7 @@ import fs from 'fs/promises'; import { parse } from 'yaml'; import path from 'path'; import { z } from 'zod'; + import { ProjectNameNotFoundError, ServerConfigReadingError } from '@/errors'; const serverConfigSchema = z.object({ diff --git a/webapp/src/utils/unflattenObject.spec.ts b/webapp/src/utils/unflattenObject.spec.ts index 4e14883f..07c7cb9e 100644 --- a/webapp/src/utils/unflattenObject.spec.ts +++ b/webapp/src/utils/unflattenObject.spec.ts @@ -1,6 +1,7 @@ -import { unflattenObject } from './unflattenObject'; import { describe, expect, it } from '@jest/globals'; +import { unflattenObject } from './unflattenObject'; + describe('unflattenObject()', () => { it('returns empty object for empty obj', () => { const actual = unflattenObject({}); diff --git a/yarn.lock b/yarn.lock index dcc5dc38..23835d48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2330,7 +2330,7 @@ eslint-module-utils@^2.8.0: dependencies: debug "^3.2.7" -eslint-plugin-import@^2.28.1: +eslint-plugin-import@^2.28.1, eslint-plugin-import@^2.29.1: version "2.29.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==