Skip to content

feat!: rewrite#179

Merged
Viren070 merged 217 commits intomainfrom
rewrite
Jun 13, 2025
Merged

feat!: rewrite#179
Viren070 merged 217 commits intomainfrom
rewrite

Conversation

@Viren070
Copy link
Copy Markdown
Owner

@Viren070 Viren070 commented May 26, 2025

closes #176
closes #174
closes #158
closes #141 😐
closes #53
closes #126 😐
closes #32 😐
closes #64
closes #116
closes #114
closes #101
closes #46
closes #96
closes #95
closes #90
closes #55
closes #73
closes #111
closes #182
closes #180
closes #143
closes #167
closes #60
closes #11
closes #153
closes #113

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive core package with advanced streaming, proxy, formatting, parsing, and preset management.
    • Added robust configuration validation, encryption, user data handling, and feature control.
    • Implemented support for numerous streaming services, presets, and proxy integrations with dynamic addon generation.
    • Enhanced metadata retrieval, language mapping, and catalogue management including TMDB and RPDB integration.
    • Added detailed logging, HTTP utilities, caching, and cryptographic utilities.
    • Integrated new stream parsers and formatters with customizable templates and presets for popular services.
    • Introduced environment configuration with strict validation and rate limiting controls.
    • Added proxy support with MediaFlow and StremThru integration, including public IP retrieval and URL generation.
    • Developed a new frontend stack with Tailwind CSS, PostCSS, and modern UI libraries.
    • Added database abstraction supporting PostgreSQL and SQLite with transaction queue management.
    • Implemented extensive preset system with multiple streaming service integrations and configurable options.
    • Enhanced stream parsing with detailed metadata extraction and error detection.
    • Added Stremio transformation layer for adapting streams and metadata to Stremio format.
    • Added new Docker health checks and dynamic port configuration.
    • Introduced metadata generation step in build workflow.
    • Added volume mount for local data directory in Docker Compose.
    • Updated package scripts and dependencies for streamlined build and start processes.
  • Bug Fixes

    • Improved regex parsing, language detection, and error handling in stream metadata extraction.
    • Enhanced proxy IP validation and retry logic.
  • Refactor

    • Removed deprecated addon and formatter packages; consolidated functionality into core.
    • Simplified Docker and deployment workflows with updated environment variable handling.
    • Reorganized frontend dependencies and build configurations, adopting Tailwind CSS and modern UI frameworks.
    • Streamlined TypeScript configurations and module exports for better maintainability.
    • Refined environment variable management and logging across backend and frontend.
  • Chores

    • Updated .gitignore files and documentation for frontend and core packages.
    • Added PostCSS configurations aligned with new frontend stack.
    • Cleaned up environment variable loading and logging in frontend Next.js config.
    • Removed ESLint configuration for frontend.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented May 26, 2025

Warning

Rate limit exceeded

@Viren070 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 2 minutes and 54 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 56734f0 and c8224bc.

📒 Files selected for processing (1)
  • packages/core/src/db/users.ts (1 hunks)

Walkthrough

This update restructures the codebase, consolidating multiple packages into a new core module, and removes legacy packages such as addon, formatters, and cloudflare-worker. It introduces new features, presets, and utilities, expands filtering and sorting capabilities, enhances configuration and proxy handling, and adds comprehensive support for new addons, catalogues, and custom formatting.

Changes

File(s)/Path(s) Change Summary
.github/workflows/deploy-docker.yml, .gitignore, Dockerfile, compose.yaml, package.json Updated build scripts, Docker, and Compose configuration; added metadata generation and Node.js setup; revised ignore rules for new structure.
packages/addon/, packages/formatters/, packages/cloudflare-worker/ Entirely removed: legacy addon, formatter, and Cloudflare worker packages and their source/configuration files.
packages/core/package.json, tsconfig.json, src/ (all subfolders) Introduced new core package with comprehensive modules for database, formatting, parsing, proxying, configuration, logging, metadata, languages, and numerous streaming presets. Implements a unified API for managing streams, addons, and user data.
packages/frontend/ Overhauled frontend dependencies, scripts, and configuration; added Tailwind/PostCSS setup; updated README and ignore rules; removed legacy ESLint and CSS files; simplified Next.js config.
Many new files under packages/core/src/presets/ Added numerous streaming addon presets: StremThru Torz, Stream-Fusion, MediaFusion, Marvel, DC Universe, Star Wars Universe, Debridio (multiple variants), Orion, Peerflix, Jackettio, Torrentio, Torbox, Easynews, NuvioStreams, Custom, AIOStreams, and more—each with their own parsing, manifest, and configuration logic.
packages/core/src/formatters/ Implemented new formatter system with base, predefined, custom, and utility modules; supports advanced custom templates and multiple built-in formatter types; exposes a factory for formatter instantiation.
packages/core/src/utils/ Added or refactored modules for configuration validation, environment variables, constants, crypto, cache, HTTP, logging, feature toggles, resource loading, regex handling, and language mappings.
packages/core/src/db/ Added unified database abstraction (Postgres/SQLite), user repository with encryption and validation, schema definitions using Zod, and a transaction queue for concurrency control.
packages/core/src/parser/ Introduced new file and stream parsers with enhanced regexes for resolutions, audio codecs, channels, and languages; added condition parser for advanced filtering logic.
packages/core/src/proxy/ Implemented extensible proxy system with base, MediaFlow, and StremThru proxies; supports public IP retrieval, URL generation, and credential management.
packages/core/src/transformers/ Added Stremio transformer to convert internal responses to Stremio-compatible formats, including error handling and custom formatting.
packages/core/src/main.ts Centralised streaming logic: manages addons, manifests, resources, filtering, deduplication, sorting, limiting, proxying, and error handling; supports group-based fetching and catalogue management.
packages/core/src/wrapper.ts Introduced a wrapper class for interacting with remote addon resources, manifest fetching, and response validation.
packages/core/src/utils/languages.ts Added comprehensive language mapping for accurate language extraction and display.
packages/core/src/utils/regex.ts Refactored regex utilities to be asynchronous and improved caching and hashing.
packages/core/src/formatters/utils.ts Renamed and expanded byte formatting utility to support both binary and decimal units.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Core
    participant PresetManager
    participant AddonPreset
    participant Wrapper
    participant Proxy
    participant Formatter
    participant StremioTransformer

    User->>Core: Submit stream/catalog/meta/subtitle request
    Core->>PresetManager: Retrieve applicable presets
    PresetManager->>AddonPreset: Generate addon(s) with options
    Core->>Wrapper: Fetch manifest/resources/streams from addon(s)
    Wrapper->>AddonPreset: Use parser to normalise streams
    Core->>Core: Filter, deduplicate, sort, limit streams
    Core->>Proxy: Proxy streams if configured/applicable
    Core->>Formatter: Format streams with selected/custom formatter
    Core->>StremioTransformer: Transform response to Stremio format
    StremioTransformer->>User: Return formatted response
Loading

Assessment against linked issues

Objective Addressed Explanation
Add StremThru Torz Addon (#176)
Add Stream-Fusion Addon (#180)
Add MediaFusion folder size display (#182)
Accurate language extraction from MediaFusion streams (#53)
Add easy custom formatter choices, incl. season/episode combs (#158)
Add option to hide stalled torrents (#101)
Add global and per-resolution result limits (#95, #73, #96)
Add catalogue support, including custom and chainable addons (#64, #143, #116)
Allow separate sort order for movies and TV shows (#114)
Add additional audio channel tags and audio tag filters (#60)
Add option to override addon base URL with non-manifest links (#90)
Add drag-and-drop reordering for config lists (#167)
Add ENFORCE_DEBRID and other ENFORCE options for config (#174)
Add option to request next episode for caching (#46)
Preserve addon names when chaining AIOStreams (#143)
Remove Cloudflare Worker package and fix related deployment errors (#141, #126, #32)
MediaFusion contribution streams read details from addon not filename (#111)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Removal of legacy packages: packages/addon/, packages/formatters/, packages/cloudflare-worker/ These are not directly requested by the linked issues but are part of a major refactor. Removal is justified for codebase consolidation.
Overhaul of frontend dependencies and build tooling (packages/frontend/) Not directly requested, but supports new features and modernises UI stack.
Addition of new database abstraction and user management (packages/core/src/db/) Not explicitly requested, but necessary for unified configuration and user handling.

Possibly related PRs

  • feat: add stremthru as proxy provider #160: The main PR introduces StremThru proxy support alongside MediaFlow in the deployment workflow, Docker setup, frontend configuration UI, and core logic, including proxy IP retrieval and stream proxying in the AIOStreams class; the retrieved PR feat: add stremthru as proxy provider #160 specifically modifies the AIOStreams class to add StremThru proxy support with IP retrieval, proxy eligibility checks, and proxied stream URL generation, directly overlapping the same class and methods for proxy integration.

Poem

  (\(\ 
 ( -.-)   A hop and a leap, new features abound,
 o_(")(")  With proxies and presets, new add-ons are found.
 
 Languages parsed, folders sized with care,
 Custom formats, drag-and-drop flair!
 Catalogues and chains, torrents that hide,
 This rabbit’s delighted—let’s stream worldwide! 🥕
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 6

♻️ Duplicate comments (10)
packages/core/src/db/schemas.ts (3)

4-18: z.enum(constants.X) still expects a readonly tuple – compile will fail

Earlier feedback noted that passing a plain string[] to z.enum violates the required Readonly<[...]> signature unless the constant is declared as const. Please apply the fix consistently:

-const ServiceIds = z.enum(constants.SERVICES);
+const ServiceIds = z.enum([...constants.SERVICES] as const);

Repeat for every z.enum(constants.*) in this file.


43-50: Plain-text credential storage

StreamProxyConfig.credentials remains an unencrypted string. Storing secrets unhashed in the DB/logs is a security liability; hash or encrypt before persistence and redact on serialisation.


70-84: SizeFilter allows zero-byte files – reconsider validation

Keeping min(0) undermines the purpose of a size filter. Use min(1) or nonnegative() as previously suggested to enforce meaningful limits.

packages/core/src/main.ts (5)

96-101: Call checkInitialised() before doing any work

getStreams() can be called directly by consumers.
Without an initial safety-net the whole pipeline may crash if initialise() was forgotten. We already raised this in an earlier review – please add the guard as the first statement and return early if it throws.

public async getStreams(
   id: string,
   type: string,
   preCaching: boolean = false
 ): Promise<AIOStreamsResponse<ParsedStream[]>> {
+  this.checkInitialised();
   logger.info(`Handling stream request`, { type, id });

1104-1131: skipReasons is still missing the AudioChannel keys → runtime crash

Later in the filter pipeline (~1652, ~1674) you increment
skipReasons.excludedAudioChannel / requiredAudioChannel, but they are not initialised here.
Accessing .total or .details on undefined will throw and break filtering for every request.

   excludedAudioTag: { total: 0, details: {} },
   requiredAudioTag: { total: 0, details: {} },
+  excludedAudioChannel: { total: 0, details: {} },
+  requiredAudioChannel: { total: 0, details: {} },

1376-1384: Unsafe optional-chaining on .length – silent crashes remain

Patterns like
file?.visualTags.length / file?.audioTags.length dereference .length even when the array is undefined, producing TypeError: Cannot read properties of undefined (reading 'length').

Refactor to double–optional chain (or coalesce) everywhere:

- (file?.visualTags.length ? file.visualTags : ['Unknown']).includes(tag)
+ ((file?.visualTags?.length ?? 0) > 0
+   ? file!.visualTags!
+   : ['Unknown']
+ ).includes(tag)

A quick grep for \?\.\w+\.length still shows 10+ occurrences.
Please fix them or introduce a helper such as safeArray<T>(a?: T[]): T[].

Also applies to: 1570-1580


2040-2056: Wrong truthiness check treats -1 as “found” – sorting bug

aProviderIndex && bProviderIndex is truthy even if both are -1, so the “provider priority” branch executes when neither provider is configured, yielding unstable order.

- if (aProviderIndex && bProviderIndex && aProviderIndex !== bProviderIndex) {
+ if (
+   aProviderIndex !== -1 &&
+   bProviderIndex !== -1 &&
+   aProviderIndex !== bProviderIndex
+ ) {
     return aProviderIndex - bProviderIndex;
 }

2273-2280: Possible TypeError when sortCriteria is undefined

this.userData.sortCriteria is optional, yet you dereference .global, .cached, .uncached without checks. The same issue was noted previously.

- let sortCriteria = this.userData.sortCriteria.global;
+ const sc = this.userData.sortCriteria ?? {};
+ let sortCriteria = sc.global ?? [];

Apply the same defensive pattern for cachedSortCriteria / uncachedSortCriteria and the movie/series overrides below.

packages/core/src/utils/constants.ts (2)

87-96: Constructor parameter order issue still present – risk of accidental mis-ordering

Previous review already highlighted that statusCode comes before message. Nothing changed, so callers supplying only a custom message will still accidentally pass it as a status code:

new APIError(ErrorCode.USER_ERROR, 'Custom message'); // ❌

The safer order is code, message?, statusCode? or an options object.


475-487: ⚠️ Potential issue

password option type missing – compilation will break wherever credentials are validated

SERVICE_DETAILS repeatedly uses type: 'password', yet PASSWORD_OPTION_TYPE is not declared and the literal is absent from OPTION_TYPES.
OptionDefinition (see db/schemas.ts) most likely does z.enum(OPTION_TYPES), so every credential definition using 'password' will now violate the schema.

 const STRING_OPTION_TYPE = 'string';
 const NUMBER_OPTION_TYPE = 'number';
 const BOOLEAN_OPTION_TYPE = 'boolean';
 const SELECT_OPTION_TYPE = 'select';
 const MULTI_SELECT_OPTION_TYPE = 'multi-select';
+const PASSWORD_OPTION_TYPE = 'password';        // ← add
 
 const OPTION_TYPES = [
   STRING_OPTION_TYPE,
   NUMBER_OPTION_TYPE,
   BOOLEAN_OPTION_TYPE,
   SELECT_OPTION_TYPE,
   MULTI_SELECT_OPTION_TYPE,
+  PASSWORD_OPTION_TYPE,                         // ← add
 ] as const;

Don’t forget the export at the bottom.

🧹 Nitpick comments (1)
packages/core/src/utils/constants.ts (1)

98-105: Minor completeness nit – standard Forwarded header omitted

Consider appending plain Forwarded (RFC 7239) so consumers that forward this list do not miss it:

   'Forwarded-For',
+  'Forwarded',
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2470ae9 and 39b1e84.

📒 Files selected for processing (6)
  • .env.sample (1 hunks)
  • packages/core/src/db/schemas.ts (1 hunks)
  • packages/core/src/formatters/base.ts (1 hunks)
  • packages/core/src/formatters/predefined.ts (1 hunks)
  • packages/core/src/main.ts (1 hunks)
  • packages/core/src/utils/constants.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/formatters/predefined.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/core/src/utils/constants.ts (1)
packages/core/src/db/schemas.ts (1)
  • Option (199-199)
🪛 Biome (1.9.4)
packages/core/src/main.ts

[error] 214-214: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 281-281: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 640-641: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1061-1062: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)


[error] 2413-2415: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 2508-2511: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

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: 3

♻️ Duplicate comments (12)
packages/core/src/db/schemas.ts (5)

4-18: z.enum(constants.X) is still fed a mutable array – compile will explode

All z.enum(constants.*) calls rely on constants.X being a readonly tuple. Unless every exported constant is declared as const, the build will fail with TS 2345. This was raised in the previous review and the code is unchanged.


42-50: Plain-text proxy credentials – same security concern

StreamProxyConfig.credentials is still stored/read as a raw string. A database leak exposes secrets instantly. Please hash, encrypt, or otherwise protect this field and mark it sensitive in serialisation.


70-84: Size filter allows zero-byte files – validation still too lax

z.number().min(0) permits a lower bound of zero, which makes little sense for torrent/file sizes. Prior review suggested min(1) or .nonnegative(). Consider tightening the constraint.


91-95: Service credentials stored as plain strings

ServiceSchema.credentials keeps clear-text values, repeating the earlier security red-flag. Encrypt or hash before persisting and treat as sensitive during logging.


357-367: TABLES is still a stub – users table only

Only the USERS table schema is defined, which suggests the abstraction isn’t finished (sessions, cache, etc., are missing). Either flesh out the constant or move individual DDL to focused files.

packages/core/src/main.ts (3)

1104-1131: ⚠️ Potential issue

Add missing audioChannel counters to prevent undefined access

skipReasons is later updated for excludedAudioChannel / requiredAudioChannel (e.g. lines 1715 & 1737).
Because the keys are not initialised here, those increments dereference undefined, crashing the filter pipeline.

       excludedAudioTag: { total: 0, details: {} },
       requiredAudioTag: { total: 0, details: {} },
+      excludedAudioChannel: { total: 0, details: {} },
+      requiredAudioChannel: { total: 0, details: {} },

2321-2330: ⚠️ Potential issue

sortCriteria access may be undefined – guard before dereference

userData.sortCriteria is optional, yet the code immediately dereferences .global, .cached, and .uncached, leading to a crash for users who omit sort settings.

-    let sortCriteria = this.userData.sortCriteria.global;
-    let cachedSortCriteria = this.userData.sortCriteria.cached;
-    let uncachedSortCriteria = this.userData.sortCriteria.uncached;
+    const sc = this.userData.sortCriteria ?? {};
+    let sortCriteria        = sc.global   ?? [];
+    let cachedSortCriteria  = sc.cached   ?? [];
+    let uncachedSortCriteria= sc.uncached ?? [];

Apply the same defensive access further down when overriding for movie / series.


96-104: 🛠️ Refactor suggestion

Call checkInitialised() at the start of getStreams

getStreams is publicly exposed and assumes initialise() has already been invoked.
Without a guard, accidental misuse leads to subtle runtime errors later in the pipeline.

   public async getStreams(
     id: string,
     type: string,
     preCaching: boolean = false
   ): Promise<AIOStreamsResponse<ParsedStream[]>> {
+    this.checkInitialised();
     logger.info(`Handling stream request`, { type, id });
packages/core/src/utils/constants.ts (4)

87-93: 🛠️ Refactor suggestion

APIError constructor’s parameter order is still counter-intuitive

statusCode precedes message, so passing only a custom message still forces callers to supply a (redundant) status code, inviting mistakes.

new APIError(ErrorCode.USER_ERROR, 'Something went wrong'); // 2nd arg = statusCode

Refactor the signature (or accept an options object) so message comes before statusCode, or remove the latter altogether since it can be derived from code.


489-493: ⚠️ Potential issue

DEDUPLICATOR_KEYS is still not exported

You declared the constant but forgot to append it to the export block, so downstream modules cannot reuse it.

Add it to the export list (see comment on lines 873-911).


475-487: ⚠️ Potential issue

Missing password option type ⇒ compilation will break

Credentials below use type: 'password', yet PASSWORD_OPTION_TYPE is not declared and 'password' is missing from OPTION_TYPES.
Add the constant, include it in OPTION_TYPES, and export it.

 const STRING_OPTION_TYPE = 'string';
 const NUMBER_OPTION_TYPE = 'number';
 const BOOLEAN_OPTION_TYPE = 'boolean';
 const SELECT_OPTION_TYPE = 'select';
 const MULTI_SELECT_OPTION_TYPE = 'multi-select';
+const PASSWORD_OPTION_TYPE = 'password';

 const OPTION_TYPES = [
   STRING_OPTION_TYPE,
   NUMBER_OPTION_TYPE,
   BOOLEAN_OPTION_TYPE,
   SELECT_OPTION_TYPE,
   MULTI_SELECT_OPTION_TYPE,
+  PASSWORD_OPTION_TYPE,
 ] as const;

873-911: ⚠️ Potential issue

Export list is incomplete – leaks types & breaks re-use

Please extend the export block to include the newly required symbols:

   MULTI_SELECT_OPTION_TYPE,
+  PASSWORD_OPTION_TYPE,
   HEADERS_FOR_IP_FORWARDING,
+  PROXY_SERVICE_DETAILS,
+  DEDUPLICATOR_KEYS,
 };

This resolves the missing-export issues noted above.

🧹 Nitpick comments (2)
packages/core/src/db/schemas.ts (2)

22-28: Schema value and type share the same identifier – rename for clarity

A value (const SortCriterion) and a type (type SortCriterion) coexist under the same name. Although legal in TS, it is easy to confuse the runtime schema with the compile-time type. Renaming the value to SortCriterionSchema keeps the mental model clear.

-const SortCriterion = z.object({
+const SortCriterionSchema = z.object({
   key: z.enum(constants.SORT_CRITERIA),
   direction: z.enum(constants.SORT_DIRECTIONS),
 });
 
-export type SortCriterion = z.infer<typeof SortCriterion>;
+export type SortCriterion = z.infer<typeof SortCriterionSchema>;

Follow-up: update the usages (e.g. sortCriteria.global) accordingly.


1-777: File has grown into a 770-line monolith – consider splitting

This single module mixes:

• primitive enums
• option/stream schemas
• user config, manifest, DB DDL, API responses

Navigation and git-blame become painful. A lightweight refactor into thematic files (e.g., user.ts, stream.ts, manifest.ts, responses.ts) will improve maintainability without functional change.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39b1e84 and 915187a.

📒 Files selected for processing (3)
  • packages/core/src/db/schemas.ts (1 hunks)
  • packages/core/src/main.ts (1 hunks)
  • packages/core/src/utils/constants.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/core/src/utils/constants.ts (1)
packages/core/src/db/schemas.ts (1)
  • Option (199-199)
🪛 Biome (1.9.4)
packages/core/src/main.ts

[error] 214-214: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 281-281: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 640-641: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1061-1062: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)


[error] 2461-2463: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 2556-2559: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

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: 3

♻️ Duplicate comments (11)
packages/core/src/utils/http.ts (2)

16-29: makeUrlLogSafe masking logic still suffers from original flaws
The condition !component.includes('.') still prevents masking of long path segments that legitimately contain a dot (e.g. versioned API paths).
The negative-look-behind regex for password= is also fragile and won’t work in older Node versions.


76-112: Proxy decision algorithm problems remain unfixed
The earlier review pointed out: rule-order overriding, wildcard mishandling, missing break. None of these have been addressed – the logic can still flip-flop on later rules and give surprising results.

packages/core/src/transformers/stremio.ts (1)

304-307: createDynamicError still returns any, losing type safety
Previous feedback recommended overloads or a discriminated union. Leaving it as any undermines the benefits of the exhaustive switch you’ve written.

packages/core/src/db/schemas.ts (4)

4-17: z.enum(constants.X) will not compile unless the constant is a readonly tuple
If constants.SERVICES (and others) is a plain string[], TypeScript will error. Cast to as const or spread into a tuple.


70-84: Size filters still allow zero-byte files
z.number().min(0) contradicts the earlier suggestion – use min(1) or nonnegative() based on the real requirement.


42-50: Credentials stored as plain text
credentials fields remain un-hashed strings. A DB leak exposes user secrets. Encrypt or hash before persistence and mark as sensitive to avoid accidental logging.

Also applies to: 91-95


358-368: TABLES constant still lists only USERS
The helper loses usefulness if other tables (sessions, cache, etc.) aren’t declared. Either flesh it out or move schema strings to a dedicated file.

packages/core/src/main.ts (4)

101-108: ⚠️ Potential issue

Call checkInitialised() at the start of getStreams

getStreams is public and can be invoked before initialise() has run, leading to subtle runtime failures later in the pipeline.
Add the guard immediately after logging:

   logger.info(`Handling stream request`, { type, id });
+  this.checkInitialised();

2545-2550: ⚠️ Potential issue

Variable declared in switch case leaks scope

const index = … is declared directly inside the case 'service' clause without braces, violating noSwitchDeclarations and risking name collisions with subsequent cases.

-        case 'service':
-          const index = userData.services?.findIndex(
+        case 'service': {
+          const index = userData.services?.findIndex(
             (service) => service.id === stream.service?.id
           );
           return multiplier * -(index === -1 ? 0 : (index ?? 0));
+        }

2336-2340: 🛠️ Refactor suggestion

Direct dereference of optional sortCriteria will crash when absent

this.userData.sortCriteria is optional, yet the code immediately reads .global, .cached, .uncached. If a user omits the field the call path throws.

Guard with defaults:

-    let sortCriteria = this.userData.sortCriteria.global;
-    let cachedSortCriteria = this.userData.sortCriteria.cached;
-    let uncachedSortCriteria = this.userData.sortCriteria.uncached;
+    const sc = this.userData.sortCriteria ?? {};
+    let sortCriteria = sc.global ?? [];
+    let cachedSortCriteria = sc.cached ?? [];
+    let uncachedSortCriteria = sc.uncached ?? [];

1116-1144: ⚠️ Potential issue

skipReasons still misses AudioChannel keys → runtime crash

Later code increments skipReasons.excludedAudioChannel / requiredAudioChannel (e.g. lines 1730-1755) but those keys are not initialised here. Accessing skipReasons.excludedAudioChannel.total when the property is undefined will throw.

       excludedAudioTag: { total: 0, details: {} },
       requiredAudioTag: { total: 0, details: {} },
+      excludedAudioChannel: { total: 0, details: {} },
+      requiredAudioChannel: { total: 0, details: {} },
🧹 Nitpick comments (3)
packages/core/src/transformers/stremio.ts (2)

83-95: bingeGroup can be empty or meaningless
If every identifying attribute is undefined, bingeGroup becomes either an empty string or just proxied. – neither is useful for grouping.

Consider falling back to a hash of the stream URL / infoHash or omit the field when no identifiers are present.


258-268: Subtitle error id is unsafe
error.${errorTitle} can contain spaces or unicode, violating Stremio’s id expectations.
Sanitise with a slug generator or at least encodeURIComponent.

packages/core/src/main.ts (1)

1070-1076: Redundant else after throw

After the throw in validateAddon the subsequent else if chain is unnecessary; execution never reaches it when the throw happens. Dropping else blocks shortens indentation.

[Nit] consider:

-    } else if (
+    }
+    if (
       Env.BASE_URL &&
🧰 Tools
🪛 Biome (1.9.4)

[error] 1075-1075: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2f4dc1 and 091394b.

📒 Files selected for processing (6)
  • packages/core/src/db/schemas.ts (1 hunks)
  • packages/core/src/main.ts (1 hunks)
  • packages/core/src/transformers/stremio.ts (1 hunks)
  • packages/core/src/utils/cache.ts (3 hunks)
  • packages/core/src/utils/env.ts (1 hunks)
  • packages/core/src/utils/http.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/core/src/utils/cache.ts
  • packages/core/src/utils/env.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/core/src/utils/http.ts (5)
packages/core/src/utils/logger.ts (1)
  • maskSensitiveInfo (123-128)
packages/core/src/utils/cache.ts (1)
  • Cache (14-126)
packages/core/src/wrapper.ts (1)
  • makeRequest (240-247)
packages/core/src/utils/constants.ts (1)
  • HEADERS_FOR_IP_FORWARDING (910-910)
packages/core/src/utils/env.ts (1)
  • Env (150-1060)
packages/core/src/transformers/stremio.ts (5)
packages/core/src/utils/logger.ts (1)
  • createLogger (62-110)
packages/core/src/db/schemas.ts (13)
  • UserData (356-356)
  • Resource (103-103)
  • ParsedStream (650-650)
  • AIOStream (652-696)
  • AIOStream (698-698)
  • Subtitle (448-448)
  • SubtitleResponse (447-447)
  • MetaPreview (562-562)
  • CatalogResponse (560-560)
  • Meta (561-561)
  • MetaResponse (559-559)
  • AddonCatalog (573-573)
  • AddonCatalogResponse (572-572)
packages/core/src/main.ts (2)
  • AIOStreamsError (49-52)
  • AIOStreamsResponse (54-58)
packages/core/src/formatters/index.ts (1)
  • createFormatter (17-41)
packages/core/src/utils/env.ts (1)
  • Env (150-1060)
🪛 Biome (1.9.4)
packages/core/src/main.ts

[error] 217-217: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 299-299: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 663-664: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1075-1075: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)


[error] 2476-2478: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 2571-2574: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

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: 6

♻️ Duplicate comments (6)
packages/core/src/utils/config.ts (2)

33-118: Refactor duplicate credential mapping logic.

The getServiceCredentialDefault and getServiceCredentialForced functions contain nearly identical switch statement structures, differing only in the environment variables they access. This violates the DRY principle.

Also applies to: 120-205


308-312: Consider separating validation from initialization.

The validateConfig function performs validation but also has the side effect of initializing AIOStreams. This violates the single responsibility principle. Consider returning the validated config and performing initialization separately.

packages/core/src/db/schemas.ts (4)

4-18: z.enum(constants.X) likely fails at compile-time if the array isn't a readonly tuple.

z.enum expects a tuple (readonly [...]), not a plain string[]. Unless every exported constant (SERVICES, RESOLUTIONS, …) is declared as as const, the current code will raise a TypeScript error.

Also applies to: 23-24, 29-30


42-47: Plain-text credential fields – consider hashing / encryption.

StreamProxyConfig.credentials and ServiceSchema.credentials accept raw strings. Storing service or proxy secrets unhashed inside the user's config/database is risky.

Also applies to: 91-95


70-84: Use non-negative validation for size filters.

The size filter tuples use min(0) which allows zero but makes little sense for file sizes. Consider using min(1) or nonnegative() for better validation.


358-368: Expand TABLES constant or consider alternative approach.

The TABLES constant only defines one table, which suggests this pattern may not be fully implemented.

🧹 Nitpick comments (3)
packages/core/src/proxy/base.ts (3)

55-69: Missing normalisation of publicIp when set in config

When this.config.publicIp is already present you return it immediately, but you never write back the fetched IP later.
Down-stream code that relies on config.publicIp will trigger a fresh network call every time the process restarts, defeating the cache after a cold start.

After successfully retrieving the IP you should persist it:

if (publicIp && cache) {
   cache.set(cacheKey, publicIp, 900);
+  this.config.publicIp = publicIp;

[performance]


70-75: Potential race condition on concurrent look-ups

Multiple concurrent getPublicIp() calls using the same cacheKey can all miss the cache before the first one stores the value, causing several redundant network requests.

Mitigate by memoising the in-flight Promise, or use the cache to store a sentinel while the request is pending.

[performance]


112-131: Return type ambiguity on failure

generateUrls resolves to null on any error but [] when input is empty. Callers now have to handle two “no data” cases (null vs []). If null means “error”, document it explicitly; otherwise return [] consistently.

[api-consistency]

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 091394b and c60ef6f.

📒 Files selected for processing (3)
  • packages/core/src/db/schemas.ts (1 hunks)
  • packages/core/src/proxy/base.ts (1 hunks)
  • packages/core/src/utils/config.ts (1 hunks)
🔇 Additional comments (1)
packages/core/src/proxy/base.ts (1)

87-91: AbortSignal.timeout limits runtime compatibility

AbortSignal.timeout() is only available in Node ≥ 18.17 and not in browsers. If the core library is meant to be isomorphic, this call will break in older runtimes.

Guard it or fall back to a manual AbortController + setTimeout.

[compatibility]

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: 0

♻️ Duplicate comments (2)
.env.sample (2)

292-293: Inline comments break .env parsing – move them above assignments.
Values such as

STATIC_RATE_LIMIT_WINDOW=5       # Time window in seconds.
STATIC_RATE_LIMIT_MAX_REQUESTS=100 # Max requests per IP in window.

include the trailing comment in the variable value. Relocate these inline comments to separate lines immediately preceding each assignment.


354-354: Inline comments break .env parsing – relocate above assignment.
The inline comment on

MEDIAFUSION_CONFIG_TIMEOUT=5000 # Timeout (ms) for /encrypt-user-data endpoint.

will be ingested as part of the value. Please extract it to the line above.

🧹 Nitpick comments (4)
.env.sample (4)

362-362: Quoted JSON in environment variable may not parse correctly.
DEFAULT_JACKETTIO_INDEXERS='["bitsearch", "eztv", "thepiratebay", "therarbg", "yts"]' embeds a JSON array in single quotes. Some parsers include quotes or misinterpret commas/escapes. Consider switching to a simple comma-separated list (e.g., bitsearch,eztv,...) or documenting the exact parser behaviour.


20-20: Clarify that BASE_URL is required.
This variable is critical for generating installation URLs and self-scraping prevention. Adding a # REQUIRED tag or an example placeholder (e.g., BASE_URL=https://yourdomain.com) will help users avoid leaving it blank.


10-10: Document expected format for ADDON_ID.
To ensure a valid reverse-domain identifier, include an example (e.g., ADDON_ID=com.yourdomain.myaddon) or reference the naming convention.


47-47: Warn about directory existence for default SQLite URI.
The default DATABASE_URI=sqlite://./data/db.sqlite assumes the data folder exists and is writable. Consider adding a note to create that directory or adjust the path accordingly.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c60ef6f and 868e867.

📒 Files selected for processing (2)
  • .env.sample (1 hunks)
  • packages/core/src/utils/env.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/utils/env.ts

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: 0

♻️ Duplicate comments (8)
packages/core/src/presets/dmmCast.ts (2)

120-124: 🛠️ Refactor suggestion

Harden URL validation

The endsWith('/manifest.json') check still allows malformed strings like foo/manifest.jsonfoo. Parse with new URL() first, then assert the pathname suffix as previously suggested.

🧰 Tools
🪛 Biome (1.9.4)

[error] 123-123: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


131-142: 🛠️ Refactor suggestion

Replace this with class name inside static methods

Using this inside static methods is flagged by Biome and hurts readability; switch to DMMCastPreset.METADATA / DMMCastPreset.generateAddon as proposed earlier.

🧰 Tools
🪛 Biome (1.9.4)

[error] 131-131: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 132-132: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-136: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 137-137: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 138-138: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 140-140: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/core/src/main.ts (6)

101-108: ⚠️ Potential issue

Call checkInitialised() at the start of getStreams

getStreams still runs without verifying that initialise() has completed, risking crashes on un-set state. Insert this.checkInitialised(); as the very first line of the method.


1116-1145: ⚠️ Potential issue

skipReasons missing audio-channel entries → runtime crash

Later code writes to skipReasons.excludedAudioChannel / requiredAudioChannel, but these keys aren’t initialised here, causing TypeError. Add both objects alongside the others.


1437-1470: ⚠️ Potential issue

Unsafe optional-chaining on .length still unguarded

Expressions like file?.visualTags.length dereference length when the array may be undefined, throwing at runtime. Use file?.visualTags?.length ?? 0 (or a helper) throughout this block and similar ones for audioTags, audioChannels, languages.


2337-2340: ⚠️ Potential issue

sortCriteria dereference can throw

this.userData.sortCriteria is optional yet .global, .cached, .uncached are accessed without guards. Apply optional-chaining/null-coalescing to prevent TypeError.


2113-2119: ⚠️ Potential issue

-1 treated as truthy in provider comparison

if (aProviderIndex && bProviderIndex && …) considers -1 as true, producing wrong ordering when neither provider is configured. Explicitly compare against -1.


2542-2547: 🛠️ Refactor suggestion

Variable leakage in switch case service

const index = … is declared directly in the case without braces, allowing it to leak into other cases and keeping Biome unhappy. Wrap the entire clause in {}.

🧹 Nitpick comments (2)
packages/core/src/parser/regex.ts (2)

105-108: AAC pattern matches too broadly

q?aac(?:[ .\\-_]?2)? will match the string “qaac” (an encoder, not the codec) and any word ending in “aac”. Consider anchoring with word-boundaries and dropping the optional leading q? unless that was intentional.


56-61: Low-resolution regexes can fire inside larger numbers

Patterns for 360p, 240p, 144p don’t enforce leading boundaries, so “1360p” will incorrectly satisfy 360p. Prefix with a word/start boundary (e.g. \\b(360[pi])\\b) to avoid false positives.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 868e867 and b16f36d.

📒 Files selected for processing (3)
  • packages/core/src/main.ts (1 hunks)
  • packages/core/src/parser/regex.ts (4 hunks)
  • packages/core/src/presets/dmmCast.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/core/src/parser/regex.ts (1)
packages/core/src/utils/constants.ts (7)
  • RESOLUTIONS (876-876)
  • QUALITIES (877-877)
  • VISUAL_TAGS (878-878)
  • AUDIO_TAGS (879-879)
  • AUDIO_CHANNELS (880-880)
  • LANGUAGES (885-885)
  • ENCODES (881-881)
🪛 Biome (1.9.4)
packages/core/src/main.ts

[error] 217-217: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 299-299: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 663-664: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1075-1075: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)


[error] 2473-2475: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 2568-2571: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

packages/core/src/presets/dmmCast.ts

[error] 123-123: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 131-131: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 132-132: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 136-136: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 137-137: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 138-138: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 140-140: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

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: 3

♻️ Duplicate comments (1)
packages/core/src/utils/constants.ts (1)

87-93: Constructor parameter order is still error-prone

Status code precedes message, so supplying only a message silently overrides statusCode. Consider swapping the parameters or accepting an options object, as suggested in the earlier review.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b16f36d and 3173caf.

📒 Files selected for processing (1)
  • packages/core/src/utils/constants.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/core/src/utils/constants.ts (1)
packages/core/src/db/schemas.ts (1)
  • Option (199-199)

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: 4

♻️ Duplicate comments (7)
packages/core/src/db/users.ts (2)

152-188: Large commented-out validation block still present

The 30-line block of commented code was flagged in earlier reviews; it remains unchanged. Please either delete it or reinstate proper validation through validateConfig / UserDataSchema.safeParse to keep the file concise.

🧰 Tools
🪛 Biome (1.9.4)

[error] 152-152: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


261-265: Use COUNT(*) instead of fetching every row

Fetching all users just to count them is O(n) and wastes memory. A single aggregate query is both faster and lighter:

-      const result = await db.query('SELECT * FROM users');
-      return result.length;
+      const result = await db.query('SELECT COUNT(*) as cnt FROM users');
+      return Number(result[0].cnt);
packages/core/src/main.ts (4)

101-108: ⚠️ Potential issue

Add initialisation guard in getStreams()

getStreams() can be invoked before initialise() has run, leaving internal structures empty and crashing downstream logic.
Insert an early this.checkInitialised().

   public async getStreams(
     id: string,
     type: string,
     preCaching: boolean = false
   ): Promise<AIOStreamsResponse<ParsedStream[]>> {
+    this.checkInitialised();
     logger.info(`Handling stream request`, { type, id });

2337-2340: ⚠️ Potential issue

sortCriteria may be undefined – add defensive defaults

this.userData.sortCriteria is optional, yet the code dereferences it unguarded. A missing user setting will explode here.

-    let sortCriteria = this.userData.sortCriteria.global;
-    let cachedSortCriteria = this.userData.sortCriteria.cached;
-    let uncachedSortCriteria = this.userData.sortCriteria.uncached;
+    const sc = this.userData.sortCriteria ?? {};
+    let sortCriteria = sc.global ?? [];
+    let cachedSortCriteria = sc.cached ?? [];
+    let uncachedSortCriteria = sc.uncached ?? [];

2113-2119: ⚠️ Potential issue

Truthiness check with -1 breaks ordering

aProviderIndex && bProviderIndex treats -1 as truthy, so two “not-found” providers pass the branch and incorrectly influence sorting.

-              if (
-                aProviderIndex &&
-                bProviderIndex &&
-                aProviderIndex !== bProviderIndex
-              ) {
+              if (
+                aProviderIndex !== -1 &&
+                bProviderIndex !== -1 &&
+                aProviderIndex !== bProviderIndex
+              ) {
                 return aProviderIndex - bProviderIndex;
               }

1437-1450: ⚠️ Potential issue

Unsafe ?.length dereference – possible TypeError

file?.visualTags.length (and similar audio/language variants) still accesses .length when the array is undefined, breaking the filter pipeline.

-          (file?.visualTags.length ? file.visualTags : ['Unknown']).includes(
+          ((file?.visualTags?.length ?? 0) > 0
+            ? file!.visualTags!
+            : ['Unknown']
+          ).includes(
             tag
           )

Apply the same double-optional-chain (or a helper like safeArray) to every .length access for visualTags, audioTags, audioChannels, and languages.

.env.sample (1)

356-356: Inline comments break .env parsing
The assignment on line 356 includes an inline comment which will be parsed as part of the value. Move the comment above the variable to keep the value clean.

- MEDIAFUSION_CONFIG_TIMEOUT=5000 # Timeout (ms) for /encrypt-user-data endpoint.
+ # Timeout (ms) for /encrypt-user-data endpoint.
+ MEDIAFUSION_CONFIG_TIMEOUT=5000
🧹 Nitpick comments (4)
packages/core/src/db/users.ts (2)

1-18: Remove unused import maskSensitiveInfo
maskSensitiveInfo is imported but never referenced, which will trigger unused-variable lint errors and slightly increases bundle size.

-import {
+import {
   decryptString,
   deriveKey,
   encryptString,
   generateUUID,
   getTextHash,
-  maskSensitiveInfo,
   createLogger,

369-381: Potential infinite recursion in generateUUID

The method retries up to 10 times, but if the UUID generator is ever faulty or the table extremely full, it returns a generic USER_ERROR. Consider:

  1. Raising a dedicated UUID_CONFLICT error for clearer diagnostics.
  2. Switching to a database-side uniqueness check (INSERT ... ON CONFLICT DO NOTHING and loop) to avoid extra round-trips.
🧰 Tools
🪛 Biome (1.9.4)

[error] 375-375: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 378-378: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

.env.sample (2)

8-10: Avoid quoting simple string values
While many dotenv parsers strip quotes, including them can sometimes lead to unexpected literal quotes in the value. Remove quotes for ADDON_NAME and ADDON_ID.

- ADDON_NAME="AIOStreams"
- ADDON_ID="aiostreams.viren070.com"
+ ADDON_NAME=AIOStreams
+ ADDON_ID=aiostreams.viren070.com

222-230: Standardise commented defaults vs assignments
Several proxy-related defaults (e.g. DEFAULT_PROXY_ENABLED) remain commented out, while other defaults are assigned. For consistency, list all default settings as active (even if they match the comments), so users can override them directly.

- # DEFAULT_PROXY_ENABLED=true  # Default state for enabling a stream proxy.
+ DEFAULT_PROXY_ENABLED=true  # Default state for enabling a stream proxy.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3173caf and 2f37187.

📒 Files selected for processing (3)
  • .env.sample (1 hunks)
  • packages/core/src/db/users.ts (1 hunks)
  • packages/core/src/main.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
packages/core/src/db/users.ts

[error] 25-383: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 64-64: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 67-67: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 142-142: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 152-152: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 229-229: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 233-233: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 375-375: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 378-378: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/core/src/main.ts

[error] 217-217: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 299-299: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 663-664: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1075-1075: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)


[error] 2473-2475: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

Comment on lines +119 to +151
// with stremio auth, we are given the encrypted password
// with api use, we are given the password
// GET /user should also return

static async getUser(
uuid: string,
password: string
): Promise<UserData | null> {
try {
const result = await db.query(
'SELECT config, config_salt, password_hash FROM users WHERE uuid = ?',
[uuid]
);

if (!result.length || !result[0].config) {
return Promise.reject(new APIError(constants.ErrorCode.USER_NOT_FOUND));
}

await db.execute(
'UPDATE users SET accessed_at = CURRENT_TIMESTAMP WHERE uuid = ?',
[uuid]
);

const isValid = await this.verifyUserPassword(
password,
result[0].password_hash
);
if (!isValid) {
return Promise.reject(
new APIError(constants.ErrorCode.USER_INVALID_PASSWORD)
);
}

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.

⚠️ Potential issue

Ambiguous password parameter may break authentication

getUser() accepts either the raw password or the previously-returned encrypted password (see comment lines 119-122).
verifyUserPassword() hashes the supplied value and compares it with the stored hash, which only works for a raw password.
Passing the already-encrypted string will always fail verification, resulting in USER_INVALID_PASSWORD.

Consider one of the following:

-  static async getUser(uuid: string, password: string)
+  // passRawPassword clarifies the caller’s intent
+  static async getUser(
+    uuid: string,
+    password: string,
+    passRawPassword = true
+  )

or expose dedicated methods (getUserWithPassword, getUserWithEncryptedPassword) to avoid overloading a single parameter.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (1.9.4)

[error] 142-142: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

🤖 Prompt for AI Agents
In packages/core/src/db/users.ts between lines 119 and 151, the getUser method's
password parameter is ambiguous because it can be either a raw or encrypted
password, but verifyUserPassword expects a raw password. To fix this, separate
the logic by creating two distinct methods, such as getUserWithPassword for raw
passwords and getUserWithEncryptedPassword for encrypted ones, ensuring each
method handles verification appropriately without overloading a single
parameter.

Comment on lines +2452 to +2458
case 'addon':
// find the first occurence of the stream.addon.id in the addons array
const idx = userData.presets.findIndex(
(p) => JSON.stringify(p) === stream.addon.id
);
return multiplier * (idx !== -1 ? -idx : 0);

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.

🛠️ Refactor suggestion

Wrap case 'addon' in braces to avoid scope leakage

Declaring const idx directly inside the switch case leaks the identifier to subsequent cases and keeps Biome unhappy.

-        case 'addon':
-          // find the first occurence of the stream.addon.id in the addons array
-          const idx = userData.presets.findIndex(
-            (p) => JSON.stringify(p) === stream.addon.id
-          );
-          return multiplier * (idx !== -1 ? -idx : 0);
+        case 'addon': {
+          const idx = userData.presets.findIndex(
+            (p) => JSON.stringify(p) === stream.addon.id
+          );
+          return multiplier * (idx !== -1 ? -idx : 0);
+        }
📝 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
case 'addon':
// find the first occurence of the stream.addon.id in the addons array
const idx = userData.presets.findIndex(
(p) => JSON.stringify(p) === stream.addon.id
);
return multiplier * (idx !== -1 ? -idx : 0);
case 'addon': {
// find the first occurence of the stream.addon.id in the addons array
const idx = userData.presets.findIndex(
(p) => JSON.stringify(p) === stream.addon.id
);
return multiplier * (idx !== -1 ? -idx : 0);
}
🤖 Prompt for AI Agents
In packages/core/src/main.ts around lines 2452 to 2458, the declaration of const
idx inside the 'addon' case of the switch statement causes scope leakage to
other cases. To fix this, wrap the entire 'addon' case block in braces { } to
create a new block scope, ensuring idx is scoped only within this case and
preventing any leakage.

Comment on lines +181 to +184
# Set the verbosity of logs. Options: "error", "warn", "info", "http", "verbose","debug", "silly"
# Default: info
LOG_LEVEL=http

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.

⚠️ Potential issue

Update default log level documentation
The comment indicates the default is info, but LOG_LEVEL is set to http. Align the documentation with the actual setting.

- # Default: info
+ # Default: http
📝 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
# Set the verbosity of logs. Options: "error", "warn", "info", "http", "verbose","debug", "silly"
# Default: info
LOG_LEVEL=http
# Set the verbosity of logs. Options: "error", "warn", "info", "http", "verbose","debug", "silly"
# Default: http
LOG_LEVEL=http
🤖 Prompt for AI Agents
In the .env.sample file around lines 181 to 184, the comment states the default
log level is "info" but the LOG_LEVEL is set to "http". Update the comment to
reflect that the default log level is "http" to match the actual setting in the
file.

Comment on lines +126 to +131
# Comma-separated list of trusted UUIDs.
# Trusted users can access features like regex filters if REGEX_FILTER_ACCESS is 'trusted'.
# Example: TRUSTED_UUIDS=ae32f456-1234-5678-9012-345678901234,another-uuid-here
# TRUSTED_UUIDS=

# --- Regex Filter Access ---
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.

🛠️ Refactor suggestion

Uncomment TRUSTED_UUIDS assignment
TRUSTED_UUIDS is currently commented out, so users won’t see the variable to populate. Provide an explicit blank assignment for clarity.

- # TRUSTED_UUIDS=
+ TRUSTED_UUIDS=
📝 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
# Comma-separated list of trusted UUIDs.
# Trusted users can access features like regex filters if REGEX_FILTER_ACCESS is 'trusted'.
# Example: TRUSTED_UUIDS=ae32f456-1234-5678-9012-345678901234,another-uuid-here
# TRUSTED_UUIDS=
# --- Regex Filter Access ---
# Comma-separated list of trusted UUIDs.
# Trusted users can access features like regex filters if REGEX_FILTER_ACCESS is 'trusted'.
# Example: TRUSTED_UUIDS=ae32f456-1234-5678-9012-345678901234,another-uuid-here
TRUSTED_UUIDS=
# --- Regex Filter Access ---
🤖 Prompt for AI Agents
In .env.sample around lines 126 to 131, the TRUSTED_UUIDS variable is commented
out, which may confuse users about where to set trusted UUIDs. Uncomment the
TRUSTED_UUIDS line and assign it an empty value to explicitly show users where
to input their trusted UUIDs.

…ration, correctly handle undefined value in tryDecrypt, only decrypt when defined
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

♻️ Duplicate comments (10)
packages/core/src/db/users.ts (2)

262-266: Fetching every row to count users remains un-optimised (see prior review).
Please switch to SELECT COUNT(*) AS count … as already suggested – it avoids a full table read.


159-185: Large commented-out validation block still clutters the file
Either re-enable the logic or delete the block to keep the codebase clean.

packages/core/src/utils/config.ts (2)

33-118: Duplicate 170-line switch can be collapsed into one helper

getServiceCredentialDefault and getServiceCredentialForced are identical apart from the env-prefix – the DRY violation was flagged previously and is still present. Extract a single getServiceCredential(serviceId, credentialId, prefix) helper to remove the duplication.

Also applies to: 120-205


308-312: validateConfig still initialises AIOStreams – breaks SRP

Validation should not have the side-effect of spinning up the streaming engine. Move the AIOStreams initialisation to the caller after successful validation to keep responsibilities separated.

packages/core/src/main.ts (6)

2337-2340: Possible TypeError when sortCriteria is undefined

this.userData.sortCriteria is optional, yet the code directly
dereferences .global, .cached, .uncached.

- let sortCriteria = this.userData.sortCriteria.global;
- let cachedSortCriteria = this.userData.sortCriteria.cached;
- let uncachedSortCriteria = this.userData.sortCriteria.uncached;
+ const sc = this.userData.sortCriteria ?? {};
+ let sortCriteria = sc.global ?? [];
+ let cachedSortCriteria = sc.cached ?? [];
+ let uncachedSortCriteria = sc.uncached ?? [];

2104-2119: Truthiness check still mis-orders providers

aProviderIndex && bProviderIndex && … considers -1 “truthy”, so when both
indices are -1 the branch executes, giving unpredictable order.

- if (aProviderIndex && bProviderIndex && aProviderIndex !== bProviderIndex) {
+ if (
+   aProviderIndex !== -1 &&
+   bProviderIndex !== -1 &&
+   aProviderIndex !== bProviderIndex
+ ) {
     return aProviderIndex - bProviderIndex;
 }

1436-1450: ⚠️ Potential issue

Unsafe optional-chaining on .length – still throws

file?.visualTags.length dereferences length even when
visualTags is undefined, producing TypeError.
This was flagged earlier but is still present in several places (visualTags,
audioTags, audioChannels, languages).

- (file?.visualTags.length ? file.visualTags : ['Unknown']).includes(tag)
+ ((file?.visualTags?.length ?? 0) > 0
+   ? file!.visualTags!
+   : ['Unknown']
+ ).includes(tag)

Please apply the same pattern to every ?.<prop>.length occurrence.


101-109: ⚠️ Potential issue

Call checkInitialised() at the start of getStreams

getStreams() is publicly exposed but still assumes that initialise() has been invoked. A single forgotten call will cause a hard-to-diagnose runtime failure deep in the pipeline.
Add the guard that was requested in previous reviews:

   public async getStreams(
     id: string,
     type: string,
     preCaching: boolean = false
   ): Promise<AIOStreamsResponse<ParsedStream[]>> {
+    this.checkInitialised();
     logger.info(`Handling stream request`, { type, id });

2470-2490: 🛠️ Refactor suggestion

Wrap case 'visualTag' in braces to avoid scope leakage

let minIndex leaks into subsequent case clauses and keeps Biome unhappy
(noSwitchDeclarations).

-        case 'visualTag':
-          let minIndex = userData.preferredVisualTags?.length;
+        case 'visualTag': {
+          let minIndex = userData.preferredVisualTags?.length;-          return multiplier * -minIndex;
+          return multiplier * -minIndex;
+        }

Apply the same pattern to other case blocks with local declarations
(e.g. audioTag, language).

🧰 Tools
🪛 Biome (1.9.4)

[error] 2473-2475: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


1116-1145: ⚠️ Potential issue

skipReasons still misses excludedAudioChannel / requiredAudioChannel

The filter logic later updates skipReasons.excludedAudioChannel and
skipReasons.requiredAudioChannel (~1724-1755), but the keys are not
initialised here, so skipReasons.excludedAudioChannel.total crashes with
TypeError: Cannot read properties of undefined.

       excludedAudioTag: { total: 0, details: {} },
       requiredAudioTag: { total: 0, details: {} },
+      excludedAudioChannel: { total: 0, details: {} },
+      requiredAudioChannel: { total: 0, details: {} },
       excludedLanguage: { total: 0, details: {} },
🧹 Nitpick comments (2)
packages/core/src/db/users.ts (2)

25-31: Static-only class – consider converting to a plain module

UserRepository only exposes static members. Replacing it with named exports (or a namespace) trims boilerplate and avoids the recurring “this in static context” lints flagged by Biome.

🧰 Tools
🪛 Biome (1.9.4)

[error] 25-384: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


65-65: Use explicit class name instead of this in static context

To silence Biome’s noThisInStatic warning and improve clarity:

-const uuid = await this.generateUUID();
+const uuid = await UserRepository.generateUUID();

Do the same for other static self-calls.

Also applies to: 82-83, 376-379

🧰 Tools
🪛 Biome (1.9.4)

[error] 65-65: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f37187 and 56734f0.

📒 Files selected for processing (4)
  • packages/core/src/db/users.ts (1 hunks)
  • packages/core/src/main.ts (1 hunks)
  • packages/core/src/utils/config.ts (1 hunks)
  • packages/core/src/utils/crypto.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/utils/crypto.ts
🧰 Additional context used
🪛 Biome (1.9.4)
packages/core/src/db/users.ts

[error] 25-384: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)


[error] 65-65: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 68-68: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 143-143: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 153-153: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 230-230: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 234-234: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 376-376: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 379-379: Using this in a static context can be confusing.

this refers to the class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

packages/core/src/main.ts

[error] 217-217: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 299-299: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 663-664: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 853-854: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1075-1075: Unnecessary continue statement

Unsafe fix: Delete the unnecessary continue statement

(lint/correctness/noUnnecessaryContinue)


[error] 2473-2475: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

@Viren070 Viren070 merged commit 92105ea into main Jun 13, 2025
6 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Mar 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment