Skip to content

Conversation

elibosley
Copy link
Member

@elibosley elibosley commented May 24, 2025

Summary by CodeRabbit

New Features

  • Introduced a comprehensive backup management system supporting scheduled and manual backup jobs with multiple source and destination types.
  • Added a user interface for creating, editing, enabling/disabling, triggering, and deleting backup job configurations.
  • Provided real-time job status tracking, progress indicators, and detailed job metrics in the UI.
  • Enabled backup job configuration via dynamic, schema-driven forms with advanced options and validation.
  • Support for multiple backup source types (ZFS, Flash, Script, Raw) and RClone destinations, including streaming and regular modes.

Bug Fixes

  • Improved error handling and status reporting for backup and RClone operations.

Documentation

  • Extended GraphQL schema and API documentation to cover all new backup management features.

Style

  • UI enhancements for backup job lists, job entries, and configuration forms.

Chores

  • Updated dependencies, configuration files, and test scripts to support new backup features and maintain code quality.

Tests

  • Added and refined unit tests for backup and RClone services, validation, and formatting utilities.

Copy link
Contributor

coderabbitai bot commented May 24, 2025

Walkthrough

This change introduces a comprehensive backup management system across the API and web UI. It adds backup job scheduling, orchestration, source/destination processors, validation, and extensive GraphQL schema/model support. The web UI gains backup job forms, configuration management, and job status displays. Supporting modules, services, and test suites are included throughout the stack.

Changes

File(s) / Path(s) Change Summary
api/src/unraid-api/graph/resolvers/backup/**, api/dev/api/backup/backup-jobs.json Added backup job management: config service, orchestration, source/destination processors, validation, JSONForms, models, and a sample config file.
api/generated-schema.graphql, packages/unraid-shared/src/graphql.model.ts Extended GraphQL schema and enums for backup jobs, job configs, statuses, sources, destinations, and mutations.
api/src/unraid-api/graph/resolvers/mutation/mutation.* Added BackupMutations class and mutation resolver for backup-related operations.
api/src/unraid-api/graph/resolvers/rclone/** Refactored and extended rclone API/service for job grouping, stats, error handling, and integration with backup jobs. Added status service and tests.
api/src/unraid-api/graph/utils/utils.module.ts, api/src/unraid-api/utils/format.service.* Introduced global utilities module and formatting service with tests.
api/src/unraid-api/graph/resolvers/resolvers.module.ts Replaced FlashBackupModule with new BackupModule and updated imports.
api/.env.development, api/src/store/modules/paths.ts, api/src/unraid-api/main.ts Added backup jobs path env var, updated log level handling, and set backupBase path.
api/package.json, api/.eslintrc.ts, api/dev/configs/api.json, api/dev/states/myservers.cfg Updated dependencies, ESLint ignores, config versions, and example states.
api/src/__test__/graphql/resolvers/rclone-api.service.test.ts Enhanced test suite with detailed mocks for rclone API and job management.
web/components/Backup/**, web/pages/flash-backup.vue, web/helpers/apollo-cache/index.ts Added backup job config, overview, entry, and item components with Apollo cache policies.
web/composables/gql/gql.ts, web/composables/gql/graphql.ts, web/components/Backup/backup-jobs.query.ts Added fragments, queries, and mutations for backup jobs and configs.
unraid-ui/src/forms/**, unraid-ui/src/components.ts, unraid-ui/package.json, unraid-ui/eslint.config.ts Added JSONForms wrapper, renderers, and UI tweaks for backup job forms. Updated dependencies and config.
plugin/builder/build-txz.ts Imported rclone helper utility.
*.last-download-time Updated test fixture timestamps.
package.json, vitest.config.ts, vitest.workspace.js Switched to Vitest for testing, updated scripts, and removed old workspace config.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WebUI
    participant GraphQL API
    participant BackupConfigService
    participant BackupOrchestrationService
    participant RCloneApiService

    User->>WebUI: Open Backup Overview / Job Config
    WebUI->>GraphQL API: Query backup jobs/configs
    GraphQL API->>BackupConfigService: getAllBackupJobConfigs()
    BackupConfigService-->>GraphQL API: List of configs
    GraphQL API-->>WebUI: Configs data

    User->>WebUI: Create/Update/Trigger Backup Job
    WebUI->>GraphQL API: Mutation (create/update/trigger)
    GraphQL API->>BackupConfigService: create/update/triggerBackupJobConfig()
    BackupConfigService->>BackupOrchestrationService: executeBackupJob()
    BackupOrchestrationService->>RCloneApiService: startBackup()
    RCloneApiService-->>BackupOrchestrationService: Job ID / status
    BackupOrchestrationService-->>BackupConfigService: Job completion callback
    BackupConfigService-->>GraphQL API: Result/status
    GraphQL API-->>WebUI: Mutation result
Loading

Possibly related PRs

  • feat: add rclone #1362: Closely related; both PRs build backup management, with this PR integrating rclone as a destination and extending the backup job framework.
  • feat: code first graphql #1347: Related at the infrastructure level; both PRs involve migration to code-first GraphQL and schema changes for extensibility.

Suggested reviewers

  • zackspear
  • mdatelle
  • pujitm

Poem

Backups now dance in orchestrated flow,
With configs and jobs in a vibrant tableau.
Snapshots and scripts, ZFS and flash,
Rclone delivers with a digital dash!
UI forms gleam, statuses beam—
Data's safe, like a dream!
🗄️✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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

Base automatically changed from feat/flash-backup-replacement to main May 27, 2025 11:52
Copy link
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: 44

🔭 Outside diff range comments (1)
api/src/unraid-api/graph/utils/utils.module.ts (1)

1-11: Remove duplicate UtilsModule.

There's already a UtilsModule in api/src/unraid-api/utils/utils.module.ts that provides and exports the same FormatService. This creates unnecessary duplication and potential confusion.

Consider removing this duplicate module and using the existing one instead. If this location is specifically needed for the graph resolvers, consider renaming it to GraphUtilsModule or similar to avoid confusion.

♻️ Duplicate comments (1)
api/dev/states/myservers.cfg (1)

2-2: Version update consistent with other myservers.cfg but inconsistent with api.json.

The version 4.8.0 matches api/dev/Unraid.net/myservers.cfg but differs from api/dev/configs/api.json (4.9.5). This reinforces the need to standardize versions across all configuration files.

🧹 Nitpick comments (20)
unraid-ui/eslint.config.ts (1)

10-11: Comment refers to the wrong module

Line 11 still mentions vue-eslint-parser, but the adjacent line actually imports eslint-plugin-storybook. Update the comment to avoid confusion.

-// Import vue-eslint-parser as an ESM import
+// Import eslint-plugin-storybook as an ESM import
web/server/api/routes.get.ts (1)

4-27: Implementation looks good but consider security and performance improvements.

The route handler correctly reads the pages directory and returns route metadata with proper error handling. However, consider these enhancements:

  1. Path validation: Ensure the pages directory exists and is within expected bounds
  2. Caching: This reads the filesystem on every request - consider caching the results
  3. Security: Validate file paths to prevent directory traversal
+const PAGES_DIR = join(process.cwd(), 'pages');
+let cachedRoutes: any[] | null = null;
+let cacheTimestamp = 0;
+const CACHE_DURATION = 60000; // 1 minute

 export default defineEventHandler(async (_event) => {
   try {
+    // Simple caching mechanism
+    const now = Date.now();
+    if (cachedRoutes && (now - cacheTimestamp) < CACHE_DURATION) {
+      return cachedRoutes;
+    }
+
-    const pagesDir = join(process.cwd(), 'pages');
-    const files = await readdir(pagesDir, { withFileTypes: true });
+    // Validate pages directory exists
+    const files = await readdir(PAGES_DIR, { withFileTypes: true });
     
     const routes = files
       .filter(file => file.isFile() && file.name.endsWith('.vue'))
+      .filter(file => !file.name.includes('..')) // Basic path validation
       .map(file => {
         const name = file.name.replace('.vue', '');
         const path = name === 'index' ? '/' : `/${name}`;
         
         return {
           path,
           name: name === 'index' ? 'index' : name
         };
       })
       .sort((a, b) => a.path.localeCompare(b.path));
     
+    // Cache the results
+    cachedRoutes = routes;
+    cacheTimestamp = now;
+    
     return routes;
   } catch (error) {
     console.error('Error reading pages directory:', error);
     return [];
   }
 });
web/pages/flash-backup.vue (1)

1-17: Add TypeScript annotations for better type safety.

Consider adding TypeScript by changing the script tag to include lang="ts" and adding proper type annotations.

-<script setup>
+<script lang="ts" setup>
web/components/Backup/BackupEntry.vue (2)

115-118: Simplify progress null checks.

The !== null && !== undefined check can be simplified.

-      <div v-if="jobData.progress !== null && jobData.progress !== undefined" class="bg-gray-50 dark:bg-gray-700 rounded-lg p-3">
+      <div v-if="jobData.progress != null" class="bg-gray-50 dark:bg-gray-700 rounded-lg p-3">

121-131: Simplify progress null checks and add defensive programming.

Same null check issue, plus the Math.round assumes progress is a number.

-    <div v-if="jobData.progress !== null && jobData.progress !== undefined" class="mt-4">
+    <div v-if="jobData.progress != null" class="mt-4">
       <div class="w-full bg-gray-200 rounded-full h-2 dark:bg-gray-700">
         <div
           :class="[
             'h-2 rounded-full transition-all duration-300',
             statusColor === 'green' ? 'bg-green-600' : statusColor === 'red' ? 'bg-red-600' : 'bg-blue-600'
           ]"
-          :style="{ width: `${Math.round(jobData.progress)}%` }"
+          :style="{ width: `${Math.max(0, Math.min(100, Math.round(jobData.progress || 0)))}%` }"
         ></div>
       </div>
     </div>
api/src/unraid-api/utils/format.service.ts (1)

25-26: Unusual rounding approach for small durations.

The manual rounding Math.round(seconds * 100) / 100 is unusual. Consider using toFixed() for consistency.

-        if (seconds < 60) return `${Math.round(seconds * 100) / 100}s`;
+        if (seconds < 60) return `${Number(seconds.toFixed(2))}s`;
api/src/unraid-api/graph/resolvers/backup/destination/backup-destination.service.ts (2)

23-28: Consider removing EventEmitter inheritance if not used.

The service extends EventEmitter but doesn't emit any events. If event emission is planned for future use, consider documenting the intended events.


73-75: Add TODO comment for unimplemented cleanup method.

The cleanup method currently only logs but doesn't perform any actual cleanup.

 async cleanup(): Promise<void> {
+    // TODO: Implement cleanup logic for destination processors
     this.logger.log('Cleaning up destination service...');
 }
api/src/unraid-api/graph/resolvers/backup/destination/backup-destination.types.ts (1)

84-93: Simplify type resolution with optional chaining.

The static analysis correctly identifies that optional chaining can simplify the type resolution logic.

 resolveType(obj: any) {
-    if (RcloneDestinationConfig.isTypeOf && RcloneDestinationConfig.isTypeOf(obj)) {
+    if (RcloneDestinationConfig.isTypeOf?.(obj)) {
         return RcloneDestinationConfig;
     }
     return null;
 },
api/src/unraid-api/graph/resolvers/backup/source/backup-source.service.ts (2)

38-48: Consider removing EventEmitter inheritance if not used.

Similar to BackupDestinationService, this service extends EventEmitter but doesn't emit any events.


81-83: Add TODO comment for unimplemented cleanup method.

The cleanup method is a stub similar to the destination service.

 async cleanup(): Promise<void> {
+    // TODO: Implement cleanup logic for source processors
     this.logger.log('Cleaning up source service...');
 }
api/src/unraid-api/graph/resolvers/backup/backup.resolver.ts (1)

129-129: Remove unnecessary type assertion

The type assertion is redundant since the method already returns the correct type.

-        return jobStatus as JobStatus;
+        return jobStatus;
api/src/unraid-api/graph/resolvers/rclone/rclone-status.service.ts (1)

248-267: Incomplete method implementation

The getBackupStatus method appears to be a stub that always returns hardcoded values.

This method needs proper implementation to fetch actual backup status. Would you like me to help implement this method or open an issue to track this?

web/components/Backup/BackupJobItem.vue (1)

473-473: Extract inline calculation to computed property.

The inline GB calculation makes the template harder to read.

Add a computed property:

const formattedTotalSize = computed(() => {
  const totalBytes = configWithJob.value?.runningJob?.totalBytes;
  if (!totalBytes) return 'N/A';
  return (totalBytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
});

Then use it in the template:

-<div><span class="font-medium">Total:</span> {{ configWithJob.runningJob.totalBytes ? (configWithJob.runningJob.totalBytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB' : 'N/A' }}</div>
+<div><span class="font-medium">Total:</span> {{ formattedTotalSize }}</div>
api/src/unraid-api/graph/resolvers/backup/source/script/script-source-processor.service.ts (1)

28-28: Consider making the output size limit configurable.

The hardcoded 100MB limit might be too restrictive for some use cases.

 export class ScriptSourceProcessor extends BackupSourceProcessor<ScriptSourceConfig> {
     readonly sourceType = SourceType.SCRIPT;
     private readonly logger = new Logger(ScriptSourceProcessor.name);
     private readonly tempDir = '/tmp/unraid-script-preprocessing';
-    private readonly maxOutputSize = 100 * 1024 * 1024; // 100MB limit
+    private readonly maxOutputSize: number;
+
+    constructor() {
+        super();
+        // Allow configuration via environment variable with 100MB default
+        this.maxOutputSize = parseInt(process.env.SCRIPT_MAX_OUTPUT_SIZE || '104857600', 10);
+    }

Update the error message to show the limit in a human-readable format:

             if (outputSize > this.maxOutputSize) {
                 throw new Error(
-                    `Script output too large: ${outputSize} bytes (max: ${this.maxOutputSize})`
+                    `Script output too large: ${(outputSize / 1024 / 1024).toFixed(2)}MB (max: ${(this.maxOutputSize / 1024 / 1024).toFixed(2)}MB)`
                 );
             }

Also applies to: 66-71

api/src/unraid-api/graph/resolvers/rclone/rclone.model.ts (1)

322-324: Consider removing the index signature for better type safety

The index signature [key: string]: any reduces type safety. If additional fields are needed, consider explicitly defining them or using a more specific type:

-    // Allow additional fields
-    [key: string]: any;
+    // Additional metadata if needed
+    @Field(() => GraphQLJSON, { nullable: true })
+    additionalMetadata?: Record<string, unknown>;
api/src/unraid-api/graph/resolvers/backup/destination/rclone/rclone-destination-processor.service.ts (1)

299-304: Use optional chaining for cleaner code

-                        if (progressMatch && progressMatch[1] && options.onProgress) {
+                        if (progressMatch?.[1] && options.onProgress) {
                             const percentage = parseInt(progressMatch[1], 10);
                             if (!isNaN(percentage)) {
                                 options.onProgress(percentage);
                             }
                         }
api/generated-schema.graphql (1)

1329-1331: Simplify the DateTimeISO scalar description

The description is excessively verbose. Consider shortening it to match the concise style of other scalar descriptions in the schema.

 """
-A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar.This scalar is serialized to a string in ISO 8601 format and parsed from a string in ISO 8601 format.
+A date-time string in ISO 8601 format at UTC, such as 2007-12-03T10:15:30Z.
 """
 scalar DateTimeISO
api/src/unraid-api/graph/resolvers/backup/backup.model.ts (1)

184-188: Remove unnecessary ValidateIf decorator

The ValidateIf decorator on the enabled field is unnecessary since enabled always has a value (defaultValue: true).

     @Field(() => Boolean, { defaultValue: true })
     @IsBoolean()
-    @ValidateIf((o) => o.schedule && o.schedule.length > 0)
     declare enabled: boolean;
api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts (1)

632-633: Use optional chaining for cleaner code

Replace the logical AND operator with optional chaining.

-        const isUnixSocket = this.rcloneSocketPath && this.rcloneSocketPath.startsWith('/');
+        const isUnixSocket = this.rcloneSocketPath?.startsWith('/');
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e1a7a3d and 872559c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (84)
  • api/.env.development (2 hunks)
  • api/.eslintrc.ts (1 hunks)
  • api/dev/Unraid.net/myservers.cfg (1 hunks)
  • api/dev/api/backup/backup-jobs.json (1 hunks)
  • api/dev/configs/api.json (1 hunks)
  • api/dev/states/myservers.cfg (1 hunks)
  • api/generated-schema.graphql (8 hunks)
  • api/src/__test__/graphql/resolvers/rclone-api.service.test.ts (3 hunks)
  • api/src/store/modules/paths.ts (1 hunks)
  • api/src/unraid-api/auth/auth.service.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/backup/backup-config.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/backup-mutations.resolver.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/backup.model.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/backup.module.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/backup.resolver.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/backup.utils.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/destination/backup-destination-jsonforms.config.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/destination/backup-destination-processor.interface.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/destination/backup-destination.module.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/destination/backup-destination.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/destination/backup-destination.types.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/destination/rclone/rclone-destination-processor.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/jsonforms/backup-jsonforms-config.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/orchestration/backup-job-status.model.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/orchestration/backup-job-status.resolver.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/orchestration/backup-job-tracking.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/orchestration/backup-orchestration.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/backup-source-jsonforms.config.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/backup-source-processor.interface.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/backup-source.module.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/backup-source.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/backup-source.types.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/base-source.types.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source-processor.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source.types.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/flash/flash-validation.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/raw/raw-source-processor.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/raw/raw-source.types.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/script/script-source-processor.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/script/script-source.types.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/script/script-validation.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/zfs/zfs-source-processor.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/zfs/zfs-source.types.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/source/zfs/zfs-validation.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/mutation/mutation.model.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/mutation/mutation.resolver.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts (6 hunks)
  • api/src/unraid-api/graph/resolvers/rclone/rclone-status.service.test.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/rclone/rclone-status.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/rclone/rclone.model.ts (3 hunks)
  • api/src/unraid-api/graph/resolvers/rclone/rclone.module.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/rclone/rclone.mutation.resolver.ts (3 hunks)
  • api/src/unraid-api/graph/resolvers/rclone/rclone.service.ts (3 hunks)
  • api/src/unraid-api/graph/resolvers/resolvers.module.ts (2 hunks)
  • api/src/unraid-api/graph/utils/utils.module.ts (1 hunks)
  • api/src/unraid-api/main.ts (1 hunks)
  • api/src/unraid-api/utils/format.service.test.ts (1 hunks)
  • api/src/unraid-api/utils/format.service.ts (1 hunks)
  • api/src/unraid-api/utils/utils.module.ts (1 hunks)
  • packages/unraid-api-plugin-connect/src/unraid-connect/connect-settings.resolver.ts (1 hunks)
  • packages/unraid-shared/src/graphql.model.ts (1 hunks)
  • plugin/builder/build-txz.ts (1 hunks)
  • unraid-ui/eslint.config.ts (1 hunks)
  • unraid-ui/src/components/form/lightswitch/Lightswitch.vue (0 hunks)
  • unraid-ui/src/components/form/lightswitch/index.ts (0 hunks)
  • unraid-ui/src/forms/JsonForms.vue (1 hunks)
  • unraid-ui/src/forms/Select.vue (0 hunks)
  • unraid-ui/src/forms/SteppedLayout.vue (2 hunks)
  • unraid-ui/src/forms/StringArrayField.vue (1 hunks)
  • unraid-ui/src/forms/renderers.ts (1 hunks)
  • web/components/Backup/BackupEntry.vue (1 hunks)
  • web/components/Backup/BackupJobConfig.vue (1 hunks)
  • web/components/Backup/BackupJobConfigForm.vue (1 hunks)
  • web/components/Backup/BackupJobItem.vue (1 hunks)
  • web/components/Backup/BackupOverview.vue (1 hunks)
  • web/components/Backup/backup-jobs.query.ts (1 hunks)
  • web/components/RClone/RCloneConfig.vue (4 hunks)
  • web/components/RClone/RCloneOverview.vue (2 hunks)
  • web/composables/gql/gql.ts (3 hunks)
  • web/composables/gql/graphql.ts (19 hunks)
  • web/helpers/apollo-cache/index.ts (1 hunks)
  • web/layouts/default.vue (2 hunks)
  • web/pages/flash-backup.vue (1 hunks)
  • web/server/api/routes.get.ts (1 hunks)
💤 Files with no reviewable changes (3)
  • unraid-ui/src/forms/Select.vue
  • unraid-ui/src/components/form/lightswitch/index.ts
  • unraid-ui/src/components/form/lightswitch/Lightswitch.vue
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
api/src/unraid-api/**/*

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
  • .cursor/rules/api-rules.mdc
api/**/*.{test,spec}.{ts,js}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
api/**/*.{test,spec}.{js,ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • .cursor/rules/api-rules.mdc
**/*.test.ts

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • .cursor/rules/web-testing-rules.mdc
web/**/*.query.ts

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
  • .cursor/rules/web-graphql.mdc
web/**/*.{query.ts,mutation.ts}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • .cursor/rules/web-graphql.mdc
🧠 Learnings (71)
📓 Common learnings
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
api/dev/Unraid.net/myservers.cfg (8)
Learnt from: elibosley
PR: unraid/api#1381
File: plugin/source/dynamix.unraid.net/usr/local/share/dynamix.unraid.net/install/scripts/setup_api.sh:107-113
Timestamp: 2025-05-07T16:07:47.236Z
Learning: The Unraid API is designed to handle missing configuration files gracefully with smart internal fallbacks rather than requiring installation scripts to create default configurations.
Learnt from: elibosley
PR: unraid/api#1381
File: plugin/source/dynamix.unraid.net/usr/local/share/dynamix.unraid.net/install/scripts/verify_install.sh:11-16
Timestamp: 2025-05-08T19:31:52.417Z
Learning: The `dynamix.my.servers` namespace is still valid and should not be changed to `dynamix.unraid.net` in file paths, as both namespaces coexist in the codebase.
Learnt from: mdatelle
PR: unraid/api#1106
File: unraid-ui/src/components/index.ts:2-2
Timestamp: 2025-02-04T17:21:39.710Z
Learning: The unraid-ui package is undergoing a major refactoring process, and breaking changes are expected during this transition period.
Learnt from: elibosley
PR: unraid/api#1101
File: api/src/unraid-api/unraid-file-modifier/modifications/__test__/generic-modification.spec.ts:80-80
Timestamp: 2025-02-03T18:57:53.577Z
Learning: In the unraid/api codebase, patch files generated for file modifications always use the .patch extension, regardless of the source file type being modified.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:39-41
Timestamp: 2025-01-29T16:35:43.699Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations, including detailed error logging with stack traces and modification IDs. Individual FileModification implementations should focus on their core functionality without duplicating error handling.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:33-37
Timestamp: 2025-01-29T16:36:04.777Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations. It includes try/catch blocks, detailed error logging, and safe rollback mechanisms. Individual FileModification implementations (like LogRotateModification) should allow errors to propagate to this service layer rather than handling them internally.
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/graphql/schema/types/connect/connect.graphql:142-146
Timestamp: 2025-03-14T16:10:38.562Z
Learning: The updateApiSettings mutation in api/src/unraid-api/graph/connect/connect.resolver.ts is protected with the @UsePermissions decorator that requires UPDATE permission on the CONFIG resource.
Learnt from: mdatelle
PR: unraid/api#1219
File: api/src/unraid-api/main.ts:32-55
Timestamp: 2025-03-07T17:35:50.406Z
Learning: Helmet security configuration in the Unraid API is intentionally relaxed (with disabled CSP, CORS policies, and HSTS) to maintain compatibility with existing Unraid plugins. Stricter security settings might break current plugin functionality.
api/dev/configs/api.json (6)
Learnt from: elibosley
PR: unraid/api#1381
File: plugin/source/dynamix.unraid.net/usr/local/share/dynamix.unraid.net/install/scripts/setup_api.sh:107-113
Timestamp: 2025-05-07T16:07:47.236Z
Learning: The Unraid API is designed to handle missing configuration files gracefully with smart internal fallbacks rather than requiring installation scripts to create default configurations.
Learnt from: mdatelle
PR: unraid/api#1106
File: unraid-ui/src/components/index.ts:2-2
Timestamp: 2025-02-04T17:21:39.710Z
Learning: The unraid-ui package is undergoing a major refactoring process, and breaking changes are expected during this transition period.
Learnt from: mdatelle
PR: unraid/api#1219
File: api/src/unraid-api/main.ts:32-55
Timestamp: 2025-03-07T17:35:50.406Z
Learning: Helmet security configuration in the Unraid API is intentionally relaxed (with disabled CSP, CORS policies, and HSTS) to maintain compatibility with existing Unraid plugins. Stricter security settings might break current plugin functionality.
Learnt from: pujitm
PR: unraid/api#1415
File: plugin/plugins/dynamix.unraid.net.plg:234-236
Timestamp: 2025-06-11T14:14:30.348Z
Learning: For the Unraid Connect plugin, the script `/etc/rc.d/rc.unraid-api` is bundled with the plugin package itself, so its presence on the target system is guaranteed during installation.
Learnt from: pujitm
PR: unraid/api#1252
File: api/src/environment.ts:56-56
Timestamp: 2025-03-27T13:34:53.438Z
Learning: For critical components in the Unraid API, such as retrieving version information from package.json, failing fast (allowing crashes) is preferred over graceful degradation with fallback values.
Learnt from: mdatelle
PR: unraid/api#1219
File: api/src/unraid-api/main.ts:57-63
Timestamp: 2025-03-07T17:36:52.790Z
Learning: The CORS configuration in the unraid API is intentionally set to allow all origins (`origin: true`). This was a deliberate architectural decision when removing the previous custom CORS implementation and implementing helmet security headers instead.
plugin/builder/build-txz.ts (7)
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
Learnt from: elibosley
PR: unraid/api#1151
File: plugin/builder/utils/consts.ts:6-6
Timestamp: 2025-03-04T14:55:00.903Z
Learning: The startingDir constant in plugin/builder/utils/consts.ts is defined using process.cwd(), which can cause issues if directory changes occur after importing this constant. Using __dirname.split('/builder')[0] would make it more reliable by making it relative to the file location rather than the current working directory.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to **/*.{ts,tsx} : TypeScript imports use .js extensions for ESM compatibility
Learnt from: elibosley
PR: unraid/api#1120
File: plugin/scripts/build-plugin-and-txz.ts:177-200
Timestamp: 2025-02-05T14:43:04.715Z
Learning: In the plugin build system (plugin/scripts/build-plugin-and-txz.ts), updating all XML entities in a single loop is an acceptable pattern when all values need to be replaced, as it ensures consistency and maintainability. The PR entity is optional and handled separately in the validation.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Don't rely on Nuxt auto-imports in tests
Learnt from: pujitm
PR: unraid/api#1417
File: web/components/ConnectSettings/ConnectSettings.ce.vue:11-18
Timestamp: 2025-06-13T17:14:21.739Z
Learning: The project’s build tooling auto-imports common Vue/Pinia helpers such as `storeToRefs`, so explicit import statements for them are not required.
api/.eslintrc.ts (14)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to **/*.{ts,tsx} : TypeScript imports use .js extensions for ESM compatibility
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.query.ts : GraphQL queries must be placed in `.query.ts` files
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in `.mutation.ts` files
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.{query.ts,mutation.ts} : All GraphQL under `web/` must follow this naming convention
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/**/*.query.ts : GraphQL queries must be placed in .query.ts files under web/
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in .mutation.ts files under web/
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Don't rely on Nuxt auto-imports in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Avoid relying on Nuxt's auto-imports in test environment
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Always run pnpm codegen for GraphQL code generation in the web directory
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Always run `pnpm codegen` for GraphQL code generation in the web directory
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Always run scripts from api/package.json unless requested
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Always run scripts from api/package.json unless requested otherwise
packages/unraid-shared/src/graphql.model.ts (1)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
unraid-ui/src/forms/StringArrayField.vue (2)
Learnt from: elibosley
PR: unraid/api#1369
File: web/components/Activation/WelcomeModal.ce.vue:40-40
Timestamp: 2025-04-25T13:29:07.868Z
Learning: The `#confirmPassword` selector in the WelcomeModal.ce.vue component is intentionally looking for an element that exists in the Unraid OS login page (.login.php), not within the component itself. This is used as part of a font-size adjustment workaround to handle different CSS between login and authenticated pages.
Learnt from: zackspear
PR: unraid/api#1143
File: web/pages/webComponents.vue:28-29
Timestamp: 2025-02-18T18:38:24.981Z
Learning: In Vue components, when there's a repeating pattern of heading + content + divider, prefer using a wrapper component that takes the heading as a prop and content via slots, rather than duplicating the structure. This improves maintainability and reduces code duplication.
api/src/unraid-api/main.ts (5)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the Nest repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/auth/auth.service.ts:42-105
Timestamp: 2024-11-04T22:00:41.946Z
Learning: In the 'AuthService' within `api/src/unraid-api/auth/auth.service.ts`, rate limiting is not required because the API is not public facing.
Learnt from: pujitm
PR: unraid/api#1219
File: api/src/unraid-api/main.ts:18-25
Timestamp: 2025-03-07T19:29:12.540Z
Learning: When handling type mismatches between dependencies in TypeScript (such as between NestJS and Fastify), prefer using `@ts-expect-error` with a detailed explanation comment instead of `as any` type assertions. This better documents the reason for the type bypass and makes the issue more visible for future maintenance.
api/src/unraid-api/auth/auth.service.ts (8)
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/auth/auth.service.ts:0-0
Timestamp: 2024-11-04T20:44:46.432Z
Learning: When modifying `apiKey.roles` in `removeRoleFromApiKey` and `addRoleToApiKey` within `api/src/unraid-api/auth/auth.service.ts`, concurrency issues are not a concern because the keys are stored in the file system.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/auth/auth.service.ts:0-0
Timestamp: 2024-11-04T20:41:22.303Z
Learning: In `api/src/unraid-api/auth/auth.service.ts`, the `addRoleToApiKey` function operates on API keys stored as JSON files in a directory, not a database, so concurrency is not a concern for modifying `apiKey.roles`.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:87-89
Timestamp: 2024-11-06T20:59:06.096Z
Learning: Error handling in mutations like `addRoleForUser` in `auth.resolver.ts` is performed at the service level, so additional error handling in the resolver is unnecessary.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/auth/auth.module.ts:94-96
Timestamp: 2024-11-15T16:22:12.460Z
Learning: In `CookieService.defaultOpts()` in `api/src/unraid-api/auth/cookie.service.ts`, use `sameSite: 'lax'` for session cookie configuration.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/auth/auth.service.ts:42-105
Timestamp: 2024-11-04T22:00:41.946Z
Learning: In the 'AuthService' within `api/src/unraid-api/auth/auth.service.ts`, rate limiting is not required because the API is not public facing.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/auth/api-key.service.ts:62-70
Timestamp: 2024-11-05T14:49:07.308Z
Learning: In `api/src/unraid-api/auth/api-key.service.ts`, when handling read errors in the `findById` method, throw a `GraphQLError` instead of an `InternalServerErrorException`.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/auth/api-key.service.ts:176-188
Timestamp: 2024-11-15T16:22:03.485Z
Learning: Atomic writes are not required for the `saveApiKey` method in `ApiKeyService` (`api/src/unraid-api/auth/api-key.service.ts`) unless specifically needed.
api/src/unraid-api/graph/resolvers/rclone/rclone.mutation.resolver.ts (11)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/graphql/schema/types/connect/connect.graphql:142-146
Timestamp: 2025-03-14T16:10:38.562Z
Learning: The updateApiSettings mutation in api/src/unraid-api/graph/connect/connect.resolver.ts is protected with the @UsePermissions decorator that requires UPDATE permission on the CONFIG resource.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:87-89
Timestamp: 2024-11-06T20:59:06.096Z
Learning: Error handling in mutations like `addRoleForUser` in `auth.resolver.ts` is performed at the service level, so additional error handling in the resolver is unnecessary.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to **/*.{ts,tsx} : TypeScript imports use .js extensions for ESM compatibility
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in `.mutation.ts` files
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/auth/auth.service.ts:0-0
Timestamp: 2024-11-04T20:44:46.432Z
Learning: When modifying `apiKey.roles` in `removeRoleFromApiKey` and `addRoleToApiKey` within `api/src/unraid-api/auth/auth.service.ts`, concurrency issues are not a concern because the keys are stored in the file system.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.{query.ts,mutation.ts} : All GraphQL under `web/` must follow this naming convention
unraid-ui/eslint.config.ts (10)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Ensure Vue reactivity imports are added to original store files as they may be missing because Nuxt auto import was turned on
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: pujitm
PR: unraid/api#1417
File: web/components/ConnectSettings/ConnectSettings.ce.vue:11-18
Timestamp: 2025-06-13T17:14:21.739Z
Learning: The project’s build tooling auto-imports common Vue/Pinia helpers such as `storeToRefs`, so explicit import statements for them are not required.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Don't rely on Nuxt auto-imports in tests
Learnt from: elibosley
PR: unraid/api#972
File: web/components/ColorSwitcher.ce.vue:1-2
Timestamp: 2024-12-17T13:55:42.068Z
Learning: In this Nuxt.js project, components used in templates are automatically imported by Nuxt, so explicit import statements for components are unnecessary.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to **/*.{ts,tsx} : TypeScript imports use .js extensions for ESM compatibility
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Avoid relying on Nuxt's auto-imports in test environment
Learnt from: elibosley
PR: unraid/api#974
File: web/components/Loading/Error.vue:1-3
Timestamp: 2024-12-06T17:38:40.999Z
Learning: In Nuxt.js projects, components are automatically imported, so explicit import statements for components like `LoadingSpinner` in `web/components/Loading/Error.vue` are not necessary.
api/src/unraid-api/graph/resolvers/mutation/mutation.resolver.ts (7)
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/graphql/schema/types/connect/connect.graphql:142-146
Timestamp: 2025-03-14T16:10:38.562Z
Learning: The updateApiSettings mutation in api/src/unraid-api/graph/connect/connect.resolver.ts is protected with the @UsePermissions decorator that requires UPDATE permission on the CONFIG resource.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in `.mutation.ts` files
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:87-89
Timestamp: 2024-11-06T20:59:06.096Z
Learning: Error handling in mutations like `addRoleForUser` in `auth.resolver.ts` is performed at the service level, so additional error handling in the resolver is unnecessary.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in .mutation.ts files under web/
api/src/unraid-api/utils/utils.module.ts (10)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Use factory functions for module mocks to avoid hoisting issues in test files
Learnt from: pujitm
PR: unraid/api#1211
File: unraid-ui/package.json:43-43
Timestamp: 2025-03-14T19:18:23.324Z
Learning: The @internationalized/number package is a dependency of reka-ui, which is used for number formatting in the Unraid UI components.
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Mock external services and API calls in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Mock external dependencies and services in tests
Learnt from: elibosley
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to web/test/mocks/**/*.ts : Frequently used mocks are stored under `web/test/mocks`
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
api/src/store/modules/paths.ts (5)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify state changes by updating the store in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify state changes after actions in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Set initial state for focused testing in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Let stores initialize with their natural default state instead of forcing initial state in store tests
Learnt from: elibosley
PR: unraid/api#1151
File: plugin/builder/utils/consts.ts:6-6
Timestamp: 2025-03-04T14:55:00.903Z
Learning: The startingDir constant in plugin/builder/utils/consts.ts is defined using process.cwd(), which can cause issues if directory changes occur after importing this constant. Using __dirname.split('/builder')[0] would make it more reliable by making it relative to the file location rather than the current working directory.
api/.env.development (7)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Always run scripts from api/package.json unless requested otherwise
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Always run scripts from api/package.json unless requested
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Run tests with: pnpm --filter ./api test
Learnt from: pujitm
PR: unraid/api#1116
File: api/src/unraid-api/cli/log.service.ts:52-56
Timestamp: 2025-02-04T20:06:52.290Z
Learning: In Node.js logging, console.trace() is specifically for outputting stack traces to stderr and should not be used for general trace-level logging. For trace-level logging of general messages, console.log() is the appropriate choice.
Learnt from: pujitm
PR: unraid/api#1116
File: api/src/unraid-api/cli/log.service.ts:52-56
Timestamp: 2025-02-04T20:06:52.290Z
Learning: In Node.js:
1. console.trace() is a debugging tool that outputs a stack trace to stderr, showing the execution path with line numbers and function names
2. For trace-level application logging (most verbose level), use console.log() as it's meant for general message output, not stack traces
3. The logging hierarchy from most to least verbose is: trace > debug > info > warn > error
Learnt from: elibosley
PR: unraid/api#1334
File: api/src/unraid-api/graph/resolvers/docker/docker-event.service.ts:63-66
Timestamp: 2025-04-07T14:34:47.255Z
Learning: In DockerEventService, the chokidar file watcher is configured with `ignoreInitial: false` to ensure that existing files (like the Docker socket) are detected and processed at application startup, not just when files change after the watcher is initialized.
Learnt from: elibosley
PR: unraid/api#1334
File: api/src/unraid-api/graph/resolvers/docker/docker-event.service.ts:63-66
Timestamp: 2025-04-07T14:34:47.255Z
Learning: In DockerEventService, the chokidar file watcher is configured with `ignoreInitial: false` to ensure that existing files (like the Docker socket) are detected and processed at application startup, not just when files change after the watcher is initialized.
web/pages/flash-backup.vue (12)
Learnt from: zackspear
PR: unraid/api#0
File: :0-0
Timestamp: 2025-03-27T23:33:13.215Z
Learning: In the unraid/api project, Vue components are compiled into web components. Using `setActivePinia(createPinia())` in store files would break the build by causing all web components to share a singular Pinia store instance. Each web component needs its own Pinia store instance to maintain proper isolation and encapsulation.
Learnt from: zackspear
PR: unraid/api#0
File: :0-0
Timestamp: 2025-03-27T23:52:57.888Z
Learning: In the unraid/api project, Vue components are compiled into web components. The `setActivePinia(createPinia())` call at the module level in store files is intentional and ensures all web components share a single Pinia store instance, which is the desired behavior. This shared state approach is critical for the application's architecture to function correctly.
Learnt from: pujitm
PR: unraid/api#1143
File: web/components/DummyServerSwitcher.vue:16-19
Timestamp: 2025-02-18T17:36:22.670Z
Learning: The DummyServerSwitcher component in web/components/DummyServerSwitcher.vue is a development tool for testing different server states, and includes intentional debug elements to aid development.
Learnt from: zackspear
PR: unraid/api#0
File: :0-0
Timestamp: 2025-03-27T23:52:57.888Z
Learning: In the unraid/api project, Vue components are compiled into web components. Using `setActivePinia(createPinia())` in store files ensures that all web components share a single Pinia store instance, which is the desired behavior. Without this initialization, each web component would have its own isolated store, breaking the intended architecture.
Learnt from: pujitm
PR: unraid/api#1211
File: plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/Connect.page:0-0
Timestamp: 2025-03-14T19:14:10.408Z
Learning: *.ce.vue components in `web/components` get built as custom elements and prefixed with `unraid-`, making them available as HTML custom elements at runtime.
Learnt from: pujitm
PR: unraid/api#1211
File: plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/Connect.page:0-0
Timestamp: 2025-03-14T19:14:10.408Z
Learning: *.ce.vue components in `web/components` get built as custom elements and prefixed with `unraid-`, making them available as HTML custom elements at runtime.
Learnt from: zackspear
PR: unraid/api#0
File: :0-0
Timestamp: 2025-03-27T23:33:13.215Z
Learning: In the unraid/api project, Vue components are compiled into web components. Using `setActivePinia(createPinia())` in store files would break the build by causing all web components to share a singular Pinia store instance. Each web component needs its own Pinia store instance to function correctly.
Learnt from: pujitm
PR: unraid/api#974
File: web/components/Loading/Error.vue:50-50
Timestamp: 2024-12-06T17:34:16.133Z
Learning: In this project, the `Button` component from `~/components/shadcn/Button.vue` is autoloaded and does not need to be imported manually in components like `web/components/Loading/Error.vue`.
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-24
Timestamp: 2024-12-09T15:47:29.325Z
Learning: In our Nuxt setup using Vue.js, components defined within the codebase are autoloaded and do not require explicit import statements in the script section. For example, components like `TabsList` and `TabsTrigger` used in `web/components/Notifications/TabList.vue` are automatically available without imports.
Learnt from: elibosley
PR: unraid/api#972
File: web/components/ColorSwitcher.ce.vue:1-2
Timestamp: 2024-12-17T13:55:42.068Z
Learning: In this Nuxt.js project, components used in templates are automatically imported by Nuxt, so explicit import statements for components are unnecessary.
api/src/unraid-api/graph/resolvers/resolvers.module.ts (11)
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/auth/auth.service.ts:0-0
Timestamp: 2024-11-04T20:44:46.432Z
Learning: When modifying `apiKey.roles` in `removeRoleFromApiKey` and `addRoleToApiKey` within `api/src/unraid-api/auth/auth.service.ts`, concurrency issues are not a concern because the keys are stored in the file system.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/auth/api-key.service.ts:176-188
Timestamp: 2024-11-15T16:22:03.485Z
Learning: Atomic writes are not required for the `saveApiKey` method in `ApiKeyService` (`api/src/unraid-api/auth/api-key.service.ts`) unless specifically needed.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/auth/auth.service.ts:0-0
Timestamp: 2024-11-04T20:41:22.303Z
Learning: In `api/src/unraid-api/auth/auth.service.ts`, the `addRoleToApiKey` function operates on API keys stored as JSON files in a directory, not a database, so concurrency is not a concern for modifying `apiKey.roles`.
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/graphql/schema/types/connect/connect.graphql:142-146
Timestamp: 2025-03-14T16:10:38.562Z
Learning: The updateApiSettings mutation in api/src/unraid-api/graph/connect/connect.resolver.ts is protected with the @UsePermissions decorator that requires UPDATE permission on the CONFIG resource.
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:87-89
Timestamp: 2024-11-06T20:59:06.096Z
Learning: Error handling in mutations like `addRoleForUser` in `auth.resolver.ts` is performed at the service level, so additional error handling in the resolver is unnecessary.
Learnt from: elibosley
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.
api/src/unraid-api/utils/format.service.test.ts (12)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Mock external services and API calls in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify state changes by updating the store in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Test async operations completely in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Test action side effects and state changes in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify state changes after actions in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify proper error handling in store tests
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/**/*.{test,spec}.{ts,js} : Test suite is VITEST, do not use jest in the API package
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Mock external dependencies and services in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Mock external dependencies appropriately in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Applies to api/**/*.{test,spec}.{js,ts,tsx} : Test suite is VITEST, do not use jest
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Test component interactions (clicks, inputs, etc.) in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Specify return values for component methods with `vi.spyOn()` in tests
web/components/RClone/RCloneOverview.vue (1)
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
unraid-ui/src/forms/renderers.ts (4)
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Verify that the expected elements are rendered in component tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Check component state through rendered output in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Assert on rendered text content with `wrapper.text()`
packages/unraid-api-plugin-connect/src/unraid-connect/connect-settings.resolver.ts (12)
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/graphql/schema/types/connect/connect.graphql:142-146
Timestamp: 2025-03-14T16:10:38.562Z
Learning: The updateApiSettings mutation in api/src/unraid-api/graph/connect/connect.resolver.ts is protected with the @UsePermissions decorator that requires UPDATE permission on the CONFIG resource.
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.query.ts : GraphQL queries must be placed in `.query.ts` files
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.{query.ts,mutation.ts} : All GraphQL under `web/` must follow this naming convention
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/auth/api-key.service.ts:62-70
Timestamp: 2024-11-05T14:49:07.308Z
Learning: In `api/src/unraid-api/auth/api-key.service.ts`, when handling read errors in the `findById` method, throw a `GraphQLError` instead of an `InternalServerErrorException`.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in `.mutation.ts` files
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/**/*.query.ts : GraphQL queries must be placed in .query.ts files under web/
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in .mutation.ts files under web/
api/src/unraid-api/graph/resolvers/backup/source/backup-source.module.ts (4)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: elibosley
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
api/src/unraid-api/graph/resolvers/backup/destination/backup-destination.module.ts (5)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the Nest repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: elibosley
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
api/src/unraid-api/graph/utils/utils.module.ts (10)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Use factory functions for module mocks to avoid hoisting issues in test files
Learnt from: pujitm
PR: unraid/api#1211
File: unraid-ui/package.json:43-43
Timestamp: 2025-03-14T19:18:23.324Z
Learning: The @internationalized/number package is a dependency of reka-ui, which is used for number formatting in the Unraid UI components.
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Mock external services and API calls in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Mock external dependencies and services in tests
Learnt from: elibosley
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to web/test/mocks/**/*.ts : Frequently used mocks are stored under `web/test/mocks`
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
api/src/unraid-api/graph/resolvers/mutation/mutation.model.ts (7)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in `.mutation.ts` files
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in .mutation.ts files under web/
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/graphql/schema/types/connect/connect.graphql:142-146
Timestamp: 2025-03-14T16:10:38.562Z
Learning: The updateApiSettings mutation in api/src/unraid-api/graph/connect/connect.resolver.ts is protected with the @UsePermissions decorator that requires UPDATE permission on the CONFIG resource.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
web/server/api/routes.get.ts (1)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
web/components/Backup/BackupJobConfig.vue (3)
Learnt from: pujitm
PR: unraid/api#941
File: web/components/Notifications/Item.vue:0-0
Timestamp: 2024-11-01T17:52:55.311Z
Learning: In the `web/components/Notifications/Item.vue` component, ensure that when delete or archive mutations fail, the notification remains displayed, and an error message is shown below the action buttons to inform the user.
Learnt from: pujitm
PR: unraid/api#974
File: web/components/Loading/Error.vue:50-50
Timestamp: 2024-12-06T17:34:16.133Z
Learning: In this project, the `Button` component from `~/components/shadcn/Button.vue` is autoloaded and does not need to be imported manually in components like `web/components/Loading/Error.vue`.
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-24
Timestamp: 2024-12-09T15:47:29.325Z
Learning: In our Nuxt setup using Vue.js, components defined within the codebase are autoloaded and do not require explicit import statements in the script section. For example, components like `TabsList` and `TabsTrigger` used in `web/components/Notifications/TabList.vue` are automatically available without imports.
web/helpers/apollo-cache/index.ts (6)
Learnt from: pujitm
PR: unraid/api#978
File: web/helpers/apollo-cache/index.ts:133-157
Timestamp: 2024-12-11T17:20:09.604Z
Learning: In `web/helpers/apollo-cache/index.ts`, when updating the cache in the `cache.updateQuery` function, it's sufficient to check if `data` is present, as type checking inside `data` is handled at the GraphQL layer.
Learnt from: pujitm
PR: unraid/api#978
File: web/helpers/apollo-cache/index.ts:134-139
Timestamp: 2024-12-11T20:39:02.511Z
Learning: In `web/helpers/apollo-cache/index.ts`, the `cache.readQuery` method returns `null` when it fails to read from the cache, rather than throwing an exception.
Learnt from: pujitm
PR: unraid/api#982
File: web/helpers/apollo-cache/index.ts:142-142
Timestamp: 2024-12-13T17:28:15.384Z
Learning: In `web/helpers/apollo-cache/index.ts`, it's acceptable to use `structuredClone` since the project targets Node.js v20 and browsers where `structuredClone` is supported.
Learnt from: pujitm
PR: unraid/api#982
File: web/helpers/apollo-cache/index.ts:140-145
Timestamp: 2024-12-13T17:26:55.220Z
Learning: In Apollo Client, the `cache.updateQuery` method can be used on the `InMemoryCache` instance to update queries, even when not using an `ApolloClient` instance directly.
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.{query.ts,mutation.ts} : All GraphQL under `web/` must follow this naming convention
api/src/__test__/graphql/resolvers/rclone-api.service.test.ts (17)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Mock external services and API calls in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Mock external dependencies and services in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Mock external dependencies appropriately in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Test getter dependencies are properly mocked in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Applies to api/**/*.{test,spec}.{js,ts,tsx} : Prefer to not mock simple dependencies in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Use factory functions for module mocks to avoid hoisting issues in test files
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to web/test/mocks/**/*.ts : Frequently used mocks are stored under `web/test/mocks`
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Clear mocks between tests to ensure isolation
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Test async operations completely in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Don't mix mock declarations and module mocks incorrectly in test files
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Remember that `vi.mock()` calls are hoisted
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Use `vi.mock()` for module-level mocks in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Reset mocks between tests with `vi.clearAllMocks()`
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Prefer to not mock simple dependencies in API tests
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/__test__/**/* : Mock external dependencies and services in web/__test__
web/components/RClone/RCloneConfig.vue (2)
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
web/components/Backup/BackupEntry.vue (1)
Learnt from: pujitm
PR: unraid/api#941
File: web/components/Notifications/Item.vue:0-0
Timestamp: 2024-11-01T17:52:55.311Z
Learning: In the `web/components/Notifications/Item.vue` component, ensure that when delete or archive mutations fail, the notification remains displayed, and an error message is shown below the action buttons to inform the user.
api/src/unraid-api/graph/resolvers/backup/source/base-source.types.ts (10)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.query.ts : GraphQL queries must be placed in `.query.ts` files
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in `.mutation.ts` files
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:0-0
Timestamp: 2025-02-24T14:51:21.328Z
Learning: In the Unraid API project's theme system, exact TypeScript type definitions are preferred over index signatures for theme variables to ensure better type safety.
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/**/*.query.ts : GraphQL queries must be placed in .query.ts files under web/
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.{query.ts,mutation.ts} : All GraphQL under `web/` must follow this naming convention
web/layouts/default.vue (11)
Learnt from: elibosley
PR: unraid/api#972
File: web/components/ColorSwitcher.ce.vue:1-2
Timestamp: 2024-12-17T13:55:42.068Z
Learning: In this Nuxt.js project, components used in templates are automatically imported by Nuxt, so explicit import statements for components are unnecessary.
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-24
Timestamp: 2024-12-09T15:47:29.325Z
Learning: In our Nuxt setup using Vue.js, components defined within the codebase are autoloaded and do not require explicit import statements in the script section. For example, components like `TabsList` and `TabsTrigger` used in `web/components/Notifications/TabList.vue` are automatically available without imports.
Learnt from: elibosley
PR: unraid/api#974
File: web/components/Loading/Error.vue:1-3
Timestamp: 2024-12-06T17:38:40.999Z
Learning: In Nuxt.js projects, components are automatically imported, so explicit import statements for components like `LoadingSpinner` in `web/components/Loading/Error.vue` are not necessary.
Learnt from: zackspear
PR: unraid/api#1143
File: web/pages/webComponents.vue:28-29
Timestamp: 2025-02-18T18:38:24.981Z
Learning: In Vue components, when there's a repeating pattern of heading + content + divider, prefer using a wrapper component that takes the heading as a prop and content via slots, rather than duplicating the structure. This improves maintainability and reduces code duplication.
Learnt from: pujitm
PR: unraid/api#974
File: web/components/Loading/Error.vue:50-50
Timestamp: 2024-12-06T17:34:16.133Z
Learning: In this project, the `Button` component from `~/components/shadcn/Button.vue` is autoloaded and does not need to be imported manually in components like `web/components/Loading/Error.vue`.
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-4
Timestamp: 2024-12-09T15:45:46.492Z
Learning: In our Nuxt.js setup for the `web` project, it's not necessary to explicitly import `computed` from `vue` in Vue components, as it's globally available.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Ensure Vue reactivity imports are added to original store files as they may be missing because Nuxt auto import was turned on
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: pujitm
PR: unraid/api#1143
File: web/components/DummyServerSwitcher.vue:16-19
Timestamp: 2025-02-18T17:36:22.670Z
Learning: The DummyServerSwitcher component in web/components/DummyServerSwitcher.vue is a development tool for testing different server states, and includes intentional debug elements to aid development.
Learnt from: elibosley
PR: unraid/api#1369
File: web/components/Activation/WelcomeModal.ce.vue:40-40
Timestamp: 2025-04-25T13:29:07.868Z
Learning: The `#confirmPassword` selector in the WelcomeModal.ce.vue component is intentionally looking for an element that exists in the Unraid OS login page (.login.php), not within the component itself. This is used as part of a font-size adjustment workaround to handle different CSS between login and authenticated pages.
unraid-ui/src/forms/SteppedLayout.vue (11)
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: elibosley
PR: unraid/api#972
File: web/components/ColorSwitcher.ce.vue:1-2
Timestamp: 2024-12-17T13:55:42.068Z
Learning: In this Nuxt.js project, components used in templates are automatically imported by Nuxt, so explicit import statements for components are unnecessary.
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-24
Timestamp: 2024-12-09T15:47:29.325Z
Learning: In our Nuxt setup using Vue.js, components defined within the codebase are autoloaded and do not require explicit import statements in the script section. For example, components like `TabsList` and `TabsTrigger` used in `web/components/Notifications/TabList.vue` are automatically available without imports.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: pujitm
PR: unraid/api#974
File: web/components/Loading/Error.vue:50-50
Timestamp: 2024-12-06T17:34:16.133Z
Learning: In this project, the `Button` component from `~/components/shadcn/Button.vue` is autoloaded and does not need to be imported manually in components like `web/components/Loading/Error.vue`.
Learnt from: zackspear
PR: unraid/api#0
File: :0-0
Timestamp: 2025-03-27T23:52:57.888Z
Learning: In the unraid/api project, Vue components are compiled into web components. The `setActivePinia(createPinia())` call at the module level in store files is intentional and ensures all web components share a single Pinia store instance, which is the desired behavior. This shared state approach is critical for the application's architecture to function correctly.
Learnt from: zackspear
PR: unraid/api#0
File: :0-0
Timestamp: 2025-03-27T23:52:57.888Z
Learning: In the unraid/api project, Vue components are compiled into web components. Using `setActivePinia(createPinia())` in store files ensures that all web components share a single Pinia store instance, which is the desired behavior. Without this initialization, each web component would have its own isolated store, breaking the intended architecture.
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-4
Timestamp: 2024-12-09T15:45:46.492Z
Learning: In our Nuxt.js setup for the `web` project, it's not necessary to explicitly import `computed` from `vue` in Vue components, as it's globally available.
Learnt from: zackspear
PR: unraid/api#0
File: :0-0
Timestamp: 2025-03-27T23:33:13.215Z
Learning: In the unraid/api project, Vue components are compiled into web components. Using `setActivePinia(createPinia())` in store files would break the build by causing all web components to share a singular Pinia store instance. Each web component needs its own Pinia store instance to maintain proper isolation and encapsulation.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Ensure Vue reactivity imports are added to original store files as they may be missing because Nuxt auto import was turned on
Learnt from: pujitm
PR: unraid/api#1417
File: web/components/ConnectSettings/ConnectSettings.ce.vue:11-18
Timestamp: 2025-06-13T17:14:21.739Z
Learning: The project’s build tooling auto-imports common Vue/Pinia helpers such as `storeToRefs`, so explicit import statements for them are not required.
api/src/unraid-api/graph/resolvers/backup/source/raw/raw-source.types.ts (3)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
api/src/unraid-api/graph/resolvers/backup/backup.utils.ts (1)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
api/src/unraid-api/graph/resolvers/backup/backup.module.ts (6)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: elibosley
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
web/components/Backup/BackupOverview.vue (3)
Learnt from: pujitm
PR: unraid/api#941
File: web/components/Notifications/Item.vue:0-0
Timestamp: 2024-11-01T17:52:55.311Z
Learning: In the `web/components/Notifications/Item.vue` component, ensure that when delete or archive mutations fail, the notification remains displayed, and an error message is shown below the action buttons to inform the user.
Learnt from: pujitm
PR: unraid/api#974
File: web/components/Loading/Error.vue:50-50
Timestamp: 2024-12-06T17:34:16.133Z
Learning: In this project, the `Button` component from `~/components/shadcn/Button.vue` is autoloaded and does not need to be imported manually in components like `web/components/Loading/Error.vue`.
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-24
Timestamp: 2024-12-09T15:47:29.325Z
Learning: In our Nuxt setup using Vue.js, components defined within the codebase are autoloaded and do not require explicit import statements in the script section. For example, components like `TabsList` and `TabsTrigger` used in `web/components/Notifications/TabList.vue` are automatically available without imports.
api/src/unraid-api/graph/resolvers/rclone/rclone.module.ts (8)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the Nest repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: elibosley
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Use factory functions for module mocks to avoid hoisting issues in test files
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
api/src/unraid-api/graph/resolvers/backup/orchestration/backup-job-status.resolver.ts (5)
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:87-89
Timestamp: 2024-11-06T20:59:06.096Z
Learning: Error handling in mutations like `addRoleForUser` in `auth.resolver.ts` is performed at the service level, so additional error handling in the resolver is unnecessary.
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: pujitm
PR: unraid/api#1352
File: packages/unraid-api-plugin-connect/src/connect.resolver.ts:14-24
Timestamp: 2025-04-21T18:04:56.755Z
Learning: Error handling in GraphQL resolvers: pujitm prefers to let errors bubble up naturally to the client rather than adding explicit try/catch blocks in each resolver method.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
api/src/unraid-api/graph/resolvers/backup/source/backup-source-jsonforms.config.ts (1)
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
api/src/unraid-api/graph/resolvers/backup/destination/backup-destination-jsonforms.config.ts (1)
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
api/src/unraid-api/graph/resolvers/backup/source/script/script-source.types.ts (7)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.query.ts : GraphQL queries must be placed in `.query.ts` files
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.{query.ts,mutation.ts} : All GraphQL under `web/` must follow this naming convention
api/src/unraid-api/utils/format.service.ts (2)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
api/src/unraid-api/graph/resolvers/rclone/rclone.service.ts (3)
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/auth/api-key.service.ts:62-70
Timestamp: 2024-11-05T14:49:07.308Z
Learning: In `api/src/unraid-api/auth/api-key.service.ts`, when handling read errors in the `findById` method, throw a `GraphQLError` instead of an `InternalServerErrorException`.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/auth/auth.service.ts:0-0
Timestamp: 2024-11-04T20:44:46.432Z
Learning: When modifying `apiKey.roles` in `removeRoleFromApiKey` and `addRoleToApiKey` within `api/src/unraid-api/auth/auth.service.ts`, concurrency issues are not a concern because the keys are stored in the file system.
api/src/unraid-api/graph/resolvers/backup/source/raw/raw-source-processor.service.ts (2)
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:33-37
Timestamp: 2025-01-29T16:36:04.777Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations. It includes try/catch blocks, detailed error logging, and safe rollback mechanisms. Individual FileModification implementations (like LogRotateModification) should allow errors to propagate to this service layer rather than handling them internally.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
api/src/unraid-api/graph/resolvers/backup/destination/backup-destination.types.ts (5)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: elibosley
PR: unraid/api#1352
File: packages/unraid-api-plugin-connect/src/config.entity.ts:37-39
Timestamp: 2025-04-21T18:44:24.383Z
Learning: The project prefers using class-validator decorators directly on entity classes rather than separate Zod schemas to maintain type consistency between GraphQL entities and validation rules.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
api/src/unraid-api/graph/resolvers/backup/source/script/script-validation.service.ts (5)
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:33-37
Timestamp: 2025-01-29T16:36:04.777Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations. It includes try/catch blocks, detailed error logging, and safe rollback mechanisms. Individual FileModification implementations (like LogRotateModification) should allow errors to propagate to this service layer rather than handling them internally.
Learnt from: elibosley
PR: unraid/api#1120
File: plugin/package.json:0-0
Timestamp: 2025-02-05T14:43:48.568Z
Learning: In Node.js projects, npm scripts should be organized with clear namespacing (e.g., build:*, docker:*, env:*) and include proper environment validation and error handling. Each script should follow the single responsibility principle.
Learnt from: elibosley
PR: unraid/api#1352
File: packages/unraid-api-plugin-connect/src/config.entity.ts:16-26
Timestamp: 2025-04-21T18:44:15.414Z
Learning: For the Unraid API project, class-validator should be used for validation to avoid mismatches between different validation schemas (like Zod).
Learnt from: elibosley
PR: unraid/api#1120
File: plugin/scripts/build-plugin-and-txz.ts:132-147
Timestamp: 2025-02-06T15:32:09.488Z
Learning: For validation steps in build scripts where the goal is to fail fast on invalid state, simple error handling (console.error + process.exit) is appropriate since we want to abort the build process immediately.
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:0-0
Timestamp: 2025-03-14T19:22:11.839Z
Learning: In the Unraid API project, input validation should happen at the store layer, not in service methods like ConnectSettingsService, to maintain proper separation of concerns.
api/src/unraid-api/graph/resolvers/backup/orchestration/backup-job-status.model.ts (2)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source.types.ts (5)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:0-0
Timestamp: 2025-02-24T14:51:21.328Z
Learning: In the Unraid API project's theme system, exact TypeScript type definitions are preferred over index signatures for theme variables to ensure better type safety.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
web/composables/gql/gql.ts (11)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in `.mutation.ts` files
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.{query.ts,mutation.ts} : All GraphQL under `web/` must follow this naming convention
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in .mutation.ts files under web/
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.query.ts : GraphQL queries must be placed in `.query.ts` files
Learnt from: pujitm
PR: unraid/api#978
File: web/helpers/apollo-cache/index.ts:133-157
Timestamp: 2024-12-11T17:20:09.604Z
Learning: In `web/helpers/apollo-cache/index.ts`, when updating the cache in the `cache.updateQuery` function, it's sufficient to check if `data` is present, as type checking inside `data` is handled at the GraphQL layer.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/**/*.query.ts : GraphQL queries must be placed in .query.ts files under web/
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: pujitm
PR: unraid/api#1047
File: api/src/unraid-api/graph/sandbox-plugin.ts:57-57
Timestamp: 2025-01-15T21:34:00.006Z
Learning: In the GraphQL sandbox (api/src/unraid-api/graph/sandbox-plugin.ts), CSRF token validation should fail silently with a fallback value to maintain sandbox accessibility, as it's a development tool where strict security measures aren't required.
api/src/unraid-api/graph/resolvers/backup/orchestration/backup-job-tracking.service.ts (1)
Learnt from: elibosley
PR: unraid/api#1222
File: api/src/unraid-api/graph/resolvers/logs/logs.resolver.ts:37-65
Timestamp: 2025-03-17T13:41:52.496Z
Learning: The LogsService in Unraid API uses a reference counting mechanism to track log file subscriptions, ensuring file watchers remain active until all subscribers have unsubscribed.
api/src/unraid-api/graph/resolvers/backup/jsonforms/backup-jsonforms-config.ts (2)
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:199-199
Timestamp: 2025-03-14T16:56:20.520Z
Learning: The JSONForms library has narrow type definitions for interfaces like SchemaBasedCondition that make augmentation difficult. Type assertions (using 'as') are sometimes necessary despite not being ideal from a typing perspective.
api/src/unraid-api/graph/resolvers/backup/source/zfs/zfs-source.types.ts (4)
Learnt from: elibosley
PR: unraid/api#1352
File: packages/unraid-api-plugin-connect/src/config.entity.ts:37-39
Timestamp: 2025-04-21T18:44:24.383Z
Learning: The project prefers using class-validator decorators directly on entity classes rather than separate Zod schemas to maintain type consistency between GraphQL entities and validation rules.
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: elibosley
PR: unraid/api#1352
File: packages/unraid-api-plugin-connect/src/config.entity.ts:16-26
Timestamp: 2025-04-21T18:44:15.414Z
Learning: For the Unraid API project, class-validator should be used for validation to avoid mismatches between different validation schemas (like Zod).
web/components/Backup/BackupJobConfigForm.vue (2)
Learnt from: pujitm
PR: unraid/api#941
File: web/components/Notifications/Item.vue:0-0
Timestamp: 2024-11-01T17:52:55.311Z
Learning: In the `web/components/Notifications/Item.vue` component, ensure that when delete or archive mutations fail, the notification remains displayed, and an error message is shown below the action buttons to inform the user.
Learnt from: elibosley
PR: unraid/api#1369
File: web/components/Activation/WelcomeModal.ce.vue:40-40
Timestamp: 2025-04-25T13:29:07.868Z
Learning: The `#confirmPassword` selector in the WelcomeModal.ce.vue component is intentionally looking for an element that exists in the Unraid OS login page (.login.php), not within the component itself. This is used as part of a font-size adjustment workaround to handle different CSS between login and authenticated pages.
api/src/unraid-api/graph/resolvers/backup/source/script/script-source-processor.service.ts (1)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
api/src/unraid-api/graph/resolvers/backup/backup.resolver.ts (6)
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:87-89
Timestamp: 2024-11-06T20:59:06.096Z
Learning: Error handling in mutations like `addRoleForUser` in `auth.resolver.ts` is performed at the service level, so additional error handling in the resolver is unnecessary.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
Learnt from: pujitm
PR: unraid/api#1352
File: packages/unraid-api-plugin-connect/src/connect.resolver.ts:14-24
Timestamp: 2025-04-21T18:04:56.755Z
Learning: Error handling in GraphQL resolvers: pujitm prefers to let errors bubble up naturally to the client rather than adding explicit try/catch blocks in each resolver method.
api/src/unraid-api/graph/resolvers/rclone/rclone-status.service.test.ts (13)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Mock external services and API calls in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Test async operations completely in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Mock external dependencies and services in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify state changes by updating the store in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Mock external dependencies appropriately in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify state changes after actions in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Test getter dependencies are properly mocked in store tests
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/**/*.{test,spec}.{ts,js} : Test suite is VITEST, do not use jest in the API package
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Verify proper error handling in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Test action side effects and state changes in store tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Applies to api/**/*.{test,spec}.{js,ts,tsx} : Test suite is VITEST, do not use jest
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Applies to api/**/*.{test,spec}.{js,ts,tsx} : Prefer to not mock simple dependencies in tests
Learnt from: elibosley
PR: unraid/api#1063
File: web/_data/serverState.ts:137-147
Timestamp: 2025-01-27T14:57:46.617Z
Learning: The values in `web/_data/serverState.ts` are used for testing purposes and should remain as hardcoded mock data to facilitate testing different scenarios.
api/src/unraid-api/graph/resolvers/backup/backup-config.service.ts (3)
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom ConfigService implementation that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:33-37
Timestamp: 2025-01-29T16:36:04.777Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations. It includes try/catch blocks, detailed error logging, and safe rollback mechanisms. Individual FileModification implementations (like LogRotateModification) should allow errors to propagate to this service layer rather than handling them internally.
unraid-ui/src/forms/JsonForms.vue (4)
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:199-199
Timestamp: 2025-03-14T16:56:20.520Z
Learning: The JSONForms library has narrow type definitions for interfaces like SchemaBasedCondition that make augmentation difficult. Type assertions (using 'as') are sometimes necessary despite not being ideal from a typing perspective.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
api/src/unraid-api/graph/resolvers/backup/source/zfs/zfs-validation.service.ts (3)
Learnt from: elibosley
PR: unraid/api#1352
File: packages/unraid-api-plugin-connect/src/config.entity.ts:16-26
Timestamp: 2025-04-21T18:44:15.414Z
Learning: For the Unraid API project, class-validator should be used for validation to avoid mismatches between different validation schemas (like Zod).
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:33-37
Timestamp: 2025-01-29T16:36:04.777Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations. It includes try/catch blocks, detailed error logging, and safe rollback mechanisms. Individual FileModification implementations (like LogRotateModification) should allow errors to propagate to this service layer rather than handling them internally.
Learnt from: elibosley
PR: unraid/api#1352
File: packages/unraid-api-plugin-connect/src/config.entity.ts:37-39
Timestamp: 2025-04-21T18:44:24.383Z
Learning: The project prefers using class-validator decorators directly on entity classes rather than separate Zod schemas to maintain type consistency between GraphQL entities and validation rules.
web/components/Backup/BackupJobItem.vue (4)
Learnt from: pujitm
PR: unraid/api#941
File: web/components/Notifications/Item.vue:0-0
Timestamp: 2024-11-01T17:52:55.311Z
Learning: In the `web/components/Notifications/Item.vue` component, ensure that when delete or archive mutations fail, the notification remains displayed, and an error message is shown below the action buttons to inform the user.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-24
Timestamp: 2024-12-09T15:47:29.325Z
Learning: In our Nuxt setup using Vue.js, components defined within the codebase are autoloaded and do not require explicit import statements in the script section. For example, components like `TabsList` and `TabsTrigger` used in `web/components/Notifications/TabList.vue` are automatically available without imports.
Learnt from: mdatelle
PR: unraid/api#1122
File: web/components/UserProfile/DropdownLaunchpad.vue:38-42
Timestamp: 2025-02-06T17:24:58.784Z
Learning: In the DropdownLaunchpad.vue component, the current implementation of conditional icon rendering using `h(BrandLoading, { variant: 'white' })` is a temporary fix to maintain build stability, with a proper refactoring being handled in a separate branch.
api/src/unraid-api/graph/resolvers/rclone/rclone-status.service.ts (1)
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:33-37
Timestamp: 2025-01-29T16:36:04.777Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations. It includes try/catch blocks, detailed error logging, and safe rollback mechanisms. Individual FileModification implementations (like LogRotateModification) should allow errors to propagate to this service layer rather than handling them internally.
api/src/unraid-api/graph/resolvers/backup/backup-mutations.resolver.ts (9)
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:87-89
Timestamp: 2024-11-06T20:59:06.096Z
Learning: Error handling in mutations like `addRoleForUser` in `auth.resolver.ts` is performed at the service level, so additional error handling in the resolver is unnecessary.
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/graphql/schema/types/connect/connect.graphql:142-146
Timestamp: 2025-03-14T16:10:38.562Z
Learning: The updateApiSettings mutation in api/src/unraid-api/graph/connect/connect.resolver.ts is protected with the @UsePermissions decorator that requires UPDATE permission on the CONFIG resource.
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in `.mutation.ts` files
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: pujitm
PR: unraid/api#1352
File: packages/unraid-api-plugin-connect/src/connect.resolver.ts:14-24
Timestamp: 2025-04-21T18:04:56.755Z
Learning: Error handling in GraphQL resolvers: pujitm prefers to let errors bubble up naturally to the client rather than adding explicit try/catch blocks in each resolver method.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.{query.ts,mutation.ts} : All GraphQL under `web/` must follow this naming convention
api/src/unraid-api/graph/resolvers/backup/source/flash/flash-validation.service.ts (2)
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:33-37
Timestamp: 2025-01-29T16:36:04.777Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations. It includes try/catch blocks, detailed error logging, and safe rollback mechanisms. Individual FileModification implementations (like LogRotateModification) should allow errors to propagate to this service layer rather than handling them internally.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:39-41
Timestamp: 2025-01-29T16:35:43.699Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations, including detailed error logging with stack traces and modification IDs. Individual FileModification implementations should focus on their core functionality without duplicating error handling.
api/src/unraid-api/graph/resolvers/rclone/rclone.model.ts (7)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
Learnt from: elibosley
PR: unraid/api#1352
File: packages/unraid-api-plugin-connect/src/config.entity.ts:37-39
Timestamp: 2025-04-21T18:44:24.383Z
Learning: The project prefers using class-validator decorators directly on entity classes rather than separate Zod schemas to maintain type consistency between GraphQL entities and validation rules.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:199-199
Timestamp: 2025-03-14T16:56:20.520Z
Learning: The JSONForms library has narrow type definitions for interfaces like SchemaBasedCondition that make augmentation difficult. Type assertions (using 'as') are sometimes necessary despite not being ideal from a typing perspective.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.{query.ts,mutation.ts} : All GraphQL under `web/` must follow this naming convention
api/src/unraid-api/graph/resolvers/backup/source/backup-source.types.ts (2)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
web/components/Backup/backup-jobs.query.ts (7)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.query.ts : GraphQL queries must be placed in `.query.ts` files
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in `.mutation.ts` files
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.{query.ts,mutation.ts} : All GraphQL under `web/` must follow this naming convention
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/**/*.query.ts : GraphQL queries must be placed in .query.ts files under web/
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in .mutation.ts files under web/
web/composables/gql/graphql.ts (11)

undefined

<retrieved_learning>
Learnt from: pujitm
PR: #1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
</retrieved_learning>

<retrieved_learning>
Learnt from: elibosley
PR: #942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
</retrieved_learning>

<retrieved_learning>
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
</retrieved_learning>

<retrieved_learning>
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.{query.ts,mutation.ts} : All GraphQL under web/ must follow this naming convention
</retrieved_learning>

<retrieved_learning>
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Applies to web/**/*.mutation.ts : GraphQL mutations must be placed in .mutation.ts files
</retrieved_learning>

<retrieved_learning>
Learnt from: pujitm
PR: #1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
</retrieved_learning>

<retrieved_learning>
Learnt from: pujitm
PR: #941
File: web/components/Notifications/Item.vue:0-0
Timestamp: 2024-11-01T17:52:55.311Z
Learning: In the web/components/Notifications/Item.vue component, ensure that when delete or archive mutations fail, the notification remains displayed, and an error message is shown below the action buttons to inform the user.
</retrieved_learning>

<retrieved_learning>
Learnt from: elibosley
PR: #1101
File: api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch:24-27
Timestamp: 2025-01-31T22:01:22.708Z
Learning: The Unraid UI uses a modern notification system with a custom unraid-toaster component replacing the legacy jGrowl notifications. The system is backed by a comprehensive GraphQL API with real-time subscription support for notification updates.
</retrieved_learning>

<retrieved_learning>
Learnt from: pujitm
PR: #1075
File: web/components/Notifications/Sidebar.vue:52-57
Timestamp: 2025-01-30T19:56:42.055Z
Learning: Notification links in the Unraid API are validated at creation time on the server side, making additional client-side validation unnecessary when receiving notifications through GraphQL subscriptions.
</retrieved_learning>

<retrieved_learning>
Learnt from: mdatelle
PR: #942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts, methods like removeRoleFromApiKey rely on service-level error handling.
</retrieved_learning>

<retrieved_learning>
Learnt from: elibosley
PR: #1120
File: plugin/package.json:0-0
Timestamp: 2025-02-05T14:43:48.568Z
Learning: In Node.js projects, npm scripts should be organized with clear namespacing (e.g., build:, docker:, env:*) and include proper environment validation and error handling. Each script should follow the single responsibility principle.
</retrieved_learning>

api/src/unraid-api/graph/resolvers/backup/backup.model.ts (5)
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:41-47
Timestamp: 2024-11-05T14:48:56.949Z
Learning: Input types for GraphQL mutations can be pulled from the GraphQL codegen types, as they are generated into the API files. Therefore, explicit typing in the resolver files may be unnecessary.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: All GraphQL under web/ must follow this naming convention (.query.ts for queries, .mutation.ts for mutations)
api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts (6)
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:33-37
Timestamp: 2025-01-29T16:36:04.777Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations. It includes try/catch blocks, detailed error logging, and safe rollback mechanisms. Individual FileModification implementations (like LogRotateModification) should allow errors to propagate to this service layer rather than handling them internally.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/auth/api-key.service.ts:62-70
Timestamp: 2024-11-05T14:49:07.308Z
Learning: In `api/src/unraid-api/auth/api-key.service.ts`, when handling read errors in the `findById` method, throw a `GraphQLError` instead of an `InternalServerErrorException`.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:39-41
Timestamp: 2025-01-29T16:35:43.699Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations, including detailed error logging with stack traces and modification IDs. Individual FileModification implementations should focus on their core functionality without duplicating error handling.
Learnt from: elibosley
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
🧬 Code Graph Analysis (16)
api/src/unraid-api/main.ts (1)
api/src/environment.ts (1)
  • LOG_LEVEL (88-92)
api/src/unraid-api/graph/resolvers/rclone/rclone.mutation.resolver.ts (1)
api/src/unraid-api/graph/resolvers/rclone/rclone.model.ts (1)
  • RCloneRemoteConfig (58-61)
api/src/unraid-api/graph/resolvers/mutation/mutation.resolver.ts (1)
web/composables/gql/graphql.ts (2)
  • Mutation (1130-1164)
  • BackupMutations (451-471)
api/src/unraid-api/utils/utils.module.ts (2)
api/src/unraid-api/graph/utils/utils.module.ts (1)
  • Global (5-10)
api/src/unraid-api/graph/resolvers/resolvers.module.ts (1)
  • Module (38-79)
api/src/unraid-api/graph/resolvers/backup/source/backup-source.module.ts (3)
api/src/unraid-api/graph/resolvers/backup/backup.module.ts (1)
  • Module (17-30)
api/src/unraid-api/graph/resolvers/rclone/rclone.module.ts (1)
  • Module (12-24)
api/src/unraid-api/graph/resolvers/backup/destination/backup-destination.module.ts (1)
  • Module (8-13)
api/src/unraid-api/graph/resolvers/backup/destination/backup-destination.module.ts (2)
api/src/unraid-api/graph/resolvers/backup/backup.module.ts (1)
  • Module (17-30)
api/src/unraid-api/graph/resolvers/backup/source/backup-source.module.ts (1)
  • Module (11-30)
api/src/unraid-api/graph/utils/utils.module.ts (3)
api/src/unraid-api/utils/utils.module.ts (1)
  • Global (5-10)
api/src/unraid-api/graph/resolvers/resolvers.module.ts (1)
  • Module (38-79)
api/src/unraid-api/graph/resolvers/rclone/rclone.module.ts (1)
  • Module (12-24)
api/src/unraid-api/graph/resolvers/backup/backup.module.ts (4)
api/src/unraid-api/graph/resolvers/backup/source/backup-source.module.ts (1)
  • Module (11-30)
api/src/unraid-api/graph/resolvers/flash-backup/flash-backup.module.ts (1)
  • Module (6-11)
api/src/unraid-api/graph/resolvers/rclone/rclone.module.ts (1)
  • Module (12-24)
api/src/unraid-api/graph/resolvers/backup/destination/backup-destination.module.ts (1)
  • Module (8-13)
api/src/unraid-api/graph/resolvers/backup/source/backup-source-jsonforms.config.ts (2)
api/src/unraid-api/types/json-forms.ts (2)
  • SettingSlice (38-46)
  • UIElement (22-24)
api/src/unraid-api/graph/utils/form-utils.ts (1)
  • createLabeledControl (6-46)
api/src/unraid-api/graph/resolvers/backup/destination/backup-destination-jsonforms.config.ts (4)
web/composables/gql/graphql.ts (1)
  • RCloneRemote (1654-1661)
api/src/unraid-api/types/json-forms.ts (2)
  • SettingSlice (38-46)
  • UIElement (22-24)
api/src/unraid-api/graph/utils/form-utils.ts (1)
  • createLabeledControl (6-46)
api/src/unraid-api/graph/resolvers/rclone/rclone.resolver.ts (1)
  • remotes (57-64)
web/composables/gql/gql.ts (1)
api/src/graphql/generated/client/gql.ts (1)
  • graphql (54-56)
api/src/unraid-api/graph/resolvers/rclone/rclone-status.service.test.ts (1)
web/composables/gql/graphql.ts (1)
  • RCloneJobStats (1569-1631)
api/src/unraid-api/graph/resolvers/backup/source/zfs/zfs-validation.service.ts (2)
api/src/unraid-api/graph/resolvers/backup/source/zfs/zfs-source-processor.service.ts (1)
  • Injectable (23-139)
api/src/unraid-api/graph/resolvers/backup/source/backup-source.types.ts (1)
  • ZfsPreprocessConfigInput (36-36)
api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source-processor.service.ts (1)
api/src/unraid-api/graph/resolvers/backup/source/backup-source-processor.interface.ts (3)
  • BackupSourceConfig (5-8)
  • BackupSourceProcessorOptions (26-32)
  • BackupSourceResult (10-24)
api/src/unraid-api/graph/resolvers/backup/source/backup-source.types.ts (6)
api/src/unraid-api/graph/resolvers/backup/backup.model.ts (10)
  • InputType (44-68)
  • InputType (135-175)
  • InputType (177-188)
  • InputType (190-206)
  • InputType (220-226)
  • ObjectType (33-42)
  • ObjectType (70-82)
  • ObjectType (84-88)
  • ObjectType (90-133)
  • ObjectType (208-218)
api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source.types.ts (2)
  • InputType (10-24)
  • ObjectType (26-43)
api/src/unraid-api/graph/resolvers/backup/source/raw/raw-source.types.ts (2)
  • InputType (10-26)
  • ObjectType (28-45)
api/src/unraid-api/graph/resolvers/backup/source/script/script-source.types.ts (2)
  • InputType (11-38)
  • ObjectType (40-63)
api/src/unraid-api/graph/resolvers/backup/source/zfs/zfs-source.types.ts (2)
  • InputType (10-39)
  • ObjectType (41-64)
web/composables/gql/graphql.ts (10)
  • SourceConfigInput (1909-1919)
  • ZfsPreprocessConfigInput (2386-2399)
  • FlashPreprocessConfigInput (937-946)
  • ScriptPreprocessConfigInput (1812-1825)
  • RawBackupConfigInput (1671-1680)
  • ZfsPreprocessConfig (2376-2384)
  • FlashPreprocessConfig (929-935)
  • ScriptPreprocessConfig (1802-1810)
  • RawBackupConfig (1663-1669)
  • SourceConfigUnion (1921-1921)
web/components/Backup/backup-jobs.query.ts (1)
web/composables/gql/gql.ts (1)
  • graphql (360-362)
🪛 Biome (1.9.4)
api/src/unraid-api/graph/resolvers/backup/source/backup-source-jsonforms.config.ts

[error] 448-448: Do not add then to an object.

(lint/suspicious/noThenProperty)


[error] 459-459: Do not add then to an object.

(lint/suspicious/noThenProperty)


[error] 470-470: Do not add then to an object.

(lint/suspicious/noThenProperty)


[error] 481-481: Do not add then to an object.

(lint/suspicious/noThenProperty)

api/src/unraid-api/graph/resolvers/backup/destination/backup-destination-jsonforms.config.ts

[error] 163-163: Do not add then to an object.

(lint/suspicious/noThenProperty)

api/src/unraid-api/graph/resolvers/backup/destination/backup-destination.types.ts

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

api/src/unraid-api/graph/resolvers/backup/orchestration/backup-job-tracking.service.ts

[error] 14-16: This constructor is unnecessary.

Unsafe fix: Remove the unnecessary constructor.

(lint/complexity/noUselessConstructor)

api/src/unraid-api/graph/resolvers/backup/backup-config.service.ts

[error] 400-400: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

api/src/unraid-api/graph/resolvers/backup/destination/rclone/rclone-destination-processor.service.ts

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

api/src/unraid-api/graph/resolvers/backup/source/backup-source.types.ts

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (94)
api/.eslintrc.ts (1)

56-56: LGTM! Consider script complexity growth over time.

The addition of 'scripts/**/*' to the ignore list is appropriate for utility scripts that typically don't need strict linting rules. This aligns well with the existing pattern of ignoring generated code.

Consider monitoring script complexity - if scripts grow substantial, targeted linting rules might be beneficial for maintainability.

api/dev/configs/api.json (1)

9-11: Good formatting improvement.

The multi-line array format improves readability and is easier to maintain.

unraid-ui/src/forms/SteppedLayout.vue (3)

19-19: Good addition of Vue lifecycle imports.

The import of onMounted and nextTick is appropriate for the initialization logic added below.


49-59: Simplified currentStep logic improves maintainability.

The removal of fallback handling for the old numeric format and focus on the new object format aligns with the standardization effort. The logic is cleaner and more predictable.


61-73: Excellent initialization pattern with proper async handling.

The onMounted hook with nextTick ensures the form data is available before initialization. The conditional check prevents overwriting existing valid data while fixing improperly formatted data.

packages/unraid-api-plugin-connect/src/unraid-connect/connect-settings.resolver.ts (1)

6-6: LGTM - Import reordering is harmless.

This is a simple import reordering with no functional impact.

packages/unraid-shared/src/graphql.model.ts (1)

13-13: LGTM - Proper enum extension for backup permissions.

The BACKUP resource is correctly added to the enum, maintaining alphabetical order and consistent naming conventions.

api/src/unraid-api/auth/auth.service.ts (2)

78-78: LGTM - Appropriate logging level adjustment.

Changing from debug to verbose for user role reporting is appropriate for operational visibility.


216-220: LGTM - Consistent logging level adjustment.

The change from debug to verbose for role sync reporting maintains consistency with other logging adjustments.

unraid-ui/src/forms/StringArrayField.vue (1)

44-44: LGTM - Good UX enhancement with security consideration.

Adding field descriptions improves user experience. The conditional rendering is appropriate.

Note: Using v-html requires ensuring the description content is sanitized to prevent XSS attacks.

api/src/unraid-api/graph/resolvers/rclone/rclone.mutation.resolver.ts (2)

17-17: Good addition of RCloneRemoteConfig import.

This import supports the type safety improvement in the createRCloneRemote method.


42-42: Excellent type safety improvement.

The explicit cast to RCloneRemoteConfig ensures type consistency with the interface requirements and improves code reliability.

api/src/store/modules/paths.ts (1)

74-74: Well-structured backup base path addition.

The new backupBase property follows the established pattern with environment variable support and sensible fallback. This properly integrates the backup functionality into the paths configuration.

api/.env.development (2)

18-18: Appropriate backup jobs path configuration.

The PATHS_BACKUP_JOBS environment variable properly supports the new backup functionality with a sensible development path.


30-30: Sensible log level adjustment.

Changing from trace to debug improves development experience by reducing noise while maintaining adequate logging detail. The explanatory comment is helpful.

api/src/unraid-api/main.ts (1)

22-22: Proper alignment with environment configuration.

The condition change from 'TRACE' to 'DEBUG' correctly aligns with the updated LOG_LEVEL default in the environment configuration, ensuring consistent logging behavior.

api/src/unraid-api/graph/resolvers/resolvers.module.ts (3)

6-6: Proper BackupModule integration.

The import correctly integrates the new backup functionality into the resolvers module.


36-36: Good UtilsModule addition.

The UtilsModule import provides necessary utilities for the backup system and other resolvers.


40-44: Excellent module organization.

Both UtilsModule and BackupModule are properly added to the imports array, following the established pattern and enabling the comprehensive backup functionality.

unraid-ui/src/forms/renderers.ts (1)

77-80: LGTM! Consistent renderer pattern for checkbox format.

The addition properly extends boolean control rendering to support checkbox format while maintaining consistency with existing toggle format renderers.

web/components/RClone/RCloneOverview.vue (2)

66-66: Initialization correctly updated to match new interface.

The initialization properly reflects the new object structure with both current and total properties.


13-13: All usages of configStep have been migrated to the object shape

  • JSON resolvers now initialise configStep as { current: number; total: number } in both backup (backup-jsonforms-config.ts) and rclone (rclone.service.ts).
  • SteppedLayout.vue normalises any legacy numeric values into the new object format on mount.
  • BackupJobConfigForm.vue and RCloneConfig.vue access configStep.current (and ignore raw numbers, relying on SteppedLayout for migration).
  • No remaining references treat configStep as a bare number.

No further changes required.

web/pages/flash-backup.vue (1)

14-16: Mock session cookie is appropriate for development.

The mock session cookie setup is correctly placed in the onMounted lifecycle hook for development testing purposes.

api/src/unraid-api/graph/resolvers/mutation/mutation.resolver.ts (2)

6-6: Import follows established pattern.

The BackupMutations import is properly added alongside other mutation imports.


31-34: Backup mutation properly implemented.

The backup mutation follows the same pattern as other mutations with correct GraphQL decorators and return type.

api/src/unraid-api/utils/utils.module.ts (1)

1-10: Well-structured global utility module.

The module follows NestJS best practices with proper @Global() decorator and service exports. This pattern ensures the FormatService is available throughout the application without explicit imports.

web/helpers/apollo-cache/index.ts (1)

42-64: LGTM!

The cache policies follow the existing patterns and appropriately use simple merge functions that replace existing data with incoming data. This is suitable for backup-related queries where fresh data should replace cached data.

api/src/unraid-api/graph/resolvers/mutation/mutation.model.ts (2)

22-25: LGTM!

The BackupMutations class follows the established pattern for mutation types in this file.


59-61: LGTM!

The integration of BackupMutations into RootMutations follows the established pattern and is properly decorated.

api/src/unraid-api/graph/resolvers/backup/source/backup-source.module.ts (1)

21-29: Verify export consistency for validation services.

FlashValidationService is provided but not exported, while ZfsValidationService is both provided and exported. Ensure this is intentional and not an oversight.

api/src/unraid-api/utils/format.service.test.ts (1)

1-6: LGTM!

The test setup properly uses vitest and follows the established testing patterns.

web/components/RClone/RCloneConfig.vue (4)

26-29: Clean interface definition for step tracking.

The ConfigStep interface provides clear structure for step management, improving type safety over the previous union type approach.


33-33: Consistent object format initialization.

The initialization now uses the standardized object format, eliminating the need for type checking elsewhere in the code.


59-60: Improved type casting with interface.

The type casting now uses the defined ConfigStep interface, providing better type safety and IntelliSense support.


177-178: Simplified computed property logic.

The computed property now directly accesses the object properties without needing to handle union types, making the code more readable.

api/src/__test__/graphql/resolvers/rclone-api.service.test.ts (3)

14-14: Added FormatService import for new dependency.

The import correctly includes the FormatService which is now a dependency of the service under test.


85-101: Comprehensive mock for RCloneStatusService.

The mock properly stubs all the methods that the enhanced RCloneStatusService provides, ensuring isolated testing of the service.


118-118: Updated constructor with mocked dependencies.

The service constructor now correctly uses the mocked RCloneStatusService, maintaining test isolation.

api/src/unraid-api/graph/resolvers/backup/backup.module.ts (3)

18-18: Well-structured module imports.

The imports properly bring in all necessary modules for backup functionality, including scheduling and RClone integration.


19-27: Comprehensive provider setup.

The providers array includes all necessary services and resolvers for complete backup management functionality.


28-28: Appropriate use of forwardRef for circular dependencies.

The forwardRef usage for BackupOrchestrationService properly handles circular dependency resolution.

api/src/unraid-api/graph/resolvers/rclone/rclone.module.ts (4)

3-3: Added BackupSourceModule integration.

The import with forwardRef properly handles circular dependencies while integrating RClone with the backup source processing.


10-10: Added UtilsModule for formatting services.

The UtilsModule import provides access to FormatService, which is used by RCloneStatusService for formatting job statistics.


17-17: Added RCloneStatusService to providers.

The new service is properly registered in the providers array for dependency injection.


22-22: Exported RCloneStatusService for other modules.

The service is properly exported, making it available for use in other modules like the backup destination module.

api/src/unraid-api/graph/resolvers/backup/source/base-source.types.ts (1)

5-14: LGTM: Well-structured base type definition.

The abstract class approach with proper GraphQL decorators and validation is excellent for creating a type hierarchy.

api/src/unraid-api/graph/resolvers/rclone/rclone.service.ts (3)

8-8: LGTM: Import updated for new functionality.

The addition of RCloneJob import supports the new enhanced job status method.


14-14: LGTM: Improved step tracking structure.

Changing configStep from a simple number to an object with current and total provides better granularity for tracking configuration progress.


129-134: LGTM: Clean delegation to API service.

The new getEnhancedJobStatus method properly delegates to the underlying API service with appropriate parameter handling.

api/dev/api/backup/backup-jobs.json (1)

2-24: LGTM: Comprehensive backup job configuration.

The JSON structure includes all necessary fields for backup job management including scheduling, source/destination configs, and metadata tracking.

web/layouts/default.vue (2)

2-2: LGTM: Clean import optimization.

Removing unused Vue composition API imports and keeping only necessary NuxtLink improves code cleanliness.


10-11: LGTM: Improved architecture with server-side route generation.

Moving route generation from client-side computation to server-side API fetching is more maintainable and aligns with the new backend-driven route system.

api/src/unraid-api/graph/resolvers/backup/orchestration/backup-job-status.resolver.ts (3)

8-11: LGTM: Proper GraphQL resolver structure.

The resolver follows correct NestJS GraphQL patterns with appropriate dependency injection and decorator usage.


12-23: LGTM: Appropriate null handling strategy.

Returning null instead of throwing an exception for missing job status is appropriate for GraphQL queries, allowing clients to handle the absence gracefully.


25-29: LGTM: Clean implementation for bulk query.

The getAllJobStatuses method provides a straightforward way to retrieve all job statuses with proper type handling.

web/components/Backup/BackupEntry.vue (1)

23-23: Missing import for computed.

The computed function is used but not imported from Vue.

-import { computed } from 'vue';
+import { computed } from 'vue';

Wait, I see computed is imported on line 6. Let me check if there are other issues.

api/src/unraid-api/graph/resolvers/backup/backup.utils.ts (1)

1-33: Clean utility functions with proper documentation.

The implementation is well-structured with clear function names, proper TypeScript typing, and comprehensive JSDoc comments. The functions follow the single responsibility principle and provide a clean API for backup job group ID management.

web/components/Backup/BackupOverview.vue (3)

14-21: Good Apollo GraphQL integration with polling.

The query setup with cache-and-network fetch policy and 5-second polling interval is appropriate for real-time backup job monitoring.


66-98: Excellent loading and error state handling.

The component provides clear feedback for loading, error, and empty states with appropriate UI elements and messaging.


1-2: Missing import for computed function.

The computed function is used on line 23 but not imported from Vue.

-import { ref } from 'vue';
+import { ref, computed } from 'vue';
⛔ Skipped due to learnings
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-4
Timestamp: 2024-12-09T15:45:46.492Z
Learning: In our Nuxt.js setup for the `web` project, it's not necessary to explicitly import `computed` from `vue` in Vue components, as it's globally available.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Ensure Vue reactivity imports are added to original store files as they may be missing because Nuxt auto import was turned on
Learnt from: elibosley
PR: unraid/api#972
File: web/components/ColorSwitcher.ce.vue:1-2
Timestamp: 2024-12-17T13:55:42.068Z
Learning: In this Nuxt.js project, components used in templates are automatically imported by Nuxt, so explicit import statements for components are unnecessary.
Learnt from: elibosley
PR: unraid/api#974
File: web/components/Loading/Error.vue:1-3
Timestamp: 2024-12-06T17:38:40.999Z
Learning: In Nuxt.js projects, components are automatically imported, so explicit import statements for components like `LoadingSpinner` in `web/components/Loading/Error.vue` are not necessary.
Learnt from: pujitm
PR: unraid/api#974
File: web/components/Loading/Error.vue:50-50
Timestamp: 2024-12-06T17:34:16.133Z
Learning: In this project, the `Button` component from `~/components/shadcn/Button.vue` is autoloaded and does not need to be imported manually in components like `web/components/Loading/Error.vue`.
Learnt from: pujitm
PR: unraid/api#1417
File: web/components/ConnectSettings/ConnectSettings.ce.vue:11-18
Timestamp: 2025-06-13T17:14:21.739Z
Learning: The project’s build tooling auto-imports common Vue/Pinia helpers such as `storeToRefs`, so explicit import statements for them are not required.
Learnt from: pujitm
PR: unraid/api#974
File: web/components/Notifications/List.vue:31-31
Timestamp: 2024-12-06T14:43:04.876Z
Learning: In the Vue.js application using `useQuery` from Vue Apollo, the `error` reactive variable captures errors from both the initial query and any `fetchMore` calls, so wrapping `fetchMore` in a try-catch block is unnecessary.
Learnt from: pujitm
PR: unraid/api#975
File: web/components/Notifications/TabList.vue:1-24
Timestamp: 2024-12-09T15:47:29.325Z
Learning: In our Nuxt setup using Vue.js, components defined within the codebase are autoloaded and do not require explicit import statements in the script section. For example, components like `TabsList` and `TabsTrigger` used in `web/components/Notifications/TabList.vue` are automatically available without imports.
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Use `mount` from Vue Test Utils for component testing
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Avoid relying on Nuxt's auto-imports in test environment
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Don't rely on Nuxt auto-imports in tests
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Set initial state for focused testing in store tests
web/components/Backup/BackupJobConfig.vue (3)

1-46: Well-structured component with good separation of concerns.

The component properly manages state, handles GraphQL operations, and delegates specific functionality to child components. The modal implementation and event handling are clean and follow Vue 3 best practices.


14-21: Appropriate polling interval for configurations.

The 50-second polling interval is reasonable for backup configurations that change less frequently than job status.


55-92: Excellent user experience with proper loading and empty states.

The component provides clear visual feedback for different states and includes helpful messaging and call-to-action buttons for users.

api/src/unraid-api/graph/resolvers/backup/source/backup-source-jsonforms.config.ts (2)

443-491: Static analysis warnings are false positives - this is valid JSON Schema conditional logic.

The then property warnings from Biome are incorrect. This code uses standard JSON Schema conditional logic (allOf with if/then patterns) which is the proper way to implement conditional validation in JSON Forms. The logic correctly ensures that only the relevant configuration object is required based on the selected backup type.


8-503: Well-structured JSON Forms configuration with comprehensive source type support.

The implementation provides a complete configuration slice for all backup source types with proper validation, UI elements, and conditional logic. The separation between UI elements and schema definitions is clean and maintainable.

api/src/unraid-api/graph/resolvers/backup/destination/backup-destination-jsonforms.config.ts (2)

163-163: Static analysis warning is a false positive - this is valid JSON Schema conditional logic.

The then property warning from Biome is incorrect. This is standard JSON Schema conditional validation syntax used in JSON Forms.


9-180: Excellent RClone integration with dynamic remote suggestions.

The implementation effectively integrates with RClone remotes to provide dynamic dropdown suggestions, making the configuration user-friendly. The conditional schema logic properly enforces RClone configuration requirements.

api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source.types.ts (1)

10-43: Clean GraphQL type definitions with proper validation.

The implementation follows NestJS and GraphQL best practices with appropriate validation decorators and a useful type guard method. The default values and field descriptions enhance developer experience.

api/src/unraid-api/graph/resolvers/backup/source/raw/raw-source.types.ts (1)

10-45: Consistent and well-structured GraphQL type definitions.

The implementation follows the same excellent patterns as other source types with appropriate validation for raw backup configurations. The include/exclude patterns provide flexible backup control.

api/src/unraid-api/graph/resolvers/backup/orchestration/backup-job-tracking.service.ts (2)

14-16: Constructor is intentionally present for future functionality.

The static analysis warning is a false positive. The constructor contains a comment indicating potential future functionality for loading persisted jobs, making it intentionally present.


8-119: Well-designed job tracking service with comprehensive status management.

The service provides robust job tracking with proper error handling, logging, and state management. The dual mapping approach (internal/external IDs) enables flexible job identification, and the status update logic handles terminal states correctly.

api/src/unraid-api/graph/resolvers/backup/source/script/script-source.types.ts (1)

1-63: LGTM!

The GraphQL types are well-structured with proper validation decorators and field definitions. The type guard implementation is clean and effective.

api/src/unraid-api/graph/resolvers/backup/source/zfs/zfs-source.types.ts (1)

1-64: LGTM!

The ZFS source types are properly structured with appropriate validation constraints. The type guard correctly validates the required fields.

api/src/unraid-api/graph/resolvers/backup/orchestration/backup-job-status.model.ts (1)

1-76: LGTM!

Well-structured GraphQL model with comprehensive status tracking fields. The inclusion of both raw and formatted values provides flexibility for clients.

unraid-ui/src/forms/JsonForms.vue (1)

1-62: Well-structured JsonForms wrapper component.

The component correctly wraps the base JsonForms with appropriate type definitions and Ajv configuration.

web/composables/gql/gql.ts (1)

26-364: Generated GraphQL code additions look correct.

The new backup-related fragments, queries, and mutations follow the established patterns and align with the GraphQL schema additions.

api/src/unraid-api/graph/resolvers/backup/backup.resolver.ts (1)

31-40: Root resolver implementation looks good

The hardcoded return values are appropriate for a root resolver that uses field resolvers.

api/src/unraid-api/graph/resolvers/backup/source/raw/raw-source-processor.service.ts (1)

98-139: Excellent validation implementation

The validation logic includes important security checks for restricted paths and helpful warnings for large directories.

api/src/unraid-api/graph/resolvers/backup/jsonforms/backup-jsonforms-config.ts (1)

29-69: Excellent cron expression suggestions

The variety of pre-configured cron patterns with clear descriptions provides great user experience.

api/src/unraid-api/graph/resolvers/rclone/rclone-status.service.ts (1)

35-101: Well-implemented statistics formatting

The method comprehensively handles all edge cases and provides consistent formatting for various statistics.

api/src/unraid-api/graph/resolvers/backup/source/zfs/zfs-validation.service.ts (1)

25-103: Comprehensive ZFS validation logic

The validation includes all necessary checks for safe ZFS operations including space validation and snapshot management warnings.

api/src/unraid-api/graph/resolvers/rclone/rclone-status.service.test.ts (1)

1-506: LGTM! Comprehensive test coverage.

The test suite is well-structured with good coverage of all public methods, edge cases, and error scenarios. Proper use of vitest and appropriate mocking.

api/src/unraid-api/graph/resolvers/backup/source/backup-source-processor.interface.ts (1)

1-53: LGTM! Well-designed interface for backup source processing

The abstract class and interface definitions provide a clear contract with good separation of concerns. The flexible design with optional streaming support and metadata handling allows for diverse implementations.

api/src/unraid-api/graph/resolvers/rclone/rclone.model.ts (1)

152-164: LGTM! Good enhancement for async backup support

The addition of async and configId fields enables better job management and tracking.

api/src/unraid-api/graph/resolvers/backup/source/flash/flash-validation.service.ts (1)

1-260: LGTM! Comprehensive validation service

Excellent implementation with thorough validation checks, proper error handling, and useful warnings. The service provides detailed metadata for debugging and user feedback.

web/components/Backup/backup-jobs.query.ts (1)

1-229: Well-structured GraphQL queries and mutations

The file correctly follows the naming convention for GraphQL queries (.query.ts) and properly uses the graphql composable function as per project standards.

api/src/unraid-api/graph/resolvers/backup/destination/backup-destination-processor.interface.ts (1)

1-60: Clean interface definitions

Well-structured interfaces and abstract class for backup destination processors.

api/generated-schema.graphql (2)

712-713: Verify the need for two date-time scalar types

The schema now has both DateTime and DateTimeISO scalars. This could cause confusion for API consumers.

Please verify whether both scalars are necessary and consider:

  1. Documenting the specific use cases for each
  2. Consolidating to a single date-time scalar if possible
  3. Adding clear descriptions to differentiate their purposes

Also applies to: 1329-1331


601-601: LGTM!

The BACKUP resource is correctly added to the enum in alphabetical order.

api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts (2)

461-476: Excellent defensive programming!

The safety checks to prevent job explosion and performance issues are well-implemented with clear logging.


156-186: Well-designed authentication logic

The conditional authentication based on socket type is correctly implemented. Unix sockets properly use --rc-no-auth since they rely on OS-level security.

web/composables/gql/graphql.ts (3)

21-22: DateTimeISO scalar properly defined.

The new ISO 8601 date-time scalar is well-documented and follows GraphQL scalar conventions.


390-523: Comprehensive backup schema implementation.

The backup-related types are well-structured with proper field definitions, nullable types, and clear relationships between entities. The schema supports flexible backup configurations through union types for sources and destinations.


1140-1140: Backup integration into root types.

The backup functionality is properly integrated into the GraphQL schema:

  • Mutation type includes backup field (line 1140)
  • Query type includes all necessary backup queries (lines 1445-1461)
  • BACKUP resource added to permissions enum (line 1765)

Also applies to: 1445-1461, 1765-1765

@@ -1,5 +1,5 @@
[api]
version="4.4.1"
version="4.8.0"
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Version update looks good, but verify consistency across configs.

The version bump to 4.8.0 aligns with the new backup management features. However, ensure this version is consistent with other configuration files in the codebase.


🏁 Script executed:

#!/bin/bash
# Description: Check for version consistency across configuration files
# Expected: All config files should have aligned versions for this release

echo "=== Configuration file versions ==="
fd -e cfg -e json . api/dev/ --exec grep -H "version" {} \;

Length of output: 380


Unify version fields across all dev configs

The bump to 4.8.0 in api/dev/Unraid.net/myservers.cfg (and api/dev/states/myservers.cfg) is correct, but I found these mismatches:

  • api/dev/Unraid.net/myservers.example.cfg: still at 4.4.1 → update to 4.8.0
  • api/dev/dynamix/default.cfg: version is empty → set to 4.8.0

The overall API config in api/dev/configs/api.json remains at 4.9.5; please confirm if that should align with the myservers release or stay as-is.
Once these are synced, the version will be consistent across the codebase.

🤖 Prompt for AI Agents
In api/dev/Unraid.net/myservers.cfg at line 2, the version is correctly set to
4.8.0, but to unify version fields across all dev configs, update the version in
api/dev/Unraid.net/myservers.example.cfg from 4.4.1 to 4.8.0 and set the empty
version field in api/dev/dynamix/default.cfg to 4.8.0. Also, verify whether the
version in api/dev/configs/api.json (currently 4.9.5) should be aligned with
these or remain unchanged.

@@ -1,10 +1,12 @@
{
"version": "4.8.0",
"version": "4.9.5",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Version inconsistency detected across configuration files.

This file shows version 4.9.5 while api/dev/Unraid.net/myservers.cfg shows 4.8.0. Ensure all configuration files use consistent versioning for this release.

🤖 Prompt for AI Agents
In api/dev/configs/api.json at line 2, the version is set to 4.9.5, which is
inconsistent with the version 4.8.0 found in api/dev/Unraid.net/myservers.cfg.
Update the version in api.json to match 4.8.0 to ensure consistent versioning
across configuration files for this release.

import { apiDir } from "./utils/paths";
import { getVendorBundleName, getVendorFullPath } from "./build-vendor-store";
import { getAssetUrl } from "./utils/bucket-urls";
import { ensureRclone } from "./utils/rclone-helper";
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify the import is used.

The ensureRclone function is imported but not called in the visible code. Ensure this import is actually used somewhere in the function.


🏁 Script executed:

#!/bin/bash
# Description: Check if ensureRclone is used in this file
# Expected: Find usage of ensureRclone function in the file

rg "ensureRclone" plugin/builder/build-txz.ts

Length of output: 99


Unused import detected – remove ensureRclone

The ensureRclone function is imported but never referenced in build-txz.ts. Please remove this unused import to keep the code clean.

  • File: plugin/builder/build-txz.ts, line 13:
    import { ensureRclone } from "./utils/rclone-helper";
🤖 Prompt for AI Agents
In plugin/builder/build-txz.ts at line 13, the import statement for
`ensureRclone` is unused. Remove the entire line importing `ensureRclone` from
"./utils/rclone-helper" to clean up the code and avoid unnecessary imports.

import { Args, ResolveField, Resolver } from '@nestjs/graphql';

import { Resource } from '@unraid/shared/graphql.model.js';
import { Resource } from '@unraid/shared/graphql.model';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Restore the .js extension for ESM compatibility.

The coding guidelines specify that TypeScript imports should use .js extensions for ESM compatibility. This change removes the required extension.

-import { Resource } from '@unraid/shared/graphql.model';
+import { Resource } from '@unraid/shared/graphql.model.js';
📝 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
import { Resource } from '@unraid/shared/graphql.model';
import { Resource } from '@unraid/shared/graphql.model.js';
🤖 Prompt for AI Agents
In api/src/unraid-api/graph/resolvers/rclone/rclone.mutation.resolver.ts at line
4, the import statement for Resource is missing the required .js extension for
ESM compatibility. Update the import path to include the .js extension as per
the coding guidelines to ensure proper module resolution.

Comment on lines +48 to +52
it('should format longer durations to best unit', () => {
expect(service.formatDuration(60)).toBe('60 s');
expect(service.formatDuration(3600)).toBe('60 min');
expect(service.formatDuration(86400)).toBe('24 h');
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix inconsistent test expectation.

The test at line 49 expects service.formatDuration(60) to return '60 s', but this is inconsistent with the pattern of converting to larger units. 60 seconds should be formatted as "1 min" to match the behavior expected in the other tests.

Verify the expected behavior and update either the test expectation or the service implementation to be consistent.

🤖 Prompt for AI Agents
In api/src/unraid-api/utils/format.service.test.ts around lines 48 to 52, the
test expects service.formatDuration(60) to return '60 s', which is inconsistent
with the other tests that convert to larger units. Update the test expectation
for 60 seconds to '1 min' to align with the pattern of converting durations to
the best larger unit, or alternatively adjust the service implementation to keep
60 seconds as '60 s' consistently.

Comment on lines +104 to +124
export const SourceConfigUnion = createUnionType({
name: 'SourceConfigUnion',
types: () =>
[ZfsPreprocessConfig, FlashPreprocessConfig, ScriptPreprocessConfig, RawBackupConfig] as const,
resolveType(obj: any, context, info) {
if (ZfsPreprocessConfig.isTypeOf && ZfsPreprocessConfig.isTypeOf(obj)) {
return ZfsPreprocessConfig;
}
if (FlashPreprocessConfig.isTypeOf && FlashPreprocessConfig.isTypeOf(obj)) {
return FlashPreprocessConfig;
}
if (ScriptPreprocessConfig.isTypeOf && ScriptPreprocessConfig.isTypeOf(obj)) {
return ScriptPreprocessConfig;
}
if (RawBackupConfig.isTypeOf && RawBackupConfig.isTypeOf(obj)) {
return RawBackupConfig;
}
console.error(`[SourceConfigUnion] Could not resolve type for object: ${JSON.stringify(obj)}`);
return null;
},
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use logger instead of console.error and apply optional chaining

Replace console.error with proper logging and simplify the type checks:

export const SourceConfigUnion = createUnionType({
    name: 'SourceConfigUnion',
    types: () =>
        [ZfsPreprocessConfig, FlashPreprocessConfig, ScriptPreprocessConfig, RawBackupConfig] as const,
    resolveType(obj: any, context, info) {
-       if (ZfsPreprocessConfig.isTypeOf && ZfsPreprocessConfig.isTypeOf(obj)) {
+       if (ZfsPreprocessConfig.isTypeOf?.(obj)) {
            return ZfsPreprocessConfig;
        }
-       if (FlashPreprocessConfig.isTypeOf && FlashPreprocessConfig.isTypeOf(obj)) {
+       if (FlashPreprocessConfig.isTypeOf?.(obj)) {
            return FlashPreprocessConfig;
        }
-       if (ScriptPreprocessConfig.isTypeOf && ScriptPreprocessConfig.isTypeOf(obj)) {
+       if (ScriptPreprocessConfig.isTypeOf?.(obj)) {
            return ScriptPreprocessConfig;
        }
-       if (RawBackupConfig.isTypeOf && RawBackupConfig.isTypeOf(obj)) {
+       if (RawBackupConfig.isTypeOf?.(obj)) {
            return RawBackupConfig;
        }
-       console.error(`[SourceConfigUnion] Could not resolve type for object: ${JSON.stringify(obj)}`);
+       // Use a proper logger instance here
+       // logger.error(`[SourceConfigUnion] Could not resolve type for object: ${JSON.stringify(obj)}`);
        return null;
    },
});

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

🧰 Tools
🪛 Biome (1.9.4)

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🤖 Prompt for AI Agents
In api/src/unraid-api/graph/resolvers/backup/source/backup-source.types.ts
between lines 104 and 124, replace the console.error call with the appropriate
logger method to ensure consistent logging practices. Also, simplify the type
checks by using optional chaining when calling isTypeOf on each config type to
avoid potential errors if isTypeOf is undefined.

Comment on lines +216 to +219
// If git repo was initialized, include it in the backup
if (gitRepoInitialized && tempGitPath) {
excludeArgs.push('--exclude', '.git-backup-temp');
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Incorrect git repository exclusion logic

The condition excludes the temporary git repository when it should be included in the backup.

-        // If git repo was initialized, include it in the backup
+        // Always exclude the temporary git repository path
-        if (gitRepoInitialized && tempGitPath) {
             excludeArgs.push('--exclude', '.git-backup-temp');
-        }

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

🤖 Prompt for AI Agents
In
api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source-processor.service.ts
around lines 216 to 219, the current logic excludes the temporary git repository
from the backup when it should be included. To fix this, remove or adjust the
condition that pushes '--exclude', '.git-backup-temp' to the excludeArgs array
so that the temporary git repository is not excluded but included in the backup
process.

return errorStream;
}

const { command, args } = this.generateStreamCommand(config, false);
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Streaming mode doesn't support git history inclusion

The streaming implementation always passes false for git repository initialization, meaning git history won't be included even when config.includeGitHistory is true.

Consider either:

  1. Document this limitation clearly
  2. Implement git repository setup before streaming
  3. Return an error if streaming is requested with includeGitHistory: true

🏁 Script executed:

#!/bin/bash
# Locate generateStreamCommand definition and its implementation
rg -n "generateStreamCommand" api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source-processor.service.ts

# Inspect getReadableStream implementation around line 247-306
sed -n '240,320p' api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source-processor.service.ts

# Search for includeGitHistory usage in the same file
rg -n "includeGitHistory" api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source-processor.service.ts

Length of output: 3298


Handle git history in streaming mode

The getReadableStream implementation always calls

const { command, args } = this.generateStreamCommand(config, false);

so even if config.includeGitHistory is true, no git repo is initialized and history is never streamed.

Consider one of the following fixes:

  • Initialize the repo before streaming when config.includeGitHistory is true, then pass that flag into generateStreamCommand.
  • Throw an error if streaming is requested with includeGitHistory: true but repo setup isn’t supported.
  • At minimum, clearly document this limitation in the method’s JSDoc.

Location to update:
• api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source-processor.service.ts line 262

Suggested diff snippet:

- const { command, args } = this.generateStreamCommand(config, false);
+ const gitRepoInitialized = config.includeGitHistory
+   ? await this.initGitRepo(config.flashPath, tempGitPath)
+   : false;
+ const { command, args } = this.generateStreamCommand(config, gitRepoInitialized);
🤖 Prompt for AI Agents
In
api/src/unraid-api/graph/resolvers/backup/source/flash/flash-source-processor.service.ts
at line 262, the call to generateStreamCommand always uses false for the git
history flag, ignoring config.includeGitHistory. Fix this by checking if
config.includeGitHistory is true; if so, initialize the git repo before
streaming and pass true to generateStreamCommand. Alternatively, throw an error
if includeGitHistory is true but repo setup is unsupported. If neither is
feasible, update the method's JSDoc to clearly document that streaming with git
history is not supported.

Comment on lines +145 to +181
await mkdir(tempGitPath, { recursive: true });
await execa('git', ['init'], { cwd: tempGitPath });

const gitignorePath = join(tempGitPath, '.gitignore');
const gitignoreContent = [
'# Exclude sensitive files',
'*.key',
'*.pem',
'*.p12',
'*.pfx',
'config/passwd',
'config/shadow',
'config/ssh/',
'config/ssl/',
'config/wireguard/',
'config/network.cfg',
'config/ident.cfg',
].join('\n');

await writeFile(gitignorePath, gitignoreContent);

await execa('git', ['add', '.'], { cwd: flashPath });
await execa(
'git',
[
'-c',
'user.name=Unraid Backup',
'-c',
'[email protected]',
'commit',
'-m',
'Flash backup snapshot',
],
{ cwd: flashPath }
);

await execa('mv', [join(flashPath, '.git'), tempGitPath]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix incorrect git repository initialization sequence

The git operations sequence has critical issues:

  1. Git repo is initialized in tempGitPath (line 146) but git add is run in flashPath (line 166) where no .git directory exists
  2. The .git directory move (line 181) attempts to move a non-existent directory
-            await mkdir(tempGitPath, { recursive: true });
-            await execa('git', ['init'], { cwd: tempGitPath });
-
-            const gitignorePath = join(tempGitPath, '.gitignore');
+            // Initialize git in flashPath first
+            await execa('git', ['init'], { cwd: flashPath });
+
+            const gitignorePath = join(flashPath, '.gitignore');
             const gitignoreContent = [
                 '# Exclude sensitive files',
                 '*.key',
                 '*.pem',
                 '*.p12',
                 '*.pfx',
                 'config/passwd',
                 'config/shadow',
                 'config/ssh/',
                 'config/ssl/',
                 'config/wireguard/',
                 'config/network.cfg',
                 'config/ident.cfg',
             ].join('\n');

             await writeFile(gitignorePath, gitignoreContent);

             await execa('git', ['add', '.'], { cwd: flashPath });
             await execa(
                 'git',
                 [
                     '-c',
                     'user.name=Unraid Backup',
                     '-c',
                     '[email protected]',
                     'commit',
                     '-m',
                     'Flash backup snapshot',
                 ],
                 { cwd: flashPath }
             );

-            await execa('mv', [join(flashPath, '.git'), tempGitPath]);
+            // Move .git directory to temp location
+            await mkdir(dirname(tempGitPath), { recursive: true });
+            await rename(join(flashPath, '.git'), tempGitPath);
📝 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
await mkdir(tempGitPath, { recursive: true });
await execa('git', ['init'], { cwd: tempGitPath });
const gitignorePath = join(tempGitPath, '.gitignore');
const gitignoreContent = [
'# Exclude sensitive files',
'*.key',
'*.pem',
'*.p12',
'*.pfx',
'config/passwd',
'config/shadow',
'config/ssh/',
'config/ssl/',
'config/wireguard/',
'config/network.cfg',
'config/ident.cfg',
].join('\n');
await writeFile(gitignorePath, gitignoreContent);
await execa('git', ['add', '.'], { cwd: flashPath });
await execa(
'git',
[
'-c',
'user.name=Unraid Backup',
'-c',
'[email protected]',
'commit',
'-m',
'Flash backup snapshot',
],
{ cwd: flashPath }
);
await execa('mv', [join(flashPath, '.git'), tempGitPath]);
// Initialize git in flashPath first
await execa('git', ['init'], { cwd: flashPath });
const gitignorePath = join(flashPath, '.gitignore');
const gitignoreContent = [
'# Exclude sensitive files',
'*.key',
'*.pem',
'*.p12',
'*.pfx',
'config/passwd',
'config/shadow',
'config/ssh/',
'config/ssl/',
'config/wireguard/',
'config/network.cfg',
'config/ident.cfg',
].join('\n');
await writeFile(gitignorePath, gitignoreContent);
await execa('git', ['add', '.'], { cwd: flashPath });
await execa(
'git',
[
'-c',
'user.name=Unraid Backup',
'-c',
'[email protected]',
'commit',
'-m',
'Flash backup snapshot',
],
{ cwd: flashPath }
);
// Move .git directory to temp location
await mkdir(dirname(tempGitPath), { recursive: true });
await rename(join(flashPath, '.git'), tempGitPath);

Comment on lines +122 to +127
private async executeStreamingBackup(
sourceProcessor: BackupSourceProcessor<any>,
destinationProcessor: BackupDestinationProcessor<any>,
jobConfig: BackupJobConfig, // This is the config object, not its ID
internalJobId: string
): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Missing configId parameter in executeStreamingBackup method

The method uses configId at lines 204-207 but it's not declared in the parameter list.

 private async executeStreamingBackup(
     sourceProcessor: BackupSourceProcessor<any>,
     destinationProcessor: BackupDestinationProcessor<any>,
     jobConfig: BackupJobConfig, // This is the config object, not its ID
-    internalJobId: string
+    internalJobId: string,
+    configId: string // Add missing parameter
 ): Promise<void> {

Also applies to: 204-207

🤖 Prompt for AI Agents
In
api/src/unraid-api/graph/resolvers/backup/orchestration/backup-orchestration.service.ts
around lines 122 to 127 and 204 to 207, the executeStreamingBackup method uses
the variable configId but it is not declared as a parameter. Add configId as a
parameter to the method signature and ensure it is passed correctly when the
method is called to fix the missing parameter issue.

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

Review continued from previous batch...

Comment on lines +359 to +362
this.jobTrackingService.updateJobStatus(internalJobId, {
status: BackupJobStatus.FAILED,
error: errorMsg,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove redundant job status updates

The updateJobStatus calls are redundant since emitJobStatus already updates the job status internally.

-                this.jobTrackingService.updateJobStatus(internalJobId, {
-                    status: BackupJobStatus.FAILED,
-                    error: errorMsg,
-                });

Also applies to: 396-399, 448-451

🤖 Prompt for AI Agents
In
api/src/unraid-api/graph/resolvers/backup/orchestration/backup-orchestration.service.ts
at lines 359-362, 396-399, and 448-451, remove the calls to
this.jobTrackingService.updateJobStatus because these updates are redundant; the
emitJobStatus method already handles updating the job status internally. Simply
delete these updateJobStatus calls to avoid duplicate status updates.

Comment on lines +111 to +112
@Field(() => SourceConfigUnion, { description: 'Source configuration for this backup job' })
sourceConfig!: typeof SourceConfigUnion;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove typeof from union type field declarations

Using typeof for GraphQL field types is incorrect. The field decorator should reference the union type directly.

-    @Field(() => SourceConfigUnion, { description: 'Source configuration for this backup job' })
-    sourceConfig!: typeof SourceConfigUnion;
+    @Field(() => SourceConfigUnion, { description: 'Source configuration for this backup job' })
+    sourceConfig!: SourceConfigUnion;

-    @Field(() => DestinationConfigUnion, {
-        description: 'Destination configuration for this backup job',
-    })
-    destinationConfig!: typeof DestinationConfigUnion;
+    @Field(() => DestinationConfigUnion, {
+        description: 'Destination configuration for this backup job',
+    })
+    destinationConfig!: DestinationConfigUnion;

Also applies to: 116-117

🤖 Prompt for AI Agents
In api/src/unraid-api/graph/resolvers/backup/backup.model.ts at lines 111-112
and 116-117, remove the `typeof` keyword from the union type field declarations.
The @Field decorator should directly reference the union type (e.g.,
SourceConfigUnion) without using `typeof` to correctly define the GraphQL field
type.

Comment on lines +331 to 339
async updateRemote(input: UpdateRCloneRemoteDto): Promise<unknown> {
await validateObject(UpdateRCloneRemoteDto, input);
this.logger.log(`Updating remote: ${input.name}`);
const params = {

return this.callRcloneApi('config/update', {
name: input.name,
...input.parameters,
};
return this.callRcloneApi('config/update', params);
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential parameter override in updateRemote

Spreading input.parameters after the name field could allow the name parameter to be overridden if input.parameters contains a name field.

 async updateRemote(input: UpdateRCloneRemoteDto): Promise<unknown> {
     await validateObject(UpdateRCloneRemoteDto, input);
     this.logger.log(`Updating remote: ${input.name}`);

     return this.callRcloneApi('config/update', {
-        name: input.name,
-        ...input.parameters,
+        ...input.parameters,
+        name: input.name,
     });
 }
📝 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
async updateRemote(input: UpdateRCloneRemoteDto): Promise<unknown> {
await validateObject(UpdateRCloneRemoteDto, input);
this.logger.log(`Updating remote: ${input.name}`);
const params = {
return this.callRcloneApi('config/update', {
name: input.name,
...input.parameters,
};
return this.callRcloneApi('config/update', params);
});
}
async updateRemote(input: UpdateRCloneRemoteDto): Promise<unknown> {
await validateObject(UpdateRCloneRemoteDto, input);
this.logger.log(`Updating remote: ${input.name}`);
return this.callRcloneApi('config/update', {
...input.parameters,
name: input.name,
});
}
🤖 Prompt for AI Agents
In api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts around lines
331 to 339, the updateRemote method spreads input.parameters after setting the
name field, which risks overriding the name if input.parameters includes a name
property. To fix this, ensure the name field is set last or explicitly override
any name in input.parameters by placing the name property after spreading
input.parameters, so the intended name value is preserved and cannot be
overridden.

Copy link
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 (6)
api/src/unraid-api/graph/resolvers/backup/backup-config.service.ts (2)

401-401: Replace delete operator with undefined assignment for better performance.

The static analysis correctly identified performance impact of the delete operator.

Also applies to: 592-592


135-190: Consider adding concurrency control to prevent race conditions.

Multiple async methods modify the shared configs Map without synchronization, which could lead to race conditions.

Also applies to: 192-271, 273-281

api/src/unraid-api/graph/resolvers/backup/orchestration/backup-orchestration.service.ts (3)

121-126: Missing configId parameter in executeStreamingBackup method.

The method uses configId at lines 203-206 but it's not declared in the parameter list.


142-142: Incorrect parameter passed to handleJobCompletion.

Should pass configId instead of internalJobId as the first parameter.


358-361: Remove redundant job status updates.

The updateJobStatus calls are redundant since emitJobStatus already updates the job status internally.

Also applies to: 396-399, 447-450

api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts (1)

375-383: Potential parameter override in updateRemote.

Spreading input.parameters after the name field could allow the name parameter to be overridden if input.parameters contains a name field.

🧹 Nitpick comments (1)
api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts (1)

674-674: Use optional chain for better readability.

The static analysis correctly suggests using optional chaining.

-        const isUnixSocket = this.rcloneSocketPath && this.rcloneSocketPath.startsWith('/');
+        const isUnixSocket = this.rcloneSocketPath?.startsWith('/');
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e7066c0 and a406fdc.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • api/package.json (3 hunks)
  • api/src/unraid-api/graph/resolvers/backup/backup-config.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/backup/orchestration/backup-orchestration.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts (5 hunks)
  • api/src/unraid-api/graph/resolvers/rclone/rclone.service.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • api/src/unraid-api/graph/resolvers/rclone/rclone.service.ts
🧰 Additional context used
📓 Path-based instructions (2)
api/src/unraid-api/**/*

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
  • .cursor/rules/api-rules.mdc
**/*.{ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
🧠 Learnings (5)
📓 Common learnings
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
api/package.json (10)
Learnt from: elibosley
PR: unraid/api#1120
File: plugin/package.json:1-8
Timestamp: 2025-02-05T14:43:25.062Z
Learning: The repository uses Renovate for automated dependency updates, making strict version pinning in package.json less critical as updates are handled automatically through PRs.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Applies to api/**/*.{test,spec}.{js,ts,tsx} : Test suite is VITEST, do not use jest
Learnt from: mdatelle
PR: unraid/api#1122
File: web/package.json:16-16
Timestamp: 2025-02-06T17:25:45.397Z
Learning: The build script in web/package.json should include type-check command (`npm run type-check`) even when NODE_ENV is production, as it provides value for local builds by catching type errors before pushing to CI/CD.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/**/*.{test,spec}.{ts,js} : Test suite is VITEST, do not use jest in the API package
Learnt from: mdatelle
PR: unraid/api#998
File: unraid-ui/package.json:57-57
Timestamp: 2025-01-08T15:28:24.733Z
Learning: ESLint version 8.x is the current major version as of January 2025, with 8.56.0 being the latest stable release. Version 9.x does not exist yet.
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to **/*.{ts,tsx} : TypeScript imports use .js extensions for ESM compatibility
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Use pnpm ONLY for package management in the API package
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Use pnpm ONLY for package management
api/src/unraid-api/graph/resolvers/backup/backup-config.service.ts (9)
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom or extended implementation of NestJS ConfigService that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: pujitm
PR: unraid/api#1367
File: packages/unraid-api-plugin-connect/src/pubsub/user.service.ts:44-52
Timestamp: 2025-04-23T20:19:42.542Z
Learning: The project uses a custom ConfigService implementation that includes a `set()` method for runtime configuration mutation, unlike the standard @nestjs/config package which only provides getter methods.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:33-37
Timestamp: 2025-01-29T16:36:04.777Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations. It includes try/catch blocks, detailed error logging, and safe rollback mechanisms. Individual FileModification implementations (like LogRotateModification) should allow errors to propagate to this service layer rather than handling them internally.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/auth/auth.service.ts:0-0
Timestamp: 2024-11-04T20:44:46.432Z
Learning: When modifying `apiKey.roles` in `removeRoleFromApiKey` and `addRoleToApiKey` within `api/src/unraid-api/auth/auth.service.ts`, concurrency issues are not a concern because the keys are stored in the file system.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/auth/auth.service.ts:0-0
Timestamp: 2024-11-04T20:41:22.303Z
Learning: In `api/src/unraid-api/auth/auth.service.ts`, the `addRoleToApiKey` function operates on API keys stored as JSON files in a directory, not a database, so concurrency is not a concern for modifying `apiKey.roles`.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/auth/api-key.service.ts:176-188
Timestamp: 2024-11-15T16:22:03.485Z
Learning: Atomic writes are not required for the `saveApiKey` method in `ApiKeyService` (`api/src/unraid-api/auth/api-key.service.ts`) unless specifically needed.
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/__test__/store/**/*.ts : Test async operations completely in store tests
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/graphql/schema/types/connect/connect.graphql:142-146
Timestamp: 2025-03-14T16:10:38.562Z
Learning: The updateApiSettings mutation in api/src/unraid-api/graph/connect/connect.resolver.ts is protected with the @UsePermissions decorator that requires UPDATE permission on the CONFIG resource.
api/src/unraid-api/graph/resolvers/backup/orchestration/backup-orchestration.service.ts (1)
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/auth/api-key.service.ts:62-70
Timestamp: 2024-11-05T14:49:07.308Z
Learning: In `api/src/unraid-api/auth/api-key.service.ts`, when handling read errors in the `findById` method, throw a `GraphQLError` instead of an `InternalServerErrorException`.
api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts (9)
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:33-37
Timestamp: 2025-01-29T16:36:04.777Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations. It includes try/catch blocks, detailed error logging, and safe rollback mechanisms. Individual FileModification implementations (like LogRotateModification) should allow errors to propagate to this service layer rather than handling them internally.
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/auth/api-key.service.ts:62-70
Timestamp: 2024-11-05T14:49:07.308Z
Learning: In `api/src/unraid-api/auth/api-key.service.ts`, when handling read errors in the `findById` method, throw a `GraphQLError` instead of an `InternalServerErrorException`.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:39-41
Timestamp: 2025-01-29T16:35:43.699Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations, including detailed error logging with stack traces and modification IDs. Individual FileModification implementations should focus on their core functionality without duplicating error handling.
Learnt from: elibosley
PR: unraid/api#1425
File: api/dev/configs/connect.json:2-3
Timestamp: 2025-06-20T21:05:24.582Z
Learning: When reviewing configuration files in refactoring PRs, avoid suggesting field name changes that could break compatibility with existing code that references those fields, even if the naming doesn't follow ideal conventions.
Learnt from: pujitm
PR: unraid/api#1040
File: api/src/unraid-api/auth/api-key.service.spec.ts:116-116
Timestamp: 2025-01-14T17:45:01.646Z
Learning: In the ApiKeyService, directory initialization is performed synchronously using `ensureDirSync` in the constructor, rather than through an async `initialize` method.
Learnt from: elibosley
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:48-53
Timestamp: 2025-03-13T16:17:55.820Z
Learning: In NestJS services, dynamic imports should be wrapped in try/catch blocks with proper error logging and fallback handling to prevent unhandled rejections from crashing the application.
Learnt from: elibosley
PR: unraid/api#1334
File: api/src/unraid-api/graph/resolvers/docker/docker-event.service.ts:63-66
Timestamp: 2025-04-07T14:34:47.255Z
Learning: In DockerEventService, the chokidar file watcher is configured with `ignoreInitial: false` to ensure that existing files (like the Docker socket) are detected and processed at application startup, not just when files change after the watcher is initialized.
Learnt from: elibosley
PR: unraid/api#1334
File: api/src/unraid-api/graph/resolvers/docker/docker-event.service.ts:63-66
Timestamp: 2025-04-07T14:34:47.255Z
Learning: In DockerEventService, the chokidar file watcher is configured with `ignoreInitial: false` to ensure that existing files (like the Docker socket) are detected and processed at application startup, not just when files change after the watcher is initialized.
🪛 Biome (1.9.4)
api/src/unraid-api/graph/resolvers/backup/backup-config.service.ts

[error] 401-401: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts

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

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build Web App
  • GitHub Check: Build API
  • GitHub Check: Test API
  • GitHub Check: Deploy Storybook
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
api/package.json (1)

97-97: Clarify the cron dependency downgrade and override pattern.

The cron dependency was downgraded from 4.3.1 to 4.3.0, but then an override forces it back to 4.3.1. This suggests a compatibility issue that required a workaround.

Consider documenting why this override is necessary to help future maintainers understand the reasoning.

Also applies to: 229-229

api/src/unraid-api/graph/resolvers/backup/backup-config.service.ts (1)

1-50: Well-structured service architecture with comprehensive backup management.

The service provides excellent separation of concerns with clear transformation methods, proper validation, and comprehensive error handling. The integration with NestJS scheduling and the orchestration service is well-designed.

api/src/unraid-api/graph/resolvers/backup/orchestration/backup-orchestration.service.ts (1)

1-50: Excellent orchestration architecture with proper stream handling.

The service demonstrates solid design patterns for coordinating backup execution, with comprehensive error handling, proper cleanup procedures, and effective separation between streaming and regular backup flows.

api/src/unraid-api/graph/resolvers/rclone/rclone-api.service.ts (2)

78-163: Excellent refactoring of daemon lifecycle management.

The enhanced initialization logic with proper cleanup of stale processes and sockets significantly improves reliability. The Unix socket authentication handling and retry mechanisms are well-implemented.


487-584: Robust job management with comprehensive safety checks.

The job listing and status retrieval methods include excellent safety mechanisms to prevent job explosion and performance issues. The backup group filtering and active job detection logic is well-designed.

Copy link
Contributor

🚀 Storybook has been deployed to staging: https://unraid-ui-storybook-staging.unraid-workers.workers.dev

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a406fdc and 0d864fa.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • .claude/settings.local.json (1 hunks)
  • unraid-ui/package.json (3 hunks)
  • unraid-ui/src/components.ts (1 hunks)
  • unraid-ui/src/components/form/lightswitch/Lightswitch.vue (0 hunks)
  • unraid-ui/src/forms/LabelRenderer.vue (1 hunks)
  • unraid-ui/src/forms/SteppedLayout.vue (4 hunks)
  • unraid-ui/src/forms/UnraidSettingsLayout.vue (1 hunks)
  • unraid-ui/src/forms/VerticalLayout.vue (1 hunks)
  • unraid-ui/src/forms/jsonforms.d.ts (0 hunks)
  • web/layouts/default.vue (2 hunks)
  • web/server/api/routes.get.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • unraid-ui/src/components/form/lightswitch/Lightswitch.vue
  • unraid-ui/src/forms/jsonforms.d.ts
✅ Files skipped from review due to trivial changes (2)
  • unraid-ui/src/forms/LabelRenderer.vue
  • unraid-ui/src/forms/UnraidSettingsLayout.vue
🚧 Files skipped from review as they are similar to previous changes (4)
  • unraid-ui/src/components.ts
  • web/layouts/default.vue
  • web/server/api/routes.get.ts
  • unraid-ui/src/forms/SteppedLayout.vue
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: mdatelle
PR: unraid/api#1106
File: unraid-ui/src/components/index.ts:2-2
Timestamp: 2025-02-04T17:21:39.710Z
Learning: The unraid-ui package is undergoing a major refactoring process, and breaking changes are expected during this transition period.
Learnt from: elibosley
PR: unraid/api#1101
File: api/src/unraid-api/unraid-file-modifier/modifications/patches/default-page-layout.patch:24-27
Timestamp: 2025-01-31T22:01:22.708Z
Learning: The Unraid UI uses a modern notification system with a custom `unraid-toaster` component replacing the legacy jGrowl notifications. The system is backed by a comprehensive GraphQL API with real-time subscription support for notification updates.
Learnt from: elibosley
PR: unraid/api#1381
File: plugin/source/dynamix.unraid.net/usr/local/share/dynamix.unraid.net/install/scripts/setup_api.sh:107-113
Timestamp: 2025-05-07T16:07:47.236Z
Learning: The Unraid API is designed to handle missing configuration files gracefully with smart internal fallbacks rather than requiring installation scripts to create default configurations.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:33-37
Timestamp: 2025-01-29T16:36:04.777Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations. It includes try/catch blocks, detailed error logging, and safe rollback mechanisms. Individual FileModification implementations (like LogRotateModification) should allow errors to propagate to this service layer rather than handling them internally.
Learnt from: pujitm
PR: unraid/api#1211
File: web/composables/gql/gql.ts:17-18
Timestamp: 2025-03-12T13:48:14.850Z
Learning: In the Unraid API project, the duplicate GraphQL query and mutation strings in gql.ts files are intentionally generated by GraphQL CodeGen tool and are necessary for the type system to function properly.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:39-41
Timestamp: 2025-01-29T16:35:43.699Z
Learning: The UnraidFileModifierService in the Unraid API provides comprehensive error handling for all FileModification implementations, including detailed error logging with stack traces and modification IDs. Individual FileModification implementations should focus on their core functionality without duplicating error handling.
Learnt from: elibosley
PR: unraid/api#1082
File: api/src/unraid-api/unraid-file-modifier/modifications/log-rotate.modification.ts:39-41
Timestamp: 2025-01-29T16:35:43.699Z
Learning: In the Unraid API, FileModification implementations (apply/rollback methods) don't need to implement their own error handling as it's handled by the UnraidFileModifierService caller.
unraid-ui/src/forms/VerticalLayout.vue (8)
Learnt from: pujitm
PR: unraid/api#1211
File: web/codegen.ts:14-14
Timestamp: 2025-03-12T13:35:43.900Z
Learning: The JSON scalar type in web/codegen.ts was temporarily changed from 'string' to 'any' for compatibility with JsonForms integration. This change facilitates the implementation of the Connect settings web component.
Learnt from: elibosley
PR: unraid/api#1181
File: web/store/theme.ts:0-0
Timestamp: 2025-02-24T14:51:21.328Z
Learning: In the Unraid API project's theme system, exact TypeScript type definitions are preferred over index signatures for theme variables to ensure better type safety.
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/unraid-api/graph/connect/connect-settings.service.ts:199-199
Timestamp: 2025-03-14T16:56:20.520Z
Learning: The JSONForms library has narrow type definitions for interfaces like SchemaBasedCondition that make augmentation difficult. Type assertions (using 'as') are sometimes necessary despite not being ideal from a typing perspective.
Learnt from: pujitm
PR: unraid/api#1219
File: api/src/unraid-api/main.ts:18-25
Timestamp: 2025-03-07T19:29:12.540Z
Learning: When handling type mismatches between dependencies in TypeScript (such as between NestJS and Fastify), prefer using `@ts-expect-error` with a detailed explanation comment instead of `as any` type assertions. This better documents the reason for the type bypass and makes the issue more visible for future maintenance.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Verify that the expected elements are rendered in component tests
Learnt from: mdatelle
PR: unraid/api#1106
File: unraid-ui/src/components/index.ts:2-2
Timestamp: 2025-02-04T17:21:39.710Z
Learning: The unraid-ui package is undergoing a major refactoring process, and breaking changes are expected during this transition period.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Check for expected prop handling and event emissions in component tests
.claude/settings.local.json (9)
Learnt from: elibosley
PR: unraid/api#1120
File: api/scripts/build.mjs:81-83
Timestamp: 2025-02-05T17:48:23.465Z
Learning: In Node.js projects, executable permissions (755) must be set for:
1. All files in node_modules/.bin and their symlink targets
2. JavaScript files (*.js and *.mjs)
3. All directories (for traversal)
While other files should be read-only (644).
Learnt from: pujitm
PR: unraid/api#1211
File: api/src/graphql/schema/types/connect/connect.graphql:142-146
Timestamp: 2025-03-14T16:10:38.562Z
Learning: The updateApiSettings mutation in api/src/unraid-api/graph/connect/connect.resolver.ts is protected with the @UsePermissions decorator that requires UPDATE permission on the CONFIG resource.
Learnt from: elibosley
PR: unraid/api#1120
File: plugin/package.json:0-0
Timestamp: 2025-02-05T14:43:48.568Z
Learning: In Node.js projects, npm scripts should be organized with clear namespacing (e.g., build:*, docker:*, env:*) and include proper environment validation and error handling. Each script should follow the single responsibility principle.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Run tests with: pnpm --filter ./api test
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/__test__/**/* : Tests are located under web/__test__, run with pnpm test
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Always run scripts from api/package.json unless requested
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Always run scripts from api/package.json unless requested otherwise
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/**/*.{test,spec}.{ts,js} : Test suite is VITEST, do not use jest in the API package
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Applies to api/**/*.{test,spec}.{js,ts,tsx} : Test suite is VITEST, do not use jest
unraid-ui/package.json (14)
Learnt from: mdatelle
PR: unraid/api#1106
File: unraid-ui/src/components/index.ts:2-2
Timestamp: 2025-02-04T17:21:39.710Z
Learning: The unraid-ui package is undergoing a major refactoring process, and breaking changes are expected during this transition period.
Learnt from: pujitm
PR: unraid/api#1211
File: unraid-ui/package.json:43-43
Timestamp: 2025-03-14T19:18:23.324Z
Learning: The @internationalized/number package is a dependency of reka-ui, which is used for number formatting in the Unraid UI components.
Learnt from: elibosley
PR: unraid/api#1211
File: unraid-ui/src/components/form/number/NumberFieldInput.vue:1-21
Timestamp: 2025-03-13T16:17:21.897Z
Learning: The unraid-ui is a UI library being published externally, where wrapping third-party components (like those from reka-ui) is an intentional design choice to maintain a consistent interface, standardize styling, and control the exposed API.
Learnt from: elibosley
PR: unraid/api#1308
File: unraid-ui/src/components/common/loading/Error.vue:2-2
Timestamp: 2025-04-02T21:21:29.168Z
Learning: Components in the unraid-ui folder require explicit imports and are not autoloaded, unlike other parts of the project that may use Nuxt.js autoloading features.
Learnt from: zackspear
PR: unraid/api#1079
File: web/scripts/deploy-dev.sh:51-54
Timestamp: 2025-01-29T00:59:26.633Z
Learning: For the Unraid web components deployment process, JS file validation isn't required in auth-request.php updates since the files come from the controlled build pipeline where we are the source.
Learnt from: elibosley
PR: unraid/api#1120
File: plugin/package.json:1-8
Timestamp: 2025-02-05T14:43:25.062Z
Learning: The repository uses Renovate for automated dependency updates, making strict version pinning in package.json less critical as updates are handled automatically through PRs.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/src/unraid-api/**/* : Prefer adding new files to the NestJS repo located at api/src/unraid-api/ instead of the legacy code
Learnt from: elibosley
PR: unraid/api#1408
File: web/components/ApiKey/PermissionCounter.vue:6-6
Timestamp: 2025-05-23T21:59:29.632Z
Learning: This codebase uses ESM (ECMAScript Modules) and requires .js extensions in import statements, even when importing from TypeScript files, as the imports refer to the compiled JavaScript output.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/store/**/*.{ts,js} : Ensure Vue reactivity imports are added to store files (computed, ref, watchEffect)
Learnt from: mdatelle
PR: unraid/api#998
File: unraid-ui/package.json:57-57
Timestamp: 2025-01-08T15:28:24.733Z
Learning: ESLint version 8.x is the current major version as of January 2025, with 8.56.0 being the latest stable release. Version 9.x does not exist yet.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to **/*.{ts,tsx} : TypeScript imports use .js extensions for ESM compatibility
Learnt from: pujitm
PR: unraid/api#1417
File: web/components/ConnectSettings/ConnectSettings.ce.vue:11-18
Timestamp: 2025-06-13T17:14:21.739Z
Learning: The project’s build tooling auto-imports common Vue/Pinia helpers such as `storeToRefs`, so explicit import statements for them are not required.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Applies to api/**/*.{test,spec}.{js,ts,tsx} : Test suite is VITEST, do not use jest
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Avoid relying on Nuxt's auto-imports in test environment
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build API
  • GitHub Check: Test API
  • GitHub Check: Build Web App
  • GitHub Check: Deploy Storybook
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
unraid-ui/src/forms/VerticalLayout.vue (1)

46-46: Type assertion aligns with established JSONForms compatibility pattern.

This change follows the established pattern across form components for handling JSONForms type compatibility issues. While the as any assertion reduces type safety, it appears necessary given the narrow type definitions in the JSONForms library as mentioned in the retrieved learnings.

unraid-ui/package.json (2)

58-58: Ajv version is three years behind the latest 8-series release

^8.17.1 dates back to 2022. Recent Ajv releases (≥ 8.24) ship smaller bundles, fix security issues (e.g. CVE-2023-52404) and add draft-2020-12 compliance used by @jsonforms/*. Lock to the latest 8.x or add an explicit renovate rule so we stay current.

-    "ajv": "^8.17.1",
+    "ajv": "^8.24.0",

116-116: Verify vue-eslint-parser compatibility with chosen ESLint major

vue-eslint-parser@^10.2.0 supports ESLint ≥ 7 < 9. If you stick with ESLint 9 the parser must be bumped to v @eslint-community/vue-eslint-parser (the new fork) which officially supports 9.x.

Double-check and align the trio: ESLint, vue-eslint-parser, eslint-plugin-vue.

⛔ Skipped due to learnings
Learnt from: mdatelle
PR: unraid/api#998
File: unraid-ui/package.json:57-57
Timestamp: 2025-01-08T15:28:24.733Z
Learning: ESLint version 8.x is the current major version as of January 2025, with 8.56.0 being the latest stable release. Version 9.x does not exist yet.

Comment on lines 17 to 21
"Bash(pnpm --filter \"*connect*\" test connect-status-writer.service.spec)",
"Bash(pnpm add:*)",
"Bash(npx tsc:*)",
"Bash(pnpm list:*)",
"Bash(rm:*)"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Unrestricted patterns (rm:*, pnpm add:*) open the door to destructive or supply-chain attacks

Granting blanket permission to any rm invocation means a malicious script could wipe arbitrary paths.
Similarly, allowing any pnpm add:* lets unreviewed packages be installed at review-time, bypassing lock-file scrutiny.

Diff proposal – drop the wildcard or scope it tightly to known-safe use-cases (example shows a minimal rm pattern; adjust to your needs):

-      "Bash(pnpm add:*)",
-      "Bash(rm:*)"
+      "Bash(pnpm add @types/node@latest)",       // explicit, pinned
+      "Bash(rm -rf ./tmp/*)"                     // confined to temp artefacts

If you truly need wide rm/install freedom, consider:

  1. Moving those steps to a dedicated CI job with least-privilege credentials.
  2. Adding a confirmation prompt or checksum enforcement before destructive/installation commands run.
📝 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
"Bash(pnpm --filter \"*connect*\" test connect-status-writer.service.spec)",
"Bash(pnpm add:*)",
"Bash(npx tsc:*)",
"Bash(pnpm list:*)",
"Bash(rm:*)"
"Bash(pnpm --filter \"*connect*\" test connect-status-writer.service.spec)",
"Bash(pnpm add @types/node@latest)", // explicit, pinned
"Bash(npx tsc:*)",
"Bash(pnpm list:*)",
"Bash(rm -rf ./tmp/*)" // confined to temp artefacts
🤖 Prompt for AI Agents
In .claude/settings.local.json around lines 17 to 21, the use of unrestricted
wildcard patterns like "rm:*" and "pnpm add:*" poses security risks by allowing
potentially destructive or unreviewed commands. To fix this, replace these
wildcards with specific, tightly scoped command patterns that only allow
known-safe operations. Alternatively, move these commands to a separate CI job
with restricted permissions or add confirmation prompts/checksum checks before
executing such commands to prevent misuse.

"vue-sonner": "1.3.2"
},
"devDependencies": {
"@eslint/js": "9.30.1",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

ESLint 9 introduced but ecosystem plugins are still on the 8-series → install will error

@typescript-eslint/[email protected] and [email protected] both declare peer-dep eslint@"* <9". With eslint 9.30.1 + @eslint/js 9.30.1 PNPM will refuse to install (or linting will crash).

Upgrade the plugins to their v9 counterparts or stay on ESLint 8 until the ecosystem catches up.

-    "@typescript-eslint/eslint-plugin": "8.36.0",
+    "@typescript-eslint/eslint-plugin": "9.6.0",
 ...
-    "eslint": "9.30.1",
+    "eslint": "8.56.0",
🤖 Prompt for AI Agents
In unraid-ui/package.json at line 71, ESLint version 9.30.1 is introduced, but
the plugins @typescript-eslint/[email protected] and [email protected]
require ESLint versions below 9, causing installation errors. To fix this,
either downgrade ESLint to a compatible 8-series version or upgrade these
plugins to their versions that support ESLint 9, ensuring all dependencies align
to prevent installation or linting failures.

- Replace vitest.workspace.js with vitest.config.ts for better project configuration
- Add vitest dependency and update test script in package.json
- Improve RCloneApiService tests with better mocking and error handling
- Update test snapshots to include backupBase path
- Change lint-staged command from pnpm to npx pnpm for consistency
- Add nvm and git config commands to settings.local.json for better tooling support
Copy link
Contributor

🚀 Storybook has been deployed to staging: https://unraid-ui-storybook-staging.unraid-workers.workers.dev

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0d864fa and b663293.

⛔ Files ignored due to path filters (2)
  • api/src/__test__/store/modules/__snapshots__/paths.test.ts.snap is excluded by !**/*.snap
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • .claude/settings.local.json (1 hunks)
  • api/src/__test__/graphql/resolvers/rclone-api.service.test.ts (9 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/.login.php.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/DefaultPageLayout.php.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/Notifications.page.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/auth-request.php.last-download-time (1 hunks)
  • api/src/unraid-api/unraid-file-modifier/modifications/__test__/__fixtures__/downloaded/rc.nginx.last-download-time (1 hunks)
  • package.json (3 hunks)
  • vitest.config.ts (1 hunks)
  • vitest.workspace.js (0 hunks)
💤 Files with no reviewable changes (1)
  • vitest.workspace.js
✅ Files skipped from review due to trivial changes (6)
  • api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/DefaultPageLayout.php.last-download-time
  • api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/auth-request.php.last-download-time
  • api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/rc.nginx.last-download-time
  • api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/Notifications.page.last-download-time
  • api/src/unraid-api/unraid-file-modifier/modifications/test/fixtures/downloaded/.login.php.last-download-time
  • vitest.config.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • .claude/settings.local.json
  • api/src/test/graphql/resolvers/rclone-api.service.test.ts
🧰 Additional context used
🧠 Learnings (1)
package.json (16)
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to api/**/*.{test,spec}.{ts,js} : Test suite is VITEST, do not use jest in the API package
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Applies to api/**/*.{test,spec}.{js,ts,tsx} : Test suite is VITEST, do not use jest
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Applies to web/__test__/**/* : Tests are located under web/__test__, run with pnpm test
Learnt from: mdatelle
PR: unraid/api#1122
File: web/package.json:16-16
Timestamp: 2025-02-06T17:25:45.397Z
Learning: The build script in web/package.json should include type-check command (`npm run type-check`) even when NODE_ENV is production, as it provides value for local builds by catching type errors before pushing to CI/CD.
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Run tests with: pnpm --filter ./api test
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Always run scripts from api/package.json unless requested otherwise
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Always run scripts from api/package.json unless requested
Learnt from: elibosley
PR: unraid/api#1120
File: plugin/package.json:1-8
Timestamp: 2025-02-05T14:43:25.062Z
Learning: The repository uses Renovate for automated dependency updates, making strict version pinning in package.json less critical as updates are handled automatically through PRs.
Learnt from: elibosley
PR: unraid/api#1105
File: api/scripts/build.mjs:0-0
Timestamp: 2025-02-04T16:42:21.782Z
Learning: In Node.js build scripts, avoid manually copying node_modules as a cache layer. Instead, rely on npm's built-in caching mechanism and use direct `npm install` commands, as this ensures dependency consistency and proper version resolution while still maintaining good performance through npm's cache.
Learnt from: elibosley
PR: unraid/api#1120
File: plugin/package.json:0-0
Timestamp: 2025-02-05T14:43:48.568Z
Learning: In Node.js projects, npm scripts should be organized with clear namespacing (e.g., build:*, docker:*, env:*) and include proper environment validation and error handling. Each script should follow the single responsibility principle.
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/api-rules.mdc:0-0
Timestamp: 2025-06-30T14:50:52.281Z
Learning: Use pnpm ONLY for package management
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Use pnpm ONLY for package management in the API package
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T14:50:43.946Z
Learning: Always run pnpm codegen for GraphQL code generation in the web directory
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Remember that `vi.mock()` calls are hoisted
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-testing-rules.mdc:0-0
Timestamp: 2025-06-30T14:52:37.535Z
Learning: Applies to **/*.test.ts : Avoid relying on Nuxt's auto-imports in test environment
Learnt from: CR
PR: unraid/api#0
File: .cursor/rules/web-graphql.mdc:0-0
Timestamp: 2025-06-30T14:51:12.348Z
Learning: Always run `pnpm codegen` for GraphQL code generation in the web directory
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build API
  • GitHub Check: Build Web App
  • GitHub Check: Test API
  • GitHub Check: Deploy Storybook
  • GitHub Check: Analyze (javascript-typescript)

"lint-staged": {
"*.{js,jsx,ts,tsx,vue}": [
"pnpm lint:fix"
"npx pnpm lint:fix"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

npx pnpm contradicts the “pnpm-only” policy

Running pnpm through npx pulls it via npm, defeating the repository’s guideline to use pnpm exclusively and adding network overhead on each commit.

-      "npx pnpm lint:fix"
+      "pnpm lint:fix"

If PATH availability is a concern, prefer pnpm exec but avoid the npx shim.

📝 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
"npx pnpm lint:fix"
"pnpm lint:fix"
🤖 Prompt for AI Agents
In package.json at line 58, replace the command "npx pnpm lint:fix" with "pnpm
exec lint:fix" to avoid using npx, which pulls pnpm via npm and contradicts the
pnpm-only policy. This change ensures pnpm is used directly without unnecessary
network overhead.

Comment on lines +46 to +47
"ignore": "7.0.5",
"vitest": "3.2.4"
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Move vitest to devDependencies

vitest is a pure test-runner; shipping it in "dependencies" inflates production install size and can slow CI caches.

 "dependencies": {
     "chalk": "5.4.1",
-    "ignore": "7.0.5",
-    "vitest": "3.2.4"
+    "ignore": "7.0.5"
 },
 "devDependencies": {
     "lint-staged": "16.1.2",
     "simple-git-hooks": "2.13.0",
+    "vitest": "3.2.4"
 },
📝 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
"ignore": "7.0.5",
"vitest": "3.2.4"
"dependencies": {
"chalk": "5.4.1",
"ignore": "7.0.5"
},
"devDependencies": {
"lint-staged": "16.1.2",
"simple-git-hooks": "2.13.0",
"vitest": "3.2.4"
},
🤖 Prompt for AI Agents
In package.json around lines 46 to 47, the "vitest" package is currently listed
under "dependencies" but it should be moved to "devDependencies" because it is
only needed for testing and not in production. Remove "vitest" from the
"dependencies" section and add it to the "devDependencies" section to reduce
production install size and improve CI cache efficiency.

"dev": "pnpm -r dev",
"unraid:deploy": "pnpm -r unraid:deploy",
"test": "pnpm -r test",
"test": "vitest",
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Monorepo test coverage likely reduced

"test": "vitest" runs the root-level Vitest instance only.
Previously we executed each workspace’s own test script via pnpm -r test, so package-scoped tests (e.g. api, web) may now be silently skipped unless the new monorepo-wide vitest.config.ts explicitly enumerates every project.

-    "test": "vitest",
+    "test": "pnpm exec vitest",          # keeps pnpm context
+    "test:all": "pnpm -r test"           # optional: retain legacy behaviour

Please verify that all workspaces are discovered by Vitest or keep the recursive script alongside the new one.


🏁 Script executed:

#!/bin/bash
# 1. List workspace packages from pnpm-workspace.yaml
echo "---- pnpm-workspace.yaml ----"
if [ -f pnpm-workspace.yaml ]; then
  sed -n '1,50p' pnpm-workspace.yaml
else
  echo "pnpm-workspace.yaml not found"
fi

# 2. Find all Vitest config files
echo
echo "---- Vitest config files ----"
fd --hidden --ignore-file .gitignore vitest.config.ts -t f || echo "No vitest.config.ts found"

# 3. Show contents of each Vitest config up to 200 lines
for cfg in $(fd --hidden --ignore-file .gitignore vitest.config.ts -t f); do
  echo
  echo "=== $cfg ==="
  sed -n '1,200p' "$cfg"
done

Length of output: 2026


Monorepo Vitest projects missing workspaces

Your root vitest.config.ts only enumerates api, plugin, unraid-ui and web, but your pnpm-workspace.yaml also includes libvirt and packages/*. As a result the "test": "vitest" script will skip those tests.

Please update:

vitest.config.ts – extend the projects array to include the missing workspaces, for example:

 export default defineConfig({
   test: {
     projects: [
       "./api/vite.config.ts",
       "./plugin/vitest.config.ts",
       "./unraid-ui/vitest.config.ts",
+      "./libvirt/vitest.config.ts",
+      "./packages/*/vitest.config.ts",
       "./web/vitest.config.mjs"
     ]
   }
 })

package.json – use pnpm exec vitest to preserve workspace context, and optionally retain the recursive fallback:

-  "test": "vitest",
+  "test": "pnpm exec vitest",
+  "test:all": "pnpm -r test"

This ensures no workspace tests are silently skipped.

🤖 Prompt for AI Agents
In package.json at line 10, update the "test" script to use "pnpm exec vitest"
instead of just "vitest" to ensure the workspace context is preserved when
running tests. Additionally, verify that vitest.config.ts includes all workspace
projects listed in pnpm-workspace.yaml, such as "libvirt" and "packages/*", by
extending the projects array accordingly. This will prevent tests in those
workspaces from being skipped.

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.

1 participant