evlog 2.3.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +105 -25
  2. package/dist/elysia/index.d.mts +7 -24
  3. package/dist/elysia/index.d.mts.map +1 -1
  4. package/dist/elysia/index.mjs +14 -4
  5. package/dist/elysia/index.mjs.map +1 -1
  6. package/dist/express/index.d.mts +4 -39
  7. package/dist/express/index.d.mts.map +1 -1
  8. package/dist/express/index.mjs +2 -21
  9. package/dist/express/index.mjs.map +1 -1
  10. package/dist/fastify/index.d.mts +37 -0
  11. package/dist/fastify/index.d.mts.map +1 -0
  12. package/dist/fastify/index.mjs +73 -0
  13. package/dist/fastify/index.mjs.map +1 -0
  14. package/dist/headers-CXOd5EyZ.mjs.map +1 -1
  15. package/dist/hono/index.d.mts +3 -24
  16. package/dist/hono/index.d.mts.map +1 -1
  17. package/dist/hono/index.mjs.map +1 -1
  18. package/dist/middleware-BoVCgsfQ.d.mts +36 -0
  19. package/dist/middleware-BoVCgsfQ.d.mts.map +1 -0
  20. package/dist/nestjs/index.d.mts +83 -0
  21. package/dist/nestjs/index.d.mts.map +1 -0
  22. package/dist/nestjs/index.mjs +109 -0
  23. package/dist/nestjs/index.mjs.map +1 -0
  24. package/dist/next/index.d.mts +3 -34
  25. package/dist/next/index.d.mts.map +1 -1
  26. package/dist/nitro/module.d.mts +1 -1
  27. package/dist/nitro/v3/module.d.mts +1 -1
  28. package/dist/{nitro-Nxg6qcXd.d.mts → nitro-BRisWfGy.d.mts} +1 -1
  29. package/dist/{nitro-Nxg6qcXd.d.mts.map → nitro-BRisWfGy.d.mts.map} +1 -1
  30. package/dist/nuxt/module.mjs +1 -1
  31. package/dist/storage-CejtuV76.mjs +45 -0
  32. package/dist/storage-CejtuV76.mjs.map +1 -0
  33. package/dist/sveltekit/index.d.mts +128 -0
  34. package/dist/sveltekit/index.d.mts.map +1 -0
  35. package/dist/sveltekit/index.mjs +163 -0
  36. package/dist/sveltekit/index.mjs.map +1 -0
  37. package/package.json +39 -2
@@ -0,0 +1,163 @@
1
+ import { EvlogError } from "../error.mjs";
2
+ import { n as resolveEvlogError, r as serializeEvlogErrorResponse, t as extractErrorStatus } from "../nitro-Da8tEfJ3.mjs";
3
+ import { r as createMiddlewareLogger, t as extractSafeHeaders } from "../headers-CXOd5EyZ.mjs";
4
+ import { t as createLoggerStorage } from "../storage-CejtuV76.mjs";
5
+
6
+ //#region src/sveltekit/index.ts
7
+ const { storage, useLogger } = createLoggerStorage("handle context. Make sure evlog() handle is added to your hooks.server.ts.");
8
+ /**
9
+ * Create an evlog handle hook for SvelteKit.
10
+ *
11
+ * Add it to your `src/hooks.server.ts` using SvelteKit's `sequence` helper
12
+ * or as the sole handle export.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // src/hooks.server.ts
17
+ * import { initLogger } from 'evlog'
18
+ * import { evlog } from 'evlog/sveltekit'
19
+ * import { createAxiomDrain } from 'evlog/axiom'
20
+ *
21
+ * initLogger({ env: { service: 'my-sveltekit-app' } })
22
+ *
23
+ * export const handle = evlog({
24
+ * drain: createAxiomDrain(),
25
+ * enrich: (ctx) => {
26
+ * ctx.event.region = process.env.FLY_REGION
27
+ * },
28
+ * })
29
+ * ```
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * // Compose with other hooks using sequence
34
+ * import { sequence } from '@sveltejs/kit/hooks'
35
+ * import { evlog } from 'evlog/sveltekit'
36
+ *
37
+ * export const handle = sequence(evlog(), yourOtherHook)
38
+ * ```
39
+ */
40
+ function evlog(options = {}) {
41
+ return async ({ event, resolve }) => {
42
+ const { logger, finish, skipped } = createMiddlewareLogger({
43
+ method: event.request.method,
44
+ path: event.url.pathname,
45
+ requestId: event.request.headers.get("x-request-id") || crypto.randomUUID(),
46
+ headers: extractSafeHeaders(event.request.headers),
47
+ ...options
48
+ });
49
+ if (skipped) return await resolve(event);
50
+ event.locals.log = logger;
51
+ return storage.run(logger, async () => {
52
+ try {
53
+ const response = await resolve(event);
54
+ const errorData = logger.getContext().error;
55
+ if (response.status >= 500 && errorData?.name === "EvlogError" && errorData.status) {
56
+ const { status } = errorData;
57
+ await finish({ status });
58
+ const body = serializeEvlogErrorResponse(errorData, event.url.pathname);
59
+ return new Response(JSON.stringify(body), {
60
+ status,
61
+ headers: { "content-type": "application/json" }
62
+ });
63
+ }
64
+ await finish({ status: response.status });
65
+ return response;
66
+ } catch (error) {
67
+ await finish({ error });
68
+ if (error instanceof EvlogError) {
69
+ const status = error.status ?? 500;
70
+ const body = serializeEvlogErrorResponse(error, event.url.pathname);
71
+ return new Response(JSON.stringify(body), {
72
+ status,
73
+ headers: { "content-type": "application/json" }
74
+ });
75
+ }
76
+ throw error;
77
+ }
78
+ });
79
+ };
80
+ }
81
+ /**
82
+ * Create an evlog error handler for SvelteKit.
83
+ *
84
+ * Logs unhandled errors via `event.locals.log` (if available) and returns
85
+ * structured error responses for `EvlogError` instances. For non-evlog errors,
86
+ * returns a generic error response with sanitized messages in production.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * // src/hooks.server.ts
91
+ * import { evlog, evlogHandleError } from 'evlog/sveltekit'
92
+ *
93
+ * export const handle = evlog()
94
+ * export const handleError = evlogHandleError()
95
+ * ```
96
+ */
97
+ function evlogHandleError() {
98
+ return ({ error, event, status, message }) => {
99
+ const logger = event.locals.log;
100
+ if (logger && error instanceof Error) logger.error(error);
101
+ const evlogError = error instanceof Error ? resolveEvlogError(error) : null;
102
+ if (evlogError) {
103
+ const errorStatus = extractErrorStatus(evlogError);
104
+ const response = serializeEvlogErrorResponse(evlogError, event.url.pathname);
105
+ return {
106
+ message: response.message,
107
+ status: errorStatus,
108
+ why: response.data?.why,
109
+ fix: response.data?.fix,
110
+ link: response.data?.link
111
+ };
112
+ }
113
+ return {
114
+ message,
115
+ status
116
+ };
117
+ };
118
+ }
119
+ /**
120
+ * Create both `handle` and `handleError` hooks in a single call.
121
+ *
122
+ * This is the recommended setup for SvelteKit — it returns both hooks
123
+ * pre-configured and ready to export from `hooks.server.ts`.
124
+ *
125
+ * @example
126
+ * ```ts
127
+ * // src/hooks.server.ts
128
+ * import { initLogger } from 'evlog'
129
+ * import { createEvlogHooks } from 'evlog/sveltekit'
130
+ * import { createAxiomDrain } from 'evlog/axiom'
131
+ *
132
+ * initLogger({ env: { service: 'my-app' } })
133
+ *
134
+ * export const { handle, handleError } = createEvlogHooks({
135
+ * drain: createAxiomDrain(),
136
+ * enrich: (ctx) => {
137
+ * ctx.event.region = process.env.FLY_REGION
138
+ * },
139
+ * })
140
+ * ```
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * // Compose with other hooks using sequence
145
+ * import { sequence } from '@sveltejs/kit/hooks'
146
+ * import { createEvlogHooks } from 'evlog/sveltekit'
147
+ *
148
+ * const evlogHooks = createEvlogHooks()
149
+ *
150
+ * export const handle = sequence(evlogHooks.handle, yourOtherHook)
151
+ * export const handleError = evlogHooks.handleError
152
+ * ```
153
+ */
154
+ function createEvlogHooks(options = {}) {
155
+ return {
156
+ handle: evlog(options),
157
+ handleError: evlogHandleError()
158
+ };
159
+ }
160
+
161
+ //#endregion
162
+ export { createEvlogHooks, evlog, evlogHandleError, useLogger };
163
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/sveltekit/index.ts"],"sourcesContent":["import type { RequestLogger } from '../types'\nimport { createMiddlewareLogger, type BaseEvlogOptions } from '../shared/middleware'\nimport { extractSafeHeaders } from '../shared/headers'\nimport { createLoggerStorage } from '../shared/storage'\nimport { resolveEvlogError, extractErrorStatus, serializeEvlogErrorResponse } from '../nitro'\nimport { EvlogError } from '../error'\n\nconst { storage, useLogger } = createLoggerStorage(\n 'handle context. Make sure evlog() handle is added to your hooks.server.ts.',\n)\n\nexport type EvlogSvelteKitOptions = BaseEvlogOptions\n\nexport { useLogger }\n\n/**\n * SvelteKit `Handle` function signature — avoids a hard dependency on `@sveltejs/kit`.\n */\ntype SvelteKitHandle = (input: {\n event: { request: Request; url: URL; locals: Record<string, any> }\n resolve: (event: any) => Promise<Response>\n}) => Promise<Response>\n\n/**\n * SvelteKit `HandleServerError` signature — avoids a hard dependency on `@sveltejs/kit`.\n */\ntype SvelteKitHandleServerError = (input: {\n error: unknown\n event: { request: Request; url: URL; locals: Record<string, any> }\n status: number\n message: string\n}) => MaybePromise<void | AppError>\n\ntype MaybePromise<T> = T | Promise<T>\n\n/** Minimal SvelteKit `App.Error` shape */\ninterface AppError {\n message: string\n [key: string]: unknown\n}\n\n/**\n * Create an evlog handle hook for SvelteKit.\n *\n * Add it to your `src/hooks.server.ts` using SvelteKit's `sequence` helper\n * or as the sole handle export.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { initLogger } from 'evlog'\n * import { evlog } from 'evlog/sveltekit'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'my-sveltekit-app' } })\n *\n * export const handle = evlog({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n *\n * @example\n * ```ts\n * // Compose with other hooks using sequence\n * import { sequence } from '@sveltejs/kit/hooks'\n * import { evlog } from 'evlog/sveltekit'\n *\n * export const handle = sequence(evlog(), yourOtherHook)\n * ```\n */\nexport function evlog(options: EvlogSvelteKitOptions = {}): SvelteKitHandle {\n return async ({ event, resolve }) => {\n const { logger, finish, skipped } = createMiddlewareLogger({\n method: event.request.method,\n path: event.url.pathname,\n requestId: event.request.headers.get('x-request-id') || crypto.randomUUID(),\n headers: extractSafeHeaders(event.request.headers),\n ...options,\n })\n\n if (skipped) {\n return await resolve(event)\n }\n\n event.locals.log = logger\n\n return storage.run(logger, async () => {\n try {\n const response = await resolve(event)\n\n // SvelteKit catches route errors internally and returns 500.\n // If handleError already logged an EvlogError with a specific status,\n // return a structured JSON response instead of SvelteKit's generic 500.\n const ctx = logger.getContext()\n const errorData = ctx.error as { name?: string; status?: number; message?: string; data?: unknown } | undefined\n if (response.status >= 500 && errorData?.name === 'EvlogError' && errorData.status) {\n const { status } = errorData\n await finish({ status })\n const body = serializeEvlogErrorResponse(errorData as EvlogError, event.url.pathname)\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n }\n\n await finish({ status: response.status })\n return response\n } catch (error) {\n await finish({ error: error as Error })\n\n // Return structured JSON for EvlogError (like NextJS withEvlog / Nuxt errorHandler)\n if (error instanceof EvlogError) {\n const status = error.status ?? 500\n const body = serializeEvlogErrorResponse(error, event.url.pathname)\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'content-type': 'application/json' },\n })\n }\n\n throw error\n }\n })\n }\n}\n\n/**\n * Create an evlog error handler for SvelteKit.\n *\n * Logs unhandled errors via `event.locals.log` (if available) and returns\n * structured error responses for `EvlogError` instances. For non-evlog errors,\n * returns a generic error response with sanitized messages in production.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { evlog, evlogHandleError } from 'evlog/sveltekit'\n *\n * export const handle = evlog()\n * export const handleError = evlogHandleError()\n * ```\n */\nexport function evlogHandleError(): SvelteKitHandleServerError {\n return ({ error, event, status, message }) => {\n const logger = event.locals.log as RequestLogger | undefined\n\n if (logger && error instanceof Error) {\n logger.error(error)\n }\n\n const evlogError = error instanceof Error ? resolveEvlogError(error) : null\n\n if (evlogError) {\n const errorStatus = extractErrorStatus(evlogError)\n const response = serializeEvlogErrorResponse(evlogError, event.url.pathname)\n return {\n message: response.message as string,\n status: errorStatus,\n why: (response.data as { why?: string })?.why,\n fix: (response.data as { fix?: string })?.fix,\n link: (response.data as { link?: string })?.link,\n } as AppError\n }\n\n return { message, status } as AppError\n }\n}\n\n/**\n * Create both `handle` and `handleError` hooks in a single call.\n *\n * This is the recommended setup for SvelteKit — it returns both hooks\n * pre-configured and ready to export from `hooks.server.ts`.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { initLogger } from 'evlog'\n * import { createEvlogHooks } from 'evlog/sveltekit'\n * import { createAxiomDrain } from 'evlog/axiom'\n *\n * initLogger({ env: { service: 'my-app' } })\n *\n * export const { handle, handleError } = createEvlogHooks({\n * drain: createAxiomDrain(),\n * enrich: (ctx) => {\n * ctx.event.region = process.env.FLY_REGION\n * },\n * })\n * ```\n *\n * @example\n * ```ts\n * // Compose with other hooks using sequence\n * import { sequence } from '@sveltejs/kit/hooks'\n * import { createEvlogHooks } from 'evlog/sveltekit'\n *\n * const evlogHooks = createEvlogHooks()\n *\n * export const handle = sequence(evlogHooks.handle, yourOtherHook)\n * export const handleError = evlogHooks.handleError\n * ```\n */\nexport function createEvlogHooks(options: EvlogSvelteKitOptions = {}) {\n return {\n handle: evlog(options),\n handleError: evlogHandleError(),\n }\n}\n"],"mappings":";;;;;;AAOA,MAAM,EAAE,SAAS,cAAc,oBAC7B,6EACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgED,SAAgB,MAAM,UAAiC,EAAE,EAAmB;AAC1E,QAAO,OAAO,EAAE,OAAO,cAAc;EACnC,MAAM,EAAE,QAAQ,QAAQ,YAAY,uBAAuB;GACzD,QAAQ,MAAM,QAAQ;GACtB,MAAM,MAAM,IAAI;GAChB,WAAW,MAAM,QAAQ,QAAQ,IAAI,eAAe,IAAI,OAAO,YAAY;GAC3E,SAAS,mBAAmB,MAAM,QAAQ,QAAQ;GAClD,GAAG;GACJ,CAAC;AAEF,MAAI,QACF,QAAO,MAAM,QAAQ,MAAM;AAG7B,QAAM,OAAO,MAAM;AAEnB,SAAO,QAAQ,IAAI,QAAQ,YAAY;AACrC,OAAI;IACF,MAAM,WAAW,MAAM,QAAQ,MAAM;IAMrC,MAAM,YADM,OAAO,YAAY,CACT;AACtB,QAAI,SAAS,UAAU,OAAO,WAAW,SAAS,gBAAgB,UAAU,QAAQ;KAClF,MAAM,EAAE,WAAW;AACnB,WAAM,OAAO,EAAE,QAAQ,CAAC;KACxB,MAAM,OAAO,4BAA4B,WAAyB,MAAM,IAAI,SAAS;AACrF,YAAO,IAAI,SAAS,KAAK,UAAU,KAAK,EAAE;MACxC;MACA,SAAS,EAAE,gBAAgB,oBAAoB;MAChD,CAAC;;AAGJ,UAAM,OAAO,EAAE,QAAQ,SAAS,QAAQ,CAAC;AACzC,WAAO;YACA,OAAO;AACd,UAAM,OAAO,EAAS,OAAgB,CAAC;AAGvC,QAAI,iBAAiB,YAAY;KAC/B,MAAM,SAAS,MAAM,UAAU;KAC/B,MAAM,OAAO,4BAA4B,OAAO,MAAM,IAAI,SAAS;AACnE,YAAO,IAAI,SAAS,KAAK,UAAU,KAAK,EAAE;MACxC;MACA,SAAS,EAAE,gBAAgB,oBAAoB;MAChD,CAAC;;AAGJ,UAAM;;IAER;;;;;;;;;;;;;;;;;;;AAoBN,SAAgB,mBAA+C;AAC7D,SAAQ,EAAE,OAAO,OAAO,QAAQ,cAAc;EAC5C,MAAM,SAAS,MAAM,OAAO;AAE5B,MAAI,UAAU,iBAAiB,MAC7B,QAAO,MAAM,MAAM;EAGrB,MAAM,aAAa,iBAAiB,QAAQ,kBAAkB,MAAM,GAAG;AAEvE,MAAI,YAAY;GACd,MAAM,cAAc,mBAAmB,WAAW;GAClD,MAAM,WAAW,4BAA4B,YAAY,MAAM,IAAI,SAAS;AAC5E,UAAO;IACL,SAAS,SAAS;IAClB,QAAQ;IACR,KAAM,SAAS,MAA2B;IAC1C,KAAM,SAAS,MAA2B;IAC1C,MAAO,SAAS,MAA4B;IAC7C;;AAGH,SAAO;GAAE;GAAS;GAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuC9B,SAAgB,iBAAiB,UAAiC,EAAE,EAAE;AACpE,QAAO;EACL,QAAQ,MAAM,QAAQ;EACtB,aAAa,kBAAkB;EAChC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evlog",
3
- "version": "2.3.0",
3
+ "version": "2.4.1",
4
4
  "description": "Wide event logging library with structured error handling. Inspired by LoggingSucks.",
5
5
  "author": "HugoRCD <contact@hrcd.fr>",
6
6
  "homepage": "https://evlog.dev",
@@ -23,6 +23,8 @@
23
23
  "express",
24
24
  "hono",
25
25
  "elysia",
26
+ "nestjs",
27
+ "sveltekit",
26
28
  "typescript"
27
29
  ],
28
30
  "license": "MIT",
@@ -100,6 +102,18 @@
100
102
  "./elysia": {
101
103
  "types": "./dist/elysia/index.d.mts",
102
104
  "import": "./dist/elysia/index.mjs"
105
+ },
106
+ "./fastify": {
107
+ "types": "./dist/fastify/index.d.mts",
108
+ "import": "./dist/fastify/index.mjs"
109
+ },
110
+ "./nestjs": {
111
+ "types": "./dist/nestjs/index.d.mts",
112
+ "import": "./dist/nestjs/index.mjs"
113
+ },
114
+ "./sveltekit": {
115
+ "types": "./dist/sveltekit/index.d.mts",
116
+ "import": "./dist/sveltekit/index.mjs"
103
117
  }
104
118
  },
105
119
  "main": "./dist/index.mjs",
@@ -159,6 +173,15 @@
159
173
  ],
160
174
  "elysia": [
161
175
  "./dist/elysia/index.d.mts"
176
+ ],
177
+ "fastify": [
178
+ "./dist/fastify/index.d.mts"
179
+ ],
180
+ "nestjs": [
181
+ "./dist/nestjs/index.d.mts"
182
+ ],
183
+ "sveltekit": [
184
+ "./dist/sveltekit/index.d.mts"
162
185
  ]
163
186
  }
164
187
  },
@@ -187,6 +210,8 @@
187
210
  "consola": "^3.4.2",
188
211
  "elysia": "^1.4.27",
189
212
  "express": "^5.2.1",
213
+ "@nestjs/common": "^10.0.0",
214
+ "fastify": "^5.2.1",
190
215
  "h3": "^1.15.5",
191
216
  "happy-dom": "^20.7.2",
192
217
  "nitro": "^3.0.1-alpha.2",
@@ -207,7 +232,10 @@
207
232
  "react": ">=19.2.4",
208
233
  "hono": "",
209
234
  "express": ">=4.21.0",
210
- "elysia": ">=1.0.0"
235
+ "elysia": ">=1.0.0",
236
+ "fastify": ">=4.0.0",
237
+ "@nestjs/common": ">=9.0.0",
238
+ "@sveltejs/kit": ">=2.0.0"
211
239
  },
212
240
  "peerDependenciesMeta": {
213
241
  "@nuxt/kit": {
@@ -239,6 +267,15 @@
239
267
  },
240
268
  "elysia": {
241
269
  "optional": true
270
+ },
271
+ "fastify": {
272
+ "optional": true
273
+ },
274
+ "@nestjs/common": {
275
+ "optional": true
276
+ },
277
+ "@sveltejs/kit": {
278
+ "optional": true
242
279
  }
243
280
  }
244
281
  }