Skip to content

patch: 1.4.22#1657

Merged
SaltyAom merged 16 commits intomainfrom
next
Jan 14, 2026
Merged

patch: 1.4.22#1657
SaltyAom merged 16 commits intomainfrom
next

Conversation

@SaltyAom
Copy link
Member

@SaltyAom SaltyAom commented Jan 5, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Mounted routes now correctly strip server prefix and mount paths.
    • Mounting can skip body parsing in dynamic mode so request bodies are preserved.
    • Restored consistent validation error summaries and fixed several runtime crashes (thenable/map responses, SSE wrapping).
    • Improved error handling to support asynchronous error-to-response conversion.
  • Tests

    • Added mount tests covering prefix stripping and body handling.
  • Chores / Documentation

    • Added changelog entry for version 1.4.22.
  • Other

    • Simplified example app and added a small diagnostic log for file-type detection.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 5, 2026

Warning

Rate limit exceeded

@SaltyAom has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 34 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between bc882d4 and 131a452.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • package.json
  • src/dynamic-handle.ts
  • src/index.ts

Walkthrough

Adds CHANGELOG entry for 1.4.22; replaces a WebSocket example with an HTTP POST example; introduces ValueErrorWithSummary and updates error mapping; converts a handler type alias to an interface; tightens Bun routing guard; changes mount/path handling and short-circuits mount via an early mount hook; adds tests and logging.

Changes

Cohort / File(s) Summary
Version Documentation
CHANGELOG.md
Added 1.4.22 notes (replaceURLPath change, mount URL path with prefix, skip body parsing on mount, ValueError summary fix, Bun.routes behavior, other fixes).
Example app
example/a.ts
Removed WS server example/export; added an HTTP POST mount (/create-post / /api) with request body schema validation and JSON response.
Error types & mapping
src/error.ts
Added ValueErrorWithSummary (optional summary); changed mapValueError to return it and updated ValidationError.all() / detail() to use guarded summary extraction.
Mounting & path handling
src/index.ts, src/utils.ts, test/core/mount.test.ts
Compute fullPath when server prefix exists for slicing; replace URL-constructor path replacement with manual string reconstruction preserving query; added mount tests (with/without prefix and AOT body).
Dynamic mount short-circuit
src/dynamic-handle.ts
If hooks.config?.mount exists, invoke it immediately and return its result, bypassing body parsing and remaining flow.
Adapter types
src/adapter/utils.ts
Converted exported CreateHandlerParameter from a type alias to an interface with same mapResponse / mapCompactResponse signatures.
Adapter promise/thenable handling
src/adapter/bun/handler.ts, src/adapter/web-standard/handler.ts
Reworked promise checks to use explicit Promise typing and MaybePromise; adjusted errorToResponse signature to accept possibly-async toResponse; removed several ts-expect-error/ts-ignore annotations.
Bun adapter routing guard
src/adapter/bun/index.ts
Treated explicit false for systemRouter as disabling routing while allowing undefined to enable routing when AOT is true.
Compose & formatting
src/compose.ts, src/adapter/bun/compose.ts
Removed unused import and minor formatting tweaks in generated string (no behavior change).
File-type detection logging
src/type-system/utils.ts
Added console.log(result, extension) after file-type detection (no change to validation/error behavior).

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant DynamicHandle
  participant HooksMount as hooks.config.mount
  participant BodyParser
  participant Handler

  Client->>DynamicHandle: HTTP request
  alt hooks.config.mount present
    DynamicHandle->>HooksMount: invoke mount(request)
    HooksMount-->>DynamicHandle: Response (short-circuit)
    DynamicHandle-->>Client: return mount response
  else no mount hook
    DynamicHandle->>BodyParser: parse body
    BodyParser-->>DynamicHandle: parsed body
    DynamicHandle->>Handler: route to handler with parsed body
    Handler-->>DynamicHandle: handler response
    DynamicHandle-->>Client: return handler response
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 I hopped through mounts and trimmed a route,
I swapped WS for POST and checked each route.
I wrapped up errors with a tiny new summary,
Logged a file-type and skipped a parsing flurry—
Little rabbit fixes, tidy and astute.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'patch: 1.4.22' is directly related to the changeset, which consists entirely of bug fixes, improvements, and feature adjustments for version 1.4.22 as documented in CHANGELOG.md.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 5, 2026

Open in StackBlitz

npm i https://pkg.pr.new/elysiajs/elysia@1657

commit: 4478914

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
example/a.ts (1)

25-39: Consider type narrowing for safer status code extraction.

The status code logic handles cases where error.status might be a string or invalid number. However, casting with Number() on non-numeric strings yields NaN, which then falls back to 500 via || 500. This works but could be clearer.

🔎 Slightly cleaner approach
 default: {
-	const statusCode =
-		"status" in error
-			? (typeof error.status === "number" ? error.status : Number(error.status)) || 500
-			: 500
+	let statusCode = 500
+	if ("status" in error && typeof error.status === "number") {
+		statusCode = error.status
+	}

 	let errMsg = "An error occurred"
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 969fc76 and 250dec6.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • example/a.ts
  • src/error.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/error.ts (1)
src/index.ts (2)
  • mapValueError (8224-8224)
  • error (3088-3128)
🔇 Additional comments (5)
CHANGELOG.md (1)

1-4: LGTM!

The changelog entry accurately documents the bug fix for missing summary types on ValueError, which corresponds to the new ValueErrorWithSummary interface introduced in src/error.ts.

src/error.ts (4)

47-49: LGTM!

Formatting change improves readability.


159-161: LGTM!

The new ValueErrorWithSummary interface cleanly extends ValueError with an optional summary field, addressing the type-safety issue mentioned in the changelog.


487-487: LGTM!

Return type correctly updated to ValueErrorWithSummary[] to reflect the mapped error structure.


599-601: LGTM!

Safe access pattern correctly guards against undefined valueError before calling mapValueError, avoiding potential runtime errors.

Comment on lines +163 to +166
export const mapValueError = (error: ValueError): ValueErrorWithSummary => {
if (!error) return error

let { message, path, value, type } = error
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Type signature inconsistency with runtime guard.

The parameter is typed as ValueError (non-nullable), but line 164 guards against falsy values and returns error (potentially undefined). This creates a mismatch: the return type is ValueErrorWithSummary, but the function can actually return undefined.

Consider either:

  1. Updating the signature to reflect nullable input/output: (error: ValueError | undefined): ValueErrorWithSummary | undefined
  2. Removing the guard if callers are guaranteed to pass non-null values
🔎 Option 1: Reflect nullable types
-export const mapValueError = (error: ValueError): ValueErrorWithSummary => {
-	if (!error) return error
+export const mapValueError = (error: ValueError | undefined): ValueErrorWithSummary | undefined => {
+	if (!error) return undefined
🤖 Prompt for AI Agents
In src/error.ts around lines 163 to 166, the function mapValueError is typed to
accept a non-nullable ValueError but contains a runtime guard that returns the
(possibly undefined) error, causing a signature mismatch; update the function
signature to accept and return nullable types like (error: ValueError |
undefined): ValueErrorWithSummary | undefined, or if callers never pass
undefined, remove the guard and keep the non-nullable signature—choose one
approach and adjust the type annotations accordingly so runtime behavior matches
the TypeScript types.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/type-system/utils.ts`:
- Around line 148-149: Remove the debug console.log call that prints detection
results; specifically delete the line console.log(result, extension) in
src/type-system/utils.ts (inside the file type validation routine) so the file
type detection no longer logs result and extension for every validation before
merging.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 250dec6 and c047fb4.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • example/a.ts
  • src/adapter/bun/index.ts
  • src/adapter/utils.ts
  • src/compose.ts
  • src/type-system/utils.ts
💤 Files with no reviewable changes (1)
  • src/compose.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md
🔇 Additional comments (3)
src/adapter/bun/index.ts (1)

86-87: LGTM! Stricter check for systemRouter opt-out.

The change from !app.config.systemRouter to === false is more intentional—only an explicit false disables the system router. When systemRouter is undefined, routing now activates if aot is enabled, which is a sensible default.

src/adapter/utils.ts (1)

139-146: LGTM!

Converting the type alias to an interface is a clean refactor. Interfaces provide better error messages and support declaration merging if needed in the future.

example/a.ts (1)

1-3: LGTM!

The simplified example is clean and demonstrates basic Elysia usage. This also resolves the previous review feedback about unused error.detail by removing the complex error handling code entirely.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/index.ts (1)

5616-5626: Fix mount path normalization before computing fullPath.length (breaks mount('foo', ...) with prefix).

If a caller passes mount('problems-domain', ...) (no leading /), routing will normalize to /<...> later, but fullPath/length will be computed from the unnormalized string, so path.slice(length) strips the wrong segment.

Proposed fix
-		const fullPath =
-			typeof path === 'string' && this.config.prefix
-				? this.config.prefix + path
-				: path
-
-		const length = fullPath.length - (path.endsWith('*') ? 1 : 0)
+		const mountPath = path.charCodeAt(0) === 47 ? path : `/${path}`
+		const fullPath = this.config.prefix ? this.config.prefix + mountPath : mountPath
+		const length = fullPath.length - (mountPath.endsWith('*') ? 1 : 0)
 		const handler: Handler = ({ request, path }) =>
 			handle(
 				new Request(
 					replaceUrlPath(request.url, path.slice(length) || '/'),
 					{
🤖 Fix all issues with AI agents
In `@example/a.ts`:
- Around line 1-18: Remove the noisy console.log from the request handler used
to build sdkApp: inside the callback passed to new
Elysia(...).mount('/problems-domain', (request) => { ... }) delete the
console.log(request.url) line (or move it outside the handler to a demo-level
log) so the handler returns only Response.json({ path: new
URL(request.url).pathname }) without printing the URL; leave Elysia, sdkApp and
the rest of the example unchanged.

In `@src/utils.ts`:
- Around line 30-38: The replaceUrlPath function breaks for short hosts because
it uses a hardcoded indexOf('/', 11); update it to locate the path start in a
scheme-aware way (find "://", then search for the next '/' after the host: use
url.indexOf('://') to compute hostStart = index + 3 and then pathStartIndex =
url.indexOf('/', hostStart)); if pathStartIndex === -1 treat the URL as having
no path (use the whole url as base before adding pathname) and preserve any
query by locating '?' relative to pathStartIndex or host end; keep the existing
pathname leading-slash logic (pathname.charCodeAt(0) === 47) and ensure you
build the final string using the computed base, the normalized pathname, and any
query fragment.
🧹 Nitpick comments (1)
test/core/mount.test.ts (1)

140-172: Nice coverage for mount path stripping with and without prefix.

This directly exercises the fullPath.length slicing regression scenario.

Consider adding a third test for mount('problems-domain', ...) (no leading /) if that’s intended to be supported, to lock in the normalization behavior.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c047fb4 and a555850.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • example/a.ts
  • src/adapter/bun/compose.ts
  • src/index.ts
  • src/utils.ts
  • test/core/mount.test.ts
✅ Files skipped from review due to trivial changes (1)
  • src/adapter/bun/compose.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md
🧰 Additional context used
🧬 Code graph analysis (2)
test/core/mount.test.ts (1)
src/index.ts (2)
  • Elysia (190-8185)
  • Elysia (8187-8187)
example/a.ts (1)
src/index.ts (2)
  • Elysia (190-8185)
  • Elysia (8187-8187)

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines 30 to 38
export const replaceUrlPath = (url: string, pathname: string) => {
const urlObject = new URL(url)
urlObject.pathname = pathname
return urlObject.toString()
const pathStartIndex = url.indexOf('/', 11)
const queryIndex = url.indexOf('?', pathStartIndex)

if (queryIndex === -1)
return `${url.slice(0, pathStartIndex)}${pathname.charCodeAt(0) === 47 ? '' : '/'}${pathname}`

return `${url.slice(0, pathStartIndex)}${pathname.charCodeAt(0) === 47 ? '' : '/'}${pathname}${url.slice(queryIndex)}`
}
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 14, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -name "src/utils.ts" -type f | head -1

Repository: elysiajs/elysia

Length of output: 41


🏁 Script executed:

cat -n src/utils.ts | sed -n '25,45p'

Repository: elysiajs/elysia

Length of output: 995


🏁 Script executed:

rg -n --type=ts -C2 'replaceUrlPath\s*\(' --max-count=20

Repository: elysiajs/elysia

Length of output: 543


🏁 Script executed:

sed -n '5570,5590p' src/index.ts

Repository: elysiajs/elysia

Length of output: 662


🏁 Script executed:

sed -n '5620,5635p' src/index.ts

Repository: elysiajs/elysia

Length of output: 580


🏁 Script executed:

node <<'EOF'
// Test the buggy logic
const replaceUrlPath = (url, pathname) => {
	const pathStartIndex = url.indexOf('/', 11)
	console.log(`URL: ${url}`)
	console.log(`  pathStartIndex: ${pathStartIndex}`)
	const queryIndex = url.indexOf('?', pathStartIndex)
	
	if (queryIndex === -1)
		return `${url.slice(0, pathStartIndex)}${pathname.charCodeAt(0) === 47 ? '' : '/'}${pathname}`
	
	return `${url.slice(0, pathStartIndex)}${pathname.charCodeAt(0) === 47 ? '' : '/'}${pathname}${url.slice(queryIndex)}`
}

// Test case 1: short hostname
console.log('\n=== Test 1: Short hostname ===')
console.log('Result:', replaceUrlPath('http://a/original', '/new'))

// Test case 2: localhost
console.log('\n=== Test 2: localhost ===')
console.log('Result:', replaceUrlPath('http://localhost/original', '/new'))

// Test case 3: empty pathname
console.log('\n=== Test 3: Empty pathname ===')
console.log('Result:', replaceUrlPath('http://localhost/original', ''))

// Test case 4: with query string
console.log('\n=== Test 4: With query string ===')
console.log('Result:', replaceUrlPath('http://localhost/original?foo=bar', '/new'))
EOF

Repository: elysiajs/elysia

Length of output: 513


replaceUrlPath: indexOf('/', 11) returns -1 for short hosts and corrupts URLs.

The hardcoded index 11 assumes the host is always at least 11 characters long. For short hostnames like http://a/path, the first / is at index 8, so indexOf('/', 11) returns -1. This causes url.slice(0, -1) to remove the last character instead of slicing correctly, corrupting the URL (e.g., http://a/original becomes http://a/origina/new).

Use a scheme-aware approach to find the path start safely:

Proposed fix
 export const replaceUrlPath = (url: string, pathname: string) => {
-	const pathStartIndex = url.indexOf('/', 11)
-	const queryIndex = url.indexOf('?', pathStartIndex)
+	const schemeSep = url.indexOf('://')
+	const hostStart = schemeSep === -1 ? 0 : schemeSep + 3
+	const pathStartIndex = url.indexOf('/', hostStart)
+	const safePathStartIndex = pathStartIndex === -1 ? url.length : pathStartIndex
+	const queryIndex = url.indexOf('?', safePathStartIndex)
+
+	const nextPath = pathname && pathname.charCodeAt(0) === 47 ? pathname : `/${pathname || ''}`

-	if (queryIndex === -1)
-		return `${url.slice(0, pathStartIndex)}${pathname.charCodeAt(0) === 47 ? '' : '/'}${pathname}`
+	if (queryIndex === -1) return `${url.slice(0, safePathStartIndex)}${nextPath}`

-	return `${url.slice(0, pathStartIndex)}${pathname.charCodeAt(0) === 47 ? '' : '/'}${pathname}${url.slice(queryIndex)}`
+	return `${url.slice(0, safePathStartIndex)}${nextPath}${url.slice(queryIndex)}`
 }
🤖 Prompt for AI Agents
In `@src/utils.ts` around lines 30 - 38, The replaceUrlPath function breaks for
short hosts because it uses a hardcoded indexOf('/', 11); update it to locate
the path start in a scheme-aware way (find "://", then search for the next '/'
after the host: use url.indexOf('://') to compute hostStart = index + 3 and then
pathStartIndex = url.indexOf('/', hostStart)); if pathStartIndex === -1 treat
the URL as having no path (use the whole url as base before adding pathname) and
preserve any query by locating '?' relative to pathStartIndex or host end; keep
the existing pathname leading-slash logic (pathname.charCodeAt(0) === 47) and
ensure you build the final string using the computed base, the normalized
pathname, and any query fragment.

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah don't worry, invalid URL cannot reach this part of the code

Copy link
Contributor

Choose a reason for hiding this comment

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

@SaltyAom, understood! If there's upstream validation ensuring only well-formed URLs reach replaceUrlPath, then the hardcoded offset is safe.


✏️ Learnings added
Learnt from: SaltyAom
Repo: elysiajs/elysia PR: 1657
File: src/utils.ts:30-38
Timestamp: 2026-01-14T04:50:53.210Z
Learning: The `replaceUrlPath` function in `src/utils.ts` assumes valid, well-formed URLs as input because upstream validation prevents invalid or malformed URLs from reaching this code path.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@CHANGELOG.md`:
- Line 1: The changelog header "# 1.4.22" is missing the release date and should
follow the existing format; update the header string to include the release date
(e.g., change "# 1.4.22" to "# 1.4.22 - <RELEASE DATE>") so it matches other
entries like "# 1.4.21 - 4 Jan 2026".

In `@example/a.ts`:
- Around line 3-5: The function mountedHandler is declared but never used and
duplicates the inline request handler; either remove the unused function
mountedHandler or replace the inline handler passed to .mount(...) with a
reference to mountedHandler so the named function is used instead of a
duplicate; update any imports/exports if you remove it and run a quick lint to
ensure no unused-symbol warnings remain.

In `@src/dynamic-handle.ts`:
- Around line 117-120: The mount handler return is not awaited which prevents
async errors from hooks.config.mount being caught by the surrounding catch
block; update the early-return to await the mount invocation (i.e., return await
hooks.config.mount(request)) and remove the unnecessary // `@ts-ignore`
annotations by fixing the type for hooks.config to include an optional mount:
(req: Request) => Promise<Response> | Response so TypeScript recognizes
hooks.config.mount as a possibly-async function.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a555850 and c7d7f99.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • example/a.ts
  • src/dynamic-handle.ts
  • test/core/mount.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/core/mount.test.ts
🧰 Additional context used
🧬 Code graph analysis (1)
example/a.ts (1)
src/index.ts (2)
  • Elysia (190-8185)
  • Elysia (8187-8187)
🔇 Additional comments (3)
example/a.ts (1)

7-9: Example demonstrates aot: false mount behavior correctly.

The mount usage aligns with the test cases in test/core/mount.test.ts that verify body handling with aot: false. Consider using the named mountedHandler function (if retained) for clarity, or removing it entirely.

CHANGELOG.md (1)

2-6: LGTM!

The bug fix entries are well-documented with appropriate issue references and clear descriptions that align with the code changes in this PR.

src/dynamic-handle.ts (1)

114-120: LGTM! Correctly placed early return for mount handlers.

The mount check is properly positioned after handler resolution but before body parsing, correctly implementing the "skip body parsing on mount with dynamic mode" fix. The hooks assignment before the early return ensures the finally block can still access hooks.afterResponse.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@example/a.ts`:
- Around line 3-18: The Elysia app chain and .post() call are left unterminated
causing a parse error; close the route options and callback by adding the
missing closing braces/parentheses and finish the Elysia chain (e.g., close the
.post(...) call, then call .listen(...) or start the server) so the file ends
with a complete expression; specifically update the code around the Elysia
instance and the "/create-post" route (the new Elysia() instantiation and its
.post handler) to include the missing closing brace/parenthesis and a server
startup call such as .listen(3000) or equivalent, then add the terminating
semicolon.
- Line 1: The file uses t.Object, t.String, and t.Number but never imports t;
add an import that brings TypeBox's Type into the module under the alias t
(i.e., import Type from '@sinclair/typebox' aliased to t) so the schema builder
symbols t.Object/t.String/t.Number resolve; update the top of the file to
include this import and ensure any existing imports (like Elysia) remain intact.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c7d7f99 and 0506a55.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • example/a.ts
  • example/newFile.ts
🧰 Additional context used
🪛 Biome (2.1.2)
example/a.ts

[error] 18-18: Expected an expression but instead found the end of the file.

Expected an expression here.

(parse)

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

import { Elysia, t } from '../src'
import { z } from 'zod'
import { req } from '../test/utils'
import { Elysia } from '../src'
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Missing import for t (TypeBox schema builder).

The code uses t.Object(), t.String(), and t.Number() for body validation, but t is never imported. This will cause a ReferenceError at runtime.

Proposed fix
-import { Elysia } from '../src'
+import { Elysia, t } from '../src'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { Elysia } from '../src'
import { Elysia, t } from '../src'
🤖 Prompt for AI Agents
In `@example/a.ts` at line 1, The file uses t.Object, t.String, and t.Number but
never imports t; add an import that brings TypeBox's Type into the module under
the alias t (i.e., import Type from '@sinclair/typebox' aliased to t) so the
schema builder symbols t.Object/t.String/t.Number resolve; update the top of the
file to include this import and ensure any existing imports (like Elysia) remain
intact.

Comment on lines +3 to +18
new Elysia()
.post(
"/create-post",
async (ctx) => {
return {
message: "Post Created",
data: ctx.body,
};
},
{
body: t.Object({
name: t.String(),
content: t.String(),
safeAge: t.Number(),
}),
},
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Truncated file — missing closing syntax and server startup.

The file ends abruptly at line 18 with a trailing comma, leaving the .post() call and Elysia chain incomplete. This causes the parse error flagged by static analysis.

Proposed fix
 new Elysia()
-.post(
+  .post(
     "/create-post",
     async (ctx) => {
       return {
         message: "Post Created",
         data: ctx.body,
       };
     },
     {
       body: t.Object({
         name: t.String(),
         content: t.String(),
         safeAge: t.Number(),
       }),
-    },
+    }
+  )
+  .listen(3000)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
new Elysia()
.post(
"/create-post",
async (ctx) => {
return {
message: "Post Created",
data: ctx.body,
};
},
{
body: t.Object({
name: t.String(),
content: t.String(),
safeAge: t.Number(),
}),
},
new Elysia()
.post(
"/create-post",
async (ctx) => {
return {
message: "Post Created",
data: ctx.body,
};
},
{
body: t.Object({
name: t.String(),
content: t.String(),
safeAge: t.Number(),
}),
}
)
.listen(3000)
🧰 Tools
🪛 Biome (2.1.2)

[error] 18-18: Expected an expression but instead found the end of the file.

Expected an expression here.

(parse)

🤖 Prompt for AI Agents
In `@example/a.ts` around lines 3 - 18, The Elysia app chain and .post() call are
left unterminated causing a parse error; close the route options and callback by
adding the missing closing braces/parentheses and finish the Elysia chain (e.g.,
close the .post(...) call, then call .listen(...) or start the server) so the
file ends with a complete expression; specifically update the code around the
Elysia instance and the "/create-post" route (the new Elysia() instantiation and
its .post handler) to include the missing closing brace/parenthesis and a server
startup call such as .listen(3000) or equivalent, then add the terminating
semicolon.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/adapter/bun/handler.ts`:
- Around line 502-503: There's a typo in the TypeScript directive above the
conditional checking response?.toResponse: replace the incorrect
"@ts-expect-errors" with the correct "@ts-expect-error" so the compiler
recognizes the directive; update the comment immediately above the if (typeof
response?.toResponse === 'function') check to use the singular form.
♻️ Duplicate comments (1)
CHANGELOG.md (1)

1-1: Missing release date in version header.

This issue was previously flagged. Consider adding the release date for consistency with other changelog entries (e.g., # 1.4.22 - 5 Jan 2026).

🧹 Nitpick comments (3)
CHANGELOG.md (1)

8-8: Inconsistent markdown link format.

The first link uses the full URL as display text [https://github.com/elysiajs/elysia/issues/1617](...) while other changelog entries use the shorthand format [#1617](...). Consider using the shorthand for consistency.

-- [https://github.com/elysiajs/elysia/issues/1617](https://github.com/elysiajs/elysia/issues/1617), [`#1623`](https://github.com/elysiajs/elysia/pull/1623) AOT compilation removes beforeHandle when using arrow function expression
+- [`#1617`](https://github.com/elysiajs/elysia/issues/1617), [`#1623`](https://github.com/elysiajs/elysia/pull/1623) AOT compilation removes beforeHandle when using arrow function expression
src/adapter/bun/handler.ts (1)

522-536: Consider aligning errorToResponse signature with web-standard handler.

The web-standard version types the error parameter as Error & { toResponse?(): MaybePromise<Response> }, which allows removing some @ts-expect-error comments. This handler still uses @ts-expect-error on lines 523 and 525. For consistency and to further reduce suppressions, consider adding the same typed signature here.

src/adapter/web-standard/handler.ts (1)

560-576: Good typing improvement, but inconsistent @ts-ignore usage with bun handler.

The typed toResponse?(): MaybePromise<Response> signature is a nice improvement. However, line 575 still uses @ts-ignore for the raw?.then check, while the equivalent code in src/adapter/bun/handler.ts (line 535) has no suppression. Given the changelog goal to "reduce ts-ignore/ts-expect-error on promise map handler", consider removing this @ts-ignore if the typed signature makes it unnecessary, or add consistent suppression to the bun handler if it's still needed.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0506a55 and bc882d4.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • src/adapter/bun/handler.ts
  • src/adapter/utils.ts
  • src/adapter/web-standard/handler.ts
  • src/compose.ts
💤 Files with no reviewable changes (1)
  • src/compose.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/adapter/utils.ts
🧰 Additional context used
🧬 Code graph analysis (2)
src/adapter/bun/handler.ts (2)
src/adapter/utils.ts (1)
  • handleFile (8-61)
src/universal/file.ts (1)
  • ElysiaFile (99-168)
src/adapter/web-standard/handler.ts (3)
src/adapter/bun/handler.ts (3)
  • mapResponse (22-156)
  • mapCompactResponse (404-520)
  • errorToResponse (522-550)
src/index.ts (4)
  • mapResponse (2758-2769)
  • error (3088-3128)
  • MaybePromise (8267-8267)
  • Context (8197-8197)
src/types.ts (1)
  • MaybePromise (286-286)
🔇 Additional comments (5)
src/adapter/bun/handler.ts (2)

40-40: LGTM!

Good simplification - inlining the handleFile call is cleaner.


122-123: LGTM!

The explicit Promise<unknown> type casting improves type safety over bare response?.then checks, aligning with the goal to reduce ts-ignore/ts-expect-error usage.

src/adapter/web-standard/handler.ts (3)

16-16: LGTM!

Good addition of MaybePromise import to support the improved typing in errorToResponse.


152-155: LGTM!

Consistent Promise handling refactor using explicit type casting, improving type safety.


292-295: LGTM!

Consistent Promise handling refactors across the default case branches, using explicit Promise<unknown> type casting.

Also applies to: 411-414, 535-538

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +502 to 503
// @ts-expect-errors
if (typeof response?.toResponse === 'function')
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Typo in TypeScript directive comment.

@ts-expect-errors should be @ts-expect-error (singular). The current typo means the directive won't be recognized by TypeScript.

🔧 Proposed fix
-			// `@ts-expect-errors`
+			// `@ts-expect-error`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// @ts-expect-errors
if (typeof response?.toResponse === 'function')
// `@ts-expect-error`
if (typeof response?.toResponse === 'function')
🤖 Prompt for AI Agents
In `@src/adapter/bun/handler.ts` around lines 502 - 503, There's a typo in the
TypeScript directive above the conditional checking response?.toResponse:
replace the incorrect "@ts-expect-errors" with the correct "@ts-expect-error" so
the compiler recognizes the directive; update the comment immediately above the
if (typeof response?.toResponse === 'function') check to use the singular form.

@SaltyAom SaltyAom merged commit 935efe2 into main Jan 14, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant