-
Notifications
You must be signed in to change notification settings - Fork 10
Feat/flash-backup-implementation #1409
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
WalkthroughThis 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
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
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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
inapi/src/unraid-api/utils/utils.module.ts
that provides and exports the sameFormatService
. 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 fromapi/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 moduleLine 11 still mentions
vue-eslint-parser
, but the adjacent line actually importseslint-plugin-storybook
. Update the comment to avoid confusion.-// Import vue-eslint-parser as an ESM import +// Import eslint-plugin-storybook as an ESM importweb/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:
- Path validation: Ensure the pages directory exists and is within expected bounds
- Caching: This reads the filesystem on every request - consider caching the results
- 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 usingtoFixed()
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 assertionThe 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 implementationThe
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 safetyThe 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 descriptionThe 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 DateTimeISOapi/src/unraid-api/graph/resolvers/backup/backup.model.ts (1)
184-188
: Remove unnecessary ValidateIf decoratorThe
ValidateIf
decorator on theenabled
field is unnecessary sinceenabled
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 codeReplace 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
⛔ 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
andnextTick
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 withnextTick
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
toverbose
for user role reporting is appropriate for operational visibility.
216-220
: LGTM - Consistent logging level adjustment.The change from
debug
toverbose
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
todebug
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 updatedLOG_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
andBackupModule
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 ofconfigStep
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
intoRootMutations
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, whileZfsValidationService
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 withcurrent
andtotal
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
withif/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 goodThe 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 implementationThe 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 suggestionsThe 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 formattingThe 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 logicThe 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 processingThe 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 supportThe addition of
async
andconfigId
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 serviceExcellent 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 mutationsThe file correctly follows the naming convention for GraphQL queries (
.query.ts
) and properly uses thegraphql
composable function as per project standards.api/src/unraid-api/graph/resolvers/backup/destination/backup-destination-processor.interface.ts (1)
1-60
: Clean interface definitionsWell-structured interfaces and abstract class for backup destination processors.
api/generated-schema.graphql (2)
712-713
: Verify the need for two date-time scalar typesThe schema now has both
DateTime
andDateTimeISO
scalars. This could cause confusion for API consumers.Please verify whether both scalars are necessary and consider:
- Documenting the specific use cases for each
- Consolidating to a single date-time scalar if possible
- 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 logicThe 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
api/dev/Unraid.net/myservers.cfg
Outdated
@@ -1,5 +1,5 @@ | |||
[api] | |||
version="4.4.1" | |||
version="4.8.0" |
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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"; |
There was a problem hiding this comment.
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'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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.
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'); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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; | ||
}, | ||
}); |
There was a problem hiding this comment.
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.
// If git repo was initialized, include it in the backup | ||
if (gitRepoInitialized && tempGitPath) { | ||
excludeArgs.push('--exclude', '.git-backup-temp'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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); |
There was a problem hiding this comment.
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:
- Document this limitation clearly
- Implement git repository setup before streaming
- 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 intogenerateStreamCommand
. - 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.
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]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect git repository initialization sequence
The git operations sequence has critical issues:
- Git repo is initialized in
tempGitPath
(line 146) butgit add
is run inflashPath
(line 166) where no.git
directory exists - 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.
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); |
private async executeStreamingBackup( | ||
sourceProcessor: BackupSourceProcessor<any>, | ||
destinationProcessor: BackupDestinationProcessor<any>, | ||
jobConfig: BackupJobConfig, // This is the config object, not its ID | ||
internalJobId: string | ||
): Promise<void> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this 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...
api/src/unraid-api/graph/resolvers/backup/orchestration/backup-orchestration.service.ts
Show resolved
Hide resolved
this.jobTrackingService.updateJobStatus(internalJobId, { | ||
status: BackupJobStatus.FAILED, | ||
error: errorMsg, | ||
}); |
There was a problem hiding this comment.
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.
@Field(() => SourceConfigUnion, { description: 'Source configuration for this backup job' }) | ||
sourceConfig!: typeof SourceConfigUnion; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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.
There was a problem hiding this 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 ofinternalJobId
as the first parameter.
358-361
: Remove redundant job status updates.The
updateJobStatus
calls are redundant sinceemitJobStatus
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 thename
field could allow thename
parameter to be overridden ifinput.parameters
contains aname
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
⛔ 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.
🚀 Storybook has been deployed to staging: https://unraid-ui-storybook-staging.unraid-workers.workers.dev |
There was a problem hiding this 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
⛔ 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
: Verifyvue-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.
.claude/settings.local.json
Outdated
"Bash(pnpm --filter \"*connect*\" test connect-status-writer.service.spec)", | ||
"Bash(pnpm add:*)", | ||
"Bash(npx tsc:*)", | ||
"Bash(pnpm list:*)", | ||
"Bash(rm:*)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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:
- Moving those steps to a dedicated CI job with least-privilege credentials.
- 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.
"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", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
🚀 Storybook has been deployed to staging: https://unraid-ui-storybook-staging.unraid-workers.workers.dev |
There was a problem hiding this 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
⛔ 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" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
"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.
"ignore": "7.0.5", | ||
"vitest": "3.2.4" |
There was a problem hiding this comment.
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.
"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", |
There was a problem hiding this comment.
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.
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Style
Chores
Tests