Skip to content

feat: pre-commit type checking#2277

Draft
kyrers wants to merge 19 commits intodevfrom
feat/pre-commit-type-check
Draft

feat: pre-commit type checking#2277
kyrers wants to merge 19 commits intodevfrom
feat/pre-commit-type-check

Conversation

@kyrers
Copy link
Copy Markdown
Contributor

@kyrers kyrers commented Apr 22, 2026

Resolves #2273.


PR-Codex overview

This PR primarily focuses on improving code quality and consistency by updating TypeScript types, enhancing error handling, and refining ESLint configurations across various modules.

Detailed summary

  • Updated additionalContext type from any to unknown in GetDisputeParametersOptions.
  • Refined error messages with improved formatting in fetchDisputeDetails and fetchDisputeTemplateFromId.
  • Enhanced type safety in fetchIpfsJsonAction and other action mappings.
  • Consolidated ESLint configurations for multiple projects.
  • Added linting rules for staged files in .lintstagedrc.json files.
  • Updated imports and exports in various files for better organization.
  • Improved code readability and maintainability through formatting adjustments.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • Chores
    • Pre-commit hook now fails fast and conditionally runs type checks for affected packages.
    • Staged JS/TS files are auto-fixed with ESLint then formatted with Prettier; per-package lint-staged configs were added.
    • Type-checking scope narrowed to source files for faster checks.
    • ESLint configuration modernized and added a flat-config entrypoint.
    • Various TypeScript typings tightened and internal formatting improved.

@kyrers kyrers self-assigned this Apr 22, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 22, 2026

Deploy Preview for kleros-v2-testnet-devtools failed. Why did it fail? →

Name Link
🔨 Latest commit dc582f3
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-testnet-devtools/deploys/69f3a869e94db100089673a0

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 22, 2026

Deploy Preview for kleros-v2-neo failed. Why did it fail? →

Name Link
🔨 Latest commit dc582f3
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-neo/deploys/69f3a8697797840008799f6e

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 22, 2026

Deploy Preview for kleros-v2-testnet ready!

Name Link
🔨 Latest commit dc582f3
🔍 Latest deploy log https://app.netlify.com/projects/kleros-v2-testnet/deploys/69f3a8691754e3000858489d
😎 Deploy Preview https://deploy-preview-2277--kleros-v2-testnet.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)

Walkthrough

Pre-commit hook now fails fast and conditionally runs kleros-app type checks on staged files. A dedicated tsconfig.check.json limits type checking to src/**/*, check-types uses that config, and lint-staged now runs eslint --fix before Prettier for JS/TS files.

Changes

Cohort / File(s) Summary
Pre-commit hook
.husky/pre-commit
Enable set -e; inspect staged files and run workspace @kleros/kleros-app check-types when matching kleros-app/ before continuing to lint-staged.
kleros-app config & scripts
kleros-app/package.json, kleros-app/tsconfig.check.json
check-types script changed to tsc -p kleros-app/tsconfig.check.json; new tsconfig.check.json inherits base config and restricts includes to src/**/*.
Staged formatting/linting
.lintstagedrc.json
JS/TS staged files now run eslint --fix then prettier --write (reordered/expanded from Prettier-only).

Sequence Diagram(s)

sequenceDiagram
  participant Dev as Developer (git)
  participant Husky as Husky pre-commit
  participant Staged as Staged Files
  participant Yarn as Yarn workspace
  participant TSC as TypeScript (tsc)
  participant Lint as lint-staged -> ESLint/Prettier

  Dev->>Husky: git commit (triggers pre-commit)
  Husky->>Staged: list staged paths
  Staged-->>Husky: paths
  alt paths include kleros-app/
    Husky->>Yarn: run yarn workspace `@kleros/kleros-app` check-types
    Yarn->>TSC: tsc -p kleros-app/tsconfig.check.json
    TSC-->>Yarn: success/failure
    Yarn-->>Husky: exit code
    opt failure
      Husky-->>Dev: abort commit (fail-fast)
    end
  end
  Husky->>Lint: run lint-staged (eslint --fix, prettier)
  Lint-->>Husky: exit code
  Husky-->>Dev: allow/abort commit
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

  • Add pre-commit type checking and linting #2273 — Implements pre-commit type checking and linting as requested (conditional type checks, revive yarn check-types).
  • kleros/atlas#633 — Similar pre-commit fail-fast behavior and conditional type check logic touching .husky/pre-commit.

Poem

🐰 I hop through staged files, ears all perked,
I run my checks so no bug goes unchecked,
Types and lint I chase with speed,
A tidy commit is my small deed! 🌿✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: pre-commit type checking' clearly summarizes the main change: adding type checking to the pre-commit workflow.
Linked Issues check ✅ Passed All linked issue #2273 requirements are met: pre-commit hook added with type checking, check-types command restored and enhanced, ESLint integrated with staging workflow.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing pre-commit type checking and linting as specified in issue #2273; no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/pre-commit-type-check

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 22, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 22, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 22, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 23, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 23, 2026
@kyrers
Copy link
Copy Markdown
Contributor Author

kyrers commented Apr 28, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
kleros-sdk/test/dataMappings.test.ts (1)

283-285: Avoid repeated as unknown as test casts.

At Line 283, Line 309, Line 335, and Line 358, double assertions bypass type checks entirely. Prefer a small runtime narrowing helper so test failures surface shape mismatches earlier.

♻️ Suggested pattern
+const expectRecord = (value: unknown): Record<string, unknown> => {
+  expect(value).to.be.an("object");
+  expect(value).to.not.equal(null);
+  return value as Record<string, unknown>;
+};

-const result = (await subgraphAction(mapping)) as unknown as SubgraphActionResult;
+const raw = expectRecord(await subgraphAction(mapping));
+expect(raw).to.have.property("escrowsData");
+const result = raw as SubgraphActionResult;

Also applies to: 309-309, 335-335, 358-360

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kleros-sdk/test/dataMappings.test.ts` around lines 283 - 285, The test uses
unsafe double-casts like "(await subgraphAction(mapping)) as unknown as
SubgraphActionResult" which hides shape mismatches; replace these with a small
runtime narrowing helper (e.g., assertIsSubgraphActionResult(value) or a
validateSubgraphActionResult function) that takes the raw await
subgraphAction(mapping) output, performs runtime type checks for the expected
fields, and returns the value typed as SubgraphActionResult or throws a
descriptive error; update the occurrences around the result variable in the
subgraphAction(...) calls so tests fail with clear messages instead of silently
bypassing type checking.
kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts (1)

9-12: Refactor isMultiaddr into smaller validators.

Line 10 packs multiple URI formats/protocol alternatives into one regex, which is hard to maintain and already triggers complexity checks. Splitting the checks into separate validators will keep behavior clearer and easier to evolve.

♻️ Proposed refactor
+const MULTIADDR_PATH_REGEX =
+  /^\/(?:ip4|ip6|dns4|dns6|dnsaddr|tcp|udp|utp|tls|ws|wss|p2p-circuit|p2p-webrtc-star|p2p-webrtc-direct|p2p-websocket-star|onion|ipfs)(\/[^\s/]+)+$/;
+const IPFS_URI_REGEX =
+  /^ipfs:\/\/[a-zA-Z0-9]+\/[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)?$/;
+
 export const isMultiaddr = (str: string): boolean =>
-  /^\/(?:ip4|ip6|dns4|dns6|dnsaddr|tcp|udp|utp|tls|ws|wss|p2p-circuit|p2p-webrtc-star|p2p-webrtc-direct|p2p-websocket-star|onion|ipfs)(\/[^\s/]+)+$|^ipfs:\/\/[a-zA-Z0-9]+\/[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)?$/.test(
-    str,
-  );
+  MULTIADDR_PATH_REGEX.test(str) || IPFS_URI_REGEX.test(str);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts` around lines 9 -
12, The isMultiaddr regexp is doing too much and should be split into smaller,
composable validators: create separate helper functions (e.g., isMultiaddrPath,
isIpfsUri, isOnionAddr or similar) that each validate one URI/scheme pattern,
export them if needed, then rewrite isMultiaddr to return the OR of those
helpers (e.g., return isMultiaddrPath(str) || isIpfsUri(str) ||
isOnionAddr(str)); update any callers/tests to use the new helpers or keep
behavior identical and add unit tests for each helper to preserve coverage and
clarity; refer to the existing isMultiaddr function name to locate where to
change the logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@kleros-sdk/src/dataMappings/retrieveRealityData.ts`:
- Around line 87-90: populatedTemplate returned from
rc_question.populatedJSONForTemplate is typed as any and its .type is accessed
later (at uses around where .type is read); add a runtime type-narrowing guard
before those accesses by checking the value is an object and has a string 'type'
property (e.g. if (populatedTemplate && typeof populatedTemplate === 'object' &&
'type' in populatedTemplate && typeof populatedTemplate.type === 'string') { ...
} ), or define and use a local interface (e.g. PopulatedTemplate { type: string;
[key: string]: any }) then narrow/cast after validating the shape so subsequent
reads at the locations that reference populatedTemplate.type (calls near
rc_question.populatedJSONForTemplate) are safe.

In `@kleros-sdk/src/dataMappings/utils/createResultObject.ts`:
- Around line 10-18: The traversal guards in createResultObject.ts use truthy
checks that drop valid falsy values (e.g., 0, false, ""), so change those checks
to nullish checks: replace "if (!acc)" with "if (acc == null)" and replace the
"innerData ? ... : undefined" condition with a nullish check like "if (innerData
== null) return undefined" before accessing (innerData as Record<string,
unknown>)[index]; ensure you reference the variables acc, accRecord, part, and
innerData in the updated checks so valid falsy values are preserved during
traversal.

---

Nitpick comments:
In `@kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts`:
- Around line 9-12: The isMultiaddr regexp is doing too much and should be split
into smaller, composable validators: create separate helper functions (e.g.,
isMultiaddrPath, isIpfsUri, isOnionAddr or similar) that each validate one
URI/scheme pattern, export them if needed, then rewrite isMultiaddr to return
the OR of those helpers (e.g., return isMultiaddrPath(str) || isIpfsUri(str) ||
isOnionAddr(str)); update any callers/tests to use the new helpers or keep
behavior identical and add unit tests for each helper to preserve coverage and
clarity; refer to the existing isMultiaddr function name to locate where to
change the logic.

In `@kleros-sdk/test/dataMappings.test.ts`:
- Around line 283-285: The test uses unsafe double-casts like "(await
subgraphAction(mapping)) as unknown as SubgraphActionResult" which hides shape
mismatches; replace these with a small runtime narrowing helper (e.g.,
assertIsSubgraphActionResult(value) or a validateSubgraphActionResult function)
that takes the raw await subgraphAction(mapping) output, performs runtime type
checks for the expected fields, and returns the value typed as
SubgraphActionResult or throws a descriptive error; update the occurrences
around the result variable in the subgraphAction(...) calls so tests fail with
clear messages instead of silently bypassing type checking.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8c7c7f72-4c06-4591-8653-9ac9a051a51d

📥 Commits

Reviewing files that changed from the base of the PR and between 65c8528 and 2597fde.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (31)
  • .husky/pre-commit
  • .lintstagedrc.json
  • eslint-config/.eslintrc.js
  • eslint-config/flat.mjs
  • eslint-config/package.json
  • eslint.config.mjs
  • kleros-app/.lintstagedrc.json
  • kleros-app/tsconfig.check.json
  • kleros-sdk/.lintstagedrc.json
  • kleros-sdk/eslint.config.mjs
  • kleros-sdk/package.json
  • kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts
  • kleros-sdk/src/dataMappings/actions/subgraphAction.ts
  • kleros-sdk/src/dataMappings/executeActions.ts
  • kleros-sdk/src/dataMappings/retrieveRealityData.ts
  • kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts
  • kleros-sdk/src/dataMappings/utils/actionTypes.ts
  • kleros-sdk/src/dataMappings/utils/createResultObject.ts
  • kleros-sdk/src/dataMappings/utils/disputeDetailsSchema.ts
  • kleros-sdk/src/dataMappings/utils/disputeDetailsTypes.ts
  • kleros-sdk/src/dataMappings/utils/index.ts
  • kleros-sdk/src/dataMappings/utils/populateTemplate.ts
  • kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts
  • kleros-sdk/src/errors/index.ts
  • kleros-sdk/src/requests/fetchDisputeDetails.ts
  • kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts
  • kleros-sdk/src/types/index.ts
  • kleros-sdk/src/types/reality-eth-lib.d.ts
  • kleros-sdk/src/utils/getDispute.ts
  • kleros-sdk/test/dataMappings.test.ts
  • package.json
✅ Files skipped from review due to trivial changes (19)
  • kleros-sdk/.lintstagedrc.json
  • kleros-sdk/src/types/reality-eth-lib.d.ts
  • kleros-sdk/src/dataMappings/utils/disputeDetailsTypes.ts
  • kleros-sdk/src/dataMappings/actions/subgraphAction.ts
  • eslint.config.mjs
  • kleros-sdk/src/dataMappings/utils/index.ts
  • kleros-sdk/src/dataMappings/actions/fetchIpfsJsonAction.ts
  • kleros-sdk/src/errors/index.ts
  • kleros-app/tsconfig.check.json
  • kleros-sdk/src/types/index.ts
  • kleros-sdk/eslint.config.mjs
  • kleros-sdk/src/dataMappings/utils/actionTypeValidators.ts
  • kleros-sdk/src/dataMappings/utils/actionTypes.ts
  • kleros-sdk/src/requests/fetchDisputeDetails.ts
  • kleros-sdk/src/dataMappings/utils/populateTemplate.ts
  • package.json
  • kleros-sdk/src/dataMappings/utils/replacePlaceholdersWithValues.ts
  • kleros-sdk/src/requests/fetchDisputeTemplateFromId.ts
  • kleros-sdk/src/dataMappings/executeActions.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • .lintstagedrc.json
  • .husky/pre-commit

Comment thread kleros-sdk/src/dataMappings/retrieveRealityData.ts
Comment thread kleros-sdk/src/dataMappings/utils/createResultObject.ts
coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 28, 2026
Comment thread kleros-sdk/src/dataMappings/retrieveRealityData.ts Outdated
Comment thread kleros-sdk/src/utils/getDispute.ts Outdated
} catch (err: any) {
throw err;
}
data = await executeActions(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to unwrap the try-catch 👀

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it was flagged by no-useless-catch as the behavior is the same.
The try-catch only threw the error, which is the same behavior as now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, makes sense.
In that case we can just do

const data = await executeActions

wdyt, there is no reason to initialize to an empty object

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in dd3f18f.
It can't be exactly like that because it is inside an if, and I don't think populateTemplate can handle undefined, but you're right that it can be simplified.

Comment thread package.json
coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 29, 2026
@kyrers kyrers force-pushed the feat/pre-commit-type-check branch from dd3f18f to c5b4ce8 Compare April 30, 2026 15:41
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)
4.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add pre-commit type checking and linting

2 participants