Skip to content

Commit ef2d78a

Browse files
committed
chore(web): Biome lint rules and named-export style
- Enable useExplicitType, useArrowFunction, and style/noDefaultExport (with overrides for Vite and openapi-ts config entrypoints). - Refactor app and API surface to named exports and const arrow functions; keep explicit types on apiClient and SDK wrappers. - Add Cursor rule for no default exports across TS/TSX. Made-with: Cursor
1 parent 9966d8a commit ef2d78a

10 files changed

Lines changed: 92 additions & 57 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
description: Named exports only in TypeScript; no default exports
3+
globs:
4+
- "**/*.ts"
5+
- "**/*.tsx"
6+
alwaysApply: false
7+
---
8+
9+
# No default exports (TypeScript)
10+
11+
- Prefer **named exports** only: `export const Component = …`, `export { foo }`, and similar.
12+
- Do **not** add `export default`, including `export { Name as default }`, unless the file is an allowed tooling entrypoint (see below).
13+
14+
**Exception:** `apps/web/vite.config.ts` and `apps/web/openapi-ts.config.ts` may use `export default` because Vite and `@hey-api/openapi-ts` load the config via the module’s default export. Biome disables `style/noDefaultExport` for those paths in `apps/web/biome.json`.
15+
16+
Where this repository runs Biome with `style.noDefaultExport`, that config applies to the linted tree (see `apps/web/biome.json`).

apps/web/biome.json

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,30 @@
1717
"linter": {
1818
"enabled": true,
1919
"rules": {
20-
"recommended": true
20+
"recommended": true,
21+
"complexity": {
22+
"useArrowFunction": "error"
23+
},
24+
"nursery": {
25+
"useExplicitType": "error"
26+
},
27+
"style": {
28+
"noDefaultExport": "error"
29+
}
2130
}
2231
},
32+
"overrides": [
33+
{
34+
"includes": ["vite.config.ts", "openapi-ts.config.ts"],
35+
"linter": {
36+
"rules": {
37+
"style": {
38+
"noDefaultExport": "off"
39+
}
40+
}
41+
}
42+
}
43+
],
2344
"javascript": {
2445
"formatter": {
2546
"quoteStyle": "single",

apps/web/src/App.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { render, screen } from '@solidjs/testing-library';
22
import { describe, expect, it } from 'vitest';
3-
import App from './App';
3+
import { App } from './App';
44

55
describe('App', () => {
66
it('renders the main heading', () => {

apps/web/src/App.tsx

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { Route, Router } from '@solidjs/router';
2-
import AppShell from './layout/AppShell';
3-
import Home from './pages/Home';
4-
import RecipePage from './pages/RecipePage';
2+
import type { JSX } from 'solid-js';
3+
import { AppShell } from './layout/AppShell';
4+
import { Home } from './pages/Home';
5+
import { RecipePage } from './pages/RecipePage';
56

6-
export default function App() {
7-
return (
8-
<Router root={AppShell}>
9-
<Route path="/" component={Home} />
10-
<Route path="/recipes/:id" component={RecipePage} />
11-
</Router>
12-
);
13-
}
7+
export const App = (): JSX.Element => (
8+
<Router root={AppShell}>
9+
<Route path="/" component={Home} />
10+
<Route path="/recipes/:id" component={RecipePage} />
11+
</Router>
12+
);

apps/web/src/api/client.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
type Client,
23
type ClientOptions,
34
createClient,
45
createConfig,
@@ -16,6 +17,6 @@ function resolveBaseUrl(): string {
1617
}
1718

1819
/** Shared fetch client for generated SDK calls (base URL from `VITE_API_BASE_URL`, or local API in dev). */
19-
export const apiClient = createClient(
20+
export const apiClient: Client = createClient(
2021
createConfig<ClientOptions>({ baseUrl: resolveBaseUrl() }),
2122
);

apps/web/src/api/index.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,20 @@ import type { GetRecipeByIdData, ListRecipesData } from './generated/types.gen';
88

99
export { apiClient } from './client';
1010

11-
export function listRecipes<ThrowOnError extends boolean = false>(
11+
export const listRecipes = <ThrowOnError extends boolean = false>(
1212
options?: Options<ListRecipesData, ThrowOnError>,
13-
) {
14-
return listRecipesSdk({
13+
): ReturnType<typeof listRecipesSdk<ThrowOnError>> =>
14+
listRecipesSdk({
1515
...options,
1616
client: options?.client ?? apiClient,
1717
});
18-
}
1918

20-
export function getRecipeById<ThrowOnError extends boolean = false>(
19+
export const getRecipeById = <ThrowOnError extends boolean = false>(
2120
options: Options<GetRecipeByIdData, ThrowOnError>,
22-
) {
23-
return getRecipeByIdSdk({
21+
): ReturnType<typeof getRecipeByIdSdk<ThrowOnError>> =>
22+
getRecipeByIdSdk({
2423
...options,
2524
client: options?.client ?? apiClient,
2625
});
27-
}
2826

2927
export type * from './generated/types.gen';

apps/web/src/index.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
/* @refresh reload */
2+
import type { JSX } from 'solid-js';
23
import { render } from 'solid-js/web';
34
import './index.css';
4-
import App from './App.tsx';
5+
import { App } from './App.tsx';
56

6-
const root = document.getElementById('root');
7+
const root: HTMLElement | null = document.getElementById('root');
78
if (!root) {
89
throw new Error('Missing #root element');
910
}
1011

11-
render(() => <App />, root);
12+
render((): JSX.Element => <App />, root);

apps/web/src/layout/AppShell.tsx

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
11
import type { RouteSectionProps } from '@solidjs/router';
22
import { A } from '@solidjs/router';
3+
import type { JSX } from 'solid-js';
34
import './AppShell.css';
45

5-
export default function AppShell(props: RouteSectionProps) {
6-
return (
7-
<div class="shell">
8-
<header class="shell-header">
9-
<div class="shell-header-inner">
10-
<h1 class="site-title">
11-
<A href="/" class="site-title-link" end>
12-
Bread Recipes
13-
</A>
14-
</h1>
15-
<p class="site-tagline">Simple loaves, clear steps</p>
16-
</div>
17-
</header>
18-
<main class="shell-main">{props.children}</main>
19-
<footer class="shell-footer">
20-
<p class="shell-footer-note">A bread recipes browser</p>
21-
</footer>
22-
</div>
23-
);
24-
}
6+
export const AppShell = (props: RouteSectionProps): JSX.Element => (
7+
<div class="shell">
8+
<header class="shell-header">
9+
<div class="shell-header-inner">
10+
<h1 class="site-title">
11+
<A href="/" class="site-title-link" end>
12+
Bread Recipes
13+
</A>
14+
</h1>
15+
<p class="site-tagline">Simple loaves, clear steps</p>
16+
</div>
17+
</header>
18+
<main class="shell-main">{props.children}</main>
19+
<footer class="shell-footer">
20+
<p class="shell-footer-note">A bread recipes browser</p>
21+
</footer>
22+
</div>
23+
);

apps/web/src/pages/Home.tsx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1+
import type { JSX } from 'solid-js';
12
import './Page.css';
23

3-
export default function Home() {
4-
return (
5-
<section class="page" aria-labelledby="home-intro">
6-
<p id="home-intro" class="lede">
7-
Browse sourdough and yeasted recipes from the API. List and detail views
8-
follow in the next milestones.
9-
</p>
10-
</section>
11-
);
12-
}
4+
export const Home = (): JSX.Element => (
5+
<section class="page" aria-labelledby="home-intro">
6+
<p id="home-intro" class="lede">
7+
Browse sourdough and yeasted recipes from the API. List and detail views
8+
follow in the next milestones.
9+
</p>
10+
</section>
11+
);

apps/web/src/pages/RecipePage.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { useParams } from '@solidjs/router';
2+
import type { JSX } from 'solid-js';
23
import './Page.css';
34

4-
export default function RecipePage() {
5+
export const RecipePage = (): JSX.Element => {
56
const params = useParams<{ id: string }>();
67

78
return (
@@ -15,4 +16,4 @@ export default function RecipePage() {
1516
</p>
1617
</section>
1718
);
18-
}
19+
};

0 commit comments

Comments
 (0)