feat(dashboard): select optional Xray API services in both core editors - #662
feat(dashboard): select optional Xray API services in both core editors#662Multi-Engineer-dev wants to merge 13 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThe dashboard adds Xray API service helpers, validation, configuration controls, a dedicated core-editor section, localized UI text, tests, and Node.js test runtime configuration. ChangesXray API configuration
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant EditorPage
participant XrayCoreEditor
participant XrayApiSection
participant XrayProfile
participant APIServiceHelpers
EditorPage->>XrayCoreEditor: select api section
XrayCoreEditor->>XrayApiSection: mount API controls
XrayApiSection->>XrayProfile: read raw.topLevel configuration
XrayApiSection->>APIServiceHelpers: derive selected and unknown services
APIServiceHelpers-->>XrayApiSection: return service state
XrayApiSection->>XrayProfile: toggle optional service
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@dashboard/package.json`:
- Around line 11-12: Update the test script in dashboard/package.json to use a
pinned Node runtime, or replace the node --test invocation with Bun’s test
runner so test execution is deterministic and aligned with the repository’s
existing Bun version pin.
In `@dashboard/public/statics/locales/en.json`:
- Around line 2236-2238: Add the missing alwaysOn and unknown localization keys
to the api objects in dashboard/public/statics/locales/en.json (2236-2238),
dashboard/public/statics/locales/fa.json (2151-2153), and
dashboard/public/statics/locales/ru.json (2125-2127), using the exact English,
Persian, and Russian translations specified in the review comment and preserving
the {{names}} interpolation placeholder.
In `@dashboard/public/statics/locales/zh.json`:
- Around line 2196-2199: Add the missing coreEditor.api.alwaysOn and
coreEditor.api.unknown translation keys to the api locale sections in fa.json,
ru.json, and zh.json, using appropriate translations consistent with each
locale’s existing terminology and the English defaults.
In `@dashboard/src/features/nodes/dialogs/core-config-modal.tsx`:
- Around line 153-164: Gate the API-service derivation in the useMemo containing
selectedApiServices and unknownApiServices with isXrayBackend (or backendType
!== 'wg'), returning empty API-service lists for WireGuard configurations. Apply
the same Xray-only guard to the submit validation near the related submission
logic so unknown API services cannot block wg configurations, while preserving
existing Xray validation.
- Around line 166-175: Update handleToggleApiService to validate that the parsed
JSON is a non-null object before passing it to setOptionalService; return early
for null, arrays, and primitive values while preserving the existing behavior
for valid configuration objects.
In `@dashboard/src/lib/xray-api-services.ts`:
- Around line 66-68: Restrict the helper using CANONICAL_API_SERVICES to the
optional-services set so required services such as HandlerService are ignored
and the existing config is returned unchanged. Add tests covering both enabling
and disabling a required service, asserting each operation is a no-op.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 83f34bfa-3e98-4edd-8dd7-7b2cfc574bf4
📒 Files selected for processing (15)
.gitignoredashboard/package.jsondashboard/public/statics/locales/en.jsondashboard/public/statics/locales/fa.jsondashboard/public/statics/locales/ru.jsondashboard/public/statics/locales/zh.jsondashboard/src/components/layout/page-header.tsxdashboard/src/features/core-editor/components/xray/xray-api-section.tsxdashboard/src/features/core-editor/components/xray/xray-core-editor.tsxdashboard/src/features/core-editor/kit/core-section-nav.tsdashboard/src/features/core-editor/routes/core-editor-page.tsxdashboard/src/features/core-editor/state/core-editor-store.tsdashboard/src/features/nodes/dialogs/core-config-modal.tsxdashboard/src/lib/xray-api-services.test.tsdashboard/src/lib/xray-api-services.ts
| "api": { | ||
| "title": "API Services", | ||
| "hint": "gRPC API services exposed by this core. The node always enables the required services; enable optional ones as needed." |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Missing localization keys for the API section.
The translation keys alwaysOn and unknown are utilized in the xray-api-section.tsx component via t('coreEditor.api.alwaysOn', ...) and t('coreEditor.api.unknown', ...), but they were omitted from the localization bundles. Although fallback values are provided in the code, missing keys prevent proper localization.
dashboard/public/statics/locales/en.json#L2236-L2238: add"alwaysOn": "always on"and"unknown": "Unrecognized API service(s): {{names}}. Fix them in the Advanced tab."to theapiobject.dashboard/public/statics/locales/fa.json#L2151-L2153: add"alwaysOn": "همیشه روشن"and"unknown": "سرویس(های) API ناشناخته: {{names}}. آنها را در تب پیشرفته اصلاح کنید."to theapiobject.dashboard/public/statics/locales/ru.json#L2125-L2127: add"alwaysOn": "всегда включено"and"unknown": "Нераспознанные сервисы API: {{names}}. Исправьте их на вкладке «Дополнительно»."to theapiobject.
📍 Affects 3 files
dashboard/public/statics/locales/en.json#L2236-L2238(this comment)dashboard/public/statics/locales/fa.json#L2151-L2153dashboard/public/statics/locales/ru.json#L2125-L2127
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@dashboard/public/statics/locales/en.json` around lines 2236 - 2238, Add the
missing alwaysOn and unknown localization keys to the api objects in
dashboard/public/statics/locales/en.json (2236-2238),
dashboard/public/statics/locales/fa.json (2151-2153), and
dashboard/public/statics/locales/ru.json (2125-2127), using the exact English,
Persian, and Russian translations specified in the review comment and preserving
the {{names}} interpolation placeholder.
| "api": { | ||
| "title": "API 服务", | ||
| "hint": "此核心提供的 gRPC API 服务。节点始终启用必需的服务;可按需启用可选服务。" | ||
| }, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Verify the presence of the new `alwaysOn` and `unknown` keys across all locale files.
for file in dashboard/public/statics/locales/*.json; do
echo "--- $file ---"
jq '.coreEditor.api | {title, alwaysOn, unknown}' "$file"
doneRepository: PasarGuard/panel
Length of output: 620
🏁 Script executed:
rg -n '"(alwaysOn|unknown)"|coreEditor\.api|XrayApiSection' dashboard/public/statics/locales dashboard -g '*.json' -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx'Repository: PasarGuard/panel
Length of output: 1712
🏁 Script executed:
python3 - <<'PY'
import json, pathlib
for name in ['en','fa','ru','zh']:
p = pathlib.Path('dashboard/public/statics/locales/%s.json' % name)
data = json.loads(p.read_text(encoding='utf-8'))
api = data.get('coreEditor', {}).get('api', {})
print(f'--- {p} ---')
for k in ['title','hint','alwaysOn','unknown']:
print(k, '=>', api.get(k))
PYRepository: PasarGuard/panel
Length of output: 1025
Add the missing coreEditor.api locale keys.
XrayApiSection reads coreEditor.api.alwaysOn and coreEditor.api.unknown, and they’re missing from the non-English locale files in this PR (fa.json, ru.json, zh.json), so those users will fall back to the English defaults.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@dashboard/public/statics/locales/zh.json` around lines 2196 - 2199, Add the
missing coreEditor.api.alwaysOn and coreEditor.api.unknown translation keys to
the api locale sections in fa.json, ru.json, and zh.json, using appropriate
translations consistent with each locale’s existing terminology and the English
defaults.
…ject json api.services is Xray-only, but the submit validation ran before the backend type was read, so a WireGuard config carrying an api.services block could be rejected by Xray rules; the derivation memo was likewise unscoped. Both now gate on the backend type, matching the existing isXrayBackend render gate. handleToggleApiService also accepted any valid JSON: toggling on a non-object config (null/array/primitive) silently replaced or mangled it on re-serialize. Toggles now early-return unless the config is a plain object. Addresses CodeRabbit review on PasarGuard#662.
…vice The helper resolved names via CANONICAL_API_SERVICES, which also contains the required services, so a caller could write HandlerService into api.services -- contradicting the documented invariant that the panel never writes them (the node injects required services itself). Restrict the lookup to the optional set and pin the invariant with enable/disable no-op tests. Addresses CodeRabbit review on PasarGuard#662.
coreEditor.api.alwaysOn / .unknown were read by the structured editor's API
section but missing from every locale, so fa/ru/zh fell back to the inline
English defaults. The legacy modal's coreConfigModal.apiServices /
apiServiceAlwaysOn / apiServicesUnknown keys had the same gap. Add all of them
to en/fa/ru/zh (with the {{names}} interpolation preserved).
Addresses CodeRabbit review on PasarGuard#662.
The test script runs node --test over .ts files, which relies on native type stripping (default since Node 22.18/23.6) and test-runner globs; the repo only pinned bun. Document the real constraint with an engines field. Addresses CodeRabbit review on PasarGuard#662.
Adds an "API" section to the route-based core editor (Nodes > Cores), mirroring the legacy core-config modal's control. Reuses the existing xray-api-services helpers; optional services are stored on the profile's preserved top-level `api` block and persisted through the xray adapter.
…ction Unchecking the last optional api service emptied raw.topLevel.api, so the adapter override disappeared and the kit re-emitted the original api from raw.source, leaving the persisted config unchanged (Save never enabled and the removal would not stick). setRawOptionalService now edits raw.source and raw.topLevel in lockstep so toggles round-trip cleanly. The API section header rendered the raw i18n key whenever a stale (service-worker cached) locale bundle lacked the new keys. PageHeader now accepts title/description defaults, matching the codebase's defaultValue pattern, so the header reads correctly regardless of cache state.
The structured core editor's API section was only partly localized: - coreEditor.section.api / sectionDesc.api existed in en.json only, so fa/ru/zh fell back to English for the section header. - coreEditor.api.title / api.hint (the section card title and hint) were inline English defaultValues, absent from every locale file. Add the section header keys to fa/ru/zh and the card title + hint to all four locales (the "API" acronym is kept; descriptive text translated).
…ject json api.services is Xray-only, but the submit validation ran before the backend type was read, so a WireGuard config carrying an api.services block could be rejected by Xray rules; the derivation memo was likewise unscoped. Both now gate on the backend type, matching the existing isXrayBackend render gate. handleToggleApiService also accepted any valid JSON: toggling on a non-object config (null/array/primitive) silently replaced or mangled it on re-serialize. Toggles now early-return unless the config is a plain object. Addresses CodeRabbit review on PasarGuard#662.
…vice The helper resolved names via CANONICAL_API_SERVICES, which also contains the required services, so a caller could write HandlerService into api.services -- contradicting the documented invariant that the panel never writes them (the node injects required services itself). Restrict the lookup to the optional set and pin the invariant with enable/disable no-op tests. Addresses CodeRabbit review on PasarGuard#662.
coreEditor.api.alwaysOn / .unknown were read by the structured editor's API
section but missing from every locale, so fa/ru/zh fell back to the inline
English defaults. The legacy modal's coreConfigModal.apiServices /
apiServiceAlwaysOn / apiServicesUnknown keys had the same gap. Add all of them
to en/fa/ru/zh (with the {{names}} interpolation preserved).
Addresses CodeRabbit review on PasarGuard#662.
The test script runs node --test over .ts files, which relies on native type stripping (default since Node 22.18/23.6) and test-runner globs; the repo only pinned bun. Document the real constraint with an engines field. Addresses CodeRabbit review on PasarGuard#662.
662fd60 to
441c179
Compare
|
1. Unpinned Node for the test script — applied (441c179), via an 2/3. Missing locale keys — applied (81fadea), and extended. Added 4. Xray-only validation applied to WG configs — applied (1acea75). The 5. Non-object JSON toggle guard — applied (1acea75), with a corrected 6. Not addressed: the docstring-coverage pre-merge warning (35.71% < 80%). |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@dashboard/public/statics/locales/zh.json`:
- Line 748: Replace the placeholder value for the "disabled" localization key
with a proper Chinese translation, such as "已禁用", so the label renders correctly
in the UI.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5801404a-a439-4840-a883-45b1d7aa08f0
📒 Files selected for processing (15)
.gitignoredashboard/package.jsondashboard/public/statics/locales/en.jsondashboard/public/statics/locales/fa.jsondashboard/public/statics/locales/ru.jsondashboard/public/statics/locales/zh.jsondashboard/src/components/layout/page-header.tsxdashboard/src/features/core-editor/components/xray/xray-api-section.tsxdashboard/src/features/core-editor/components/xray/xray-core-editor.tsxdashboard/src/features/core-editor/kit/core-section-nav.tsdashboard/src/features/core-editor/routes/core-editor-page.tsxdashboard/src/features/core-editor/state/core-editor-store.tsdashboard/src/features/nodes/dialogs/core-config-modal.tsxdashboard/src/lib/xray-api-services.test.tsdashboard/src/lib/xray-api-services.ts
🚧 Files skipped from review as they are similar to previous changes (12)
- dashboard/src/features/core-editor/state/core-editor-store.ts
- dashboard/src/features/core-editor/components/xray/xray-core-editor.tsx
- dashboard/src/features/core-editor/components/xray/xray-api-section.tsx
- dashboard/src/features/core-editor/kit/core-section-nav.ts
- dashboard/public/statics/locales/ru.json
- dashboard/public/statics/locales/en.json
- dashboard/public/statics/locales/fa.json
- dashboard/src/lib/xray-api-services.test.ts
- .gitignore
- dashboard/src/features/nodes/dialogs/core-config-modal.tsx
- dashboard/src/features/core-editor/routes/core-editor-page.tsx
- dashboard/src/lib/xray-api-services.ts
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@dashboard/public/statics/locales/zh.json`:
- Line 748: Replace the placeholder value for the "disabled" localization key
with a proper Chinese translation, such as "已禁用", so the label renders correctly
in the UI.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5801404a-a439-4840-a883-45b1d7aa08f0
📒 Files selected for processing (15)
.gitignoredashboard/package.jsondashboard/public/statics/locales/en.jsondashboard/public/statics/locales/fa.jsondashboard/public/statics/locales/ru.jsondashboard/public/statics/locales/zh.jsondashboard/src/components/layout/page-header.tsxdashboard/src/features/core-editor/components/xray/xray-api-section.tsxdashboard/src/features/core-editor/components/xray/xray-core-editor.tsxdashboard/src/features/core-editor/kit/core-section-nav.tsdashboard/src/features/core-editor/routes/core-editor-page.tsxdashboard/src/features/core-editor/state/core-editor-store.tsdashboard/src/features/nodes/dialogs/core-config-modal.tsxdashboard/src/lib/xray-api-services.test.tsdashboard/src/lib/xray-api-services.ts
🚧 Files skipped from review as they are similar to previous changes (12)
- dashboard/src/features/core-editor/state/core-editor-store.ts
- dashboard/src/features/core-editor/components/xray/xray-core-editor.tsx
- dashboard/src/features/core-editor/components/xray/xray-api-section.tsx
- dashboard/src/features/core-editor/kit/core-section-nav.ts
- dashboard/public/statics/locales/ru.json
- dashboard/public/statics/locales/en.json
- dashboard/public/statics/locales/fa.json
- dashboard/src/lib/xray-api-services.test.ts
- .gitignore
- dashboard/src/features/nodes/dialogs/core-config-modal.tsx
- dashboard/src/features/core-editor/routes/core-editor-page.tsx
- dashboard/src/lib/xray-api-services.ts
🛑 Comments failed to post (1)
dashboard/public/statics/locales/zh.json (1)
748-748: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Replace the placeholder disabled label.
"??"is not a usable Chinese translation and will appear directly in the UI. Use a proper value such as"已禁用".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@dashboard/public/statics/locales/zh.json` at line 748, Replace the placeholder value for the "disabled" localization key with a proper Chinese translation, such as "已禁用", so the label renders correctly in the UI.
The key landed in PasarGuard#549 with "??"-style placeholder values in every non-English locale (zh "??", fa "???????", ru "????????"), so the label rendered as question marks. Fill in the proper translations, matching each locale's existing "disabled" terminology. Pre-existing on dev (not from this branch); surfaced by CodeRabbit's incremental review after the rebase. Fixed here since it's a one-line-per-file locale correction.
|
Fixed in 7da7180 — with two notes. Scope: this placeholder isn't from this branch. The finding was also incomplete: the same Validated: all four locale files parse and no |
What
Adds first-class support for selecting optional Xray gRPC API services from
the dashboard, in both core-config editors, plus the supporting validation,
persistence, and localization.
Why
Xray exposes optional API services (e.g.
RoutingService,ObservatoryService)beyond the always-on
HandlerService/LoggerService/StatsService.Operators previously had to hand-edit raw JSON to enable them. This adds a
guided, validated control and ensures the selection round-trips correctly
through the structured editor.
What's included
lib/xray-api-services.ts): canonical required andoptional service lists mirrored from xray-core, with pure helpers to read and
toggle the selected optional services. Unit tests pin the allowlist so it
can't drift silently.
services, with blocking validation that rejects unknown names and de-dupes
them, plus accessible label/checkbox associations.
the default route-based editor.
(title + hint) are translated across all four locales (en/fa/ru/zh); the
"API" acronym is kept as-is.
adapter re-emits
apifromraw.source, so toggles now updateraw.sourceand
raw.topLevelin lockstep (setRawOptionalService) — otherwise removingthe last optional service produced no diff and left Save disabled.
locale is served, via
defaultValuefallbacks onPageHeader.Tests
toggle-persistence fix.
esbuildintegration check against a real core config, lints, and aproduction build all pass.
Related
Dashboard half of the Xray API services feature, which spans three repos:
(instead of overwriting), fixes the
ObservatoryServicestartup crash, and addsthe
RoutingServiceRPCs: Node PR 60.Bridge PR 16.
This PR ships the enable/disable toggles; the dashboard UI to use
RoutingService(manage rules, balancers, test routes) is a follow-up on top of the bridge.
Summary by CodeRabbit