Repository navigation
Effect Service Conventions: 1 issue found
One convention violation found in the changed scope.
apps/server/src/http.ts(line 33): The newHttpResponseCompressionservice module is imported with a named import (import { HttpResponseCompression }), which erases the module namespace at a service boundary. The convention requires importing the local service module as a namespace (import * as HttpResponseCompression from ...) and consuming it via its public module shape (HttpResponseCompression.HttpResponseCompression). The rest of this PR —server.ts,server.test.ts, andhttp.test.ts— already imports the module as a namespace, so this line is inconsistent with both the codebase and the PR's own convention.
An inline review comment with the suggested fix has been posted.
Details
Note
Your check run agent prompt is: .macroscope/check-run-agents/effect-service-conventions.md
More information about how Check Run Agents work can be found in our Help Center.
Reviewed the new service module apps/server/src/httpCompression/HttpResponseCompression.ts and its call sites.
Items checked and found compliant:
- Effect library modules imported as namespaces from subpaths (Context, Effect, Layer, HttpServerResponse).
- Service defined via
Context.Servicewith an inline interface; no standaloneFooShapetype. layerNode/layerBunare legitimate implementation-specific layer names for an abstract port with multiple platform implementations, so a genericmake/layeris not required.layerBunusesLayer.succeedappropriately:CompressionStreamis a synchronous global Web API and the method body runs lazily on invocation, so no asynchronous dependency is hidden in the layer.layerNodecorrectly usesLayer.effectbecause it must dynamically importnode:stream/node:zlib.compressHttpResponseacquires the dependency from the environment viayield* HttpResponseCompression; no fake dependency injection,ManagedRuntime.make, orrunPromisein service code.- No error/predicate conventions in scope (service defines no tagged errors).
Only the namespace-import convention at the http.ts service boundary was violated.
🔍 Agent activity — 1 tool call
💭 I'm examining this PR to see how it implements a new
HttpResponseCompressionservice module and whether it follows Effect's service conventions. Looking at the imports and the beginning of the class definition, it's setting up a Context-based service that extends from the HTTP server response module. Defining the service implementation... er.succeedworks fine because it's using synchronous global Web APIs rather than async imports. The distinction is that the Node version needs async module imports, so it properly usesLayer.effect, while Bun'sCompressionStreamis available globally without async dependencies—soLayer.succeedis appropriate here. I need to examine the http.ts file more closely to see if there are any convention violations in how the code is structured. I'm checking theHttpResponseCompression.tsservice definition against the project conventions. The module structure looks solid with proper namespace imports and a Context.Service with an inline interface, but I'm noticing there's nomakeexport. The convention typically requires exporting a realmakefunction when a module owns construction, though for abstract ports with multiple implementations like this one, implementation-specific names are allowed. Since the service construction is straightforward—just wrapping a function—I need to determine if the absence ofmakeviolates the convention or if it's acceptable given the module's abstract nature. Looking at thelayerBunimplementation, it usesLayer.succeedwith a method that callsnew CompressionStream("gzip"), which is a synchronous Web API available globally in Bun. The convention warns againstLayer.succeedimplementations that hide async dependencies, but here the service method does its work lazily when called rather than during layer construction, so there's no hidden async service—this is a legitimate synchronous implementation. Now I'm noticing an inconsistency in how the service is imported:http.tsuses a named import{ HttpResponseCompression }while the test files andserver.tsuse a namespace importimport * as HttpResponseCompression. The convention specifies importing the local service module as a namespace to use its public module shape, so this named import inhttp.tscould be flagged as a violation. The convention explicitly states that namespace imports should be used at service boundaries, and this module is indeed a service being consumed for its service tag. The named import ofHttpResponseCompressionin http.ts was added in this PR, so it's a concrete violation introduced in the changed scope that should be flagged. The Bun layer correctly usesLayer.succeedsinceCompressionStreamis synchronous, while the Node version appropriately usesLayer.effectfor dynamic imports — that's consistent. Now I'm checking whether the named import violation in http.ts is actually worth flagging by looking at how other services are imported across the file to see if namespace imports are the established pattern. Looking at the imports in http.ts, I see everything else uses namespace imports likeimport * as ServerConfigandimport * as BrowserTraceCollector. The newHttpResponseCompressionnamed import breaks that convention, so this is a concrete inconsistency I should flag. The fix would be to switch to a namespace import and update the usage site accordingly at line 91. I need to verify this is a clear convention violation worth failing the check. The named import ofHttpResponseCompressionat the service boundary directly contradicts the requirement to use namespace imports, which is meant to preserve the module namespace. This is the exact anti-pattern the convention warns against, so I'll fail the review. Now I'll write the inline comment with a concrete diff suggestion. I'm seeing thatserver.tsuses a namespace import whilehttp.tsuses a named import, which breaks the established convention. Looking at theHttpResponseCompression` service module, it exposes multiple exports and sits at a service boundary, so it should follow the namespace import pattern. I'll add an inline comment flagging this inconsistency.
1. modify_pr — Effect Service Conventions — 1 finding. At a service boundary the local service module should be imported as a namespace (import * as HttpResponseCompression from ...) and consumed via its public module shape (HttpResponseCompression.HttpResponseCompression), matching how server.ts and the test files in this same PR already import it. See the inline comment.
💭 I'm generating the JSON output for the check run with a failure state since a finding was detected.
Agent Credits: 61 credits