Repository navigation
Conversation
time - Add `finished_at` column to deployments table - Implement status-based timestamping for deployment completion - Update runtime reconciliation to skip non-existent containers - Fix Ko-fi popup mounting in dashboard sidebar - Update docker-compose configuration for local builds
customization - Add `project_type`, `buildCommand`, and `startCommand` fields to projects. - Implement dynamic `railpack.json` generation for better build/runtime compatibility. - Add `ProjectSettingsTab` to the dashboard for managing build settings. - Update Caddy reverse proxy to correctly pass the Host header to upstream containers.
|
Warning Review limit reached
Next review available in: 51 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. 📝 WalkthroughWalkthroughThe release adds project type and build/start command configuration, dynamic Railpack build generation, build-safe environment filtering, deployment completion timestamps, project-aware deployment branches, scaling and runtime handling updates, dashboard project settings, local Compose builds, and v0.2.1 release tooling. ChangesProject configuration and dashboard settings
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant ProjectSettingsTab
participant useUpdateProject
participant API
participant ProjectRepository
participant Database
ProjectSettingsTab->>useUpdateProject: submit project settings
useUpdateProject->>API: update project payload
API->>ProjectRepository: update project fields
ProjectRepository->>Database: persist project_type and commands
Database-->>ProjectRepository: updated row
ProjectRepository-->>API: updated project
API-->>ProjectSettingsTab: mutation result
Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 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 |
There was a problem hiding this comment.
Actionable comments posted: 17
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
apps/api/src/orchestrator/pipeline.ts (2)
391-411: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winUse the deployment environment for build variables.
Line 391 always loads
production, while the runtime path usesdeployment.environment. A non-production deployment can therefore embed production public values during its build. Usedeployment.environment ?? undefinedhere as well.Proposed fix
- const envVars = deployment.projectId ? await listEnvironmentVariablesForDeploy(deployment.projectId, "production") : []; + const envVars = deployment.projectId + ? await listEnvironmentVariablesForDeploy( + deployment.projectId, + deployment.environment ?? undefined, + ) + : [];🤖 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 `@apps/api/src/orchestrator/pipeline.ts` around lines 391 - 411, Update the environment argument in the envVars lookup within the build pipeline before buildWithRailpack, replacing the hardcoded "production" value with deployment.environment ?? undefined. Keep the existing filterBuildEnvVars and buildWithRailpack flow unchanged.
284-705: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftSplit this oversized orchestrator.
apps/api/src/orchestrator/pipeline.tsis 881 lines. Extract cohesive deployment-build, runtime-deploy, and rollback responsibilities before expanding it further.As per coding guidelines, “No file should be above 500 lines of code; if it is, refactor and split into smaller files with proper feature grouping in a folder rather than scattered across the codebase”.
🤖 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 `@apps/api/src/orchestrator/pipeline.ts` around lines 284 - 705, Refactor the oversized runDeployment method in the deployment orchestrator into cohesive modules under a focused orchestrator feature folder, keeping pipeline.ts below 500 lines. Extract the build/source preparation flow, runtime deployment configuration and execution, and rollback/failure cleanup responsibilities into appropriately named helpers or services, while preserving runDeployment’s existing status updates, cancellation handling, cleanup, and return behavior.Source: Coding guidelines
apps/docs/.astro/astro/content.d.ts (1)
143-165: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winGenerated types are stale:
v0.2.1.mdis missing from thechangelogscollection.This PR adds
apps/docs/src/content/changelogs/v0.2.1.md, but the committedContentEntryMaponly lists up tov0.2.0.md, while an unrelateddocs/changelog.mdentry was added at Lines 174-180. Re-runastro syncand commit the regenerated file — or addapps/docs/.astro/to.gitignoreso this artifact stops drifting from the content directory.🤖 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 `@apps/docs/.astro/astro/content.d.ts` around lines 143 - 165, Regenerate the ContentEntryMap in the generated content types so the “changelogs” collection includes the new “v0.2.1.md” entry and remove the unrelated “docs/changelog.md” entry if it was generated incorrectly. Use the Astro sync workflow to update the generated artifact, or configure the project to ignore “apps/docs/.astro/” so committed generated types no longer drift.apps/web/src/components/project/create/CreateProjectDialog.tsx (1)
381-499: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftSplit the oversized project-creation components into feature-focused modules.
Both changed files exceed the 500-line limit; extract cohesive creation-flow sections rather than extending these components further.
apps/web/src/components/project/create/CreateProjectDialog.tsx#L381-L499: extract step orchestration/rendering into focused create-flow components or hooks.apps/web/src/components/project/create/StepBasics.tsx#L180-L222: extract general settings and source-detail sections into feature-grouped child components.As per coding guidelines, “No file should be above 500 lines of code; if it is, refactor and split into smaller files with proper feature grouping in a folder rather than scattered across the codebase.”
🤖 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 `@apps/web/src/components/project/create/CreateProjectDialog.tsx` around lines 381 - 499, Split the oversized project-creation components into feature-focused modules while preserving behavior: in apps/web/src/components/project/create/CreateProjectDialog.tsx lines 381-499, extract the step orchestration/rendering around StepBasics, StepEnvironment, and StepResources into focused components or hooks; in apps/web/src/components/project/create/StepBasics.tsx lines 180-222, extract the general-settings and source-details sections into grouped child components. Keep the extracted modules within the create feature area and ensure both original files remain under 500 lines.Source: Coding guidelines
🧹 Nitpick comments (4)
apps/api/src/scaling/__tests__/engine.test.ts (1)
95-95: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd regression cases for the new guard and resource propagation.
This fixture no longer exercises missing projects or non-positive CPU limits. Add explicit cases for those paths and verify scale-up forwards
--cpusand--memory.As per coding guidelines,
apps/api/src/**/*.ts: Runbun testinapps/api/before committing API changes.🤖 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 `@apps/api/src/scaling/__tests__/engine.test.ts` at line 95, Add regression tests in the engine test suite for missing projects and non-positive CPU limits, covering the new guard behavior. Extend the scale-up success case to verify the generated command forwards both --cpus and --memory values, and run bun test from apps/api before committing.Source: Coding guidelines
apps/docs/src/content/changelogs/v0.2.1.md (1)
8-15: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSeveral entries under "Improvements" are fixes.
Host-header forwarding, the reconciliation skip, and compose config are bug fixes; moving them under "Bug Fixes" makes the release notes more scannable.
🤖 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 `@apps/docs/src/content/changelogs/v0.2.1.md` around lines 8 - 15, Move the entries for Caddy Host-header forwarding, runtime reconciliation skipping non-existent containers, and Docker-compose configuration from the “Improvements” section into “Bug Fixes” in the changelog. Leave the remaining improvement entries unchanged.apps/api/src/orchestrator/railpack-config-utils.ts (2)
385-465: 🗄️ Data Integrity & Integration | 🔵 Trivial | 🏗️ Heavy liftSynthesizing workspace dependency versions is likely to build the wrong thing.
Falling back to a hardcoded
commonDepstable andversion = "*"for everything else silently resolves dependencies the user never pinned, and the hardcodededition = "2021"/rust-version = "1.89"may not match the real workspace. Failing the build with a clear "workspace root not found in the selected source dir" message is more predictable than guessing. At minimum, log which versions were substituted.🤖 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 `@apps/api/src/orchestrator/railpack-config-utils.ts` around lines 385 - 465, Remove the synthetic workspace metadata and dependency version substitution around commonDeps and the cargoContent replacement loop. Validate that the selected source directory includes the workspace root and fail with a clear “workspace root not found in the selected source dir” error when it does not, rather than guessing versions, edition, or rust-version; preserve existing content when the workspace root is present.
112-116: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueType the config instead of
Record<string, any>.A small interface (
caches,steps,deploy.startCommand) would catch key typos in the branches below at compile time.🤖 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 `@apps/api/src/orchestrator/railpack-config-utils.ts` around lines 112 - 116, Replace the broad Record<string, any> annotation on config with a focused interface describing caches, steps, and deploy.startCommand. Use that typed config throughout the surrounding utility so misspelled keys in its branches are caught at compile time, while preserving the existing defaults and behavior.
🤖 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 `@apps/api/package.json`:
- Line 13: Align the Elysia and `@sinclair/typebox` dependency declarations in
apps/api: either update the lockfile to resolve elysia within the declared
^1.1.26 range, or, if the resolved 1.4.x version is intended, update the elysia
range in package.json accordingly while retaining a compatible `@sinclair/typebox`
range.
In `@apps/api/src/api/projects/index.ts`:
- Around line 69-70: Guard the PATCH request body before the `"buildCommand" in
...` and `"startCommand" in ...` checks: require a non-null object and return
the handler’s established controlled 4xx response for primitive or otherwise
invalid bodies. Preserve the existing command normalization for valid object
bodies, and add a regression test covering JSON string or number payloads.
In `@apps/api/src/orchestrator/railpack-config-utils.ts`:
- Around line 335-371: The ancestor-walk boundary checks in the Rust lookup and
the corresponding Go lookup must not accept sibling paths that merely share the
workspace prefix. Update the checks around currentDir and the Go lookup’s
equivalent path variable to require workspace plus a path separator (or an
equivalent path.relative boundary test), while preserving traversal of the
workspace directory itself and stopping when the path leaves it.
- Around line 32-86: Restrict rewriteLocalhostBinding so it only changes
loopback values used in detected server bind/listen configuration, such as
127.0.0.1:<port> near listen, bind, or host settings, rather than replacing
every occurrence in allowed files. Preserve unrelated database targets,
allow-lists, proxy settings, and fixture data; alternatively require an explicit
project opt-in before applying the rewrite.
- Around line 235-296: Extract the duplicated static serving template into a
shared buildStaticServeScript(cleanSourceDir) helper, preferably in a sibling
static-serve-template module, and replace both serve-script branches with it.
Preserve the generated script’s behavior exactly, including directory selection,
URL decoding, file serving, SPA fallback, and 404 handling. Split
railpack-config-utils.ts and group Node, Rust, and Go detectors under a
railpack/ folder so no file exceeds 500 lines.
- Around line 235-239: Update the serveScript template construction to
interpolate cleanSourceDir using JSON.stringify(cleanSourceDir), preserving
valid and non-injectable JavaScript string syntax for quotes, backslashes, and
newlines.
- Around line 262-296: Update the generated Bun.serve static-server fetch
handler in both script copies to prevent traversal after decodeURIComponent:
resolve the requested path against staticDir, verify the resolved path remains
within staticDir, and return a 404 response without reading it when containment
fails. Apply the same containment check to the fallback flow while preserving
normal file serving and index.html fallback behavior.
- Around line 231-314: Update the isStatic classification in the surrounding
configuration flow so Node services without scripts.start or scripts.server are
not treated as static solely because hasPackageJson is true; reserve static
deployment for explicit static projects or reliably identified static builds.
Preserve the node dist/index.js fallback in the final else branch for backend
services, and avoid generating a Bun-dependent serve command when the selected
package manager/runtime is not Bun by using a compatible serving strategy.
In `@apps/api/src/orchestrator/railpack.ts`:
- Around line 357-363: Validate each user-supplied env key in the
opts.environmentVariables loop before pushing its --env argument: reject empty
keys and keys containing "=" or whitespace, using the existing error-handling
approach in the surrounding railpack flow. Only append --env for validated keys,
while preserving the current value formatting and workspace argument behavior.
In `@apps/api/src/scaling/engine.ts`:
- Around line 60-61: Update the project handling around getProjectById so a
missing or non-positive project.cpuLimit does not exit before scale-down
cleanup. Disable the scaling policy or reconcile existing replicas down to
minReplicas, then return; preserve normal scaling behavior when a valid CPU
limit exists.
- Line 283: Update Caddy route generation in
apps/api/src/scaling/engine.ts:283-283 and
apps/api/src/utils/domain-verifier.ts:147-147 so reverse_proxy target parsing
excludes the trailing “{” before counting replicas, or centralize generation to
ensure both use the same compatible format. Add regression coverage in
apps/api/src/utils/__tests__/domain-verifier.test.ts:154-160 verifying
block-style reverse_proxy output counts replicas correctly.
- Line 65: Update the scaling slug construction in the relevant scaling flow to
use the persisted project slug or a collision-safe value that includes the
canonical projectId after sanitization. Ensure the resulting routing slug is
always non-empty and unique, including for names that normalize identically or
contain only punctuation/whitespace, and keep it consistent with the slug used
by saveProject.
In `@apps/api/src/utils/env-filter.ts`:
- Around line 27-29: Remove SENTRY_AUTH_TOKEN from BUILD_SAFE_EXACT in
apps/api/src/utils/env-filter.ts (lines 27-29). In
apps/api/src/utils/__tests__/env-filter.test.ts (lines 48-56), add an assertion
confirming SENTRY_AUTH_TOKEN is rejected by the filter.
In `@apps/docs/src/content/changelogs/v0.2.1.md`:
- Line 11: Update the changelog entry to use the API’s consistent camelCase
field names, replacing project_type with projectType while preserving
buildCommand and startCommand.
In `@apps/web/src/components/project/create/CreateProjectDialog.tsx`:
- Around line 63-64: Update the dialog close-reset branch to call
setProjectType("web") alongside the existing creation-field resets, ensuring a
canceled static-project draft does not affect the next project.
In `@apps/web/src/components/project/settings/ProjectSettingsTab.tsx`:
- Around line 89-204: Remove the redundant JSX label comments in the project
settings form, including “Project Type,” “Root Directory / Source Dir,”
“Internal Port,” “Build Command Override,” and “Start Command Override,” while
leaving the surrounding controls and behavior unchanged.
- Around line 43-47: Update the project settings payload around port to accept
only integer values in the range 1–65535, using null for blank input and
rejecting invalid values rather than persisting them. Apply the same bounds
validation in the PATCH handler before saving, including values forwarded
through the existing persistence path.
---
Outside diff comments:
In `@apps/api/src/orchestrator/pipeline.ts`:
- Around line 391-411: Update the environment argument in the envVars lookup
within the build pipeline before buildWithRailpack, replacing the hardcoded
"production" value with deployment.environment ?? undefined. Keep the existing
filterBuildEnvVars and buildWithRailpack flow unchanged.
- Around line 284-705: Refactor the oversized runDeployment method in the
deployment orchestrator into cohesive modules under a focused orchestrator
feature folder, keeping pipeline.ts below 500 lines. Extract the build/source
preparation flow, runtime deployment configuration and execution, and
rollback/failure cleanup responsibilities into appropriately named helpers or
services, while preserving runDeployment’s existing status updates, cancellation
handling, cleanup, and return behavior.
In `@apps/docs/.astro/astro/content.d.ts`:
- Around line 143-165: Regenerate the ContentEntryMap in the generated content
types so the “changelogs” collection includes the new “v0.2.1.md” entry and
remove the unrelated “docs/changelog.md” entry if it was generated incorrectly.
Use the Astro sync workflow to update the generated artifact, or configure the
project to ignore “apps/docs/.astro/” so committed generated types no longer
drift.
In `@apps/web/src/components/project/create/CreateProjectDialog.tsx`:
- Around line 381-499: Split the oversized project-creation components into
feature-focused modules while preserving behavior: in
apps/web/src/components/project/create/CreateProjectDialog.tsx lines 381-499,
extract the step orchestration/rendering around StepBasics, StepEnvironment, and
StepResources into focused components or hooks; in
apps/web/src/components/project/create/StepBasics.tsx lines 180-222, extract the
general-settings and source-details sections into grouped child components. Keep
the extracted modules within the create feature area and ensure both original
files remain under 500 lines.
---
Nitpick comments:
In `@apps/api/src/orchestrator/railpack-config-utils.ts`:
- Around line 385-465: Remove the synthetic workspace metadata and dependency
version substitution around commonDeps and the cargoContent replacement loop.
Validate that the selected source directory includes the workspace root and fail
with a clear “workspace root not found in the selected source dir” error when it
does not, rather than guessing versions, edition, or rust-version; preserve
existing content when the workspace root is present.
- Around line 112-116: Replace the broad Record<string, any> annotation on
config with a focused interface describing caches, steps, and
deploy.startCommand. Use that typed config throughout the surrounding utility so
misspelled keys in its branches are caught at compile time, while preserving the
existing defaults and behavior.
In `@apps/api/src/scaling/__tests__/engine.test.ts`:
- Line 95: Add regression tests in the engine test suite for missing projects
and non-positive CPU limits, covering the new guard behavior. Extend the
scale-up success case to verify the generated command forwards both --cpus and
--memory values, and run bun test from apps/api before committing.
In `@apps/docs/src/content/changelogs/v0.2.1.md`:
- Around line 8-15: Move the entries for Caddy Host-header forwarding, runtime
reconciliation skipping non-existent containers, and Docker-compose
configuration from the “Improvements” section into “Bug Fixes” in the changelog.
Leave the remaining improvement entries unchanged.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 48e6b465-6efc-4bed-9a97-3935d3d2b5ac
📒 Files selected for processing (44)
VERSIONapps/api/package.jsonapps/api/src/api/deployments/index.tsapps/api/src/api/projects/index.tsapps/api/src/api/scaling/index.tsapps/api/src/db/migrate.tsapps/api/src/db/migrations/0002_colossal_flatman.sqlapps/api/src/db/migrations/0003_aberrant_viper.sqlapps/api/src/db/migrations/meta/0002_snapshot.jsonapps/api/src/db/migrations/meta/0003_snapshot.jsonapps/api/src/db/migrations/meta/_journal.jsonapps/api/src/db/repo/deployments.tsapps/api/src/db/repo/projects.tsapps/api/src/db/schema.tsapps/api/src/orchestrator/pipeline.tsapps/api/src/orchestrator/railpack-config-utils.tsapps/api/src/orchestrator/railpack.tsapps/api/src/orchestrator/runtime.tsapps/api/src/scaling/__tests__/engine.test.tsapps/api/src/scaling/engine.tsapps/api/src/types.tsapps/api/src/utils/__tests__/domain-verifier.test.tsapps/api/src/utils/__tests__/env-filter.test.tsapps/api/src/utils/domain-verifier.tsapps/api/src/utils/env-filter.tsapps/docs/.astro/astro/content.d.tsapps/docs/package.jsonapps/docs/src/content/changelogs/v0.2.1.mdapps/web/package.jsonapps/web/src/api/client.tsapps/web/src/components/layout/Sidebar.tsxapps/web/src/components/layout/SupportSection.tsxapps/web/src/components/project/create/CreateProjectDialog.tsxapps/web/src/components/project/create/StepBasics.tsxapps/web/src/components/project/deployments/deployment-logs.tsxapps/web/src/components/project/settings/ProjectSettingsTab.tsxapps/web/src/hooks/useProjects.tsapps/web/src/index.cssapps/web/src/routes/ProjectDetail.tsxapps/web/src/types/index.tsdocker-compose.ymlpackage.jsonscripts/dequelscripts/install.sh
💤 Files with no reviewable changes (1)
- apps/web/src/index.css
| }, | ||
| "dependencies": { | ||
| "@elysiajs/cors": "^1.1.1", | ||
| "@sinclair/typebox": "^0.34.13", |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
curl -s https://registry.npmjs.org/elysia/1.1.26 | jq '.dependencies["`@sinclair/typebox`"]'
curl -s https://registry.npmjs.org/@sinclair/typebox | jq '."dist-tags"'Repository: Lftobs/dequel
Length of output: 490
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== apps/api/package.json relevant dependencies =="
python3 - <<'PY'
import json, pathlib
p=pathlib.Path('apps/api/package.json')
if p.exists():
data=json.loads(p.read_text())
for sec in ['dependencies','devDependencies','peerDependencies']:
vals={k:v for k,v in data.get(sec,{}).items() if k in {'`@sinclair/typebox`','elysia'} or k.startswith('`@sinclair/typebox`')}
if vals:
print(sec, vals)
PY
echo
echo "== elysia package files mentioning TypeBox references =="
git ls-files '*.js' '*.ts' 'apps/**' 'packages/**' 2>/dev/null | rg 'packages|apps' | head -100
echo
rg -n "Symbol\.for\('TypeBox\.Kind'\)|function TypeBox|TypeBox\.Kind|Symbol\.FOR|Elysia" package.json apps packages 2>/dev/null || true
echo
echo "== lockfile `@sinclair/typebox` resolution snippets =="
for f in package-lock.json pnpm-lock.yaml yarn.lock bun.lockb bun.lock apps/api/package-lock.json apps/api/pnpm-lock.yaml apps/api/yarn.lock; do
if [ -f "$f" ]; then
echo "--- $f"
rg -n -A2 -B2 '`@sinclair/typebox`|elysia' "$f" | head -200
fi
done
echo
echo "== elysia 1.1.26 package registry summary =="
curl -s https://registry.npmjs.org/elysia/1.1.26 | jq '{version, dependencies, peerDependencies}'
echo
echo "== elysia 1.1.x `@sinclair/typebox` range across patch/minor if available =="
for patch in 1.1.0 1.1.1 1.1.10 1.1.20 1.1.26; do
echo "--- $patch"
curl -s "https://registry.npmjs.org/elysia/$patch" | jq '{version, dependencies, peerDependencies}' | rg '"`@sinclair/typebox`"|"Version|"Peer'
done
echo
echo "== local typebox import snippets =="
rg -n '"`@sinclair/typebox`"|from "`@sinclair/typebox`"|require\("`@sinclair/typebox`"\)' apps/api -S 2>/dev/null || trueRepository: Lftobs/dequel
Length of output: 7245
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== bun.lock `@sinclair/typebox` entries =="
if [ -f apps/api/bun.lock ]; then
rg -n -A3 -B3 '`@sinclair/typebox`' apps/api/bun.lock
else
echo "apps/api/bun.lock not found"
fi
echo
echo "== npm elysia 1.1.26 package tarball TypeBox file references =="
tmp="$(mktemp -d)"
curl -sL https://registry.npmjs.org/elysia/-/elysia-1.1.26.tgz -o "$tmp/elysia.tgz"
tar -xzf "$tmp/elysia.tgz" -C "$tmp"
rg -n "TypeBox\.Kind|Symbol\.for|`@sinclair/typebox`" "$tmp/package"/dist "$tmp/package/src" 2>/dev/null | head -200 || true
echo
echo "== `@sinclair/typebox` 0.32.34 and 0.34.13 Kind symbol =="
for v in 0.32.34 0.34.13; do
echo "--- $v"
curl -sL "https://registry.npmjs.org/@sinclair%2ftypebox/-/typebox-$v.tgz" -o "$tmp/typebox-$v.tgz"
tar -xzf "$tmp/typebox-$v.tgz" -C "$tmp"
rg -n "Symbol\.for\('TypeBox\.Kind'\)|let Kind|exports\.Kind" "$tmp/package/src" | head -100
doneRepository: Lftobs/dequel
Length of output: 24922
🏁 Script executed:
#!/bin/bash
set -euo pipefail
tmp="$(mktemp -d)"
echo "== elysia latest package summary =="
curl -s https://registry.npmjs.org/elysia/latest\?metadata=true | jq '{latest: ."dist-tags".latest, version: .version, dependencies: .dependencies, peerDependencies: .peerDependencies}'
echo
echo "== bun.lock package map around elysia/typebox/exact =="
python3 - <<'PY'
from pathlib import Path
p = Path('apps/api/bun.lock')
text = p.read_text(errors='replace').splitlines()
for i,line in enumerate(text,1):
if any(pkg in line for pkg in ['`@sinclair/typebox`', 'elysia', 'exact-mirror']):
start=max(1,i-2); end=min(len(text),i+3)
print(f'[{i}] {line}')
for n in range(start,end+1):
if n!=i:
print(f'[{n}] {text[n-1]}')
print()
PY
echo
echo "== TypeBox 0.32.34 Kind export =="
curl -sL "https://registry.npmjs.org/@sinclair%2ftypebox/-/typebox-0.32.34.tgz" -o "$tmp/tbox-0.32.34.tgz"
tar -xzf "$tmp/tbox-0.32.34.tgz" -C "$tmp/0.32"
rg -n "KindSymbol|Symbol\.for\(\"TypeBox\.Kind\"\)|exports\.Kind|return .*KindSymbol" "$tmp/0.32/package" | head -50
echo
echo "== TypeBox 0.34.13 Kind export =="
curl -sL "https://registry.npmjs.org/@sinclair%2ftypebox/-/typebox-0.34.13.tgz" -o "$tmp/tbox-0.34.13.tgz"
tar -xzf "$tmp/tbox-0.34.13.tgz" -C "$tmp/0.34"
rg -n "KindSymbol|Symbol\.for\(\"TypeBox\.Kind\"\)|exports\.Kind|return .*KindSymbol" "$tmp/0.34/package" | head -50
echo
echo "== npm tarball source file names containing KindSymbol =="
for v in 0.32.34 0.34.13; do
echo "--- $v"
tar -tzf "$tmp/tbox-$v.tgz" | rg 'KindSymbol|value|index|system' | head -80
done
echo
echo "== TypeBox KindSymbol definition files =="
for file in "$tmp/0.32/package/src/type-system.ts" "$tmp/0.32/package/src/type.ts" "$tmp/0.34/package/src/type-system.ts" "$tmp/0.34/package/src/type.ts"; do
if [ -f "$file" ]; then
echo "--- $file"
rg -n -C 5 "KindSymbol|Symbol\.for\(\"TypeBox\.Kind\"\)" "$file" || true
fi
doneRepository: Lftobs/dequel
Length of output: 7105
Align @sinclair/typebox with the installed Elysia package.
apps/api/package.json declares elysia: ^1.1.26, but apps/api/bun.lock resolves elysia@1.4.28, whose peer dependency requires @sinclair/typebox >= 0.34.0 < 1. If you stay with Elysia 1.1.x, update the lockfile to match; if Elysia 1.4.x is intended, update the package range to avoid drift.
🤖 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 `@apps/api/package.json` at line 13, Align the Elysia and `@sinclair/typebox`
dependency declarations in apps/api: either update the lockfile to resolve
elysia within the declared ^1.1.26 range, or, if the resolved 1.4.x version is
intended, update the elysia range in package.json accordingly while retaining a
compatible `@sinclair/typebox` range.
| buildCommand: "buildCommand" in (body ?? {}) ? (body.buildCommand ?? "") || null : undefined, | ||
| startCommand: "startCommand" in (body ?? {}) ? (body.startCommand ?? "") || null : undefined, |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Guard primitive PATCH bodies before using in.
Because body is any, a valid JSON string or number can reach this handler. Lines [69-70] then throw a TypeError because the right-hand operand of in must be an object, producing a 500 instead of a controlled 4xx response. Validate that body is a non-null object before these checks and add a regression test.
Suggested fix
async ({ params: { id }, body, set }: any) => {
+ if (body === null || typeof body !== "object" || Array.isArray(body)) {
+ set.status = 400;
+ return { error: "body must be an object" };
+ }
+
const project = await updateProject(id, {
...
- buildCommand: "buildCommand" in (body ?? {}) ? ...
+ buildCommand: Object.prototype.hasOwnProperty.call(body, "buildCommand") ? ...📝 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.
| buildCommand: "buildCommand" in (body ?? {}) ? (body.buildCommand ?? "") || null : undefined, | |
| startCommand: "startCommand" in (body ?? {}) ? (body.startCommand ?? "") || null : undefined, | |
| async ({ params: { id }, body, set }: any) => { | |
| if (body === null || typeof body !== "object" || Array.isArray(body)) { | |
| set.status = 400; | |
| return { error: "body must be an object" }; | |
| } | |
| const project = await updateProject(id, { | |
| buildCommand: Object.prototype.hasOwnProperty.call(body, "buildCommand") ? (body.buildCommand ?? "") || null : undefined, | |
| startCommand: Object.prototype.hasOwnProperty.call(body, "startCommand") ? (body.startCommand ?? "") || null : undefined, |
🤖 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 `@apps/api/src/api/projects/index.ts` around lines 69 - 70, Guard the PATCH
request body before the `"buildCommand" in ...` and `"startCommand" in ...`
checks: require a non-null object and return the handler’s established
controlled 4xx response for primitive or otherwise invalid bodies. Preserve the
existing command normalization for valid object bodies, and add a regression
test covering JSON string or number payloads.
| try { | ||
| const entries = await readdir(dir, { | ||
| withFileTypes: true, | ||
| }); | ||
| for (const entry of entries) { | ||
| const fullPath = join( | ||
| dir, | ||
| entry.name, | ||
| ); | ||
| if (entry.isDirectory()) { | ||
| if (ignoreDirs.has(entry.name)) { | ||
| continue; | ||
| } | ||
| await rewriteLocalhostBinding( | ||
| fullPath, | ||
| onLog, | ||
| ); | ||
| } else if (entry.isFile()) { | ||
| const ext = entry.name | ||
| .split(".") | ||
| .pop(); | ||
| if (ext && allowedExts.has(ext)) { | ||
| try { | ||
| let content = | ||
| await Bun.file( | ||
| fullPath, | ||
| ).text(); | ||
| if ( | ||
| content.includes( | ||
| "127.0.0.1", | ||
| ) | ||
| ) { | ||
| content = | ||
| content.replaceAll( | ||
| "127.0.0.1", | ||
| "0.0.0.0", | ||
| ); | ||
| await Bun.write( | ||
| fullPath, | ||
| content, | ||
| ); | ||
| await onLog( | ||
| `Auto-rewrote 127.0.0.1 to 0.0.0.0 in ${entry.name} for container compatibility.`, | ||
| ); | ||
| } | ||
| } catch { | ||
| // Ignore read errors | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } catch { | ||
| // Ignore readdir/directory access errors | ||
| } | ||
| }; |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Blanket 127.0.0.1 → 0.0.0.0 rewrite over the whole tree can corrupt user code and config.
This mutates every .json/.toml/.yml/.py/.java… file under the build dir, not just server bind addresses. Things like DB/test/proxy targets, allow-lists, and fixture data pointing at loopback get silently rewritten, and the failure only shows up at runtime. Consider restricting to detected bind/listen patterns (e.g. 127.0.0.1:<port> adjacent to listen/bind/host) or gating it behind an opt-in project setting.
🤖 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 `@apps/api/src/orchestrator/railpack-config-utils.ts` around lines 32 - 86,
Restrict rewriteLocalhostBinding so it only changes loopback values used in
detected server bind/listen configuration, such as 127.0.0.1:<port> near listen,
bind, or host settings, rather than replacing every occurrence in allowed files.
Preserve unrelated database targets, allow-lists, proxy settings, and fixture
data; alternatively require an explicit project opt-in before applying the
rewrite.
| const hasServerScript = !!scripts.server; | ||
| const isStatic = projectType === "static" || (!scripts.start && !hasServerScript && (scripts.build || hasPackageJson)); | ||
|
|
||
| if (isStatic) { | ||
| const serveScript = ` | ||
| const fs = require("fs"); | ||
| const path = require("path"); | ||
| const PORT = Number(process.env.PORT || 3000); | ||
| const cleanSourceDir = "${cleanSourceDir}"; | ||
| let staticDir = "."; | ||
| const candidates = [ | ||
| path.join(cleanSourceDir, "dist"), | ||
| path.join(cleanSourceDir, "build"), | ||
| path.join(cleanSourceDir, "out"), | ||
| path.join(cleanSourceDir, "public"), | ||
| "dist", | ||
| "build", | ||
| "out", | ||
| "public", | ||
| "." | ||
| ]; | ||
| for (const dir of candidates) { | ||
| const fullPath = path.join(process.cwd(), dir); | ||
| if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) { | ||
| if (fs.existsSync(path.join(fullPath, "index.html"))) { | ||
| staticDir = dir; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| console.log("Serving static directory:", staticDir, "on port", PORT); | ||
| Bun.serve({ | ||
| port: PORT, | ||
| async fetch(req) { | ||
| const url = new URL(req.url); | ||
| let decodedPathname = "/"; | ||
| try { | ||
| decodedPathname = decodeURIComponent(url.pathname); | ||
| } catch { | ||
| decodedPathname = url.pathname; | ||
| } | ||
| let filePath = path.join(staticDir, decodedPathname); | ||
| if (decodedPathname.endsWith("/")) { | ||
| filePath = path.join(filePath, "index.html"); | ||
| } | ||
| let file = Bun.file(filePath); | ||
| if (await file.exists()) { | ||
| return new Response(file, { | ||
| headers: { | ||
| "content-type": file.type || "application/octet-stream" | ||
| } | ||
| }); | ||
| } | ||
| const fallbackPath = path.join(staticDir, "index.html"); | ||
| const fallbackFile = Bun.file(fallbackPath); | ||
| if (await fallbackFile.exists()) { | ||
| return new Response(fallbackFile, { | ||
| headers: { | ||
| "content-type": fallbackFile.type || "text/html" | ||
| } | ||
| }); | ||
| } | ||
| return new Response("Not Found", { status: 404 }); | ||
| } | ||
| }); | ||
| `; | ||
| await Bun.write(join(workspace, "dequel-serve.js"), serveScript); | ||
| config.deploy.startCommand = "bun dequel-serve.js"; | ||
| } else if (scripts.start) { | ||
| config.deploy.startCommand = | ||
| cleanSourceDir | ||
| ? `cd ${cleanSourceDir} && ${pm} run start` | ||
| : `${pm} run start`; | ||
| } else if (scripts.server) { | ||
| config.deploy.startCommand = | ||
| cleanSourceDir | ||
| ? `cd ${cleanSourceDir} && ${pm} run server` | ||
| : `${pm} run server`; | ||
| } else { | ||
| config.deploy.startCommand = | ||
| cleanSourceDir | ||
| ? `cd ${cleanSourceDir} && node dist/index.js` | ||
| : "node dist/index.js"; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
isStatic misclassifies Node services and makes the node dist/index.js fallback unreachable.
hasPackageJson is always true inside this branch, so the condition collapses to !scripts.start && !scripts.server. Any Node backend without a start script (bin entry, main, node server.js documented in README) is deployed as a static file server, and the else at Line 309 is dead code. Also, bun dequel-serve.js assumes bun exists in the runtime image even when pm is npm/yarn/pnpm.
🐛 Suggested tightening
- const hasServerScript = !!scripts.server;
- const isStatic = projectType === "static" || (!scripts.start && !hasServerScript && (scripts.build || hasPackageJson));
+ const hasServerScript = !!scripts.server;
+ const isStatic =
+ projectType === "static" ||
+ (!projectType && !scripts.start && !hasServerScript && !!scripts.build);🤖 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 `@apps/api/src/orchestrator/railpack-config-utils.ts` around lines 231 - 314,
Update the isStatic classification in the surrounding configuration flow so Node
services without scripts.start or scripts.server are not treated as static
solely because hasPackageJson is true; reserve static deployment for explicit
static projects or reliably identified static builds. Preserve the node
dist/index.js fallback in the final else branch for backend services, and avoid
generating a Bun-dependent serve command when the selected package
manager/runtime is not Bun by using a compatible serving strategy.
| const serveScript = ` | ||
| const fs = require("fs"); | ||
| const path = require("path"); | ||
| const PORT = Number(process.env.PORT || 3000); | ||
| const cleanSourceDir = "${cleanSourceDir}"; |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Unescaped interpolation of cleanSourceDir into a generated JS string literal.
A source dir containing ", \, or a newline produces a syntactically broken dequel-serve.js (or injects code). Use JSON.stringify(cleanSourceDir) instead of manual quoting.
🛡️ Proposed fix
-const cleanSourceDir = "${cleanSourceDir}";
+const cleanSourceDir = ${JSON.stringify(cleanSourceDir)};📝 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.
| const serveScript = ` | |
| const fs = require("fs"); | |
| const path = require("path"); | |
| const PORT = Number(process.env.PORT || 3000); | |
| const cleanSourceDir = "${cleanSourceDir}"; | |
| const serveScript = ` | |
| const fs = require("fs"); | |
| const path = require("path"); | |
| const PORT = Number(process.env.PORT || 3000); | |
| const cleanSourceDir = ${JSON.stringify(cleanSourceDir)}; | |
| ` |
🤖 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 `@apps/api/src/orchestrator/railpack-config-utils.ts` around lines 235 - 239,
Update the serveScript template construction to interpolate cleanSourceDir using
JSON.stringify(cleanSourceDir), preserving valid and non-injectable JavaScript
string syntax for quotes, backslashes, and newlines.
| "SENTRY_DSN", | ||
| "SENTRY_AUTH_TOKEN", | ||
| ]); |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Do not classify SENTRY_AUTH_TOKEN as build-safe.
Decrypted project variables that pass this filter are forwarded to Railpack as build-time --env values. This allowlist entry exposes a credential to arbitrary build commands and conflicts with the test suite’s secret-rejection policy.
apps/api/src/utils/env-filter.ts#L27-L29: removeSENTRY_AUTH_TOKENfromBUILD_SAFE_EXACT.apps/api/src/utils/__tests__/env-filter.test.ts#L48-L56: add an assertion thatSENTRY_AUTH_TOKENis rejected.
📍 Affects 2 files
apps/api/src/utils/env-filter.ts#L27-L29(this comment)apps/api/src/utils/__tests__/env-filter.test.ts#L48-L56
🤖 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 `@apps/api/src/utils/env-filter.ts` around lines 27 - 29, Remove
SENTRY_AUTH_TOKEN from BUILD_SAFE_EXACT in apps/api/src/utils/env-filter.ts
(lines 27-29). In apps/api/src/utils/__tests__/env-filter.test.ts (lines 48-56),
add an assertion confirming SENTRY_AUTH_TOKEN is rejected by the filter.
| - Caddy reverse proxy now passes the Host header correctly to upstream containers ([f20e3fa](https://github.com/Lftobs/dequel/commit/f20e3fa)) | ||
| - Runtime reconciliation skips non-existent containers ([dc4593c](https://github.com/Lftobs/dequel/commit/dc4593c)) | ||
| - Docker-compose configuration updated for local builds ([dc4593c](https://github.com/Lftobs/dequel/commit/dc4593c)) | ||
| - Add `project_type`, `buildCommand`, and `startCommand` fields to projects ([f20e3fa](https://github.com/Lftobs/dequel/commit/f20e3fa)) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Inconsistent field naming in a user-facing changelog.
project_type is snake_case while buildCommand/startCommand are camelCase. Pick one representation (API field names are projectType, buildCommand, startCommand).
🤖 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 `@apps/docs/src/content/changelogs/v0.2.1.md` at line 11, Update the changelog
entry to use the API’s consistent camelCase field names, replacing project_type
with projectType while preserving buildCommand and startCommand.
| const [projectType, setProjectType] = | ||
| useState("web"); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Reset the project type when the dialog closes.
Canceling a static-project draft leaves projectType set to static for the next project, while every other creation field is reset. Add setProjectType("web") in the close-reset branch.
🤖 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 `@apps/web/src/components/project/create/CreateProjectDialog.tsx` around lines
63 - 64, Update the dialog close-reset branch to call setProjectType("web")
alongside the existing creation-field resets, ensuring a canceled static-project
draft does not affect the next project.
| sourceDir: sourceDir.trim() || null, | ||
| buildCommand: buildCommand.trim() || null, | ||
| startCommand: startCommand.trim() || null, | ||
| port: port.trim() ? Number(port) || null : null, | ||
| description: description.trim() || null, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Reject invalid port values instead of persisting them.
Number(port) || null accepts values such as -1 and 70000; this form has no bounds, and the supplied PATCH handler forwards truthy values to persistence. Validate integer ports in 1..65535 here and enforce the same range in the API before saving.
🤖 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 `@apps/web/src/components/project/settings/ProjectSettingsTab.tsx` around lines
43 - 47, Update the project settings payload around port to accept only integer
values in the range 1–65535, using null for blank input and rejecting invalid
values rather than persisting them. Apply the same bounds validation in the
PATCH handler before saving, including values forwarded through the existing
persistence path.
| {/* Project Type */} | ||
| <div className="space-y-2.5"> | ||
| <label className="font-semibold text-xs text-zinc-400"> | ||
| Project Type | ||
| </label> | ||
| <div className="grid grid-cols-1 md:grid-cols-2 gap-3"> | ||
| <button | ||
| type="button" | ||
| onClick={() => setProjectType("web")} | ||
| className={cn( | ||
| "flex flex-col items-start gap-2 p-4 rounded-xl border text-left transition-all select-none active:scale-[0.98]", | ||
| projectType === "web" | ||
| ? "border-amber-500/30 bg-amber-500/5 text-zinc-200" | ||
| : "border-[#222227] bg-[#141418] hover:bg-[#1a1a20] text-zinc-400" | ||
| )} | ||
| > | ||
| <div className="flex items-center gap-1.5 font-bold text-xs text-zinc-250"> | ||
| <Box className="h-4 w-4 text-amber-500" /> | ||
| Web Application | ||
| </div> | ||
| <span className="text-[10px] text-zinc-500 leading-relaxed"> | ||
| Build and launch standard persistent backend engines or databases (Node.js, Rust, Go, Python, APIs). | ||
| </span> | ||
| </button> | ||
| <button | ||
| type="button" | ||
| onClick={() => setProjectType("static")} | ||
| className={cn( | ||
| "flex flex-col items-start gap-2 p-4 rounded-xl border text-left transition-all select-none active:scale-[0.98]", | ||
| projectType === "static" | ||
| ? "border-amber-500/30 bg-amber-500/5 text-zinc-200" | ||
| : "border-[#222227] bg-[#141418] hover:bg-[#1a1a20] text-zinc-400" | ||
| )} | ||
| > | ||
| <div className="flex items-center gap-1.5 font-bold text-xs text-zinc-250"> | ||
| <Globe className="h-4 w-4 text-amber-500" /> | ||
| Static Site | ||
| </div> | ||
| <span className="text-[10px] text-zinc-500 leading-relaxed"> | ||
| Generate static client bundles (Vite, Astro, Vue) served automatically by Dequel's SPA static web server. | ||
| </span> | ||
| </button> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className="grid grid-cols-1 md:grid-cols-2 gap-5"> | ||
| {/* Root Directory / Source Dir */} | ||
| <div className="space-y-2"> | ||
| <label htmlFor="sourceDir" className="font-semibold text-xs text-zinc-400"> | ||
| Root Directory | ||
| </label> | ||
| <Input | ||
| id="sourceDir" | ||
| placeholder="e.g. apps/web (leave empty for repo root)" | ||
| className="bg-[#141418] border-[#222227] focus:border-amber-500 text-zinc-200 text-xs h-9 rounded-lg" | ||
| value={sourceDir} | ||
| onChange={(e) => setSourceDir(e.target.value)} | ||
| /> | ||
| <p className="text-[10px] text-zinc-500 leading-normal"> | ||
| Path inside your repository where build operations should run. | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* Internal Port */} | ||
| <div className="space-y-2"> | ||
| <label htmlFor="port" className="font-semibold text-xs text-zinc-400"> | ||
| Port | ||
| </label> | ||
| <Input | ||
| id="port" | ||
| type="number" | ||
| placeholder="e.g. 3000" | ||
| className="bg-[#141418] border-[#222227] focus:border-amber-500 text-zinc-200 text-xs h-9 rounded-lg" | ||
| value={port} | ||
| onChange={(e) => setPort(e.target.value)} | ||
| /> | ||
| <p className="text-[10px] text-zinc-500 leading-normal"> | ||
| The internal port number your application container listens on. | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* Build Command Override */} | ||
| <div className="space-y-2"> | ||
| <label htmlFor="buildCommand" className="font-semibold text-xs text-zinc-400"> | ||
| Build Command | ||
| </label> | ||
| <Input | ||
| id="buildCommand" | ||
| placeholder="e.g. npm run build (leave empty for auto)" | ||
| className="bg-[#141418] border-[#222227] focus:border-amber-500 text-zinc-200 text-xs h-9 rounded-lg font-mono" | ||
| value={buildCommand} | ||
| onChange={(e) => setBuildCommand(e.target.value)} | ||
| /> | ||
| <p className="text-[10px] text-zinc-500 leading-normal"> | ||
| Override the build command execution. Leave blank to let Dequel auto-detect it. | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* Start Command Override */} | ||
| <div className="space-y-2"> | ||
| <label htmlFor="startCommand" className="font-semibold text-xs text-zinc-400"> | ||
| Start Command | ||
| </label> | ||
| <Input | ||
| id="startCommand" | ||
| placeholder="e.g. node dist/index.js (leave empty for auto)" | ||
| className="bg-[#141418] border-[#222227] focus:border-amber-500 text-zinc-200 text-xs h-9 rounded-lg font-mono" | ||
| value={startCommand} | ||
| onChange={(e) => setStartCommand(e.target.value)} | ||
| /> | ||
| <p className="text-[10px] text-zinc-500 leading-normal"> | ||
| Override the launch start command. Leave blank to let Dequel auto-detect it. | ||
| </p> | ||
| </div> | ||
|
|
||
| {/* Description */} |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Remove the redundant JSX comments.
These comments only label the immediately following controls and are not necessary.
As per coding guidelines, **/*.{ts,tsx,js,jsx} permits no source comments unless absolutely necessary.
🤖 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 `@apps/web/src/components/project/settings/ProjectSettingsTab.tsx` around lines
89 - 204, Remove the redundant JSX label comments in the project settings form,
including “Project Type,” “Root Directory / Source Dir,” “Internal Port,” “Build
Command Override,” and “Start Command Override,” while leaving the surrounding
controls and behavior unchanged.
Source: Coding guidelines
Summary by CodeRabbit
New Features
Bug Fixes
Chores