Files
twenty/packages/twenty-docs/l/tr/developers/contribute/capabilities/frontend-development/style-guide.mdx
T
Charles Bochet 9d57bc39e5 Migrate from ESLint to OxLint (#18443)
## Summary

Fully replaces ESLint with OxLint across the entire monorepo:

- **Replaced all ESLint configs** (`eslint.config.mjs`) with OxLint
configs (`.oxlintrc.json`) for every package: `twenty-front`,
`twenty-server`, `twenty-emails`, `twenty-ui`, `twenty-shared`,
`twenty-sdk`, `twenty-zapier`, `twenty-docs`, `twenty-website`,
`twenty-apps/*`, `create-twenty-app`
- **Migrated custom lint rules** from ESLint plugin format to OxLint JS
plugin system (`@oxlint/plugins`), including
`styled-components-prefixed-with-styled`, `no-hardcoded-colors`,
`sort-css-properties-alphabetically`,
`graphql-resolvers-should-be-guarded`,
`rest-api-methods-should-be-guarded`, `max-consts-per-file`, and
Jotai-related rules
- **Migrated custom rule tests** from ESLint `RuleTester` + Jest to
`oxlint/plugins-dev` `RuleTester` + Vitest
- **Removed all ESLint dependencies** from `package.json` files and
regenerated lockfiles
- **Updated Nx targets** (`lint`, `lint:diff-with-main`, `fmt`) in
`nx.json` and per-project `project.json` to use `oxlint` commands with
proper `dependsOn` for plugin builds
- **Updated CI workflows** (`.github/workflows/ci-*.yaml`) — no more
ESLint executor
- **Updated IDE setup**: replaced `dbaeumer.vscode-eslint` with
`oxc.oxc-vscode` extension, configured `source.fixAll.oxc` and
format-on-save with Prettier
- **Replaced all `eslint-disable` comments** with `oxlint-disable`
equivalents across the codebase
- **Updated docs** (`twenty-docs`) to reference OxLint instead of ESLint
- **Renamed** `twenty-eslint-rules` package to `twenty-oxlint-rules`

### Temporarily disabled rules (tracked in `OXLINT_MIGRATION_TODO.md`)

| Rule | Package | Violations | Auto-fixable |
|------|---------|-----------|-------------|
| `twenty/sort-css-properties-alphabetically` | twenty-front | 578 | Yes
|
| `typescript/consistent-type-imports` | twenty-server | 3814 | Yes |
| `twenty/max-consts-per-file` | twenty-server | 94 | No |

### Dropped plugins (no OxLint equivalent)

`eslint-plugin-project-structure`, `lingui/*`, `@stylistic/*`,
`import/order`, `prefer-arrow/prefer-arrow-functions`,
`eslint-plugin-mdx`, `@next/eslint-plugin-next`,
`eslint-plugin-storybook`, `eslint-plugin-react-refresh`. Partial
coverage for `jsx-a11y` and `unused-imports`.

### Additional fixes (pre-existing issues exposed by merge)

- Fixed `EmailThreadPreview.tsx` broken import from main rename
(`useOpenEmailThreadInSidePanel`)
- Restored truthiness guard in `getActivityTargetObjectRecords.ts`
- Fixed `AgentTurnResolver` return types to match entity (virtual
`fileMediaType`/`fileUrl` are resolved via `@ResolveField()`)

## Test plan

- [x] `npx nx lint twenty-front` passes
- [x] `npx nx lint twenty-server` passes
- [x] `npx nx lint twenty-docs` passes
- [x] Custom oxlint rules validated with Vitest: `npx nx test
twenty-oxlint-rules`
- [x] `npx nx typecheck twenty-front` passes
- [x] `npx nx typecheck twenty-server` passes
- [x] CI workflows trigger correctly with `dependsOn:
["twenty-oxlint-rules:build"]`
- [x] IDE linting works with `oxc.oxc-vscode` extension
2026-03-06 01:03:50 +01:00

290 lines
8.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Stil Rehberi
---
Bu belge, kod yazarken uyulması gereken kuralları içermektedir.
Buradaki amaç, okunması ve bakımı kolay tutarlı bir kod tabanı oluşturmaktır.
Bunun için, biraz daha ayrıntılı olmak, çok kısa olmaktan daha iyidir.
İnsanların kodu yazmaktan daha sık okuduğunu her zaman aklınızda bulundurun; özellikle herkesin katkıda bulunabildiği açık kaynak bir projede.
Burada tanımlanmayan, ancak linters tarafından otomatik olarak kontrol edilen birçok kural vardır.
## React
### Fonksiyonel bileşenler kullanın
Her zaman TSX fonksiyonel bileşenlerini kullanın.
Varsayılan `import`'u `const` ile kullanmayın, çünkü okunması daha zordur ve kod tamamlama ile içe aktarmak daha zordur.
```tsx
// ❌ Bad, harder to read, harder to import with code completion
const MyComponent = () => {
return <div>Hello World</div>;
};
export default MyComponent;
// ✅ Good, easy to read, easy to import with code completion
export function MyComponent() {
return <div>Hello World</div>;
};
```
### Özellikler
Prop'ların türünü oluşturun ve dışa aktarmaya gerek yoksa ona `(ComponentName)Props` adını verin.
Props destructuring kullanın.
```tsx
// ❌ Bad, no type
export const MyComponent = (props) => <div>Hello {props.name}</div>;
// ✅ Good, type
type MyComponentProps = {
name: string;
};
export const MyComponent = ({ name }: MyComponentProps) => <div>Hello {name}</div>;
```
#### Prop türlerini tanımlamak için `React.FC` veya `React.FunctionComponent` kullanmaktan kaçının
```tsx
/* ❌ - Bad, defines the component type annotations with `FC`
* - With `React.FC`, the component implicitly accepts a `children` prop
* even if it's not defined in the prop type. This might not always be
* desirable, especially if the component doesn't intend to render
* children.
*/
const EmailField: React.FC<{
value: string;
}> = ({ value }) => <TextInput value={value} disabled fullWidth />;
```
```tsx
/* ✅ - İyi, bileşenin prop'ları için ayrı bir tür (OwnProps) açıkça tanımlanmıştır
* - Bu yöntem çocuk prop'unu otomatik olarak içermez.
* Onu dahil etmek istiyorsanız, OwnProps'ta belirtmeniz gerekir.
*/
type EmailFieldProps = {
value: string;
};
const EmailField = ({ value }: EmailFieldProps) => (
<TextInput value={value} disabled fullWidth />
);
```
#### JSX Elemanlarında Tek Değişkenli Prop Yayılımından Kaçının
JSX elemanlarında tek değişkenli prop yayılımını, örneğin `{...props}` kullanmaktan kaçının. Bu uygulama, bileşenin hangi prop'ları aldığını belirsizleştirdiği için okunması zor ve bakımı güç kodlara yol açar.
```tsx
/* ❌ - Bad, spreads a single variable prop into the underlying component
*/
const MyComponent = (props: OwnProps) => {
return <OtherComponent {...props} />;
}
```
```tsx
/* ✅ - İyi, tüm prop'ları açıkça listeler
* - Okunabilirliği ve bakımı arttırır
*/
const MyComponent = ({ prop1, prop2, prop3 }: MyComponentProps) => {
return <OtherComponent {...{ prop1, prop2, prop3 }} />;
};
```
Gerekçe:
* İlk bakışta, hangi prop'ların kod tarafından geçirildiği daha açıktır, bu da anlamayı ve bakımı kolaylaştırır.
* Prop'lar aracılığıyla bileşenler arasında sıkı bağlanmayı önlemeye yardımcı olur.
* Linting araçları, prop'ları açıkça listelediğinizde yanlış yazılmış veya kullanılmayan prop'ları tanımlamayı kolaylaştırır.
## JavaScript
### Nullish-birleştirme operatörü `??` kullanın
```tsx
// ❌ Kötü, değer 0 veya '' olsa bile 'default' döndürebilir
const value = process.env.MY_VALUE || 'default';
// ✅ İyi, 'default' yalnızca değer null veya undefined olduğunda döner
const value = process.env.MY_VALUE ?? 'default';
```
### Opsiyonel zincirleme `?.` kullanın
```tsx
// ❌ Kötü
onClick && onClick();
// ✅ İyi
onClick?.();
```
## TypeScript
### `interface` yerine `type` kullanın
Neredeyse her zaman örtüştükleri ve `type` daha esnek olduğu için her zaman `interface` yerine `type` kullanın.
```tsx
// ❌ Bad
interface MyInterface {
name: string;
}
// ✅ Good
type MyType = {
name: string;
};
```
### enum'lar yerine string literal'leri kullanın
[String literalleri](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types), TypeScript'te enum benzeri değerleri yönetmek için en iyi yöntemdir. Pick ve Omit ile genişletilmesi daha kolay olur ve özellikle kod tamamlama ile daha iyi bir geliştirici deneyimi sunarlar.
TypeScript, enum'ların neden kaçınılması gereken bir seçenek olduğunu [burada](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums) açıklamaktadır.
```tsx
// ❌ Bad, utilizes an enum
enum Color {
Red = "red",
Green = "green",
Blue = "blue",
}
let color = Color.Red;
```
```tsx
// ✅ İyi, bir string literal kullanıyor
let color: "red" | "green" | "blue" = "red";
```
#### GraphQL ve iç kütüphaneler
GraphQL codegen tarafından üretilen enum'ları kullanmalısınız.
Bir iç kütüphane kullanırken de bir enum kullanmak daha iyidir, böylece iç kütüphane, iç API ile ilgili olmayan bir string literal türü açmak zorunda kalmaz.
Örnek:
```TSX
const {
setHotkeyScopeAndMemorizePreviousScope,
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
setHotkeyScopeAndMemorizePreviousScope(
RelationPickerHotkeyScope.RelationPicker,
);
```
## Şekil Verme
### StyledComponents kullanın
Bileşenleri [Linaria styled](https://github.com/callstack/linaria) ile stillendirin.
```tsx
// ❌ Kötü
<div className=\"my-class\">Hello World</div>
```
```tsx
// ✅ İyi
const StyledTitle = styled.div`
color: red;
`;
```
Styled bileşenleri, bunları "gerçek" bileşenlerden ayırt etmek için "Styled" önekiyle belirtin.
```tsx
// ❌ Kötü
const Title = styled.div`
color: red;
`;
```
```tsx
// ✅ İyi
const StyledTitle = styled.div`
color: red;
`;
```
### Temalandırma
Çoğu bileşen şekillendirmesi için temayı kullanmak tercih edilen bir yaklaşımdır.
#### Ölçü birimleri
Styled bileşenler içinde doğrudan `px` veya `rem` değerlerini kullanmaktan kaçının. Gerekli değerler genellikle temada tanımlanmıştır, bu nedenle bu amaçlar için temayı kullanmak önerilir.
#### Renkler
Yeni renkler eklemekten kaçının; Bunun yerine temadaki mevcut paleti kullanın. Palet uyum sağlamıyorsa, lütfen ekibin düzeltmesi için bir yorum bırakın.
```tsx
// ❌ Kötü, tema kullanmadan doğrudan stil değerleri belirtiyor
const StyledButton = styled.button`
color: #333333;
font-size: 1rem;
font-weight: 400;
margin-left: 4px;
border-radius: 50px;
`;
```
```tsx
// ✅ İyi, temayı kullanıyor
const StyledButton = styled.button`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.regular};
margin-left: ${({ theme }) => theme.spacing(1)};
border-radius: ${({ theme }) => theme.border.rounded};
`;
```
## Tip içermeyen importları zorunlu kılma
Tip ithalatlarından kaçının. Bu standardı uygulamak için bir Oxlint kuralı, herhangi bir tip ithalatını kontrol eder ve raporlar. Bu, TypeScript kodunda tutarlılık ve okunabilirliği sağlamaya yardımcı olur.
```tsx
// ❌ Kötü
import { type Meta, type StoryObj } from '@storybook/react';
// ❌ Kötü
import type { Meta, StoryObj } from '@storybook/react';
// ✅ İyi
import { Meta, StoryObj } from '@storybook/react';
```
### Neden Tip İthalatları Yok
* **Tutarlılık**: Hem tip hem de değer ithalatları için tek bir yaklaşım kullanarak, kod tabanı modül import stilinde tutarlı kalır.
* **Okunabilirlik**: İthalat türü olmadığında, değer veya tip ithal ettiğiniz zaman daha anlaşılır olur böylece kod okunabilirliği artırılır. Bu belirsizliği azaltır ve ithal edilen sembollerinin amacını anlamayı kolaylaştırır.
* **Bakım Kolaylığı**: Kod tabanının bakımını kolaylaştırır çünkü geliştiriciler kodu incelerken veya değiştirirken yalnızca tip ithalatlarını tanımlayabilir ve bulabilirler.
### Oxlint kuralı
Oxlint kuralı, `typescript/consistent-type-imports`, tip ithalat standardını uygular. Bu kural, herhangi bir tip ithalat ihlali için hata veya uyarı üretir.
Lütfen unutmayın ki bu kural, istemeden yapılan tip ithalatlarının gerçekleştiği nadir durumları özellikle ele alır. TypeScript'in kendisi, [TypeScript 3.8 sürüm notlarında](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) belirtildiği gibi, bu uygulamayı caydırmaktadır. Çoğu durumda, yalnızca tip ithalatları kullanmanıza gerek yoktur.
Kodunuzun bu kurala uygun olduğundan emin olmak için, geliştirme iş akışınızın bir parçası olarak Oxlint'i çalıştırdığınızdan emin olun.