refactor: deduplicate framework options and useLogger#148
Conversation
…ions Extract BaseEvlogOptions in shared/middleware.ts and createLoggerStorage factory in shared/storage.ts to eliminate ~170 lines of copy-pasted types, JSDoc, and AsyncLocalStorage boilerplate across 7 framework integrations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Thank you for following the naming conventions! 🙏 |
Update the template to use BaseEvlogOptions and createLoggerStorage instead of the old copy-paste pattern. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace `interface Evlog*Options extends BaseEvlogOptions {}` with
`type Evlog*Options = BaseEvlogOptions` to satisfy
@typescript-eslint/no-empty-object-type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
useLogger
There was a problem hiding this comment.
Pull request overview
This PR refactors the evlog framework adapters to reduce duplication by extracting shared option types and a shared AsyncLocalStorage/useLogger() factory into packages/evlog/src/shared/.
Changes:
- Introduces
BaseEvlogOptions(shared user-facing options) and updates framework option interfaces to extend it. - Adds
createLoggerStorage()to centralize theAsyncLocalStorage+useLogger()pattern, used by Express/Fastify/NestJS/SvelteKit. - Updates the framework integration skill guide to reflect the new shared utilities.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/evlog/src/sveltekit/index.ts | Switches SvelteKit adapter to BaseEvlogOptions + createLoggerStorage and re-exports useLogger. |
| packages/evlog/src/shared/storage.ts | Adds shared factory for request-scoped storage and useLogger() accessor. |
| packages/evlog/src/shared/middleware.ts | Extracts BaseEvlogOptions and makes MiddlewareLoggerOptions extend it. |
| packages/evlog/src/next/types.ts | Refactors Next options type to extend BaseEvlogOptions. |
| packages/evlog/src/nestjs/index.ts | Switches NestJS adapter to BaseEvlogOptions + createLoggerStorage and re-exports useLogger. |
| packages/evlog/src/hono/index.ts | Refactors Hono options type to extend BaseEvlogOptions. |
| packages/evlog/src/fastify/index.ts | Switches Fastify adapter to BaseEvlogOptions + createLoggerStorage and re-exports useLogger. |
| packages/evlog/src/express/index.ts | Switches Express adapter to BaseEvlogOptions + createLoggerStorage and re-exports useLogger. |
| packages/evlog/src/elysia/index.ts | Refactors Elysia options type to extend BaseEvlogOptions (keeps custom useLogger). |
| .agents/skills/create-framework-integration/SKILL.md | Updates integration template/docs for the new shared types and storage factory. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export type EvlogExpressOptions = BaseEvlogOptions | ||
|
|
||
| export { useLogger } |
There was a problem hiding this comment.
This refactor removes the exported useLogger() JSDoc/examples from the Express entrypoint (it is now a re-exported destructured value). That’s a user-facing docs/IntelliSense regression; consider reintroducing an exported wrapper/alias with JSDoc in this module while delegating to the factory implementation.
| export type EvlogNestJSOptions = BaseEvlogOptions | ||
|
|
||
| export { useLogger } |
There was a problem hiding this comment.
This refactor removes the exported useLogger() JSDoc/examples from the NestJS entrypoint (it is now a re-exported destructured value). That’s a user-facing docs/IntelliSense regression; consider reintroducing an exported wrapper/alias with JSDoc in this module while delegating to the factory implementation.
| export type EvlogSvelteKitOptions = BaseEvlogOptions | ||
|
|
||
| export { useLogger } |
There was a problem hiding this comment.
This refactor removes the exported useLogger() JSDoc/examples from the SvelteKit entrypoint (it is now a re-exported destructured value). That’s a user-facing docs/IntelliSense regression; consider reintroducing an exported wrapper/alias with JSDoc in this module while delegating to the factory implementation.
| import type { FastifyPluginCallback } from 'fastify' | ||
| import type { DrainContext, EnrichContext, RequestLogger, RouteConfig, TailSamplingContext } from '../types' | ||
| import { createMiddlewareLogger } from '../shared/middleware' | ||
| import type { RequestLogger } from '../types' | ||
| import { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware' |
There was a problem hiding this comment.
RequestLogger is imported but no longer referenced in this file (FastifyRequest.log is typed as any, and useLogger/storage typing moved to createLoggerStorage). This will be flagged as an unused import by typical ESLint/TS configs; please remove the import (or reintroduce a typed usage) to keep lint/typecheck clean.
| const { storage, useLogger } = createLoggerStorage( | ||
| 'plugin context. Make sure app.register(evlog) is called before your routes.', | ||
| ) | ||
|
|
||
| export type EvlogFastifyOptions = BaseEvlogOptions | ||
|
|
||
| export { useLogger } |
There was a problem hiding this comment.
This refactor removes the exported useLogger() JSDoc/examples from the Fastify entrypoint (it is now a re-exported destructured value). That’s a user-facing docs/IntelliSense regression; consider reintroducing an exported wrapper/alias with JSDoc in this module while delegating to the factory implementation.
| const { storage, useLogger } = createLoggerStorage( | |
| 'plugin context. Make sure app.register(evlog) is called before your routes.', | |
| ) | |
| export type EvlogFastifyOptions = BaseEvlogOptions | |
| export { useLogger } | |
| const { storage, useLogger: internalUseLogger } = createLoggerStorage( | |
| 'plugin context. Make sure app.register(evlog) is called before your routes.', | |
| ) | |
| export type EvlogFastifyOptions = BaseEvlogOptions | |
| /** | |
| * Get the current request-scoped evlog logger within a Fastify request. | |
| * | |
| * This must be called inside a request lifecycle where the `evlog` Fastify | |
| * plugin has been registered and the request is currently being handled. | |
| * | |
| * @example | |
| * ```ts | |
| * import { evlog, useLogger } from 'evlog/fastify' | |
| * | |
| * app.register(evlog) | |
| * | |
| * app.get('/hello', async (request, reply) => { | |
| * const log = useLogger() | |
| * log.info({ path: request.url }, 'Handling request') | |
| * return { ok: true } | |
| * }) | |
| * ``` | |
| */ | |
| export function useLogger() { | |
| return internalUseLogger() | |
| } |
Add JSDoc to the shared useLogger function in createLoggerStorage so IntelliSense documentation propagates through re-exports. Remove unused RequestLogger import from fastify/index.ts. Addresses review feedback from #148. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
BaseEvlogOptionsinshared/middleware.ts— the 7 framework options interfaces (Express, Fastify, NestJS, Elysia, SvelteKit, Hono, Next.js) nowextends BaseEvlogOptionsinstead of redeclaring the same 6 fields with identical JSDoccreateLoggerStorage()factory inshared/storage.ts— theAsyncLocalStorage+useLogger()pattern was copy-pasted in 5 frameworks, now it's a single factory (Elysia keeps its ownuseLoggerdue to theactiveLoggerscheck)