Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
efb3e58
feat: add custom dialog component to unraid ui
Jun 17, 2025
8d80fed
create story and temp move new dialog for rebase
Jun 18, 2025
bd5a496
chore: add claude and pnpm-lock changes
Jun 18, 2025
5d67182
refactor: update Dialog component functionality and refactor ApiKeyCr…
Jun 19, 2025
e5be368
refactor: create custom dialog and accordion modals and apply to ApiK…
Jun 20, 2025
8c05b46
refactor: update accordion story with use case patterns
Jun 20, 2025
c1cc18d
refactor: install latest dropdown-menu and export setup
Jun 23, 2025
e56f2dd
refactor: add component files
Jun 23, 2025
52812eb
refactor: update imports, update UserProfile with new dropdown menu a…
Jun 23, 2025
aca07e2
feat: add custom select component and move to ui directory
Jun 25, 2025
2ff40d1
refactor: cleanup Select stories and component and replace in ApiKeyC…
Jun 25, 2025
da75eae
refactor: apply coderabbit suggestions
Jun 25, 2025
2250f90
fix: change var to let to fix lint error
Jun 25, 2025
acfe783
fix: revert let back to var
Jun 25, 2025
0ba3960
chore: add eslint disable no-var
Jun 26, 2025
9d4a728
refactor: rename slot from default
Jun 26, 2025
051283c
chore: update @jsonforms/core to 3.6.0
Jun 26, 2025
88062e9
fix: update sheet story with custom select
Jul 1, 2025
3691e6a
refactor: add teleports to new shadcn primitives
Jul 2, 2025
4649b3a
refactor: add responsive classes to UserProfile menu
Jul 2, 2025
0bf3594
chore: update package.json with pnpm up
Jul 2, 2025
29d94d4
chore: upgrade graphql
elibosley Jul 3, 2025
b704b4a
feat: add size prop to dialog component
Jul 3, 2025
e14c4f7
refactor: swap out primitives with new select component in Sidebar
Jul 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This is the Unraid API monorepo containing multiple packages that provide API fu
## Essential Commands

### Development

```bash
pnpm install # Install all dependencies
pnpm dev # Run all dev servers concurrently
Expand All @@ -23,6 +24,7 @@ pnpm build:watch # Watch mode with local plugin build
```

### Testing & Code Quality

```bash
pnpm test # Run all tests
pnpm lint # Run linting
Expand All @@ -31,47 +33,55 @@ pnpm type-check # TypeScript type checking
```

### API Development

```bash
cd api && pnpm dev # Run API server (http://localhost:3001)
cd api && pnpm test:watch # Run tests in watch mode
cd api && pnpm codegen # Generate GraphQL types
```

### Deployment

```bash
pnpm unraid:deploy <SERVER_IP> # Deploy all to Unraid server
```

## Architecture Notes

### API Structure (NestJS)

- Modules: `auth`, `config`, `plugins`, `emhttp`, `monitoring`
- GraphQL API with Apollo Server at `/graphql`
- Redux store for state management in `src/store/`
- Plugin system for extending functionality
- Entry points: `src/index.ts` (server), `src/cli.ts` (CLI)

### Key Patterns

- TypeScript imports use `.js` extensions (ESM compatibility)
- NestJS dependency injection with decorators
- GraphQL schema-first approach with code generation
- API plugins follow specific structure (see `api/docs/developer/api-plugins.md`)

### Authentication

- API key authentication via headers
- Cookie-based session management
- Keys stored in `/boot/config/plugins/unraid-api/`

### Development Workflow

1. Work Intent required before starting development
2. Fork from `main` branch
3. Reference Work Intent in PR
4. No direct pushes to main

### Debug Mode

```bash
LOG_LEVEL=debug unraid-api start --debug
```

Enables GraphQL playground at `http://tower.local/graphql`

## Coding Guidelines
Expand Down
174 changes: 87 additions & 87 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,97 +52,97 @@
"unraid-api": "dist/cli.js"
},
"dependencies": {
"@apollo/client": "^3.11.8",
"@apollo/server": "^4.11.2",
"@apollo/client": "^3.13.8",
"@apollo/server": "^4.12.2",
"@as-integrations/fastify": "^2.1.1",
"@fastify/cookie": "^11.0.2",
"@fastify/helmet": "^13.0.1",
"@graphql-codegen/client-preset": "^4.5.0",
"@graphql-tools/load-files": "^7.0.0",
"@graphql-tools/merge": "^9.0.8",
"@graphql-tools/schema": "^10.0.7",
"@graphql-tools/utils": "^10.5.5",
"@jsonforms/core": "^3.5.1",
"@nestjs/apollo": "^13.0.3",
"@graphql-codegen/client-preset": "^4.8.3",
"@graphql-tools/load-files": "^7.0.1",
"@graphql-tools/merge": "^9.0.24",
"@graphql-tools/schema": "^10.0.23",
"@graphql-tools/utils": "^10.8.6",
"@jsonforms/core": "^3.6.0",
"@nestjs/apollo": "^13.1.0",
"@nestjs/cache-manager": "^3.0.1",
"@nestjs/common": "^11.0.11",
"@nestjs/common": "^11.1.3",
"@nestjs/config": "^4.0.2",
"@nestjs/core": "^11.0.11",
"@nestjs/core": "^11.1.3",
"@nestjs/event-emitter": "^3.0.1",
"@nestjs/graphql": "^13.0.3",
"@nestjs/passport": "^11.0.0",
"@nestjs/platform-fastify": "^11.0.11",
"@nestjs/graphql": "^13.1.0",
"@nestjs/passport": "^11.0.5",
"@nestjs/platform-fastify": "^11.1.3",
"@nestjs/schedule": "^6.0.0",
"@nestjs/throttler": "^6.4.0",
"@reduxjs/toolkit": "^2.3.0",
"@reduxjs/toolkit": "^2.8.2",
"@runonflux/nat-upnp": "^1.0.2",
"@types/diff": "^8.0.0",
"@unraid/libvirt": "^2.1.0",
"@unraid/shared": "workspace:*",
"accesscontrol": "^2.2.1",
"bycontract": "^2.0.11",
"bytes": "^3.1.2",
"cache-manager": "^7.0.0",
"cache-manager": "^7.0.1",
"cacheable-lookup": "^7.0.0",
"camelcase-keys": "^9.1.3",
"casbin": "^5.32.0",
"casbin": "^5.38.0",
"change-case": "^5.4.4",
"chokidar": "^4.0.1",
"chokidar": "^4.0.3",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"class-validator": "^0.14.2",
"cli-table": "^0.3.11",
"command-exists": "^1.2.9",
"convert": "^5.8.0",
"convert": "^5.12.0",
"cookie": "^1.0.2",
"cron": "4.3.1",
"cross-fetch": "^4.0.0",
"diff": "^8.0.0",
"dockerode": "^4.0.5",
"dotenv": "^16.4.5",
"execa": "^9.5.1",
"cross-fetch": "^4.1.0",
"diff": "^8.0.2",
"dockerode": "^4.0.7",
"dotenv": "^16.6.1",
"execa": "^9.6.0",
"exit-hook": "^4.0.0",
"fastify": "^5.2.1",
"fastify": "^5.4.0",
"filenamify": "^6.0.0",
"fs-extra": "^11.2.0",
"glob": "^11.0.1",
"fs-extra": "^11.3.0",
"glob": "^11.0.3",
"global-agent": "^3.0.0",
"got": "^14.4.6",
"graphql": "^16.9.0",
"got": "^14.4.7",
"graphql": "^16.11.0",
"graphql-fields": "^2.0.3",
"graphql-scalars": "^1.23.0",
"graphql-scalars": "^1.24.2",
"graphql-subscriptions": "^3.0.0",
"graphql-tag": "^2.12.6",
"graphql-ws": "^6.0.0",
"graphql-ws": "^6.0.5",
"ini": "^5.0.0",
"ip": "^2.0.1",
"jose": "^6.0.0",
"jose": "^6.0.11",
"json-bigint-patch": "^0.0.8",
"lodash-es": "^4.17.21",
"multi-ini": "^2.3.2",
"mustache": "^4.2.0",
"nest-authz": "^2.14.0",
"nest-commander": "^3.15.0",
"nestjs-pino": "^4.1.0",
"nest-authz": "^2.17.0",
"nest-commander": "^3.17.0",
"nestjs-pino": "^4.4.0",
"node-cache": "^5.1.2",
"node-window-polyfill": "^1.0.2",
"p-retry": "^6.2.0",
"node-window-polyfill": "^1.0.4",
"p-retry": "^6.2.1",
"passport-custom": "^1.1.1",
"passport-http-header-strategy": "^1.1.0",
"path-type": "^6.0.0",
"pino": "^9.5.0",
"pino-http": "^10.3.0",
"pino": "^9.7.0",
"pino-http": "^10.5.0",
"pino-pretty": "^13.0.0",
"pm2": "^6.0.0",
"pm2": "^6.0.8",
"reflect-metadata": "^0.1.14",
"request": "^2.88.2",
"rxjs": "^7.8.2",
"semver": "^7.6.3",
"semver": "^7.7.2",
"strftime": "^0.10.3",
"systeminformation": "^5.25.11",
"uuid": "^11.0.2",
"ws": "^8.18.0",
"systeminformation": "^5.27.7",
"uuid": "^11.1.0",
"ws": "^8.18.3",
"zen-observable-ts": "^1.1.0",
"zod": "^3.23.8"
"zod": "^3.25.69"
},
"peerDependencies": {
"unraid-api-plugin-connect": "workspace:*"
Expand All @@ -153,67 +153,67 @@
}
},
"devDependencies": {
"@eslint/js": "^9.21.0",
"@eslint/js": "^9.30.1",
"@graphql-codegen/add": "^5.0.3",
"@graphql-codegen/cli": "^5.0.3",
"@graphql-codegen/fragment-matcher": "^5.0.2",
"@graphql-codegen/import-types-preset": "^3.0.0",
"@graphql-codegen/typed-document-node": "^5.0.11",
"@graphql-codegen/typescript": "^4.1.1",
"@graphql-codegen/typescript-operations": "^4.3.1",
"@graphql-codegen/cli": "^5.0.7",
"@graphql-codegen/fragment-matcher": "^5.1.0",
"@graphql-codegen/import-types-preset": "^3.0.1",
"@graphql-codegen/typed-document-node": "^5.1.2",
"@graphql-codegen/typescript": "^4.1.6",
"@graphql-codegen/typescript-operations": "^4.6.1",
"@graphql-codegen/typescript-resolvers": "4.5.1",
"@graphql-typed-document-node/core": "^3.2.0",
"@ianvs/prettier-plugin-sort-imports": "^4.4.0",
"@nestjs/testing": "^11.0.11",
"@ianvs/prettier-plugin-sort-imports": "^4.4.2",
"@nestjs/testing": "^11.1.3",
"@originjs/vite-plugin-commonjs": "^1.0.3",
"@rollup/plugin-node-resolve": "^16.0.0",
"@swc/core": "^1.10.1",
"@rollup/plugin-node-resolve": "^16.0.1",
"@swc/core": "^1.12.9",
"@types/async-exit-hook": "^2.0.2",
"@types/bytes": "^3.1.4",
"@types/bytes": "^3.1.5",
"@types/cli-table": "^0.3.4",
"@types/command-exists": "^1.2.3",
"@types/cors": "^2.8.17",
"@types/dockerode": "^3.3.31",
"@types/cors": "^2.8.19",
"@types/dockerode": "^3.3.42",
"@types/graphql-fields": "^1.3.9",
"@types/graphql-type-uuid": "^0.2.6",
"@types/ini": "^4.1.1",
"@types/ip": "^1.1.3",
"@types/lodash": "^4.17.13",
"@types/lodash": "^4.17.20",
"@types/lodash-es": "^4.17.12",
"@types/mustache": "^4.2.5",
"@types/node": "^22.13.4",
"@types/pify": "^6.0.0",
"@types/semver": "^7.5.8",
"@types/mustache": "^4.2.6",
"@types/node": "^22.16.0",
"@types/pify": "^6.1.0",
"@types/semver": "^7.7.0",
"@types/sendmail": "^1.4.7",
"@types/stoppable": "^1.1.3",
"@types/strftime": "^0.9.8",
"@types/uuid": "^10.0.0",
"@types/ws": "^8.5.13",
"@types/ws": "^8.18.1",
"@types/wtfnode": "^0.7.3",
"@vitest/coverage-v8": "^3.0.5",
"@vitest/ui": "^3.0.5",
"@vitest/coverage-v8": "^3.2.4",
"@vitest/ui": "^3.2.4",
"cz-conventional-changelog": "3.3.0",
"eslint": "^9.20.1",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-n": "^17.0.0",
"eslint": "^9.30.1",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-n": "^17.20.0",
"eslint-plugin-no-relative-import-paths": "^1.6.1",
"eslint-plugin-prettier": "^5.2.3",
"graphql-codegen-typescript-validation-schema": "^0.17.0",
"jiti": "^2.4.0",
"nodemon": "^3.1.7",
"prettier": "^3.5.2",
"rollup-plugin-node-externals": "^8.0.0",
"eslint-plugin-prettier": "^5.5.1",
"graphql-codegen-typescript-validation-schema": "^0.17.1",
"jiti": "^2.4.2",
"nodemon": "^3.1.10",
"prettier": "^3.6.2",
"rollup-plugin-node-externals": "^8.0.1",
"standard-version": "^9.5.0",
"tsx": "^4.19.3",
"type-fest": "^4.37.0",
"typescript": "^5.6.3",
"typescript-eslint": "^8.13.0",
"unplugin-swc": "^1.5.1",
"vite": "^6.0.0",
"vite-plugin-node": "^5.0.0",
"vite-tsconfig-paths": "^5.1.0",
"vitest": "^3.0.5",
"zx": "^8.3.2"
"tsx": "^4.20.3",
"type-fest": "^4.41.0",
"typescript": "^5.8.3",
"typescript-eslint": "^8.35.1",
"unplugin-swc": "^1.5.5",
"vite": "^6.3.5",
"vite-plugin-node": "^5.0.1",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.2.4",
"zx": "^8.6.1"
},
"overrides": {
"eslint": {
Expand Down
8 changes: 4 additions & 4 deletions packages/unraid-api-plugin-connect/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"@graphql-codegen/cli": "^5.0.3",
"@graphql-typed-document-node/core": "^3.2.0",
"@ianvs/prettier-plugin-sort-imports": "^4.4.1",
"@jsonforms/core": "^3.5.1",
"@jsonforms/core": "^3.6.0",
"@nestjs/apollo": "^13.0.3",
"@nestjs/common": "^11.0.11",
"@nestjs/config": "^4.0.2",
Expand All @@ -49,7 +49,7 @@
"execa": "^9.5.1",
"fast-check": "^4.1.1",
"got": "^14.4.6",
"graphql": "^16.9.0",
"graphql": "^16.11.0",
"graphql-scalars": "^1.23.0",
"graphql-subscriptions": "^3.0.0",
"graphql-ws": "^6.0.0",
Expand All @@ -74,7 +74,7 @@
"peerDependencies": {
"@apollo/client": "^3.11.8",
"@graphql-typed-document-node/core": "^3.2.0",
"@jsonforms/core": "^3.5.1",
"@jsonforms/core": "^3.6.0",
"@nestjs/apollo": "^13.0.3",
"@nestjs/common": "^11.0.11",
"@nestjs/config": "^4.0.2",
Expand All @@ -88,7 +88,7 @@
"class-validator": "^0.14.1",
"execa": "^9.5.1",
"got": "^14.4.6",
"graphql": "^16.9.0",
"graphql": "^16.11.0",
"graphql-scalars": "^1.23.0",
"graphql-subscriptions": "^3.0.0",
"graphql-ws": "^6.0.0",
Expand Down
8 changes: 4 additions & 4 deletions packages/unraid-shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@
"description": "Shared utilities and types for Unraid API ecosystem",
"devDependencies": {
"@graphql-tools/utils": "^10.5.5",
"@jsonforms/core": "^3.5.1",
"@jsonforms/core": "^3.6.0",
"@nestjs/common": "^11.0.11",
"@nestjs/graphql": "^13.0.3",
"@types/bun": "^1.2.15",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.14.0",
"class-validator": "^0.14.1",
"graphql": "^16.9.0",
"graphql": "^16.11.0",
"graphql-scalars": "^1.23.0",
"lodash-es": "^4.17.21",
"nest-authz": "^2.14.0",
Expand All @@ -45,11 +45,11 @@
},
"peerDependencies": {
"@graphql-tools/utils": "^10.5.5",
"@jsonforms/core": "^3.5.1",
"@jsonforms/core": "^3.6.0",
"@nestjs/common": "^11.0.11",
"@nestjs/graphql": "^13.0.3",
"class-validator": "^0.14.1",
"graphql": "^16.9.0",
"graphql": "^16.11.0",
"graphql-scalars": "^1.23.0",
"lodash-es": "^4.17.21",
"nest-authz": "^2.14.0"
Expand Down
Loading