Conversation
|
Warning Rate limit exceeded@SaltyAom has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 8 minutes and 4 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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. 📒 Files selected for processing (5)
WalkthroughAdds CHANGELOG v1.4.19; exposes runtime hasSetImmediate and replaces direct setImmediate calls with a Promise fallback; schedules afterResponse hooks via the runtime-aware scheduler; fixes multi-secret cookie verification; tightens schema UnwrapSchema typing; adjusts group path typing and compile caching; refactors sucrose context detection; wires composeErrorHandler into Cloudflare adapter; updates examples and tests. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant App as Elysia App
participant Handler
participant Scheduler as setImmediate?/Promise
participant After as afterResponse hooks
participant Adapter as Cloudflare Adapter
Client->>App: HTTP request
App->>Handler: invoke route handler (uses compiled/_compiled cache if present)
Handler-->>App: Response
App->>Scheduler: schedule afterResponse (checks hasSetImmediate)
Scheduler->>After: invoke afterResponse hooks asynchronously
After-->>App: side-effects (cookies, logs, etc.)
App-->>Client: final Response
Note over Adapter: Cloudflare adapter now wires composeErrorHandler before compile/listen
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
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 |
commit: |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
CHANGELOG.md (1)
2-2: Minor: Add missing colon after "Improvement" for consistency.Line 2 lacks a colon after
Improvement, while line 6 hasBug fix:with a colon. For consistency with established formatting, add the colon.-Improvement +Improvement:
CHANGELOG.md
Outdated
| # 1.4.19 - 9 Dec 2025 | ||
| Improvement | ||
| - [#1588](https://github.com/elysiajs/elysia/pull/1588), [#1587](https://github.com/elysiajs/elysia/pull/1587) add seen weakset during mergeDeep | ||
| - [#1607](https://github.com/elysiajs/elysia/issues/1607), [#1606](https://github.com/elysiajs/elysia/issues/1606), [#1139](https://github.com/elysiajs/elysia/issues/1138) nested form data |
There was a problem hiding this comment.
Fix broken reference link on line 4.
The issue reference displays #1139 but the URL points to #1138. Update the URL to match the displayed issue number.
-- [#1607](https://github.com/elysiajs/elysia/issues/1607), [#1606](https://github.com/elysiajs/elysia/issues/1606), [#1139](https://github.com/elysiajs/elysia/issues/1138) nested form data
+- [#1607](https://github.com/elysiajs/elysia/issues/1607), [#1606](https://github.com/elysiajs/elysia/issues/1606), [#1139](https://github.com/elysiajs/elysia/issues/1139) nested form data📝 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.
| - [#1607](https://github.com/elysiajs/elysia/issues/1607), [#1606](https://github.com/elysiajs/elysia/issues/1606), [#1139](https://github.com/elysiajs/elysia/issues/1138) nested form data | |
| - [#1607](https://github.com/elysiajs/elysia/issues/1607), [#1606](https://github.com/elysiajs/elysia/issues/1606), [#1139](https://github.com/elysiajs/elysia/issues/1139) nested form data |
🤖 Prompt for AI Agents
In CHANGELOG.md around line 4, the displayed issue reference shows #1139 but its
URL points to .../issues/1138; update the third link's URL to .../issues/1139 so
the href matches the displayed issue number (change the 1138 in the URL to
1139).
There was a problem hiding this comment.
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)
813-833: Bug: encoded loose path is never actually registered (duplicate add ofloosePath)In the non‑AOT dynamic router branch:
const loosePath = getLoosePath(path) this.router.dynamic.add(method, loosePath, { ... }) const encoded = encodePath(loosePath) if (loosePath !== encoded) this.router.dynamic.add(method, loosePath, { ... })the second
addstill usesloosePathinstead ofencoded, so:
- The encoded loose path is never registered.
- The same path/method pair is added twice, which is redundant and could mask intent.
This should mirror the earlier
pathhandling and actually registerencoded:- const encoded = encodePath(loosePath) - if (loosePath !== encoded) - this.router.dynamic.add(method, loosePath, { + const encoded = encodePath(loosePath) + if (loosePath !== encoded) + this.router.dynamic.add(method, encoded, { validator, hooks, content: localHook?.type as string, handle, route: path })
🧹 Nitpick comments (1)
src/sucrose.ts (1)
547-583: Escapecontextbefore embedding it in regex to avoid syntax errors and static-analysis noise
isContextPassToFunctioncurrently builds regexes directly from thecontextstring:const captureFunction = new RegExp(`\\w\\((?:.*?)?${context}(?:.*?)?\\)`, 'gs') const exactParameter = new RegExp(`${context}(,|\\))`, 'gs')Because
contextis derived from the parameter string, it can sometimes include characters like{,},.or whitespace (e.g. rest-destructuring forms), which makes these patterns syntactically invalid and forces you into the try/catch path. It also triggers the static “regexp-from-variable” warning.You can keep the current matching strategy but escape
contextonce before use:- const captureFunction = new RegExp( - `\\w\\((?:.*?)?${context}(?:.*?)?\\)`, - 'gs' - ) - const exactParameter = new RegExp(`${context}(,|\\))`, 'gs') + const escaped = context.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + const captureFunction = new RegExp( + `\\w\\((?:.*?)?${escaped}(?:.*?)?\\)`, + 'gs' + ) + const exactParameter = new RegExp(`${escaped}(,|\\))`, 'gs')This avoids regex syntax errors, reduces reliance on the catch-all error handler, and should satisfy the static-analysis warning without changing semantics.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
CHANGELOG.md(1 hunks)example/a.ts(1 hunks)src/index.ts(1 hunks)src/schema.ts(2 hunks)src/sucrose.ts(2 hunks)test/core/dynamic.test.ts(1 hunks)test/sucrose/sucrose.test.ts(1 hunks)test/types/utils.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- CHANGELOG.md
- example/a.ts
🧰 Additional context used
🧬 Code graph analysis (5)
test/types/utils.ts (1)
src/schema.ts (1)
getSchemaValidator(380-1041)
src/schema.ts (2)
src/index.ts (1)
UnwrapSchema(8223-8223)src/types.ts (1)
UnwrapSchema(457-495)
test/core/dynamic.test.ts (2)
src/index.ts (2)
Elysia(185-8135)Elysia(8137-8137)test/utils.ts (1)
req(1-2)
src/sucrose.ts (1)
src/universal/request.ts (1)
body(81-144)
test/sucrose/sucrose.test.ts (1)
src/sucrose.ts (1)
sucrose(652-766)
🪛 ast-grep (0.40.0)
src/sucrose.ts
[warning] 557-557: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(${context}(,|\\)), 'gs')
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
🔇 Additional comments (4)
src/index.ts (1)
584-601: Form-data coercion gate looks correct and avoids touching non-TypeBox schemasThe new
additionalCoercelogic that firstresolveSchema(cloned.body, models, modules)and then requiresKind in resolved && (hasType('File', resolved) || hasType('Files', resolved))before switching tocoerceFormData()is a good guardrail: it keeps form-data coercion limited to actual TypeBox file schemas and falls back tocoercePrimitiveRoot()otherwise. This aligns with the intent to support nested form data without impacting standard/custom schemas.Also applies to: 652-665
test/types/utils.ts (1)
1-17: Type-level test correctly validatessafeParse().datainferenceThe new test directly asserts that
getSchemaValidator(schema).safeParse(...).datais{ id: number; name: string }on success, which matches the intendedUnwrapSchemabehavior for object schemas. This is a good, minimal guard for future typing changes.test/sucrose/sucrose.test.ts (1)
311-330: New sucrose test usefully extends context-inference coverageThe
handle context pass to function with sub contextcase validates that passingcontextas the single handler parameter—and only accessing a nested property—still flips all inference flags totrue. This matches the newisContextPassToFunctionlogic and strengthens regression coverage around context-based inference.src/schema.ts (1)
24-35: UnwrapSchema integration and resolveSchema helper correctly align with runtime behavior
- Importing
UnwrapSchemaand updatingElysiaTypeCheck<T>soClean,parse, and the success branch ofsafeParseall returnUnwrapSchema<T>matches how TypeBox and StandardSchemaV1Like schemas are decoded at runtime. For TypeBox schemas,UnwrapSchemaextracts the static output type viaTImport['static']; for StandardSchemaV1Like, it usesSchema['~standard']['types']['output'].- The new
resolveSchemahelper (string → module$defs→ models map) centralizes schema resolution and is used from other modules to determine coercion strategy without duplicating lookup logic.- The
replaceSchemaTypeFromManyOptionscall for root object schemas withoutadditionalPropertiesset (wrapping them into an explicitt.Object(..., { additionalProperties: false })) is a targeted normalization that keeps response/body cleaning strict by default while honoring explicit settings.- The type-level test in
test/types/utils.tsconfirms thatgetSchemaValidator(t.Object({...})).safeParse().datais correctly typed as the unwrapped static type, validating the end-to-end behavior.
| it('call local afterResponse on aot: false', async () => { | ||
| let called = false | ||
|
|
||
| const app = new Elysia({ aot: false }) | ||
| .use(IdsModel) | ||
| .get('/', ({ query }) => query, { | ||
| name: 'ids' | ||
| }) | ||
|
|
||
| const data = await app | ||
| .handle(req('/?names=rapi&names=anis')) | ||
| .then((x) => x.json()) | ||
|
|
||
| expect(data).toEqual({ | ||
| names: ['rapi', 'anis'] | ||
| }) | ||
| }) | ||
| .guard( | ||
| { | ||
| afterResponse: () => { | ||
| called = true | ||
| } | ||
| }, | ||
| (app) => app.get('/test', () => 'afterResponse') | ||
| ) | ||
| .get('/', () => 'hi') | ||
|
|
||
| const value = await app.handle(req('/test')).then((x) => x.text()) | ||
| await Bun.sleep(6.7) | ||
|
|
||
| expect(value).toBe('afterResponse') | ||
| expect(called).toBeTrue() | ||
| }) |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Bun.sleep milliseconds unit documentation
💡 Result:
Bun.sleep expects milliseconds (number) — or a Date to sleep until. Example: await Bun.sleep(1000) sleeps ~1000 ms. Bun.sleepSync also uses milliseconds. [1][2][3]
Sources:
[1] Bun API — Bun.sleep.
[2] Bun runtime/utils documentation — Bun.sleep.
[3] Bun v0.5.8 release notes (sleepSync uses milliseconds).
🏁 Script executed:
cd test/core && wc -l dynamic.test.tsRepository: elysiajs/elysia
Length of output: 78
🏁 Script executed:
sed -n '697,750p' test/core/dynamic.test.tsRepository: elysiajs/elysia
Length of output: 1346
Make afterResponse timing in this test more robust and remove dead code
The new call local afterResponse on aot: false test correctly exercises a local afterResponse hook in dynamic mode, but it relies on await Bun.sleep(6.7) (6.7 milliseconds) as a timing buffer before asserting called === true. This is a very tight margin and can be flaky under CI load or slower environments where afterResponse scheduling may not complete within that window.
Consider either:
- Increasing the wait to a more conservative value (e.g. 50–100ms), or
- Refactoring to assert via a polling loop or explicit signal from the scheduler instead of a hard-coded timeout.
Additionally, the large commented-out block of duplicate "handle query array reference…" tests immediately below this test should be deleted entirely rather than left commented.
🤖 Prompt for AI Agents
In test/core/dynamic.test.ts around lines 697 to 716, the test uses a very short
fixed delay (await Bun.sleep(6.7)) before asserting the afterResponse hook was
called, which is flaky; replace that hard-coded 6.7ms wait with a more robust
approach such as increasing the delay to a conservative 50–100ms or, better,
poll/wait until the `called` flag becomes true with a short timeout to avoid
flakiness; also remove the large commented-out block of duplicate "handle query
array reference…" tests immediately below this test.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/index.ts (2)
591-609: Form-data detection viaresolveSchemais sound; consider deduplicating helperUsing
resolveSchema+hasType('File' | 'Files')to switch betweencoerceFormData()andcoercePrimitiveRoot()is a solid way to support nested/file schemas, including refs and named models, in both precompiled and lazy body validators.You have essentially identical closures in the precompile and lazy branches; factoring this into a small local helper (e.g.,
getBodyCoercion(cloned.body, models, modules)) would remove duplication without changing behavior.Also applies to: 671-685
3840-3873: Empty-prefixgrouptyping fix aligns with new tests; optional schema-path tweakSwitching the grouped instance’s
BasePathtoPrefix extends '' ? BasePath : JoinPath<BasePath, Prefix>fixes the double‑slash / extra segment issue forgroup('')at the type level, matching the newRoutes = 'ok'test.For full internal consistency, you might also want to apply the same conditional inside this overload’s
UnwrapRoute<..., JoinPath<BasePath, Prefix>>arguments (and possibly in the second overload), so schema unwrapping uses the same notion of “effective base path” whenPrefixis''. That’s type-level only and can be done later if you start relying on those paths more heavily.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
CHANGELOG.md(1 hunks)example/a.ts(1 hunks)src/index.ts(6 hunks)test/types/index.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- CHANGELOG.md
- example/a.ts
🧰 Additional context used
🧬 Code graph analysis (2)
test/types/index.ts (1)
src/index.ts (2)
Elysia(190-8153)Elysia(8155-8155)
src/index.ts (2)
src/schema.ts (2)
resolveSchema(130-146)hasType(148-184)src/types.ts (1)
JoinPath(2582-2585)
🔇 Additional comments (2)
test/types/index.ts (1)
2925-2937: Empty-prefix group type test matches intent and implementationThe new
group('', ...)test correctly asserts that~Routesexposes a single'ok'key, matching the updatedgrouptyping for empty prefixes. Looks consistent with surrounding type tests and thegroupoverload change insrc/index.ts.src/index.ts (1)
45-52: Schema/coercion imports and new exports look consistentImporting
resolveSchemaalongsidehasType, moving coercion helpers (coercePrimitiveRoot,coerceFormData,queryCoercions,stringToStructureCoercions) into their own module, and re‑exportinggetSchemaValidator/getResponseSchemaValidator/replaceSchemaTypefrom the root all line up cleanly with the rest of the file and broaden the public API without altering existing behavior.Also applies to: 167-172, 8175-8176
There was a problem hiding this comment.
Actionable comments posted: 1
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)
943-1037: Fix precompile crash + make_compiledexplicitly optional.When
shouldPrecompileis true for a new route (oldIndex === undefined),route[index]doesn’t exist yet, but thehandlerobject later readsroute[index].composed(can throw). Also_compiledis used as optional but typed as required.Suggested patch (adjust to exact local context):
- // For pre-compilation stage, eg. Cloudflare Worker - let _compiled: ComposedHandler + // For pre-compilation stage, eg. Cloudflare Worker + let _compiled: ComposedHandler | undefined const compile = () => { if (_compiled) return _compiled const compiled = composeHandler({ app: this, path, method, hooks, validator: createValidator(), handler: typeof handle !== 'function' && typeof adapter.createStaticHandler !== 'function' ? () => handle : handle, allowMeta, inference: this.inference }) if (this.router.history[index]) _compiled = this.router.history[index].composed = compiled return compiled } @@ - const mainHandler = shouldPrecompile - ? compile() + const mainHandler = shouldPrecompile + ? compile() : (ctx: Context) => _compiled ? _compiled(ctx) : ( (route[index].composed = compile!()) as ComposedHandler )(ctx) @@ - const handler = { - handler: shouldPrecompile - ? (route[index].composed as ComposedHandler) - : undefined, + const handler = { + // route[index] may not exist yet for new routes; use the computed mainHandler + handler: shouldPrecompile ? (mainHandler as ComposedHandler) : undefined, compile() { return (this.handler = compile!()) } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (6)
CHANGELOG.md(1 hunks)example/a.ts(1 hunks)src/adapter/cloudflare-worker/index.ts(2 hunks)src/compose.ts(8 hunks)src/index.ts(10 hunks)test/cloudflare/src/index.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- CHANGELOG.md
🧰 Additional context used
🧬 Code graph analysis (5)
test/cloudflare/src/index.ts (2)
src/index.ts (2)
Elysia(190-8160)Elysia(8162-8162)src/adapter/cloudflare-worker/index.ts (1)
CloudflareAdapter(43-77)
example/a.ts (1)
src/index.ts (2)
Elysia(190-8160)Elysia(8162-8162)
src/adapter/cloudflare-worker/index.ts (1)
src/compose.ts (1)
composeErrorHandler(2537-2762)
src/compose.ts (1)
src/utils.ts (1)
hasSetImmediate(402-402)
src/index.ts (3)
src/schema.ts (2)
resolveSchema(130-146)hasType(148-184)src/types.ts (2)
ComposedHandler(1883-1883)JoinPath(2582-2585)src/type-system/utils.ts (1)
compile(38-76)
🔇 Additional comments (12)
example/a.ts (1)
1-8: Example looks fine; intentional failure route is clear.src/index.ts (5)
51-52: Good: schema-aware coercion imports are now wired in.Also applies to: 167-172
597-609: Coercion selection viaresolveSchema()is a solid fix for File/Files detection.Also applies to: 672-684
3847-3853: Type-level fix forgroup('')base path inference is on point.
8026-8041: Good: web-standardcompile()now wires_handleconsistently.
8182-8184: Public exports added—worth double-checking API intent + docs.This changes the package surface area (
getSchemaValidator,getResponseSchemaValidator,replaceSchemaType). Ensure it’s intended for semver + documented in the changelog/website.src/adapter/cloudflare-worker/index.ts (2)
3-3: Cloudflare beforeCompile wiring looks consistent with composed error handling.Also applies to: 65-69
70-76: listen() warning behavior is fine (Cloudflare Workers).test/cloudflare/src/index.ts (1)
4-8: Good: test now exercises.use(sub)composition under Cloudflare + AOT.src/compose.ts (3)
22-31: Nice: runtime-agnostic scheduling primitive fits the codegen model.Also applies to: 448-451
812-845: Scheduling via${setImmediateFn}is consistent; consider whether microtask timing is acceptable for afterResponse.In runtimes without
setImmediate, this becomesPromise.resolve().then(...)(microtask). That can run earlier than a macrotask-based defer; please sanity-check expected ordering forafterResponse/stream listeners in Worker-like environments.Also applies to: 1786-1792, 2350-2360, 2584-2612
2225-2227: Good: avoids crashing onprocess-less runtimes when composition fails.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/index.ts (2)
942-990: Fix_compiledtyping and avoid “used before assigned” semantics.
let _compiled: ComposedHandleris read before assignment; make it optional/undefinedable to match the control flow.- let _compiled: ComposedHandler + let _compiled: ComposedHandler | undefined
8019-8031: Blocker:compile()assigns tofetchgetter → TS2540 (pipeline failure).
You’re correctly cachingfetchviaObject.definePropertyin the getter, butcompile()still doesthis.fetch = .... Switchcompile()to define the instance property instead of assignment.if (this['~adapter'].isWebStandard) { - this._handle = this.fetch = this.config.aot - ? composeGeneralHandler(this) - : createDynamicHandler(this) + const fetch = this.config.aot + ? composeGeneralHandler(this) + : createDynamicHandler(this) + + this._handle = fetch + Object.defineProperty(this, 'fetch', { + value: fetch, + configurable: true, + writable: true + }) if (typeof this.server?.reload === 'function') this.server.reload({ ...(this.server || {}), - fetch: this.fetch + fetch }) return this }Also applies to: 8048-8060
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
CHANGELOG.md(1 hunks)example/a.ts(1 hunks)src/adapter/bun/index.ts(2 hunks)src/index.ts(11 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- CHANGELOG.md
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-22T23:46:33.200Z
Learnt from: 81reap
Repo: elysiajs/elysia PR: 1431
File: src/dynamic-handle.ts:127-131
Timestamp: 2025-09-22T23:46:33.200Z
Learning: The File System Routing feature in Elysia is Bun-specific and only works with Bun.FileSystemRouter, so Bun-specific import patterns and path resolution using import.meta.url are acceptable in this context.
Applied to files:
example/a.ts
🧬 Code graph analysis (1)
src/adapter/bun/index.ts (2)
test/types/index.ts (2)
message(1220-1220)message(2465-2467)src/ws/index.ts (1)
message(22-24)
🪛 GitHub Actions: Build and Test
src/index.ts
[error] 8020-8020: TS2540: Cannot assign to 'fetch' because it is a read-only property. Build failed. Command 'bun run build' exited with code 1.
🔇 Additional comments (6)
src/adapter/bun/index.ts (2)
442-448: LGTM!The multi-line formatting improves readability of the nested ternary without changing the validation logic. Both validator branches correctly return truthy values when validation fails.
574-577: LGTM!The multi-line if-condition formatting improves readability while preserving the same short-circuit evaluation logic for WebSocket message validation.
src/index.ts (2)
3846-3860: Group prefix typing improvement looks good.
HandlingPrefix extends ''avoids producingJoinPath<BasePath, ''>-style artifacts and matches expected ergonomics for “no prefix” groups.
8181-8182: Public export rename: confirm this is intentional and documented.
replaceSchemaTypeFromManyOptions as replaceSchemaTypelooks like a public surface change; please confirm downstream docs/tests align and no older named export is relied upon.example/a.ts (2)
8-11: Passingapp.fetchintoBun.serveis fine with the lazy getter.
The getter returns a stable handler function and will cache itself viaObject.defineProperty.
3-6: Remove misleading comment about aot being broken on Bun.The comment "aot: true by default in 1.4 (broken on Bun)" is incorrect. The Bun adapter explicitly requires both
aot: trueandsystemRouter: trueto enable route optimization. Simply remove the comment or update it to reflect actual behavior.
| additionalCoerce: (() => { | ||
| const resolved = resolveSchema(cloned.body, models, modules) | ||
| const resolved = resolveSchema( | ||
| cloned.body, | ||
| models, | ||
| modules | ||
| ) | ||
| // Only check for Files if resolved schema is a TypeBox schema (has Kind symbol) | ||
| return (resolved && Kind in resolved && (hasType('File', resolved) || hasType('Files', resolved))) | ||
| return resolved && | ||
| Kind in resolved && | ||
| (hasType('File', resolved) || | ||
| hasType('Files', resolved)) | ||
| ? coerceFormData() | ||
| : coercePrimitiveRoot() | ||
| })(), |
There was a problem hiding this comment.
Guard Kind in resolved against non-object returns from resolveSchema.
resolved && Kind in resolved will throw if resolved is a truthy primitive. Safer to gate on typeof resolved === 'object' || typeof resolved === 'function'.
- return resolved &&
- Kind in resolved &&
+ return resolved &&
+ (typeof resolved === 'object' ||
+ typeof resolved === 'function') &&
+ Kind in resolved &&
(hasType('File', resolved) ||
hasType('Files', resolved))
? coerceFormData()
: coercePrimitiveRoot()Also applies to: 670-683
🤖 Prompt for AI Agents
In src/index.ts around lines 595-608 (and similarly around 670-683), the code
uses "resolved && Kind in resolved" which will throw if resolved is a truthy
primitive; replace that guard with an explicit object/function check such as
"resolved !== null && (typeof resolved === 'object' || typeof resolved ===
'function') && Kind in resolved" (or equivalent) so the in-check only runs for
objects/functions, and apply the same fix to the second occurrence.
There was a problem hiding this comment.
this is fine because we enforced resolved to be StandardSchemaV1Like elsewhere which enforce to always be either object or undefined
There was a problem hiding this comment.
@SaltyAom, understood! If resolveSchema is typed to return StandardSchemaV1Like | undefined and StandardSchemaV1Like is constrained to object types only, then the check is indeed safe:
- When
resolvedisundefined, the condition short-circuits atresolved && - When
resolvedis truthy, TypeScript guarantees it's an object, makingKind in resolvedsafe
The type system enforcement eliminates the need for additional runtime guards. Thanks for clarifying the type constraints!
Improvement
Bug fix:
Summary by CodeRabbit
Bug Fixes
Improvements
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.