Skip to content

πŸ› οΈ DX: Support URL and text slug parsing in User APIs - #211

Open
bartholomej wants to merge 1 commit into
masterfrom
dx/extract-user-3725825361951973973
Open

πŸ› οΈ DX: Support URL and text slug parsing in User APIs#211
bartholomej wants to merge 1 commit into
masterfrom
dx/extract-user-3725825361951973973

Conversation

@bartholomej

@bartholomej bartholomej commented Jul 2, 2026

Copy link
Copy Markdown
Owner

πŸ’‘ What: Added an extractUser helper function.
🎯 Why: Developers can now seamlessly pass full URLs or text slugs into the user endpoints (userRatings and userReviews). Previously, this either required exact slug inputs or failed on full profile URLs, causing annoying parsing boilerplate for users. This change brings user endpoints up to parity with the movie and creator endpoints which already support extractId.
πŸš€ Examples:

// Before
const userId = myUrl.split('/uzivatel/')[1].split('/')[0];
await csfd.userRatings(userId);

// After
await csfd.userRatings('https://www.csfd.cz/uzivatel/912-bart/');

PR created automatically by Jules for task 3725825361951973973 started by @bartholomej

Summary by CodeRabbit

  • New Features

    • Added support for normalizing user inputs from IDs, usernames, and user profile URLs.
    • User-related actions now accept either a numeric ID or a slug-style username.
  • Bug Fixes

    • Improved validation for invalid user inputs with a clearer error message.
    • User lookup and paging now consistently use the normalized user value.
  • Tests

    • Added coverage for numeric strings, full URLs, relative paths, and fallback string handling.

- Added `extractUser` to `global.helper.ts` to allow passing URLs or full slugs directly to user APIs.
- Updated `userRatings` and `userReviews` to utilize `extractUser`.
- Added tests to ensure complete backwards compatibility.

Co-authored-by: bartholomej <5861310+bartholomej@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

πŸ‘‹ Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a πŸ‘€ emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

πŸ“ Walkthrough

Walkthrough

Adds a new extractUser helper function that normalizes user identifiers (numeric IDs, slugs, or URLs). Integrates this helper into UserRatingsScraper and UserReviewsScraper to validate and normalize the user argument before constructing request URLs, throwing an error on invalid input. Adds corresponding tests.

Changes

extractUser Helper and Service Integration

Layer / File(s) Summary
extractUser helper and tests
src/helpers/global.helper.ts, tests/helpers.test.ts
Adds extractUser to normalize numeric strings, slugs, and /uzivatel/<slug> URLs, with tests covering these cases.
User ratings service integration
src/services/user-ratings.service.ts
Uses extractUser to normalize and validate the user input before building initial and paginated request URLs, throwing an error on invalid values.
User reviews service integration
src/services/user-reviews.service.ts
Uses extractUser to normalize and validate the user input before building initial and paginated review URLs, throwing an error on invalid values.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant UserRatingsScraper as "UserRatingsScraper / UserReviewsScraper"
    participant extractUser

    Caller->>UserRatingsScraper: userRatings(user, config)
    UserRatingsScraper->>extractUser: extractUser(user)
    extractUser-->>UserRatingsScraper: extracted value (number/string/null)
    alt invalid extracted value
        UserRatingsScraper-->>Caller: throw "user must be a valid user ID or slug"
    else valid extracted value
        UserRatingsScraper->>UserRatingsScraper: build URL with extracted value
        UserRatingsScraper-->>Caller: return scraped data
    end
Loading

Related issues: None linked in the provided context.

Suggested labels: enhancement, refactor

Suggested reviewers: bartholomej

🐰 A slug or a number, a URL too,
extractUser sorts them, plain in view,
ratings and reviews now check what's true,
no more raw strings slipping through!

πŸš₯ Pre-merge checks | βœ… 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the change well, but it does not follow the repository template or include the required Type of change, Related Issues, and Checklist sections. Add the missing template sections, select the relevant type of change, link any related issues, and complete the checklist items.
βœ… Passed checks (4 passed)
Check name Status Explanation
Title check βœ… Passed The title clearly describes the main change: adding user URL/slug parsing support in the user APIs.
Docstring Coverage βœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.
✨ 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 dx/extract-user-3725825361951973973

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

πŸ”§ ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

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

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

Caution

This repository is currently using the Sentry GitHub App to receive Codecov PR comments. This integration will be deprecated on July 8, 2026. Please install the Codecov GitHub App to continue receiving coverage reports on your pull requests.
❌ Patch coverage is 86.36364% with 3 lines in your changes missing coverage. Please review.
βœ… Project coverage is 98.37%. Comparing base (686bd47) to head (d5d6b87).

Files with missing lines Patch % Lines
src/helpers/global.helper.ts 91.66% 1 Missing ⚠️
src/services/user-ratings.service.ts 80.00% 1 Missing ⚠️
src/services/user-reviews.service.ts 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #211      +/-   ##
==========================================
- Coverage   98.71%   98.37%   -0.35%     
==========================================
  Files          34       34              
  Lines         781      799      +18     
  Branches      202      208       +6     
==========================================
+ Hits          771      786      +15     
- Misses         10       13       +3     

β˜” View full report in Codecov by Harness.
πŸ“’ Have feedback on the report? Share it here.

πŸš€ New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • πŸ“¦ JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/services/user-ratings.service.ts (1)

25-31: πŸ“ Maintainability & Code Quality | πŸ”΅ Trivial | ⚑ Quick win

Duplicate validation logic across services.

This extractUser + null/undefined/empty validation + throw block is duplicated verbatim in user-reviews.service.ts (Lines 27-33). Consider extracting a shared helper, e.g. getValidatedUser(user): string | number in global.helper.ts, that both services call β€” keeping validation logic (helper concern) out of the orchestration layer.

As per coding guidelines, "Services in src/services should act as orchestrators: call Fetchers, use Helpers to parse data, and return typed DTOs."

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/user-ratings.service.ts` around lines 25 - 31, Duplicate user
validation exists in user-ratings.service.ts and user-reviews.service.ts, and
the validation logic should be moved out of the service orchestration layer.
Extract the repeated extractUser plus null/undefined/empty check and Error throw
into a shared helper such as getValidatedUser(user) in global.helper.ts, then
call that helper from both services so user-ratings.service and
user-reviews.service only orchestrate fetch and return typed results.

Source: Coding guidelines

πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/helpers/global.helper.ts`:
- Around line 57-78: Guard invalid numeric input in extractUser so NaN is not
propagated into URLs. Update the extractUser function to validate number inputs
the same way extractId does, returning null for invalid numbers instead of
passing NaN through, and make sure the string parsing path still returns numeric
IDs only when the trimmed value is a valid number while preserving the existing
/uzivatel/ extraction behavior.

---

Nitpick comments:
In `@src/services/user-ratings.service.ts`:
- Around line 25-31: Duplicate user validation exists in user-ratings.service.ts
and user-reviews.service.ts, and the validation logic should be moved out of the
service orchestration layer. Extract the repeated extractUser plus
null/undefined/empty check and Error throw into a shared helper such as
getValidatedUser(user) in global.helper.ts, then call that helper from both
services so user-ratings.service and user-reviews.service only orchestrate fetch
and return typed results.
πŸͺ„ 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1a3a88b2-2615-41bb-be73-9d746381cf6a

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 686bd47 and d5d6b87.

πŸ“’ Files selected for processing (4)
  • src/helpers/global.helper.ts
  • src/services/user-ratings.service.ts
  • src/services/user-reviews.service.ts
  • tests/helpers.test.ts

Comment on lines +57 to +78
export const extractUser = (userOrUrl: number | string): string | number => {
if (typeof userOrUrl === 'number') {
return userOrUrl;
}

if (typeof userOrUrl === 'string') {
const trimmed = userOrUrl.trim();
if (/^\d+$/.test(trimmed)) {
return Number(trimmed);
}

// Check for URL containing /uzivatel/
const match = trimmed.match(/\/uzivatel\/([^\/]+)/);
if (match) {
return match[1];
}

return trimmed;
}

return userOrUrl;
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟑 Minor | ⚑ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check strictness settings that determine if TS2367 fires on this comparison
fd tsconfig.json --exec cat {}

Repository: bartholomej/node-csfd-api

Length of output: 1072


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the helper and the two consuming services.
for f in src/helpers/global.helper.ts src/services/user-ratings.service.ts src/services/user-reviews.service.ts; do
  echo "===== $f ====="
  wc -l "$f"
  cat -n "$f"
done

Repository: bartholomej/node-csfd-api

Length of output: 16414


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "export const (userRatingsUrl|userReviewsUrl)|function (userRatingsUrl|userReviewsUrl)|const (userRatingsUrl|userReviewsUrl)" src

Repository: bartholomej/node-csfd-api

Length of output: 399


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,120p' src/vars.ts

Repository: bartholomej/node-csfd-api

Length of output: 2173


🏁 Script executed:

#!/bin/bash
set -euo pipefail

cat -n src/vars.ts | sed -n '1,120p'

Repository: bartholomej/node-csfd-api

Length of output: 2544


Guard NaN in extractUser

extractUser(NaN) currently returns NaN, so userRatingsUrl/userReviewsUrl build /uzivatel/NaN/... instead of rejecting the input. Mirror extractId here and return null for invalid numbers.

πŸ€– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/helpers/global.helper.ts` around lines 57 - 78, Guard invalid numeric
input in extractUser so NaN is not propagated into URLs. Update the extractUser
function to validate number inputs the same way extractId does, returning null
for invalid numbers instead of passing NaN through, and make sure the string
parsing path still returns numeric IDs only when the trimmed value is a valid
number while preserving the existing /uzivatel/ extraction behavior.

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.

2 participants