Skip to content

⚡ Bolt: Optimize JSON-LD parsing in MovieScraper#81

Closed
bartholomej wants to merge 1 commit intomasterfrom
bolt/optimize-json-parsing-5305642222362313870
Closed

⚡ Bolt: Optimize JSON-LD parsing in MovieScraper#81
bartholomej wants to merge 1 commit intomasterfrom
bolt/optimize-json-parsing-5305642222362313870

Conversation

@bartholomej
Copy link
Copy Markdown
Owner

@bartholomej bartholomej commented Feb 14, 2026

💡 What: Optimized MovieScraper to parse JSON-LD data only once instead of multiple times in helper functions.
🎯 Why: Parsing JSON is synchronous and can be expensive. Since multiple fields (year, duration) are extracted from the same JSON-LD block, it is more efficient to parse it once and pass the object.
📊 Impact: Reduces redundant work. For each movie scraped, JSON.parse is called 1 time instead of 3 times (once for year, once for duration, and potentially more if future fields are added).
🔬 Measurement: Verified with yarn test. All tests passed. The logic ensures that if JSON parsing fails, existing fallback mechanisms (DOM scraping) are used, maintaining robustness.


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

Summary by CodeRabbit

  • Refactor
    • Improved internal error handling for movie metadata processing with enhanced null-safety checks throughout the parsing pipeline
    • Streamlined data extraction with better fallback mechanisms when metadata fields are incomplete or unavailable
    • Enhanced robustness of movie information retrieval with more consistent error handling

- Parse JSON-LD once in `MovieScraper.movie` and pass the object to helpers.
- Refactor `getMovieYear` and `getMovieDuration` to accept parsed object.
- Avoids redundant `JSON.parse` calls.
- Preserves fallback logic for duration scraping.
- Updates tests to reflect signature changes.

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
Copy link
Copy Markdown

coderabbitai bot commented Feb 14, 2026

📝 Walkthrough

Walkthrough

The pull request refactors JSON-LD handling by shifting the parsing responsibility from individual helper functions to the service layer. Helper functions now accept pre-parsed JSON-LD objects instead of raw strings, with improved null-safety and error handling throughout.

Changes

Cohort / File(s) Summary
JSON-LD Helper Functions
src/helpers/movie.helper.ts
Updated getMovieYear and getMovieDuration signatures to accept parsed JSON-LD objects instead of strings. Added null-return paths for missing data and silent error handling for parsing failures.
Movie Service
src/services/movie.service.ts
Introduced JSON-LD parsing with try/catch in MovieScraper.movie, passing parsed objects to buildMovie. Updated buildMovie signature to accept parsed jsonLd: any instead of string.
Test Utilities
tests/movie.test.ts
Updated getJsonLd helper to return parsed JSON object instead of string, and adjusted getMovie test structure to reflect jsonLd as an object.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • ESM + CommonJS build 🎉  #18: Both PRs modify the same helper functions and service methods to change JSON-LD parameter handling from raw strings to parsed objects.

Suggested labels

enhancement

Poem

🐰 A parsing shift, clean and bright,
JSON-LD moves upward in flight!
Helpers now rest on parsed delight,
Error-safe code shining so right. ✨

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main optimization: parsing JSON-LD once instead of multiple times in MovieScraper.
Description check ✅ Passed The description provides clear context on the what, why, and impact of the changes, though it does not follow the exact template structure with checkboxes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into master

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bolt/optimize-json-parsing-5305642222362313870

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 and usage tips.

@codecov-commenter
Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 85.71429% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.20%. Comparing base (781d6bb) to head (2a70549).

Files with missing lines Patch % Lines
src/helpers/movie.helper.ts 88.88% 1 Missing ⚠️
src/services/movie.service.ts 80.00% 1 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #81      +/-   ##
==========================================
- Coverage   99.52%   99.20%   -0.32%     
==========================================
  Files          28       28              
  Lines         629      630       +1     
  Branches      143      145       +2     
==========================================
- Hits          626      625       -1     
- Misses          3        5       +2     

☔ View full report in Codecov by Sentry.
📢 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.

Copy link
Copy Markdown

@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: 1

🤖 Fix all issues with AI agents
In `@src/services/movie.service.ts`:
- Around line 44-50: The code calls
movieHtml.querySelector('script[type="application/ld+json"]').innerText without
checking for a null result, which can throw a TypeError before the JSON.parse
try/catch; update the block in movie.service.ts to first get the element into a
variable (e.g., const ldScript = movieHtml.querySelector(...)) and use optional
chaining or a null check when reading innerText (e.g., const jsonLd =
ldScript?.innerText), then only attempt JSON.parse when jsonLd is not null/empty
and handle the missing-script case by leaving movieJsonLd null or logging a
clear warning; reference the existing symbols movieHtml, jsonLd, movieJsonLd and
the querySelector call to locate where to change.
🧹 Nitpick comments (1)
src/services/movie.service.ts (1)

59-59: Consider a narrower type than any for jsonLd.

Using any loses all type safety. Even a minimal interface (e.g., { dateCreated?: string; duration?: string }) or Record<string, unknown> would catch misuse at compile time.

Comment on lines 44 to +50
const jsonLd = movieHtml.querySelector('script[type="application/ld+json"]').innerText;
return this.buildMovie(+movieId, movieNode, asideNode, pageClasses, jsonLd, options);
let movieJsonLd = null;
try {
movieJsonLd = JSON.parse(jsonLd);
} catch (e) {
console.error('node-csfd-api: Error parsing JSON-LD', e);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Potential TypeError if the JSON-LD <script> tag is missing.

Line 44 calls .innerText on the result of querySelector(...) without a null check. If the page lacks a script[type="application/ld+json"] element, this throws before the try/catch on line 46 can catch it.

🐛 Proposed fix — use optional chaining
-    const jsonLd = movieHtml.querySelector('script[type="application/ld+json"]').innerText;
-    let movieJsonLd = null;
-    try {
-      movieJsonLd = JSON.parse(jsonLd);
-    } catch (e) {
-      console.error('node-csfd-api: Error parsing JSON-LD', e);
-    }
+    const jsonLdRaw = movieHtml.querySelector('script[type="application/ld+json"]')?.innerText;
+    let movieJsonLd = null;
+    if (jsonLdRaw) {
+      try {
+        movieJsonLd = JSON.parse(jsonLdRaw);
+      } catch (e) {
+        console.error('node-csfd-api: Error parsing JSON-LD', e);
+      }
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const jsonLd = movieHtml.querySelector('script[type="application/ld+json"]').innerText;
return this.buildMovie(+movieId, movieNode, asideNode, pageClasses, jsonLd, options);
let movieJsonLd = null;
try {
movieJsonLd = JSON.parse(jsonLd);
} catch (e) {
console.error('node-csfd-api: Error parsing JSON-LD', e);
}
const jsonLdRaw = movieHtml.querySelector('script[type="application/ld+json"]')?.innerText;
let movieJsonLd = null;
if (jsonLdRaw) {
try {
movieJsonLd = JSON.parse(jsonLdRaw);
} catch (e) {
console.error('node-csfd-api: Error parsing JSON-LD', e);
}
}
🤖 Prompt for AI Agents
In `@src/services/movie.service.ts` around lines 44 - 50, The code calls
movieHtml.querySelector('script[type="application/ld+json"]').innerText without
checking for a null result, which can throw a TypeError before the JSON.parse
try/catch; update the block in movie.service.ts to first get the element into a
variable (e.g., const ldScript = movieHtml.querySelector(...)) and use optional
chaining or a null check when reading innerText (e.g., const jsonLd =
ldScript?.innerText), then only attempt JSON.parse when jsonLd is not null/empty
and handle the missing-script case by leaving movieJsonLd null or logging a
clear warning; reference the existing symbols movieHtml, jsonLd, movieJsonLd and
the querySelector call to locate where to change.

@bartholomej bartholomej deleted the bolt/optimize-json-parsing-5305642222362313870 branch March 20, 2026 22:49
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