-
-
Notifications
You must be signed in to change notification settings - Fork 10
fix: implement CodeRabbit findings (#3364) #3371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
47 commits
Select commit
Hold shift + click to select a range
08c2adf
docs: Add plan and review for PR #3316 post-merge fixes
KATO-Hiro 2687ff0
test: migrate process.env manual stubs to vi.stubEnv in atcoder_verif…
KATO-Hiro e50bb41
test: add unit tests for getUser, getUserById, and deleteUser
KATO-Hiro 00cbd6c
refactor: extract MIN_VOTES_FOR_STATISTICS to client-safe constant an…
KATO-Hiro c5b497a
docs: update plan - use internal_clients/vote_grade.ts instead of ser…
KATO-Hiro e117eb5
refactor: add return value to upsertVoteGradeTables and use it in vot…
KATO-Hiro 9d4ec03
fix: handle RecordNotFound error in setTaskGrade action for vote_mana…
KATO-Hiro b12edec
feat: add loading state to SubmissionButton via FormWrapper context (…
KATO-Hiro a24be95
feat: add button gap and replace custom clipboard with Flowbite Clipb…
KATO-Hiro 256bf34
fix: ensure isSubmitting is reset even when form update throws exception
KATO-Hiro c107ebf
docs: fix comment wording and remove redundant type assertion
KATO-Hiro 5b23fe1
feat: create vote_grade internal client with fetchMyVote, submitVote,…
KATO-Hiro 65a6bef
refactor: use vote_grade.ts in VotableGrade and add AbortController f…
KATO-Hiro 696e6c0
fix: update E2E test selectors and add initial state check for votes …
KATO-Hiro e037ab5
feat: add CHECK constraints for vote grade models (count >= 0, grade …
KATO-Hiro 2a4aecf
docs: add new coding rules derived from PR #3316 review (SSR, FK, aut…
KATO-Hiro 70a0767
fix: address CodeRabbit findings - remove misleading test and fix For…
KATO-Hiro 6a541e4
Merge branch 'staging' of github.com:AtCoder-NoviSteps/AtCoderNoviSte…
KATO-Hiro 0fc88a1
refactor: rename PrismaUserWithAccount to UserWithAtCoderAccount to r…
KATO-Hiro 0e124b8
refactor: use UUID format for SAMPLE_USER_ID and document Lucia depen…
KATO-Hiro bc139d8
fix: use Roles.USER enum instead of string literal in test fixtures
KATO-Hiro 89b22c4
refactor: extract mock helpers and use Partial types to avoid any/nev…
KATO-Hiro 5b2023f
test: add error case for generate function and organize describe bloc…
KATO-Hiro d64ef41
refactor: extract mockFindUniqueOrThrowError helper to avoid mock set…
KATO-Hiro 5682ed2
test: organize validate describe block by scenario
KATO-Hiro f879ce4
test: reorganize validate describe blocks by 正常系/異常系
KATO-Hiro 1ff1e19
test: split abnormal cases by return value (false vs throws)
KATO-Hiro 2d8a702
test: organize reset describe block and add error case
KATO-Hiro da0eddf
docs: formalize internal_clients and test organization patterns
KATO-Hiro c205d2f
test: reorganize users.test.ts with fixtures and organize describe bl…
KATO-Hiro 3355d24
refactor: translate SubmissionButton comment to English
KATO-Hiro ef1977c
feat: add color prop to SubmissionButton and improve ButtonColor type…
KATO-Hiro 68ca9c0
test: refactor vote_grade.test.ts with HTTP mock helpers and parametr…
KATO-Hiro 609addf
refactor: move getBaseUrl helper after exported functions in vote_gra…
KATO-Hiro 556822e
chore: fix order
KATO-Hiro 2a5cd61
docs: clean up completed plan.md for PR #3316 review
KATO-Hiro e9dfab8
docs: update Task 10 plan for votes E2E test fix
KATO-Hiro 40a4818
fix: repair vote detail E2E tests broken by search-first UI and stale…
KATO-Hiro ab4d948
docs(rules): add E2E lessons from votes test fix
KATO-Hiro e135750
style: fix formatting in testing-e2e.md
KATO-Hiro 222d409
docs: add CodeRabbit findings to plan.md
KATO-Hiro 62e9fa1
docs: add implementation plan for CodeRabbit findings
KATO-Hiro 2d3494f
docs(rules): consolidate and streamline coding standards
KATO-Hiro fb4d1a6
fix: implement CodeRabbit findings #1-10 (Phase 1-4)
KATO-Hiro 4f16134
docs: remove completed PR #3316 review notes
KATO-Hiro 1f1ab4b
fix: implement CodeRabbit findings (Phase 2)
KATO-Hiro bae4e80
fix(migration): fix failed vote grade CHECK constraint migration in s…
KATO-Hiro File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,143 +1,64 @@ | ||
| # Coding Style | ||
|
|
||
| ## Plan Time | ||
|
|
||
| ### Pre-Implementation Layer Check | ||
|
|
||
| Before writing new logic, decide which layer it belongs to. Run this check at plan time (design/architecture phase, before writing any code): | ||
|
|
||
| | Layer | Directory | Key constraints | | ||
| | -------------- | ------------------------------------------------------ | -------------------------------------------------------------------------- | | ||
| | DB schema | `prisma/` | Migrations are immutable after apply | | ||
| | DB access | `src/lib/server/` | Server-only; never import in client code | | ||
| | Validation | `src/**/zod/` | `z.number().int()` for Int fields; comment dual-enforcement with SQL CHECK | | ||
| | Domain types | `src/**/types/` (`_types/` inside `src/routes/`) | Plural aliases; TSDoc on every export; avoid `any`; see alternatives | | ||
| | Test data | `src/**/fixtures/` (`_fixtures/` inside `src/routes/`) | Write before implementation (TDD); use realistic values | | ||
| | Business logic | `src/**/services/` | Return pure values or `null`; no `Response`/`json()` | | ||
| | Pure utilities | `src/**/utils/` (`_utils/` inside `src/routes/`) | No side effects; adjacent unit test required | | ||
| | State | `src/**/stores/` | `.svelte.ts`; class + `$state()`; singleton export | | ||
| | Route handlers | `src/routes/` | Page: `redirect()`; API: `error()` | | ||
| | UI components | `src/**/*.svelte` | Svelte 5 Runes; business logic → `utils/` | | ||
|
|
||
| ## Code Structure | ||
|
|
||
| ### Naming | ||
|
|
||
| - **Abbreviations**: avoid non-standard abbreviations (`res` → `response`, `btn` → `button`). When in doubt, spell it out. | ||
| - **Lambda parameters**: no single-character names (e.g., use `placement`, `workbook`). Iterator index `i` is the only exception. | ||
| - **`upsert`**: only use when the implementation performs both insert and update. For insert-only, use `initialize`, `seed`, or another accurate verb. | ||
| - **Function verbs**: every function name must start with a verb. Noun-only names (`pointOnCircle`, `arcPath`) are ambiguous — use `calcPointOnCircle`, `buildArcPath`, etc. Common prefixes: `get` (read existing), `build`/`create` (construct new), `calc`/`compute` (derive by formula), `update`, `fetch`, `resolve`. | ||
| - **`any`**: Before using `any`, check the value's origin. If unavoidable: use `ReturnType<typeof fn>` for complex returns, `Partial<T>` for partial objects, `obj as T & { prop: U }` for property extension. Last resort: `as unknown as T`. | ||
|
|
||
| - **UI labels**: if a label does not match actual behavior, update it or add an inline comment explaining the intentional mismatch. | ||
| - **Constant names**: reflect what the value IS (content), not what it is used for (purpose). e.g., a set holding all enum tab values is `EXISTING_TABS`, not `VALID_TABS`. | ||
| - **New files**: before naming a new file or directory, grep the relevant `src/` directory to confirm existing conventions. Confirm at plan time, not during implementation: | ||
| - Custom files in routes (utilities, helpers, etc.): `snake_case` (e.g., `user_profile.ts`) | ||
| - SvelteKit special files: follow framework conventions (`+page.svelte`, `+page.server.ts`, `+server.ts`) | ||
| - Helper directories inside `src/routes/`: underscore-prefixed (`_utils/`, `_types/`, `_fixtures/`, `_components/`) | ||
| - Other directories: `kebab-case` (e.g., `contest-table/`) | ||
|
|
||
| ### Syntax | ||
|
|
||
| - **Braces**: always use braces for single-statement `if` blocks. Never `if () return;` — write `if () { return; }`. | ||
| - **Domain types over `string`**: when the Prisma schema uses an enum (e.g. `grade: TaskGrade`), the corresponding app-layer type must use the same enum — not `string`. A loose `string` type hides misspellings in fixtures and forces `as TaskGrade` casts throughout the codebase. When a field comes from an external source (form data, query params), validate and narrow it at the boundary; inside the app it must always be the domain type. | ||
| - **Plural type aliases**: define `type Placements = Placement[]` instead of using `Placement[]` directly in signatures and variables. | ||
| - **Empty `catch` blocks**: never use `catch { }` to silence errors. Either re-throw, log, or add a comment justifying suppression. Silent swallowing hides bugs. | ||
| ## Pre-Implementation Layer Check | ||
|
|
||
| ```typescript | ||
| try { ... } catch (error) { console.error('...'); throw error; } // good | ||
| try { localStorage.setItem(key, value); } catch { /* unavailable */ } // good + comment | ||
| ``` | ||
|
|
||
| ### No Hard-Coded Values | ||
|
|
||
| Extract magic numbers and strings to named constants. Never embed literal values whose meaning is not self-evident from the type or immediate context. | ||
|
|
||
| ```typescript | ||
| // Bad: magic literals embedded inline | ||
| if (grade >= 11) { ... } | ||
|
|
||
| const response = await fetch('/api/workbooks/submit', options); | ||
|
|
||
| // Good | ||
| const MIN_GRADE = 11; | ||
| const SUBMIT_URL = '/api/workbooks/submit'; | ||
|
|
||
| if (grade >= MIN_GRADE) { ... } | ||
|
|
||
| const response = await fetch(SUBMIT_URL, options); | ||
| ``` | ||
|
|
||
| Place constants at the top of the file, or in a dedicated `constants/` module when shared across files. | ||
|
|
||
| ### Function Ordering | ||
|
|
||
| Within a file, order declarations as follows: | ||
|
|
||
| 1. Exported functions and classes (public API first) | ||
| 2. Internal helper functions (supporting the exports above) | ||
| Before writing logic, decide which layer it belongs to: | ||
|
|
||
| Place a private helper immediately after the single export that uses it. Place helpers shared by two or more exports at the end of the file. | ||
| | Layer | Directory | Constraints | | ||
| | -------------- | ------------------------------------------- | ------------------------------------------------------- | | ||
| | DB schema | `prisma/` | Migrations immutable after apply | | ||
| | DB access | `src/lib/server/` | Server-only; never in client | | ||
| | Validation | `src/**/zod/` | `z.number().int()` for Int; dual-enforce with SQL CHECK | | ||
| | Domain types | `src/**/types/` | Plural aliases; TSDoc; avoid `any` | | ||
| | Test data | `src/**/fixtures/` | Write before impl (TDD); realistic values | | ||
| | Business logic | `src/**/services/` | Pure values/`null`; no `Response`/`json()` | | ||
| | External APIs | `src/lib/clients/` or `*/internal_clients/` | Shared → `lib`; feature-scoped → `internal_clients` | | ||
| | Utilities | `src/**/utils/` | No side effects; adjacent unit test required | | ||
| | State | `src/**/stores/` | `.svelte.ts`; class + `$state()`; singleton export | | ||
| | Route handlers | `src/routes/` | Page: `redirect()`; API: `error()` | | ||
| | Components | `src/**/*.svelte` | Svelte 5 Runes; logic → `utils/` | | ||
|
|
||
| ### URL Parameter Patterns | ||
| ## Naming | ||
|
|
||
| #### null-as-ALL: Omitting Params for "All" State | ||
| - **No abbreviations** unless standard (e.g., `id`, `url`) | ||
| - **Lambda params**: no single-char (except `i` for loops) | ||
| - **Function verbs**: `get` (read), `build`/`create` (construct), `calc`/`compute` (derive), `update`, `fetch`, `resolve` | ||
| - **Domain enums**: use domain type, not `string` (validates at boundary, stays typed inside) | ||
| - **Constants**: reflect content not purpose; extract magic numbers/strings | ||
| - **Files**: `snake_case` in routes, `kebab-case` dirs, underscore-prefix helpers (`_utils/`, `_types/`) | ||
|
|
||
| When a filter has an "all" or "unfiltered" state, omit the parameter entirely rather than using a magic value (e.g., "ALL", "\*"). | ||
| ## Syntax | ||
|
|
||
| **Pattern:** | ||
| - **Braces**: always for single-statement `if` blocks | ||
| - **Catch blocks**: never silent; re-throw, log, or comment | ||
| - **Plural aliases**: `type Items = Item[]` in signatures | ||
| - **TSDoc**: every export; `@param`/`@returns` when non-obvious | ||
|
|
||
| - Parse function defaults to `null` when param is absent | ||
| - `null` → "show all" (no filter applied) | ||
| - URL: `/workbooks?tab=solution` (no `categories=`) | ||
| - Browser back button naturally restores default "all" view | ||
| ## Type Guards at API Boundaries | ||
|
|
||
| **Benefit:** Cleaner URLs, intuitive history behavior, smaller sessionStorage footprint. | ||
|
|
||
| **Example:** `parseWorkBookCategory()` defaults to `null` = all categories | ||
|
|
||
| ### Type Guards: Precise Narrowing for Excluded Values | ||
|
|
||
| When a type guard intentionally excludes enum members, use `Exclude<T, 'VALUE'>` in the return type to match runtime behavior. Caller code then trusts the type system; no `as` casts needed. | ||
|
|
||
| ### Layer-Specific Responsibility: Normalization vs Filtering | ||
|
|
||
| When filtering data by multiple criteria (format + role): | ||
|
|
||
| - **Service layer**: Normalize raw data format (e.g., `null → PENDING`). Return all data; stay framework-agnostic and testable. | ||
| - **UI layer**: Filter by role/context (e.g., "admin sees PENDING, user doesn't"). Apply display rules in component. | ||
|
|
||
| **Benefit**: Services remain pure and unit-testable without mocking roles; UI logic explicit in one place. | ||
|
|
||
| ### Function Composition: Single Responsibility | ||
|
|
||
| Separate independent transformations into distinct functions. Compose at call site. | ||
| When receiving enum values from external APIs, validate with a type guard: | ||
|
|
||
| ```typescript | ||
| // groupBySolutionCategory(): pure grouping (testable) | ||
| // filterGroupsByRole(): pure filtering by role (testable) | ||
| let filtered = $derived(filterGroupsByRole(groupBySolutionCategory(workbooks, map), role)); | ||
| // Good: `isValidTaskGrade(value): value is TaskGrade` | ||
| const grade = isValidTaskGrade(data.grade) ? data.grade : null; | ||
| ``` | ||
|
|
||
| **Benefit**: Each function testable in isolation; reusable in different contexts. | ||
|
|
||
| ## Documentation | ||
|
|
||
| ### Language Policy | ||
| Extract to `src/lib/utils/` with adjacent tests. | ||
|
|
||
| Write all project documentation (plans, dev-notes, guides, refactor notes) in Japanese. Write all source code comments, TSDoc, commit messages, and test titles in English. This keeps documentation readable for the team while keeping code comments universally accessible and searchable. | ||
| ## Dead Code: Three-Condition Rule | ||
|
|
||
| **Exception**: The `## CodeRabbit Findings` section in `plan.md` must quote findings verbatim in their original language (English). Do not translate CodeRabbit output. | ||
| Delete function only if: (1) zero callers, (2) replacement exists, (3) dependent fields also deleted. | ||
|
|
||
| ### TSDoc | ||
|
|
||
| Add TSDoc to every exported function, type, class. Minimum: `@param` (non-obvious), `@returns` (not evident from type). One-liner OK; multi-line for complex behavior only. | ||
|
|
||
| ### Documentation | ||
| ## Documentation | ||
|
|
||
| Write plans/dev-notes/guides in Japanese. Source code comments in English. Always specify language on code blocks (e.g., `typescript`, `sql`, `bash`). For Svelte 5 unclear behavior: fetch official docs via WebFetch, not training knowledge. | ||
| - **Plans/dev-notes**: Japanese | ||
| - **Code/commits/tests**: English | ||
| - **TSDoc**: required on all exports | ||
| - **Code blocks**: specify language (`typescript`, `sql`, `bash`) | ||
|
|
||
| ## Security & Code Review | ||
| ## Security | ||
|
|
||
| - **Logging**: No user-identifiable data in `console.log`. Single authoritative log in service layer. | ||
| - **CodeRabbit**: Run after all phases complete. Write `critical`/`high`/`medium` findings to `plan.md` verbatim; defer `nitpick` to PR CI. | ||
| - No user-identifiable data in logs | ||
| - No Prisma imports in route handlers | ||
| - Validate input at system boundaries | ||
| - Return safe defaults on service errors |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.