From 85f1c22e6aa423d10cd619e34ebf98e7e7599514 Mon Sep 17 00:00:00 2001 From: schplitt Date: Tue, 27 Jan 2026 11:15:08 +0100 Subject: [PATCH 01/15] feat: add nitrov3 support --- packages/evlog/build.config.ts | 2 + packages/evlog/package.json | 9 ++- packages/evlog/src/nitro.ts | 21 +++++++ packages/evlog/src/nitro/plugin.ts | 23 +------- packages/evlog/src/nitrov3/plugin.ts | 86 ++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 24 deletions(-) create mode 100644 packages/evlog/src/nitro.ts create mode 100644 packages/evlog/src/nitrov3/plugin.ts diff --git a/packages/evlog/build.config.ts b/packages/evlog/build.config.ts index beba681..daf5889 100644 --- a/packages/evlog/build.config.ts +++ b/packages/evlog/build.config.ts @@ -5,6 +5,7 @@ export default defineBuildConfig({ { input: 'src/index', name: 'index' }, { input: 'src/nuxt/module', name: 'nuxt/module' }, { input: 'src/nitro/plugin', name: 'nitro/plugin' }, + { input: 'src/nitrov3/plugin', name: 'nitrov3/plugin' }, { input: 'src/runtime/client/log', name: 'runtime/client/log' }, { input: 'src/runtime/client/plugin', name: 'runtime/client/plugin' }, { input: 'src/runtime/server/useLogger', name: 'runtime/server/useLogger' }, @@ -32,5 +33,6 @@ export default defineBuildConfig({ 'nitropack', 'nitropack/runtime', 'ofetch', + 'nitro' ], }) diff --git a/packages/evlog/package.json b/packages/evlog/package.json index 24f160f..18a9794 100644 --- a/packages/evlog/package.json +++ b/packages/evlog/package.json @@ -78,12 +78,14 @@ "nitropack": "^2.13.1", "nuxt": "^4.3.0", "typescript": "^5.9.3", - "unbuild": "^3.6.1" + "unbuild": "^3.6.1", + "nitro": "^3.0.1-alpha.2" }, "peerDependencies": { "h3": "^1.15.5", "nitropack": "^2.13.1", - "ofetch": "^1.5.1" + "ofetch": "^1.5.1", + "nitro": "^3.0.1-alpha.2" }, "peerDependenciesMeta": { "h3": { @@ -94,6 +96,9 @@ }, "ofetch": { "optional": true + }, + "nitro": { + "optional": true } } } diff --git a/packages/evlog/src/nitro.ts b/packages/evlog/src/nitro.ts new file mode 100644 index 0000000..9322d74 --- /dev/null +++ b/packages/evlog/src/nitro.ts @@ -0,0 +1,21 @@ +function matchesPattern(path: string, pattern: string): boolean { + // Convert glob pattern to regex + const regexPattern = pattern + .replace(/[.+^${}()|[\]\\]/g, '\\$&') // Escape special regex chars except * and ? + .replace(/\*\*/g, '{{GLOBSTAR}}') // Temp placeholder for ** + .replace(/\*/g, '[^/]*') // * matches anything except / + .replace(/{{GLOBSTAR}}/g, '.*') // ** matches anything including / + .replace(/\?/g, '[^/]') // ? matches single char except / + + const regex = new RegExp(`^${regexPattern}$`) + return regex.test(path) +} + +export function shouldLog(path: string, include?: string[]): boolean { + // If no include patterns, log everything + if (!include || include.length === 0) { + return true + } + // Log only if path matches at least one include pattern + return include.some(pattern => matchesPattern(path, pattern)) +} diff --git a/packages/evlog/src/nitro/plugin.ts b/packages/evlog/src/nitro/plugin.ts index 0d51409..8c9f133 100644 --- a/packages/evlog/src/nitro/plugin.ts +++ b/packages/evlog/src/nitro/plugin.ts @@ -1,6 +1,7 @@ import { defineNitroPlugin, useRuntimeConfig } from 'nitropack/runtime' import { createRequestLogger, initLogger } from '../logger' import type { RequestLogger, ServerEvent } from '../types' +import { shouldLog } from '../nitro' interface EvlogConfig { env?: Record @@ -8,28 +9,6 @@ interface EvlogConfig { include?: string[] } -function matchesPattern(path: string, pattern: string): boolean { - // Convert glob pattern to regex - const regexPattern = pattern - .replace(/[.+^${}()|[\]\\]/g, '\\$&') // Escape special regex chars except * and ? - .replace(/\*\*/g, '{{GLOBSTAR}}') // Temp placeholder for ** - .replace(/\*/g, '[^/]*') // * matches anything except / - .replace(/{{GLOBSTAR}}/g, '.*') // ** matches anything including / - .replace(/\?/g, '[^/]') // ? matches single char except / - - const regex = new RegExp(`^${regexPattern}$`) - return regex.test(path) -} - -function shouldLog(path: string, include?: string[]): boolean { - // If no include patterns, log everything - if (!include || include.length === 0) { - return true - } - // Log only if path matches at least one include pattern - return include.some(pattern => matchesPattern(path, pattern)) -} - function getResponseStatus(event: ServerEvent): number { // Node.js style if (event.node?.res?.statusCode) { diff --git a/packages/evlog/src/nitrov3/plugin.ts b/packages/evlog/src/nitrov3/plugin.ts new file mode 100644 index 0000000..4e896a6 --- /dev/null +++ b/packages/evlog/src/nitrov3/plugin.ts @@ -0,0 +1,86 @@ +import { definePlugin } from 'nitro' +import { useRuntimeConfig } from 'nitro/runtime-config' +import type { CaptureError } from 'nitro/types' +import type { HTTPEvent } from 'nitro/h3' +import { parseURL } from 'ufo' +import { createRequestLogger, initLogger } from '../logger' +import { shouldLog } from '../nitro' +import type { RequestLogger } from '../types' + +interface EvlogConfig { + env?: Record + pretty?: boolean + include?: string[] +} + +// currently nitro/v3 doesnt export hook types correctly +// https://github.com/nitrojs/nitro/blob/8882bc9e1dbf2d342e73097f22a2156f70f50575/src/types/runtime/nitro.ts#L48-L53 +interface NitroRuntimeHooks { + close: () => void; + error: CaptureError; + request: (event: HTTPEvent) => void | Promise; + response: (res: Response, event: HTTPEvent) => void | Promise; +} +// Hookable core type not available so we build it our self +type Hooks = { + hook: ( + name: THookName, + listener: NitroRuntimeHooks[THookName] + ) => void; +} + +export default definePlugin((nitroApp) => { + const config = useRuntimeConfig() + const evlogConfig = config.evlog as EvlogConfig | undefined + + initLogger({ + env: evlogConfig?.env, + pretty: evlogConfig?.pretty, + }) + + const hooks = nitroApp.hooks as Hooks + + + hooks.hook('request', (event) => { + const e = event + + const { method } = e.req + const requestId = e.req.context?.requestId as string | undefined ?? crypto.randomUUID() + + const { + pathname + } = parseURL(e.req.url) + + // Skip logging for routes not matching include patterns + if (!shouldLog(pathname, evlogConfig?.include)) { + return + } + + const log = createRequestLogger({ + method: method, + path: pathname, + requestId, + }) + if (!e.req.context) { + e.req.context = {} + } + e.req.context.log = log + }) + + hooks.hook('response', (res, event) => { + const e = event + const log = e.req.context?.log as RequestLogger | undefined + if (log) { + log.set({ status: res.status }) + log.emit() + } + }) + + hooks.hook('error', (error, { event }) => { + const e = event + const log = e?.req.context?.log as RequestLogger | undefined + if (log) { + log.error(error as Error) + } + }) +}) From 3fc91f75ae029a06650013d3041c753d6a8a1cca Mon Sep 17 00:00:00 2001 From: schplitt Date: Tue, 27 Jan 2026 11:15:22 +0100 Subject: [PATCH 02/15] chore: add ufo package to dependencies --- bun.lock | 39 +++++++++++++++++++++++++++++++++++---- package.json | 1 + 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/bun.lock b/bun.lock index 2dfea06..57b3c20 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "evlog-monorepo", @@ -10,6 +11,7 @@ "eslint": "^9.39.2", "turbo": "^2.7.6", "typescript": "^5.9.3", + "ufo": "^1.6.3", "vitest": "^4.0.18", "vue-tsc": "^3.2.4", }, @@ -38,6 +40,16 @@ "rolldown": "latest", }, }, + "apps/nitrov3-playground": { + "name": "nitrov3-playground", + "dependencies": { + "evlog": "workspace:*", + }, + "devDependencies": { + "nitro": "latest", + "rolldown": "latest", + }, + }, "apps/playground": { "name": "evlog-playground", "dependencies": { @@ -49,7 +61,7 @@ }, "packages/evlog": { "name": "evlog", - "version": "1.0.0", + "version": "1.0.1", "dependencies": { "@nuxt/kit": "^4.3.0", }, @@ -59,6 +71,7 @@ "@nuxt/test-utils": "^3.23.0", "changelogen": "^0.6.2", "h3": "^1.15.5", + "nitro": "^3.0.1-alpha.2", "nitropack": "^2.13.1", "nuxt": "^4.3.0", "typescript": "^5.9.3", @@ -66,11 +79,13 @@ }, "peerDependencies": { "h3": "^1.15.5", + "nitro": "^3.0.1-alpha.2", "nitropack": "^2.13.1", "ofetch": "^1.5.1", }, "optionalPeers": [ "h3", + "nitro", "nitropack", "ofetch", ], @@ -2075,6 +2090,8 @@ "nitropack": ["nitropack@2.13.1", "", { "dependencies": { "@cloudflare/kv-asset-handler": "^0.4.2", "@rollup/plugin-alias": "^6.0.0", "@rollup/plugin-commonjs": "^29.0.0", "@rollup/plugin-inject": "^5.0.5", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.3", "@rollup/plugin-replace": "^6.0.3", "@rollup/plugin-terser": "^0.4.4", "@vercel/nft": "^1.2.0", "archiver": "^7.0.1", "c12": "^3.3.3", "chokidar": "^5.0.0", "citty": "^0.1.6", "compatx": "^0.2.0", "confbox": "^0.2.2", "consola": "^3.4.2", "cookie-es": "^2.0.0", "croner": "^9.1.0", "crossws": "^0.3.5", "db0": "^0.3.4", "defu": "^6.1.4", "destr": "^2.0.5", "dot-prop": "^10.1.0", "esbuild": "^0.27.2", "escape-string-regexp": "^5.0.0", "etag": "^1.8.1", "exsolve": "^1.0.8", "globby": "^16.1.0", "gzip-size": "^7.0.0", "h3": "^1.15.5", "hookable": "^5.5.3", "httpxy": "^0.1.7", "ioredis": "^5.9.1", "jiti": "^2.6.1", "klona": "^2.0.6", "knitwork": "^1.3.0", "listhen": "^1.9.0", "magic-string": "^0.30.21", "magicast": "^0.5.1", "mime": "^4.1.0", "mlly": "^1.8.0", "node-fetch-native": "^1.6.7", "node-mock-http": "^1.0.4", "ofetch": "^1.5.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "pretty-bytes": "^7.1.0", "radix3": "^1.1.2", "rollup": "^4.55.1", "rollup-plugin-visualizer": "^6.0.5", "scule": "^1.3.0", "semver": "^7.7.3", "serve-placeholder": "^2.0.2", "serve-static": "^2.2.1", "source-map": "^0.7.6", "std-env": "^3.10.0", "ufo": "^1.6.3", "ultrahtml": "^1.6.0", "uncrypto": "^0.1.3", "unctx": "^2.5.0", "unenv": "^2.0.0-rc.24", "unimport": "^5.6.0", "unplugin-utils": "^0.3.1", "unstorage": "^1.17.4", "untyped": "^2.0.0", "unwasm": "^0.5.3", "youch": "^4.1.0-beta.13", "youch-core": "^0.3.3" }, "peerDependencies": { "xml2js": "^0.6.2" }, "optionalPeers": ["xml2js"], "bin": { "nitro": "dist/cli/index.mjs", "nitropack": "dist/cli/index.mjs" } }, "sha512-2dDj89C4wC2uzG7guF3CnyG+zwkZosPEp7FFBGHB3AJo11AywOolWhyQJFHDzve8COvGxJaqscye9wW2IrUsNw=="], + "nitrov3-playground": ["nitrov3-playground@workspace:apps/nitrov3-playground"], + "node-abi": ["node-abi@3.87.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ=="], "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], @@ -2729,7 +2746,7 @@ "unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="], - "unstorage": ["unstorage@1.17.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.5", "lru-cache": "^11.2.0", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw=="], + "unstorage": ["unstorage@2.0.0-alpha.5", "", { "peerDependencies": { "@azure/app-configuration": "^1.9.0", "@azure/cosmos": "^4.7.0", "@azure/data-tables": "^13.3.1", "@azure/identity": "^4.13.0", "@azure/keyvault-secrets": "^4.10.0", "@azure/storage-blob": "^12.29.1", "@capacitor/preferences": "^6.0.3 || ^7.0.0", "@deno/kv": ">=0.12.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.35.6", "@vercel/blob": ">=0.27.3", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "chokidar": "^4 || ^5", "db0": ">=0.3.4", "idb-keyval": "^6.2.2", "ioredis": "^5.8.2", "lru-cache": "^11.2.2", "mongodb": "^6 || ^7", "ofetch": "*", "uploadthing": "^7.7.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "chokidar", "db0", "idb-keyval", "ioredis", "lru-cache", "mongodb", "ofetch", "uploadthing"] }, "sha512-Sj8btci21Twnd6M+N+MHhjg3fVn6lAPElPmvFTe0Y/wR0WImErUdA1PzlAaUavHylJ7uDiFwlZDQKm0elG4b7g=="], "untun": ["untun@0.1.3", "", { "dependencies": { "citty": "^0.1.5", "consola": "^3.2.3", "pathe": "^1.1.1" }, "bin": { "untun": "bin/untun.mjs" } }, "sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ=="], @@ -2907,10 +2924,14 @@ "@nuxt/fonts/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + "@nuxt/fonts/unstorage": ["unstorage@1.17.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.5", "lru-cache": "^11.2.0", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw=="], + "@nuxt/kit/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "@nuxt/nitro-server/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + "@nuxt/nitro-server/unstorage": ["unstorage@1.17.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.5", "lru-cache": "^11.2.0", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw=="], + "@nuxt/telemetry/@nuxt/kit": ["@nuxt/kit@3.21.0", "", { "dependencies": { "c12": "^3.3.3", "consola": "^3.4.2", "defu": "^6.1.4", "destr": "^2.0.5", "errx": "^0.1.0", "exsolve": "^1.0.8", "ignore": "^7.0.5", "jiti": "^2.6.1", "klona": "^2.0.6", "knitwork": "^1.3.0", "mlly": "^1.8.0", "ohash": "^2.0.11", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "rc9": "^2.1.2", "scule": "^1.3.0", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ufo": "^1.6.3", "unctx": "^2.5.0", "untyped": "^2.0.0" } }, "sha512-KMTLK/dsGaQioZzkYUvgfN9le4grNW54aNcA1jqzgVZLcFVy4jJfrJr5WZio9NT2EMfajdoZ+V28aD7BRr4Zfw=="], "@nuxt/telemetry/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], @@ -2933,6 +2954,8 @@ "@nuxtjs/i18n/unplugin-vue-router": ["unplugin-vue-router@0.16.2", "", { "dependencies": { "@babel/generator": "^7.28.5", "@vue-macros/common": "^3.1.1", "@vue/language-core": "^3.1.3", "ast-walker-scope": "^0.8.3", "chokidar": "^4.0.3", "json5": "^2.2.3", "local-pkg": "^1.1.2", "magic-string": "^0.30.21", "mlly": "^1.8.0", "muggle-string": "^0.4.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "scule": "^1.3.0", "tinyglobby": "^0.2.15", "unplugin": "^2.3.10", "unplugin-utils": "^0.3.1", "yaml": "^2.8.1" }, "peerDependencies": { "@vue/compiler-sfc": "^3.5.17", "vue-router": "^4.6.0" }, "optionalPeers": ["vue-router"] }, "sha512-lE6ZjnHaXfS2vFI/PSEwdKcdOo5RwAbCKUnPBIN9YwLgSWas3x+qivzQvJa/uxhKzJldE6WK43aDKjGj9Rij9w=="], + "@nuxtjs/i18n/unstorage": ["unstorage@1.17.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.5", "lru-cache": "^11.2.0", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw=="], + "@nuxtjs/mcp-toolkit/@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="], "@parcel/watcher-wasm/napi-wasm": ["napi-wasm@1.1.3", "", { "bundled": true }, "sha512-h/4nMGsHjZDCYmQVNODIrYACVJ+I9KItbG+0si6W/jSjdA9JbWDoU4LLeMXVcEQGHjttI2tuXqDrbGF7qkUHHg=="], @@ -3013,18 +3036,24 @@ "fontless/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + "fontless/unstorage": ["unstorage@1.17.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.5", "lru-cache": "^11.2.0", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw=="], + "glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], "globals/type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="], "globby/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + "h3-next/crossws": ["crossws@0.4.3", "", { "peerDependencies": { "srvx": ">=0.7.1" }, "optionalPeers": ["srvx"] }, "sha512-lmf5mtwHiToP3HumOx53cqS0T5TK8GMBpsbSCXRB5OuszbltTgGOO4B1WhrDYqTeXOk3BAemibNjJx8E0/ecNw=="], + "hast-util-raw/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], "impound/unplugin-utils": ["unplugin-utils@0.2.5", "", { "dependencies": { "pathe": "^2.0.3", "picomatch": "^4.0.3" } }, "sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg=="], + "ipx/unstorage": ["unstorage@1.17.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.5", "lru-cache": "^11.2.0", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw=="], + "jsonc-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "jsonc-eslint-parser/espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], @@ -3053,12 +3082,12 @@ "nitro/ofetch": ["ofetch@2.0.0-alpha.3", "", {}, "sha512-zpYTCs2byOuft65vI3z43Dd6iSdFbOZZLb9/d21aCpx2rGastVU9dOCv0lu4ykc1Ur1anAYjDi3SUvR0vq50JA=="], - "nitro/unstorage": ["unstorage@2.0.0-alpha.5", "", { "peerDependencies": { "@azure/app-configuration": "^1.9.0", "@azure/cosmos": "^4.7.0", "@azure/data-tables": "^13.3.1", "@azure/identity": "^4.13.0", "@azure/keyvault-secrets": "^4.10.0", "@azure/storage-blob": "^12.29.1", "@capacitor/preferences": "^6.0.3 || ^7.0.0", "@deno/kv": ">=0.12.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.35.6", "@vercel/blob": ">=0.27.3", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "chokidar": "^4 || ^5", "db0": ">=0.3.4", "idb-keyval": "^6.2.2", "ioredis": "^5.8.2", "lru-cache": "^11.2.2", "mongodb": "^6 || ^7", "ofetch": "*", "uploadthing": "^7.7.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "chokidar", "db0", "idb-keyval", "ioredis", "lru-cache", "mongodb", "ofetch", "uploadthing"] }, "sha512-Sj8btci21Twnd6M+N+MHhjg3fVn6lAPElPmvFTe0Y/wR0WImErUdA1PzlAaUavHylJ7uDiFwlZDQKm0elG4b7g=="], - "nitropack/cookie-es": ["cookie-es@2.0.0", "", {}, "sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg=="], "nitropack/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + "nitropack/unstorage": ["unstorage@1.17.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.5", "lru-cache": "^11.2.0", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw=="], + "node-emoji/@sindresorhus/is": ["@sindresorhus/is@4.6.0", "", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="], "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], @@ -3071,6 +3100,8 @@ "nuxt-og-image/execa": ["execa@9.6.1", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.6", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.1", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.2.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.1.1" } }, "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA=="], + "nuxt-og-image/unstorage": ["unstorage@1.17.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.5", "lru-cache": "^11.2.0", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw=="], + "nypm/citty": ["citty@0.2.0", "", {}, "sha512-8csy5IBFI2ex2hTVpaHN2j+LNE199AgiI7y4dMintrr8i0lQiFn+0AWMZrWdHKIgMOer65f8IThysYhoReqjWA=="], "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], diff --git a/package.json b/package.json index 4484843..7798ea3 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "eslint": "^9.39.2", "turbo": "^2.7.6", "typescript": "^5.9.3", + "ufo": "^1.6.3", "vitest": "^4.0.18", "vue-tsc": "^3.2.4" }, From d55f9675d34fc35fb4e17f48168bb6f4b3465d0d Mon Sep 17 00:00:00 2001 From: schplitt Date: Tue, 27 Jan 2026 11:15:35 +0100 Subject: [PATCH 03/15] docs: add note for early Nitro v3 support in installation guide --- apps/docs/content/1.getting-started/2.installation.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/docs/content/1.getting-started/2.installation.md b/apps/docs/content/1.getting-started/2.installation.md index 000910b..05d2dfa 100644 --- a/apps/docs/content/1.getting-started/2.installation.md +++ b/apps/docs/content/1.getting-started/2.installation.md @@ -61,6 +61,10 @@ export default defineNitroConfig({ }) ``` +::callout{icon="i-lucide-info" color="info"} +For early Nitro v3 support, use `evlog/nitrov3` instead of `evlog/nitro`. +:: + ## Standalone TypeScript For scripts, workers, CLI tools, or any TypeScript project: From e25ae9b5d739960bc1433fdb32227fa38452ebef Mon Sep 17 00:00:00 2001 From: schplitt Date: Tue, 27 Jan 2026 11:15:50 +0100 Subject: [PATCH 04/15] chore: initialize nitrov3 playground --- apps/nitro-playground/nitro.config.ts | 2 +- apps/nitrov3-playground/.gitignore | 8 + apps/nitrov3-playground/README.md | 18 +++ apps/nitrov3-playground/bun.lock | 171 ++++++++++++++++++++ apps/nitrov3-playground/index.html | 20 +++ apps/nitrov3-playground/nitro.config.ts | 7 + apps/nitrov3-playground/package.json | 16 ++ apps/nitrov3-playground/public/styles.css | 71 ++++++++ apps/nitrov3-playground/routes/api/index.ts | 10 ++ apps/nitrov3-playground/tsconfig.json | 8 + 10 files changed, 330 insertions(+), 1 deletion(-) create mode 100644 apps/nitrov3-playground/.gitignore create mode 100644 apps/nitrov3-playground/README.md create mode 100644 apps/nitrov3-playground/bun.lock create mode 100644 apps/nitrov3-playground/index.html create mode 100644 apps/nitrov3-playground/nitro.config.ts create mode 100644 apps/nitrov3-playground/package.json create mode 100644 apps/nitrov3-playground/public/styles.css create mode 100644 apps/nitrov3-playground/routes/api/index.ts create mode 100644 apps/nitrov3-playground/tsconfig.json diff --git a/apps/nitro-playground/nitro.config.ts b/apps/nitro-playground/nitro.config.ts index 3ecb0e0..f6b052a 100644 --- a/apps/nitro-playground/nitro.config.ts +++ b/apps/nitro-playground/nitro.config.ts @@ -2,5 +2,5 @@ import { defineConfig } from 'nitro' export default defineConfig({ serverDir: './', - // plugins: ['evlog/nitro'], TODO: update on v3 release + plugins: ['./node_modules/evlog/nitro'], }) diff --git a/apps/nitrov3-playground/.gitignore b/apps/nitrov3-playground/.gitignore new file mode 100644 index 0000000..d547d8a --- /dev/null +++ b/apps/nitrov3-playground/.gitignore @@ -0,0 +1,8 @@ +node_modules +dist +.data +.nitro +.cache +.output +.env +.env.local diff --git a/apps/nitrov3-playground/README.md b/apps/nitrov3-playground/README.md new file mode 100644 index 0000000..ce15a30 --- /dev/null +++ b/apps/nitrov3-playground/README.md @@ -0,0 +1,18 @@ +# Nitro starter + +Create your API and deploy it anywhere with this Nitro starter. + +## Getting started + +```bash +npm install +npm run dev +``` + +## Deploying + +```bash +npm run build +``` + +Then checkout the [Nitro documentation](https://v3.nitro.build/deploy) to learn more about the different deployment presets. diff --git a/apps/nitrov3-playground/bun.lock b/apps/nitrov3-playground/bun.lock new file mode 100644 index 0000000..a6c7fe5 --- /dev/null +++ b/apps/nitrov3-playground/bun.lock @@ -0,0 +1,171 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "devDependencies": { + "nitro": "latest", + "rolldown": "latest", + }, + }, + }, + "packages": { + "@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], + + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="], + + "@oxc-minify/binding-android-arm-eabi": ["@oxc-minify/binding-android-arm-eabi@0.110.0", "", { "os": "android", "cpu": "arm" }, "sha512-43fMTO8/5bMlqfOiNSZNKUzIqeLIYuB9Hr1Ohyf58B1wU11S2dPGibTXOGNaWsfgHy99eeZ1bSgeIHy/fEYqbw=="], + + "@oxc-minify/binding-android-arm64": ["@oxc-minify/binding-android-arm64@0.110.0", "", { "os": "android", "cpu": "arm64" }, "sha512-5oQrnn9eK/ccOp80PTrNj0Vq893NPNNRryjGpOIVsYNgWFuoGCfpnKg68oEFcN8bArizYAqw4nvgHljEnar69w=="], + + "@oxc-minify/binding-darwin-arm64": ["@oxc-minify/binding-darwin-arm64@0.110.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dqBDgTG9tF2z2lrZp9E8wU+Godz1i8gCGSei2eFKS2hRploBOD5dmOLp1j4IMornkPvSQmbwB3uSjPq7fjx4EA=="], + + "@oxc-minify/binding-darwin-x64": ["@oxc-minify/binding-darwin-x64@0.110.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U0AqabqaooDOpYmeeOye8wClv8PSScELXgOfYqyqgrwH9J9KrpCE1jL8Rlqgz68QbL4mPw3V6sKiiHssI4CLeQ=="], + + "@oxc-minify/binding-freebsd-x64": ["@oxc-minify/binding-freebsd-x64@0.110.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-H0w8o/Wo1072WSdLfhwwrpFpwZnPpjQODlHuRYkTfsSSSJbTxQtjJd4uxk7YJsRv5RQp69y0I7zvdH6f8Xueyw=="], + + "@oxc-minify/binding-linux-arm-gnueabihf": ["@oxc-minify/binding-linux-arm-gnueabihf@0.110.0", "", { "os": "linux", "cpu": "arm" }, "sha512-qd6sW0AvEVYZhbVVMGtmKZw3b1zDYGIW+54Uh42moWRAj6i4Jhk/LGr6r9YNZpOINeuvZfkFuEeDD/jbu7xPUA=="], + + "@oxc-minify/binding-linux-arm-musleabihf": ["@oxc-minify/binding-linux-arm-musleabihf@0.110.0", "", { "os": "linux", "cpu": "arm" }, "sha512-7WXP0aXMrWSn0ScppUBi3jf68ebfBG0eri8kxLmBOVSBj6jw1repzkHMITJMBeLr5d0tT/51qFEptiAk2EP2iA=="], + + "@oxc-minify/binding-linux-arm64-gnu": ["@oxc-minify/binding-linux-arm64-gnu@0.110.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-LYfADrq5x1W5gs+u9OIbMbDQNYkAECTXX0ufnAuf3oGmO51rF98kGFR5qJqC/6/csokDyT3wwTpxhE0TkcF/Og=="], + + "@oxc-minify/binding-linux-arm64-musl": ["@oxc-minify/binding-linux-arm64-musl@0.110.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-53GjCVY8kvymk9P6qNDh6zyblcehF5QHstq9QgCjv13ONGRnSHjeds0PxIwiihD7h295bxsWs84DN39syLPH4Q=="], + + "@oxc-minify/binding-linux-ppc64-gnu": ["@oxc-minify/binding-linux-ppc64-gnu@0.110.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-li8XcN81dxbJDMBESnTgGhoiAQ+CNIdM0QGscZ4duVPjCry1RpX+5FJySFbGqG3pk4s9ZzlL/vtQtbRzZIZOzg=="], + + "@oxc-minify/binding-linux-riscv64-gnu": ["@oxc-minify/binding-linux-riscv64-gnu@0.110.0", "", { "os": "linux", "cpu": "none" }, "sha512-SweKfsnLKShu6UFV8mwuj1d1wmlNoL/FlAxPUzwjEBgwiT2HQkY24KnjBH+TIA+//1O83kzmWKvvs4OuEhdIEQ=="], + + "@oxc-minify/binding-linux-riscv64-musl": ["@oxc-minify/binding-linux-riscv64-musl@0.110.0", "", { "os": "linux", "cpu": "none" }, "sha512-oH8G4aFMP8XyTsEpdANC5PQyHgSeGlopHZuW1rpyYcaErg5YaK0vXjQ4EM5HVvPm+feBV24JjxgakTnZoF3aOQ=="], + + "@oxc-minify/binding-linux-s390x-gnu": ["@oxc-minify/binding-linux-s390x-gnu@0.110.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-W9na+Vza7XVUlpf8wMt4QBfH35KeTENEmnpPUq3NSlbQHz8lSlSvhAafvo43NcKvHAXV3ckD/mUf2VkqSdbklg=="], + + "@oxc-minify/binding-linux-x64-gnu": ["@oxc-minify/binding-linux-x64-gnu@0.110.0", "", { "os": "linux", "cpu": "x64" }, "sha512-XJdA4mmmXOjJxSRgNJXsDP7Xe8h3gQhmb56hUcCrvq5d+h5UcEi2pR8rxsdIrS8QmkLuBA3eHkGK8E27D7DTgQ=="], + + "@oxc-minify/binding-linux-x64-musl": ["@oxc-minify/binding-linux-x64-musl@0.110.0", "", { "os": "linux", "cpu": "x64" }, "sha512-QqzvALuOTtSckI8x467R4GNArzYDb/yEh6aNzLoeaY1O7vfT7SPDwlOEcchaTznutpeS9Dy8gUS/AfqtUHaufw=="], + + "@oxc-minify/binding-openharmony-arm64": ["@oxc-minify/binding-openharmony-arm64@0.110.0", "", { "os": "none", "cpu": "arm64" }, "sha512-gAMssLs2Q3+uhLZxanh1DF+27Kaug3cf4PXb9AB7XK81DR+LVcKySXaoGYoOs20Co0fFSphd6rRzKge2qDK3dA=="], + + "@oxc-minify/binding-wasm32-wasi": ["@oxc-minify/binding-wasm32-wasi@0.110.0", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-7Wqi5Zjl022bs2zXq+ICdalDPeDuCH/Nhbi8q2isLihAonMVIT0YH2hqqnNEylRNGYck+FJ6gRZwMpGCgrNxPg=="], + + "@oxc-minify/binding-win32-arm64-msvc": ["@oxc-minify/binding-win32-arm64-msvc@0.110.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-ZPx+0Tj4dqn41ecyoGotlvekQKy6JxJCixn9Rw7h/dafZ3eDuBcEVh3c2ZoldXXsyMIt5ywI8IWzFZsjNedd5Q=="], + + "@oxc-minify/binding-win32-ia32-msvc": ["@oxc-minify/binding-win32-ia32-msvc@0.110.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-H0Oyd3RWBfpEyvJIrFK94RYiY7KKSQl11Ym7LMDwLEagelIAfRCkt1amHZhFa/S3ZRoaOJFXzEw4YKeSsjVFsg=="], + + "@oxc-minify/binding-win32-x64-msvc": ["@oxc-minify/binding-win32-x64-msvc@0.110.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Hr3nK90+qXKJ2kepXwFIcNfQQIOBecB4FFCyaMMypthoEEhVP08heRynj4eSXZ8NL9hLjs3fQzH8PJXfpznRnQ=="], + + "@oxc-project/types": ["@oxc-project/types@0.110.0", "", {}, "sha512-6Ct21OIlrEnFEJk5LT4e63pk3btsI6/TusD/GStLi7wYlGJNOl1GI9qvXAnRAxQU9zqA2Oz+UwhfTOU2rPZVow=="], + + "@oxc-transform/binding-android-arm-eabi": ["@oxc-transform/binding-android-arm-eabi@0.110.0", "", { "os": "android", "cpu": "arm" }, "sha512-sE9dxvqqAax1YYJ3t7j+h5ZSI9jl6dYuDfngl6ieZUrIy5P89/8JKVgAzgp8o3wQSo7ndpJvYsi1K4ZqrmbP7w=="], + + "@oxc-transform/binding-android-arm64": ["@oxc-transform/binding-android-arm64@0.110.0", "", { "os": "android", "cpu": "arm64" }, "sha512-nqtbP4aMCtsCZ6qpHlHaQoWVHSBtlKzwaAgwEOvR+9DWqHjk31BHvpGiDXlMeed6CVNpl3lCbWgygb3RcSjcfw=="], + + "@oxc-transform/binding-darwin-arm64": ["@oxc-transform/binding-darwin-arm64@0.110.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oeSeHnL4Z4cMXtc8V0/rwoVn0dgwlS9q0j6LcHn9dIhtFEdp3W0iSBF8YmMQA+E7sILeLDjsHmHE4Kp0sOScXw=="], + + "@oxc-transform/binding-darwin-x64": ["@oxc-transform/binding-darwin-x64@0.110.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-nL9K5x7OuZydobAGPylsEW9d4APs2qEkIBLMgQPA+kY8dtVD3IR87QsTbs4l4DBQYyun/+ay6qVCDlxqxdX2Jg=="], + + "@oxc-transform/binding-freebsd-x64": ["@oxc-transform/binding-freebsd-x64@0.110.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-GS29zXXirDQhZEUq8xKJ1azAWMuUy3Ih3W5Bc5ddk12LRthO5wRLFcKIyeHpAXCoXymQ+LmxbMtbPf84GPxouw=="], + + "@oxc-transform/binding-linux-arm-gnueabihf": ["@oxc-transform/binding-linux-arm-gnueabihf@0.110.0", "", { "os": "linux", "cpu": "arm" }, "sha512-glzDHak8ISyZJemCUi7RCvzNSl+MQ1ly9RceT2qRufhUsvNZ4C/2QLJ1HJwd2N6E88bO4laYn+RofdRzNnGGEA=="], + + "@oxc-transform/binding-linux-arm-musleabihf": ["@oxc-transform/binding-linux-arm-musleabihf@0.110.0", "", { "os": "linux", "cpu": "arm" }, "sha512-8JThvgJ2FRoTVfbp7e4wqeZqCZbtudM06SfZmNzND9kPNu/LVYygIR+72RWs+xm4bWkuYHg/islo/boNPtMT5Q=="], + + "@oxc-transform/binding-linux-arm64-gnu": ["@oxc-transform/binding-linux-arm64-gnu@0.110.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-IRh21Ub/g4bkHoErZ0AUWMlWfoZaS0A6EaOVtbcY70RSYIMlrsbjiFwJCzM+b/1DD1rXbH5tsGcH7GweTbfRqg=="], + + "@oxc-transform/binding-linux-arm64-musl": ["@oxc-transform/binding-linux-arm64-musl@0.110.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-e5JN94/oy+wevk76q+LMr+2klTTcO60uXa+Wkq558Ms7mdF2TvkKFI++d/JeiuIwJLTi/BxQ4qdT5FWcsHM/ug=="], + + "@oxc-transform/binding-linux-ppc64-gnu": ["@oxc-transform/binding-linux-ppc64-gnu@0.110.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Y3/Tnnz1GvDpmv8FXBIKtdZPsdZklOEPdrL6NHrN5i2u54BOkybFaDSptgWF53wOrJlTrcmAVSE6fRKK9XCM2Q=="], + + "@oxc-transform/binding-linux-riscv64-gnu": ["@oxc-transform/binding-linux-riscv64-gnu@0.110.0", "", { "os": "linux", "cpu": "none" }, "sha512-Y0E35iA9/v9jlkNcP6tMJ+ZFOS0rLsWDqG6rU9z+X2R3fBFJBO9UARIK6ngx8upxk81y1TFR2CmBFhupfYdH6Q=="], + + "@oxc-transform/binding-linux-riscv64-musl": ["@oxc-transform/binding-linux-riscv64-musl@0.110.0", "", { "os": "linux", "cpu": "none" }, "sha512-JOUSYFfHjBUs7xp2FHmZHb8eTYD/oEu0NklS6JgUauqnoXZHiTLPLVW2o2uVCqldnabYHcomuwI2iqVFYJNhTw=="], + + "@oxc-transform/binding-linux-s390x-gnu": ["@oxc-transform/binding-linux-s390x-gnu@0.110.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-7blgoXF9D3Ngzb7eun23pNrHJpoV/TtE6LObwlZ3Nmb4oZ6Z+yMvBVaoW68NarbmvNGfZ95zrOjgm6cVETLYBA=="], + + "@oxc-transform/binding-linux-x64-gnu": ["@oxc-transform/binding-linux-x64-gnu@0.110.0", "", { "os": "linux", "cpu": "x64" }, "sha512-YQ2joGWCVDZVEU2cD/r/w49hVjDm/Qu1BvC/7zs8LvprzdLS/HyMXGF2oA0puw0b+AqgYaz3bhwKB2xexHyITQ=="], + + "@oxc-transform/binding-linux-x64-musl": ["@oxc-transform/binding-linux-x64-musl@0.110.0", "", { "os": "linux", "cpu": "x64" }, "sha512-fkjr5qE632ULmNgvFXWDR/8668WxERz3tU7TQFp6JebPBneColitjSkdx6VKNVXEoMmQnOvBIGeP5tUNT384oA=="], + + "@oxc-transform/binding-openharmony-arm64": ["@oxc-transform/binding-openharmony-arm64@0.110.0", "", { "os": "none", "cpu": "arm64" }, "sha512-HWH9Zj+lMrdSTqFRCZsvDWMz7OnMjbdGsm3xURXWfRZpuaz0bVvyuZNDQXc4FyyhRDsemICaJbU1bgeIpUJDGw=="], + + "@oxc-transform/binding-wasm32-wasi": ["@oxc-transform/binding-wasm32-wasi@0.110.0", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-ejdxHmYfIcHDPhZUe3WklViLt9mDEJE5BzcW7+R1vc5i/5JFA8D0l7NUSsHBJ7FB8Bu9gF+5iMDm6cXGAgaghw=="], + + "@oxc-transform/binding-win32-arm64-msvc": ["@oxc-transform/binding-win32-arm64-msvc@0.110.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-9VTwpXCZs7xkV+mKhQ62dVk7KLnLXtEUxNS2T4nLz3iMl1IJbA4h5oltK0JoobtiUAnbkV53QmMVGW8+Nh3bDQ=="], + + "@oxc-transform/binding-win32-ia32-msvc": ["@oxc-transform/binding-win32-ia32-msvc@0.110.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-5y0fzuNON7/F2hh2P94vANFaRPJ/3DI1hVl5rseCT8VUVqOGIjWaza0YS/D1g6t1WwycW2LWDMi2raOKoWU5GQ=="], + + "@oxc-transform/binding-win32-x64-msvc": ["@oxc-transform/binding-win32-x64-msvc@0.110.0", "", { "os": "win32", "cpu": "x64" }, "sha512-QROrowwlrApI1fEScMknGWKM6GTM/Z2xwMnDqvSaEmzNazBsDUlE08Jasw610hFEsYAVU2K5sp/YaCa9ORdP4A=="], + + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.1", "", { "os": "android", "cpu": "arm64" }, "sha512-He6ZoCfv5D7dlRbrhNBkuMVIHd0GDnjJwbICE1OWpG7G3S2gmJ+eXkcNLJjzjNDpeI2aRy56ou39AJM9AD8YFA=="], + + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YzJdn08kSOXnj85ghHauH2iHpOJ6eSmstdRTLyaziDcUxe9SyQJgGyx/5jDIhDvtOcNvMm2Ju7m19+S/Rm1jFg=="], + + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cIvAbqM+ZVV6lBSKSBtlNqH5iCiW933t1q8j0H66B3sjbe8AxIRetVqfGgcHcJtMzBIkIALlL9fcDrElWLJQcQ=="], + + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-rVt+B1B/qmKwCl1XD02wKfgh3vQPXRXdB/TicV2w6g7RVAM1+cZcpigwhLarqiVCxDObFZ7UgXCxPC7tpDoRog=="], + + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.1", "", { "os": "linux", "cpu": "arm" }, "sha512-69YKwJJBOFprQa1GktPgbuBOfnn+EGxu8sBJ1TjPER+zhSpYeaU4N07uqmyBiksOLGXsMegymuecLobfz03h8Q=="], + + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-9JDhHUf3WcLfnViFWm+TyorqUtnSAHaCzlSNmMOq824prVuuzDOK91K0Hl8DUcEb9M5x2O+d2/jmBMsetRIn3g=="], + + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-UvApLEGholmxw/HIwmUnLq3CwdydbhaHHllvWiCTNbyGom7wTwOtz5OAQbAKZYyiEOeIXZNPkM7nA4Dtng7CLw=="], + + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.1", "", { "os": "linux", "cpu": "x64" }, "sha512-uVctNgZHiGnJx5Fij7wHLhgw4uyZBVi6mykeWKOqE7bVy9Hcxn0fM/IuqdMwk6hXlaf9fFShDTFz2+YejP+x0A=="], + + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.1", "", { "os": "linux", "cpu": "x64" }, "sha512-T6Eg0xWwcxd/MzBcuv4Z37YVbUbJxy5cMNnbIt/Yr99wFwli30O4BPlY8hKeGyn6lWNtU0QioBS46lVzDN38bg=="], + + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.1", "", { "os": "none", "cpu": "arm64" }, "sha512-PuGZVS2xNJyLADeh2F04b+Cz4NwvpglbtWACgrDOa5YDTEHKwmiTDjoD5eZ9/ptXtcpeFrMqD2H4Zn33KAh1Eg=="], + + "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-2mOxY562ihHlz9lEXuaGEIDCZ1vI+zyFdtsoa3M62xsEunDXQE+DVPO4S4x5MPK9tKulG/aFcA/IH5eVN257Cw=="], + + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-oQVOP5cfAWZwRD0Q3nGn/cA9FW3KhMMuQ0NIndALAe6obqjLhqYVYDiGGRGrxvnjJsVbpLwR14gIUYnpIcHR1g=="], + + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.1", "", { "os": "win32", "cpu": "x64" }, "sha512-Ydsxxx++FNOuov3wCBPaYjZrEvKOOGq3k+BF4BPridhg2pENfitSRD2TEuQ8i33bp5VptuNdC9IzxRKU031z5A=="], + + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.1", "", {}, "sha512-UTBjtTxVOhodhzFVp/ayITaTETRHPUPYZPXQe0WU0wOgxghMojXxYjOiPOauKIYNWJAWS2fd7gJgGQK8GU8vDA=="], + + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], + + "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], + + "crossws": ["crossws@0.4.3", "", { "peerDependencies": { "srvx": ">=0.7.1" }, "optionalPeers": ["srvx"] }, "sha512-lmf5mtwHiToP3HumOx53cqS0T5TK8GMBpsbSCXRB5OuszbltTgGOO4B1WhrDYqTeXOk3BAemibNjJx8E0/ecNw=="], + + "db0": ["db0@0.3.4", "", { "peerDependencies": { "@electric-sql/pglite": "*", "@libsql/client": "*", "better-sqlite3": "*", "drizzle-orm": "*", "mysql2": "*", "sqlite3": "*" }, "optionalPeers": ["@electric-sql/pglite", "@libsql/client", "better-sqlite3", "drizzle-orm", "mysql2", "sqlite3"] }, "sha512-RiXXi4WaNzPTHEOu8UPQKMooIbqOEyqA1t7Z6MsdxSCeb8iUC9ko3LcmsLmeUt2SM5bctfArZKkRQggKZz7JNw=="], + + "h3": ["h3@2.0.1-rc.11", "", { "dependencies": { "rou3": "^0.7.12", "srvx": "^0.10.1" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"] }, "sha512-2myzjCqy32c1As9TjZW9fNZXtLqNedjFSrdFy2AjFBQQ3LzrnGoDdFDYfC0tV2e4vcyfJ2Sfo/F6NQhO2Ly/Mw=="], + + "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], + + "nf3": ["nf3@0.3.6", "", {}, "sha512-/XRUUILTAyuy1XunyVQuqGp8aEmZ2TfRTn8Rji+FA4xqv20qzL4jV7Reqbuey2XucKgPeRVcEYGScmJM0UnB6Q=="], + + "nitro": ["nitro@3.0.1-alpha.2", "", { "dependencies": { "consola": "^3.4.2", "crossws": "^0.4.3", "db0": "^0.3.4", "h3": "^2.0.1-rc.11", "jiti": "^2.6.1", "nf3": "^0.3.5", "ofetch": "^2.0.0-alpha.3", "ohash": "^2.0.11", "oxc-minify": "^0.110.0", "oxc-transform": "^0.110.0", "srvx": "^0.10.1", "undici": "^7.18.2", "unenv": "^2.0.0-rc.24", "unstorage": "^2.0.0-alpha.5" }, "peerDependencies": { "rolldown": ">=1.0.0-beta.0", "rollup": "^4", "vite": "^7 || ^8 || >=8.0.0-0", "xml2js": "^0.6.2" }, "optionalPeers": ["rolldown", "rollup", "vite", "xml2js"], "bin": { "nitro": "dist/cli/index.mjs" } }, "sha512-YviDY5J/trS821qQ1fpJtpXWIdPYiOizC/meHavlm1Hfuhx//H+Egd1+4C5SegJRgtWMnRPW9n//6Woaw81cTQ=="], + + "ofetch": ["ofetch@2.0.0-alpha.3", "", {}, "sha512-zpYTCs2byOuft65vI3z43Dd6iSdFbOZZLb9/d21aCpx2rGastVU9dOCv0lu4ykc1Ur1anAYjDi3SUvR0vq50JA=="], + + "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], + + "oxc-minify": ["oxc-minify@0.110.0", "", { "optionalDependencies": { "@oxc-minify/binding-android-arm-eabi": "0.110.0", "@oxc-minify/binding-android-arm64": "0.110.0", "@oxc-minify/binding-darwin-arm64": "0.110.0", "@oxc-minify/binding-darwin-x64": "0.110.0", "@oxc-minify/binding-freebsd-x64": "0.110.0", "@oxc-minify/binding-linux-arm-gnueabihf": "0.110.0", "@oxc-minify/binding-linux-arm-musleabihf": "0.110.0", "@oxc-minify/binding-linux-arm64-gnu": "0.110.0", "@oxc-minify/binding-linux-arm64-musl": "0.110.0", "@oxc-minify/binding-linux-ppc64-gnu": "0.110.0", "@oxc-minify/binding-linux-riscv64-gnu": "0.110.0", "@oxc-minify/binding-linux-riscv64-musl": "0.110.0", "@oxc-minify/binding-linux-s390x-gnu": "0.110.0", "@oxc-minify/binding-linux-x64-gnu": "0.110.0", "@oxc-minify/binding-linux-x64-musl": "0.110.0", "@oxc-minify/binding-openharmony-arm64": "0.110.0", "@oxc-minify/binding-wasm32-wasi": "0.110.0", "@oxc-minify/binding-win32-arm64-msvc": "0.110.0", "@oxc-minify/binding-win32-ia32-msvc": "0.110.0", "@oxc-minify/binding-win32-x64-msvc": "0.110.0" } }, "sha512-KWGTzPo83QmGrXC4ml83PM9HDwUPtZFfasiclUvTV4i3/0j7xRRqINVkrL77CbQnoWura3CMxkRofjQKVDuhBw=="], + + "oxc-transform": ["oxc-transform@0.110.0", "", { "optionalDependencies": { "@oxc-transform/binding-android-arm-eabi": "0.110.0", "@oxc-transform/binding-android-arm64": "0.110.0", "@oxc-transform/binding-darwin-arm64": "0.110.0", "@oxc-transform/binding-darwin-x64": "0.110.0", "@oxc-transform/binding-freebsd-x64": "0.110.0", "@oxc-transform/binding-linux-arm-gnueabihf": "0.110.0", "@oxc-transform/binding-linux-arm-musleabihf": "0.110.0", "@oxc-transform/binding-linux-arm64-gnu": "0.110.0", "@oxc-transform/binding-linux-arm64-musl": "0.110.0", "@oxc-transform/binding-linux-ppc64-gnu": "0.110.0", "@oxc-transform/binding-linux-riscv64-gnu": "0.110.0", "@oxc-transform/binding-linux-riscv64-musl": "0.110.0", "@oxc-transform/binding-linux-s390x-gnu": "0.110.0", "@oxc-transform/binding-linux-x64-gnu": "0.110.0", "@oxc-transform/binding-linux-x64-musl": "0.110.0", "@oxc-transform/binding-openharmony-arm64": "0.110.0", "@oxc-transform/binding-wasm32-wasi": "0.110.0", "@oxc-transform/binding-win32-arm64-msvc": "0.110.0", "@oxc-transform/binding-win32-ia32-msvc": "0.110.0", "@oxc-transform/binding-win32-x64-msvc": "0.110.0" } }, "sha512-/fymQNzzUoKZweH0nC5yvbI2eR0yWYusT9TEKDYVgOgYrf9Qmdez9lUFyvxKR9ycx+PTHi/reIOzqf3wkShQsw=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "rolldown": ["rolldown@1.0.0-rc.1", "", { "dependencies": { "@oxc-project/types": "=0.110.0", "@rolldown/pluginutils": "1.0.0-rc.1" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.1", "@rolldown/binding-darwin-arm64": "1.0.0-rc.1", "@rolldown/binding-darwin-x64": "1.0.0-rc.1", "@rolldown/binding-freebsd-x64": "1.0.0-rc.1", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.1", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.1", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.1", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.1", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.1", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.1", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.1", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.1", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.1" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-M3AeZjYE6UclblEf531Hch0WfVC/NOL43Cc+WdF3J50kk5/fvouHhDumSGTh0oRjbZ8C4faaVr5r6Nx1xMqDGg=="], + + "rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="], + + "srvx": ["srvx@0.10.1", "", { "bin": { "srvx": "bin/srvx.mjs" } }, "sha512-A//xtfak4eESMWWydSRFUVvCTQbSwivnGCEf8YGPe2eHU0+Z6znfUTCPF0a7oV3sObSOcrXHlL6Bs9vVctfXdg=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "undici": ["undici@7.19.1", "", {}, "sha512-Gpq0iNm5M6cQWlyHQv9MV+uOj1jWk7LpkoE5vSp/7zjb4zMdAcUD+VL5y0nH4p9EbUklq00eVIIX/XcDHzu5xg=="], + + "unenv": ["unenv@2.0.0-rc.24", "", { "dependencies": { "pathe": "^2.0.3" } }, "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw=="], + + "unstorage": ["unstorage@2.0.0-alpha.5", "", { "peerDependencies": { "@azure/app-configuration": "^1.9.0", "@azure/cosmos": "^4.7.0", "@azure/data-tables": "^13.3.1", "@azure/identity": "^4.13.0", "@azure/keyvault-secrets": "^4.10.0", "@azure/storage-blob": "^12.29.1", "@capacitor/preferences": "^6.0.3 || ^7.0.0", "@deno/kv": ">=0.12.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.35.6", "@vercel/blob": ">=0.27.3", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "chokidar": "^4 || ^5", "db0": ">=0.3.4", "idb-keyval": "^6.2.2", "ioredis": "^5.8.2", "lru-cache": "^11.2.2", "mongodb": "^6 || ^7", "ofetch": "*", "uploadthing": "^7.7.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "chokidar", "db0", "idb-keyval", "ioredis", "lru-cache", "mongodb", "ofetch", "uploadthing"] }, "sha512-Sj8btci21Twnd6M+N+MHhjg3fVn6lAPElPmvFTe0Y/wR0WImErUdA1PzlAaUavHylJ7uDiFwlZDQKm0elG4b7g=="], + } +} diff --git a/apps/nitrov3-playground/index.html b/apps/nitrov3-playground/index.html new file mode 100644 index 0000000..9867eea --- /dev/null +++ b/apps/nitrov3-playground/index.html @@ -0,0 +1,20 @@ + + + + + + Nitro Starter + + + + + + +
+

This is your brand new Nitro project 🚀

+

Get started by editing the index.html and routes/api/index.ts files.

+

Learn more from 📖 Nitro Documentation

+
{{{ serverFetch("/api") }}}
+
+ + diff --git a/apps/nitrov3-playground/nitro.config.ts b/apps/nitrov3-playground/nitro.config.ts new file mode 100644 index 0000000..5fff5b9 --- /dev/null +++ b/apps/nitrov3-playground/nitro.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'nitro' + +export default defineConfig({ + serverDir: './', + // TODO: make playground work with evlog/nitrov3 + plugins: ['../../packages/evlog/src/nitrov3/plugin.ts'] +}) diff --git a/apps/nitrov3-playground/package.json b/apps/nitrov3-playground/package.json new file mode 100644 index 0000000..44993e4 --- /dev/null +++ b/apps/nitrov3-playground/package.json @@ -0,0 +1,16 @@ +{ + "name": "nitrov3-playground", + "type": "module", + "scripts": { + "build": "nitro build", + "dev": "nitro dev", + "preview": "npx srvx --prod .output/" + }, + "dependencies": { + "evlog": "workspace:*" + }, + "devDependencies": { + "nitro": "latest", + "rolldown": "latest" + } +} diff --git a/apps/nitrov3-playground/public/styles.css b/apps/nitrov3-playground/public/styles.css new file mode 100644 index 0000000..dabf6e8 --- /dev/null +++ b/apps/nitrov3-playground/public/styles.css @@ -0,0 +1,71 @@ +:root { + --bg: #f7fafc; + --card: #fff; + --muted: #6b7280; + --accent: #0ea5a4; + --code-bg: #0f172a; + --code-color: #e6eef8; + --radius: 12px; +} + +html, +body { + height: 100% +} + +body { + margin: 0; + font-family: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial; + background: var(--bg); + color: #0f172a; + display: flex; + align-items: center; + justify-content: center; + padding: 48px; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.card { + background: var(--card); + padding: 28px; + border-radius: var(--radius); + max-width: 760px; + width: 100%; + box-shadow: 0 6px 20px rgba(2, 6, 23, 0.08); + border: 1px solid rgba(15, 23, 42, 0.04); +} + +h1 { + margin: 0 0 6px 0; + font-weight: 600; + font-size: 1.375rem; + color: #0f172a; +} + +p { + margin: 6px 0; + color: var(--muted) +} + +a { + color: var(--accent); + text-decoration: none +} + +code, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, "Roboto Mono", "Helvetica Neue", monospace; + font-size: 0.9rem; +} + +pre.api { + margin-top: 16px; + background: var(--code-bg); + color: var(--code-color); + padding: 12px 16px; + border-radius: 8px; + overflow: auto; + white-space: pre-wrap; + word-break: break-word; +} diff --git a/apps/nitrov3-playground/routes/api/index.ts b/apps/nitrov3-playground/routes/api/index.ts new file mode 100644 index 0000000..5efc982 --- /dev/null +++ b/apps/nitrov3-playground/routes/api/index.ts @@ -0,0 +1,10 @@ +import { useLogger } from 'evlog' +import { defineHandler } from 'nitro/h3' + +export default defineHandler((event) => { + const log = useLogger(event) + log.set({ + nitrov3: 'playground', + }) + return { message: 'Hello from API!' } +}) diff --git a/apps/nitrov3-playground/tsconfig.json b/apps/nitrov3-playground/tsconfig.json new file mode 100644 index 0000000..1099389 --- /dev/null +++ b/apps/nitrov3-playground/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": ["nitro/tsconfig"], + "compilerOptions": { + "paths": { + "~/*": ["./*"] + } + } +} From e6e9445e7a09a96baede73f5643142faa199bfb0 Mon Sep 17 00:00:00 2001 From: schplitt Date: Tue, 27 Jan 2026 11:21:10 +0100 Subject: [PATCH 05/15] revert: nitro 2 playground --- apps/nitro-playground/nitro.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/nitro-playground/nitro.config.ts b/apps/nitro-playground/nitro.config.ts index f6b052a..3ecb0e0 100644 --- a/apps/nitro-playground/nitro.config.ts +++ b/apps/nitro-playground/nitro.config.ts @@ -2,5 +2,5 @@ import { defineConfig } from 'nitro' export default defineConfig({ serverDir: './', - plugins: ['./node_modules/evlog/nitro'], + // plugins: ['evlog/nitro'], TODO: update on v3 release }) From 9d005f02eae9ff5a5fcec0b4e78550d04f100af1 Mon Sep 17 00:00:00 2001 From: schplitt Date: Tue, 27 Jan 2026 11:23:38 +0100 Subject: [PATCH 06/15] chore: add nitrov3 output to package.json --- packages/evlog/package.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/evlog/package.json b/packages/evlog/package.json index 18a9794..3efd56d 100644 --- a/packages/evlog/package.json +++ b/packages/evlog/package.json @@ -34,6 +34,10 @@ "./nitro": { "types": "./dist/nitro/plugin.d.mts", "import": "./dist/nitro/plugin.mjs" + }, + "./nitrov3": { + "types": "./dist/nitro3/plugin.d.mts", + "import": "./dist/nitro3/plugin.mjs" } }, "main": "./dist/index.mjs", @@ -48,6 +52,9 @@ ], "nitro": [ "./dist/nitro/plugin.d.mts" + ], + "nitrov3": [ + "./dist/nitro3/plugin.d.mts" ] } }, From 0b1592a504137f2ecb4e90459a80a811bd8f54e6 Mon Sep 17 00:00:00 2001 From: schplitt Date: Tue, 27 Jan 2026 11:25:05 +0100 Subject: [PATCH 07/15] docs: add note for early Nitro v3 support in README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b0af0c9..91b4d11 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,8 @@ export default defineNitroConfig({ }) ``` +> **Note**: For early Nitro v3 support, use `evlog/nitrov3` instead of `evlog/nitro`. + Same API, same wide events: ```typescript From 6e7727d7637e112ca91b34da97f77bf9739e4afb Mon Sep 17 00:00:00 2001 From: schplitt Date: Tue, 27 Jan 2026 13:32:41 +0100 Subject: [PATCH 08/15] chore: better nitro v3 playground --- apps/nitrov3-playground/index.html | 103 +++++++- apps/nitrov3-playground/public/styles.css | 244 +++++++++++++++--- apps/nitrov3-playground/routes/api/index.ts | 13 +- .../routes/api/test/create.post.ts | 29 +++ .../routes/api/test/delete.delete.ts | 28 ++ .../routes/api/test/success.get.ts | 24 ++ .../routes/api/test/update.put.ts | 26 ++ .../routes/api/test/wide-event.get.ts | 72 ++++++ 8 files changed, 501 insertions(+), 38 deletions(-) create mode 100644 apps/nitrov3-playground/routes/api/test/create.post.ts create mode 100644 apps/nitrov3-playground/routes/api/test/delete.delete.ts create mode 100644 apps/nitrov3-playground/routes/api/test/success.get.ts create mode 100644 apps/nitrov3-playground/routes/api/test/update.put.ts create mode 100644 apps/nitrov3-playground/routes/api/test/wide-event.get.ts diff --git a/apps/nitrov3-playground/index.html b/apps/nitrov3-playground/index.html index 9867eea..5485925 100644 --- a/apps/nitrov3-playground/index.html +++ b/apps/nitrov3-playground/index.html @@ -3,7 +3,7 @@ - Nitro Starter + evlog Nitro v3 Playground @@ -11,10 +11,103 @@
-

This is your brand new Nitro project 🚀

-

Get started by editing the index.html and routes/api/index.ts files.

-

Learn more from 📖 Nitro Documentation

-
{{{ serverFetch("/api") }}}
+

evlog Nitro v3 Playground 🚀

+

Test the evlog integration with different HTTP methods. Check your terminal for wide event logs!

+
+
+

Test API Endpoints

+ +
+ + +
+ +
+ + + + +
+ +
+ +
+ +
+
+
+ + diff --git a/apps/nitrov3-playground/public/styles.css b/apps/nitrov3-playground/public/styles.css index dabf6e8..61fb186 100644 --- a/apps/nitrov3-playground/public/styles.css +++ b/apps/nitrov3-playground/public/styles.css @@ -1,71 +1,253 @@ :root { - --bg: #f7fafc; - --card: #fff; - --muted: #6b7280; - --accent: #0ea5a4; - --code-bg: #0f172a; - --code-color: #e6eef8; - --radius: 12px; + --bg: #020202; + --card: #0a0a0a; + --text: #fafafa; + --muted: #94a3b8; + --border: #27272a; + --primary: #2853FF; + --primary-hover: #3d65ff; + --success: #0ea5a4; + --warning: #f59e0b; + --danger: #ef4444; + --purple: #8b5cf6; + --code-bg: #000000; + --code-text: #e6eef8; + --radius: 8px; + --section-bg: #0f0f0f; +} + +* { + box-sizing: border-box; } html, body { - height: 100% + height: 100%; + overflow: hidden; + margin: 0; + padding: 0; } body { - margin: 0; - font-family: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif; background: var(--bg); - color: #0f172a; + color: var(--text); display: flex; align-items: center; justify-content: center; - padding: 48px; + padding: 24px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + line-height: 1.5; } .card { background: var(--card); - padding: 28px; - border-radius: var(--radius); - max-width: 760px; + padding: 48px; + border-radius: 12px; + max-width: 920px; width: 100%; - box-shadow: 0 6px 20px rgba(2, 6, 23, 0.08); - border: 1px solid rgba(15, 23, 42, 0.04); + max-height: calc(100vh - 48px); + overflow-y: auto; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3), 0 20px 40px rgba(0, 0, 0, 0.5); + border: 1px solid var(--border); } h1 { - margin: 0 0 6px 0; - font-weight: 600; - font-size: 1.375rem; - color: #0f172a; + margin: 0 0 8px 0; + font-weight: 700; + font-size: 2rem; + color: var(--text); + letter-spacing: -0.02em; + line-height: 1.2; } p { - margin: 6px 0; - color: var(--muted) + margin: 0 0 24px 0; + color: var(--muted); + font-size: 1rem; } a { - color: var(--accent); - text-decoration: none + color: var(--primary); + text-decoration: none; + font-weight: 500; +} + +a:hover { + text-decoration: underline; } code, pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, "Roboto Mono", "Helvetica Neue", monospace; - font-size: 0.9rem; + font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + font-size: 0.875rem; } pre.api { - margin-top: 16px; + margin-top: 24px; background: var(--code-bg); - color: var(--code-color); - padding: 12px 16px; - border-radius: 8px; + color: var(--code-text); + padding: 16px 20px; + border-radius: var(--radius); overflow: auto; white-space: pre-wrap; word-break: break-word; + font-size: 0.8125rem; + line-height: 1.6; +} + +.demo-section { + margin-top: 40px; + padding: 32px; + background: var(--section-bg); + border-radius: var(--radius); + border: 1px solid var(--border); +} + +.demo-section h2 { + margin: 0 0 24px 0; + font-size: 1.25rem; + font-weight: 700; + color: var(--text); + letter-spacing: -0.01em; +} + +.buttons { + display: flex; + gap: 12px; + margin-bottom: 16px; + flex-wrap: wrap; +} + +button { + padding: 12px 24px; + border: none; + border-radius: 6px; + font-family: inherit; + font-size: 0.9375rem; + font-weight: 600; + cursor: pointer; + transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1); + flex: 1; + min-width: fit-content; +} + +button:hover { + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +button:active { + transform: translateY(0); +} + +.btn-get { + background: var(--success); + color: white; +} + +.btn-get:hover { + background: #0d9488; +} + +.btn-post { + background: var(--purple); + color: white; +} + +.btn-post:hover { + background: #7c3aed; +} + +.btn-delete { + background: var(--danger); + color: white; +} + +.btn-delete:hover { + background: #dc2626; +} + +.btn-wide { + background: var(--primary); + color: white; + flex: 1 1 100%; +} + +.btn-wide:hover { + background: var(--primary-hover); +} + +#result { + margin-top: 20px; + padding: 20px 24px; + background: var(--code-bg); + color: var(--code-text); + border-radius: var(--radius); + font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + font-size: 0.8125rem; + line-height: 1.7; + white-space: pre-wrap; + word-break: break-word; + min-height: 80px; + display: none; + border: 1px solid #18181b; +} + +#result.show { + display: block; + animation: fadeIn 0.2s ease-in; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(4px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.input-group { + margin-bottom: 24px; +} + +.input-group label { + display: block; + margin-bottom: 8px; + font-size: 0.875rem; + font-weight: 600; + color: var(--text); +} + +.input-group input { + width: 100%; + padding: 12px 16px; + border: 1px solid var(--border); + border-radius: 6px; + font-family: inherit; + font-size: 0.9375rem; + background: var(--code-bg); + color: var(--text); + transition: border-color 0.15s, box-shadow 0.15s; +} + +.input-group input:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px rgba(40, 83, 255, 0.1); +} + +.input-group input::placeholder { + color: #94a3b8; +} + +/* Subtle separator */ +.separator { + height: 1px; + background: linear-gradient(to right, transparent, var(--border), transparent); + margin: 32px 0; } diff --git a/apps/nitrov3-playground/routes/api/index.ts b/apps/nitrov3-playground/routes/api/index.ts index 5efc982..e1397f4 100644 --- a/apps/nitrov3-playground/routes/api/index.ts +++ b/apps/nitrov3-playground/routes/api/index.ts @@ -4,7 +4,16 @@ import { defineHandler } from 'nitro/h3' export default defineHandler((event) => { const log = useLogger(event) log.set({ - nitrov3: 'playground', + playground: 'nitrov3', }) - return { message: 'Hello from API!' } + return { + message: 'evlog Nitro v3 Playground', + endpoints: [ + 'GET /api/test/success', + 'POST /api/test/create', + 'PUT /api/test/update (always fails)', + 'DELETE /api/test/delete', + 'GET /api/test/wide-event', + ], + } }) diff --git a/apps/nitrov3-playground/routes/api/test/create.post.ts b/apps/nitrov3-playground/routes/api/test/create.post.ts new file mode 100644 index 0000000..bc3e5c2 --- /dev/null +++ b/apps/nitrov3-playground/routes/api/test/create.post.ts @@ -0,0 +1,29 @@ +import { defineHandler, readBody } from 'nitro/h3' +import { useLogger } from 'evlog' + +export default defineHandler(async (event) => { + const log = useLogger(event) + const body = await readBody(event) as { name: string; type: string } + + log.set({ user: { id: 456 } }) + log.set({ item: { name: body.name, type: body.type } }) + + // Simulate validation + await new Promise(resolve => setTimeout(resolve, 100)) + log.set({ validation: { passed: true, checks: ['name_length', 'type_valid'] } }) + + // Simulate database insert + await new Promise(resolve => setTimeout(resolve, 200)) + const itemId = `item_${Math.random().toString(36).substring(2, 8)}` + log.set({ database: { operation: 'insert', duration: '200ms' } }) + + // Simulate search indexing + await new Promise(resolve => setTimeout(resolve, 80)) + log.set({ search: { indexed: true, engine: 'elasticsearch' } }) + + return { + success: true, + message: 'Item created', + id: itemId, + } +}) diff --git a/apps/nitrov3-playground/routes/api/test/delete.delete.ts b/apps/nitrov3-playground/routes/api/test/delete.delete.ts new file mode 100644 index 0000000..350f187 --- /dev/null +++ b/apps/nitrov3-playground/routes/api/test/delete.delete.ts @@ -0,0 +1,28 @@ +import { defineHandler } from 'nitro/h3' +import { useLogger } from 'evlog' + +export default defineHandler(async (event) => { + const log = useLogger(event) + const itemId = 'item_123' + + log.set({ user: { id: 789 } }) + log.set({ action: 'delete_item', itemId }) + + // Simulate permission check + await new Promise(resolve => setTimeout(resolve, 100)) + log.set({ permissions: { checked: true, hasDelete: true } }) + + // Simulate database delete + await new Promise(resolve => setTimeout(resolve, 150)) + log.set({ database: { operation: 'delete', affected: 1 } }) + + // Simulate cache invalidation + await new Promise(resolve => setTimeout(resolve, 50)) + log.set({ cache: { invalidated: true, keys: [`item:${itemId}`] } }) + + return { + success: true, + message: 'Item deleted', + deletedId: itemId, + } +}) diff --git a/apps/nitrov3-playground/routes/api/test/success.get.ts b/apps/nitrov3-playground/routes/api/test/success.get.ts new file mode 100644 index 0000000..e5ffdcf --- /dev/null +++ b/apps/nitrov3-playground/routes/api/test/success.get.ts @@ -0,0 +1,24 @@ +import { defineHandler } from 'nitro/h3' +import { useLogger } from 'evlog' + +export default defineHandler(async (event) => { + const log = useLogger(event) + + log.set({ user: { id: 123, plan: 'pro' } }) + log.set({ action: 'fetch_profile' }) + + // Simulate database query + await new Promise(resolve => setTimeout(resolve, 150)) + const profile = { name: 'John Doe', email: 'john@example.com', lastLogin: new Date().toISOString() } + log.set({ profile }) + + // Simulate cache check + await new Promise(resolve => setTimeout(resolve, 50)) + log.set({ cache: { hit: true, ttl: 3600 } }) + + return { + success: true, + message: 'Profile fetched successfully', + data: profile, + } +}) diff --git a/apps/nitrov3-playground/routes/api/test/update.put.ts b/apps/nitrov3-playground/routes/api/test/update.put.ts new file mode 100644 index 0000000..c40f5f3 --- /dev/null +++ b/apps/nitrov3-playground/routes/api/test/update.put.ts @@ -0,0 +1,26 @@ +import { defineHandler, readBody } from 'nitro/h3' +import { useLogger, createError } from 'evlog' + +export default defineHandler(async (event) => { + const log = useLogger(event) + const body = await readBody(event) as { name: string; version: string } + + log.set({ user: { id: 999 } }) + log.set({ action: 'update_item', item: { name: body.name, version: body.version } }) + + // Simulate validation check + await new Promise(resolve => setTimeout(resolve, 100)) + log.set({ validation: { checked: true } }) + + // Simulate permission check that always fails + await new Promise(resolve => setTimeout(resolve, 150)) + log.set({ permissions: { checked: true, hasUpdate: false, requiredRole: 'admin' } }) + + throw createError({ + message: 'Update failed', + status: 403, + why: 'Insufficient permissions to update this resource', + fix: 'Request admin privileges or contact your team lead', + link: 'https://docs.example.com/permissions', + }) +}) diff --git a/apps/nitrov3-playground/routes/api/test/wide-event.get.ts b/apps/nitrov3-playground/routes/api/test/wide-event.get.ts new file mode 100644 index 0000000..b5acf65 --- /dev/null +++ b/apps/nitrov3-playground/routes/api/test/wide-event.get.ts @@ -0,0 +1,72 @@ +import { defineHandler } from 'nitro/h3' +import { useLogger } from 'evlog' + +export default defineHandler(async (event) => { + const log = useLogger(event) + + // User context + await new Promise(resolve => setTimeout(resolve, 80)) + log.set({ + user: { + id: 'user_789', + email: 'demo@example.com', + plan: 'enterprise', + accountAge: '2 years', + role: 'admin', + }, + session: { + device: 'desktop', + browser: 'Chrome 120', + country: 'US', + }, + }) + + // Cart information + await new Promise(resolve => setTimeout(resolve, 80)) + log.set({ + cart: { + items: 5, + total: 24999, + currency: 'USD', + discount: { + code: 'WINTER25', + savings: 8333, + }, + }, + }) + + // Payment processing + await new Promise(resolve => setTimeout(resolve, 80)) + log.set({ + payment: { + method: 'card', + cardBrand: 'visa', + cardLast4: '4242', + }, + fraud: { + score: 12, + riskLevel: 'low', + passed: true, + }, + }) + + // Performance metrics + await new Promise(resolve => setTimeout(resolve, 80)) + log.set({ + performance: { + dbQueries: 8, + cacheHits: 12, + cacheMisses: 2, + }, + flags: { + newCheckoutFlow: true, + experimentId: 'exp_checkout_v2', + }, + }) + + return { + success: true, + message: 'Wide event demo - check your terminal!', + orderId: 'ord_abc123xyz', + } +}) From ef07be70dd6a8ab3c4822b1bb4132f7595dcc91a Mon Sep 17 00:00:00 2001 From: schplitt Date: Tue, 27 Jan 2026 13:33:44 +0100 Subject: [PATCH 09/15] chore: expose nitro v3 at `nitro/v3` --- bun.lock | 2 +- package.json | 1 - packages/evlog/build.config.ts | 2 +- packages/evlog/package.json | 15 ++++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bun.lock b/bun.lock index 57b3c20..fb6b4e0 100644 --- a/bun.lock +++ b/bun.lock @@ -11,7 +11,6 @@ "eslint": "^9.39.2", "turbo": "^2.7.6", "typescript": "^5.9.3", - "ufo": "^1.6.3", "vitest": "^4.0.18", "vue-tsc": "^3.2.4", }, @@ -75,6 +74,7 @@ "nitropack": "^2.13.1", "nuxt": "^4.3.0", "typescript": "^5.9.3", + "ufo": "^1.6.3", "unbuild": "^3.6.1", }, "peerDependencies": { diff --git a/package.json b/package.json index 7798ea3..4484843 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "eslint": "^9.39.2", "turbo": "^2.7.6", "typescript": "^5.9.3", - "ufo": "^1.6.3", "vitest": "^4.0.18", "vue-tsc": "^3.2.4" }, diff --git a/packages/evlog/build.config.ts b/packages/evlog/build.config.ts index daf5889..9cc1c8e 100644 --- a/packages/evlog/build.config.ts +++ b/packages/evlog/build.config.ts @@ -5,7 +5,7 @@ export default defineBuildConfig({ { input: 'src/index', name: 'index' }, { input: 'src/nuxt/module', name: 'nuxt/module' }, { input: 'src/nitro/plugin', name: 'nitro/plugin' }, - { input: 'src/nitrov3/plugin', name: 'nitrov3/plugin' }, + { input: 'src/nitrov3/plugin', name: 'nitro/v3/plugin' }, { input: 'src/runtime/client/log', name: 'runtime/client/log' }, { input: 'src/runtime/client/plugin', name: 'runtime/client/plugin' }, { input: 'src/runtime/server/useLogger', name: 'runtime/server/useLogger' }, diff --git a/packages/evlog/package.json b/packages/evlog/package.json index 3efd56d..6bc94bc 100644 --- a/packages/evlog/package.json +++ b/packages/evlog/package.json @@ -35,9 +35,9 @@ "types": "./dist/nitro/plugin.d.mts", "import": "./dist/nitro/plugin.mjs" }, - "./nitrov3": { - "types": "./dist/nitro3/plugin.d.mts", - "import": "./dist/nitro3/plugin.mjs" + "./nitro/v3": { + "types": "./dist/nitro/v3/plugin.d.mts", + "import": "./dist/nitro/v3/plugin.mjs" } }, "main": "./dist/index.mjs", @@ -53,8 +53,8 @@ "nitro": [ "./dist/nitro/plugin.d.mts" ], - "nitrov3": [ - "./dist/nitro3/plugin.d.mts" + "nitro/v3": [ + "./dist/nitro/v3/plugin.d.mts" ] } }, @@ -86,7 +86,8 @@ "nuxt": "^4.3.0", "typescript": "^5.9.3", "unbuild": "^3.6.1", - "nitro": "^3.0.1-alpha.2" + "nitro": "^3.0.1-alpha.2", + "ufo": "^1.6.3" }, "peerDependencies": { "h3": "^1.15.5", @@ -108,4 +109,4 @@ "optional": true } } -} +} \ No newline at end of file From 6171d49731e5bd8c075ac4c97cda812c8a78eacb Mon Sep 17 00:00:00 2001 From: schplitt Date: Tue, 27 Jan 2026 13:34:55 +0100 Subject: [PATCH 10/15] chore: update Nitro v3 references to use `evlog/nitro/v3` --- README.md | 2 +- apps/docs/content/1.getting-started/2.installation.md | 2 +- apps/nitrov3-playground/nitro.config.ts | 2 +- apps/nitrov3-playground/routes/api/index.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 91b4d11..3a29ff4 100644 --- a/README.md +++ b/README.md @@ -172,7 +172,7 @@ export default defineNitroConfig({ }) ``` -> **Note**: For early Nitro v3 support, use `evlog/nitrov3` instead of `evlog/nitro`. +> **Note**: For early Nitro v3 support, use `evlog/nitro/v3` instead of `evlog/nitro`. Same API, same wide events: diff --git a/apps/docs/content/1.getting-started/2.installation.md b/apps/docs/content/1.getting-started/2.installation.md index 05d2dfa..1186432 100644 --- a/apps/docs/content/1.getting-started/2.installation.md +++ b/apps/docs/content/1.getting-started/2.installation.md @@ -62,7 +62,7 @@ export default defineNitroConfig({ ``` ::callout{icon="i-lucide-info" color="info"} -For early Nitro v3 support, use `evlog/nitrov3` instead of `evlog/nitro`. +For early Nitro v3 support, use `evlog/nitro/v3` instead of `evlog/nitro`. :: ## Standalone TypeScript diff --git a/apps/nitrov3-playground/nitro.config.ts b/apps/nitrov3-playground/nitro.config.ts index 5fff5b9..0cc39f7 100644 --- a/apps/nitrov3-playground/nitro.config.ts +++ b/apps/nitrov3-playground/nitro.config.ts @@ -2,6 +2,6 @@ import { defineConfig } from 'nitro' export default defineConfig({ serverDir: './', - // TODO: make playground work with evlog/nitrov3 + // TODO: make playground work with evlog/nitro/v3 plugins: ['../../packages/evlog/src/nitrov3/plugin.ts'] }) diff --git a/apps/nitrov3-playground/routes/api/index.ts b/apps/nitrov3-playground/routes/api/index.ts index e1397f4..4c37660 100644 --- a/apps/nitrov3-playground/routes/api/index.ts +++ b/apps/nitrov3-playground/routes/api/index.ts @@ -4,7 +4,7 @@ import { defineHandler } from 'nitro/h3' export default defineHandler((event) => { const log = useLogger(event) log.set({ - playground: 'nitrov3', + playground: 'nitro/v3', }) return { message: 'evlog Nitro v3 Playground', From 0994c100ebcc871cedfbea4bb34b7fd34506c47f Mon Sep 17 00:00:00 2001 From: Hugo Richard Date: Tue, 27 Jan 2026 18:47:10 +0000 Subject: [PATCH 11/15] up --- .../.gitignore | 0 .../README.md | 0 .../bun.lock | 0 .../index.html | 0 .../nitro.config.ts | 2 +- .../package.json | 2 +- .../public/styles.css | 0 .../routes/api/index.ts | 0 .../routes/api/test/create.post.ts | 0 .../routes/api/test/delete.delete.ts | 0 .../routes/api/test/success.get.ts | 0 .../routes/api/test/update.put.ts | 0 .../routes/api/test/wide-event.get.ts | 0 .../tsconfig.json | 0 bun.lock | 11 +++++------ package.json | 1 + packages/evlog/build.config.ts | 2 +- packages/evlog/package.json | 6 +++--- packages/evlog/src/{nitrov3 => nitro-v3}/plugin.ts | 0 19 files changed, 12 insertions(+), 12 deletions(-) rename apps/{nitrov3-playground => nitro-v3-playground}/.gitignore (100%) rename apps/{nitrov3-playground => nitro-v3-playground}/README.md (100%) rename apps/{nitrov3-playground => nitro-v3-playground}/bun.lock (100%) rename apps/{nitrov3-playground => nitro-v3-playground}/index.html (100%) rename apps/{nitrov3-playground => nitro-v3-playground}/nitro.config.ts (70%) rename apps/{nitrov3-playground => nitro-v3-playground}/package.json (87%) rename apps/{nitrov3-playground => nitro-v3-playground}/public/styles.css (100%) rename apps/{nitrov3-playground => nitro-v3-playground}/routes/api/index.ts (100%) rename apps/{nitrov3-playground => nitro-v3-playground}/routes/api/test/create.post.ts (100%) rename apps/{nitrov3-playground => nitro-v3-playground}/routes/api/test/delete.delete.ts (100%) rename apps/{nitrov3-playground => nitro-v3-playground}/routes/api/test/success.get.ts (100%) rename apps/{nitrov3-playground => nitro-v3-playground}/routes/api/test/update.put.ts (100%) rename apps/{nitrov3-playground => nitro-v3-playground}/routes/api/test/wide-event.get.ts (100%) rename apps/{nitrov3-playground => nitro-v3-playground}/tsconfig.json (100%) rename packages/evlog/src/{nitrov3 => nitro-v3}/plugin.ts (100%) diff --git a/apps/nitrov3-playground/.gitignore b/apps/nitro-v3-playground/.gitignore similarity index 100% rename from apps/nitrov3-playground/.gitignore rename to apps/nitro-v3-playground/.gitignore diff --git a/apps/nitrov3-playground/README.md b/apps/nitro-v3-playground/README.md similarity index 100% rename from apps/nitrov3-playground/README.md rename to apps/nitro-v3-playground/README.md diff --git a/apps/nitrov3-playground/bun.lock b/apps/nitro-v3-playground/bun.lock similarity index 100% rename from apps/nitrov3-playground/bun.lock rename to apps/nitro-v3-playground/bun.lock diff --git a/apps/nitrov3-playground/index.html b/apps/nitro-v3-playground/index.html similarity index 100% rename from apps/nitrov3-playground/index.html rename to apps/nitro-v3-playground/index.html diff --git a/apps/nitrov3-playground/nitro.config.ts b/apps/nitro-v3-playground/nitro.config.ts similarity index 70% rename from apps/nitrov3-playground/nitro.config.ts rename to apps/nitro-v3-playground/nitro.config.ts index 0cc39f7..7e29717 100644 --- a/apps/nitrov3-playground/nitro.config.ts +++ b/apps/nitro-v3-playground/nitro.config.ts @@ -3,5 +3,5 @@ import { defineConfig } from 'nitro' export default defineConfig({ serverDir: './', // TODO: make playground work with evlog/nitro/v3 - plugins: ['../../packages/evlog/src/nitrov3/plugin.ts'] + plugins: ['../../packages/evlog/src/nitro-v3/plugin.ts'] }) diff --git a/apps/nitrov3-playground/package.json b/apps/nitro-v3-playground/package.json similarity index 87% rename from apps/nitrov3-playground/package.json rename to apps/nitro-v3-playground/package.json index 44993e4..374688f 100644 --- a/apps/nitrov3-playground/package.json +++ b/apps/nitro-v3-playground/package.json @@ -1,5 +1,5 @@ { - "name": "nitrov3-playground", + "name": "evlog-nitro-v3-playground", "type": "module", "scripts": { "build": "nitro build", diff --git a/apps/nitrov3-playground/public/styles.css b/apps/nitro-v3-playground/public/styles.css similarity index 100% rename from apps/nitrov3-playground/public/styles.css rename to apps/nitro-v3-playground/public/styles.css diff --git a/apps/nitrov3-playground/routes/api/index.ts b/apps/nitro-v3-playground/routes/api/index.ts similarity index 100% rename from apps/nitrov3-playground/routes/api/index.ts rename to apps/nitro-v3-playground/routes/api/index.ts diff --git a/apps/nitrov3-playground/routes/api/test/create.post.ts b/apps/nitro-v3-playground/routes/api/test/create.post.ts similarity index 100% rename from apps/nitrov3-playground/routes/api/test/create.post.ts rename to apps/nitro-v3-playground/routes/api/test/create.post.ts diff --git a/apps/nitrov3-playground/routes/api/test/delete.delete.ts b/apps/nitro-v3-playground/routes/api/test/delete.delete.ts similarity index 100% rename from apps/nitrov3-playground/routes/api/test/delete.delete.ts rename to apps/nitro-v3-playground/routes/api/test/delete.delete.ts diff --git a/apps/nitrov3-playground/routes/api/test/success.get.ts b/apps/nitro-v3-playground/routes/api/test/success.get.ts similarity index 100% rename from apps/nitrov3-playground/routes/api/test/success.get.ts rename to apps/nitro-v3-playground/routes/api/test/success.get.ts diff --git a/apps/nitrov3-playground/routes/api/test/update.put.ts b/apps/nitro-v3-playground/routes/api/test/update.put.ts similarity index 100% rename from apps/nitrov3-playground/routes/api/test/update.put.ts rename to apps/nitro-v3-playground/routes/api/test/update.put.ts diff --git a/apps/nitrov3-playground/routes/api/test/wide-event.get.ts b/apps/nitro-v3-playground/routes/api/test/wide-event.get.ts similarity index 100% rename from apps/nitrov3-playground/routes/api/test/wide-event.get.ts rename to apps/nitro-v3-playground/routes/api/test/wide-event.get.ts diff --git a/apps/nitrov3-playground/tsconfig.json b/apps/nitro-v3-playground/tsconfig.json similarity index 100% rename from apps/nitrov3-playground/tsconfig.json rename to apps/nitro-v3-playground/tsconfig.json diff --git a/bun.lock b/bun.lock index fb6b4e0..115a1ca 100644 --- a/bun.lock +++ b/bun.lock @@ -1,6 +1,5 @@ { "lockfileVersion": 1, - "configVersion": 0, "workspaces": { "": { "name": "evlog-monorepo", @@ -39,8 +38,8 @@ "rolldown": "latest", }, }, - "apps/nitrov3-playground": { - "name": "nitrov3-playground", + "apps/nitro-v3-playground": { + "name": "evlog-nitro-v3-playground", "dependencies": { "evlog": "workspace:*", }, @@ -63,6 +62,7 @@ "version": "1.0.1", "dependencies": { "@nuxt/kit": "^4.3.0", + "ufo": "^1.6.3", }, "devDependencies": { "@nuxt/devtools": "^3.1.1", @@ -74,7 +74,6 @@ "nitropack": "^2.13.1", "nuxt": "^4.3.0", "typescript": "^5.9.3", - "ufo": "^1.6.3", "unbuild": "^3.6.1", }, "peerDependencies": { @@ -1518,6 +1517,8 @@ "evlog-nitro-playground": ["evlog-nitro-playground@workspace:apps/nitro-playground"], + "evlog-nitro-v3-playground": ["evlog-nitro-v3-playground@workspace:apps/nitro-v3-playground"], + "evlog-playground": ["evlog-playground@workspace:apps/playground"], "execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="], @@ -2090,8 +2091,6 @@ "nitropack": ["nitropack@2.13.1", "", { "dependencies": { "@cloudflare/kv-asset-handler": "^0.4.2", "@rollup/plugin-alias": "^6.0.0", "@rollup/plugin-commonjs": "^29.0.0", "@rollup/plugin-inject": "^5.0.5", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.3", "@rollup/plugin-replace": "^6.0.3", "@rollup/plugin-terser": "^0.4.4", "@vercel/nft": "^1.2.0", "archiver": "^7.0.1", "c12": "^3.3.3", "chokidar": "^5.0.0", "citty": "^0.1.6", "compatx": "^0.2.0", "confbox": "^0.2.2", "consola": "^3.4.2", "cookie-es": "^2.0.0", "croner": "^9.1.0", "crossws": "^0.3.5", "db0": "^0.3.4", "defu": "^6.1.4", "destr": "^2.0.5", "dot-prop": "^10.1.0", "esbuild": "^0.27.2", "escape-string-regexp": "^5.0.0", "etag": "^1.8.1", "exsolve": "^1.0.8", "globby": "^16.1.0", "gzip-size": "^7.0.0", "h3": "^1.15.5", "hookable": "^5.5.3", "httpxy": "^0.1.7", "ioredis": "^5.9.1", "jiti": "^2.6.1", "klona": "^2.0.6", "knitwork": "^1.3.0", "listhen": "^1.9.0", "magic-string": "^0.30.21", "magicast": "^0.5.1", "mime": "^4.1.0", "mlly": "^1.8.0", "node-fetch-native": "^1.6.7", "node-mock-http": "^1.0.4", "ofetch": "^1.5.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "pretty-bytes": "^7.1.0", "radix3": "^1.1.2", "rollup": "^4.55.1", "rollup-plugin-visualizer": "^6.0.5", "scule": "^1.3.0", "semver": "^7.7.3", "serve-placeholder": "^2.0.2", "serve-static": "^2.2.1", "source-map": "^0.7.6", "std-env": "^3.10.0", "ufo": "^1.6.3", "ultrahtml": "^1.6.0", "uncrypto": "^0.1.3", "unctx": "^2.5.0", "unenv": "^2.0.0-rc.24", "unimport": "^5.6.0", "unplugin-utils": "^0.3.1", "unstorage": "^1.17.4", "untyped": "^2.0.0", "unwasm": "^0.5.3", "youch": "^4.1.0-beta.13", "youch-core": "^0.3.3" }, "peerDependencies": { "xml2js": "^0.6.2" }, "optionalPeers": ["xml2js"], "bin": { "nitro": "dist/cli/index.mjs", "nitropack": "dist/cli/index.mjs" } }, "sha512-2dDj89C4wC2uzG7guF3CnyG+zwkZosPEp7FFBGHB3AJo11AywOolWhyQJFHDzve8COvGxJaqscye9wW2IrUsNw=="], - "nitrov3-playground": ["nitrov3-playground@workspace:apps/nitrov3-playground"], - "node-abi": ["node-abi@3.87.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ=="], "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], diff --git a/package.json b/package.json index 4484843..2eb4553 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "scripts": { "dev": "turbo run dev --filter=evlog-playground", "dev:nitro": "turbo run dev --filter=evlog-nitro-playground", + "dev:nitro:v3": "turbo run dev --filter=evlog-nitro-v3-playground", "dev:prepare": "turbo run dev:prepare", "dev:docs": "turbo run dev --filter=evlog-docs", "docs": "turbo run dev --filter=evlog-docs", diff --git a/packages/evlog/build.config.ts b/packages/evlog/build.config.ts index 9cc1c8e..bf253d3 100644 --- a/packages/evlog/build.config.ts +++ b/packages/evlog/build.config.ts @@ -5,7 +5,7 @@ export default defineBuildConfig({ { input: 'src/index', name: 'index' }, { input: 'src/nuxt/module', name: 'nuxt/module' }, { input: 'src/nitro/plugin', name: 'nitro/plugin' }, - { input: 'src/nitrov3/plugin', name: 'nitro/v3/plugin' }, + { input: 'src/nitro-v3/plugin', name: 'nitro/v3/plugin' }, { input: 'src/runtime/client/log', name: 'runtime/client/log' }, { input: 'src/runtime/client/plugin', name: 'runtime/client/plugin' }, { input: 'src/runtime/server/useLogger', name: 'runtime/server/useLogger' }, diff --git a/packages/evlog/package.json b/packages/evlog/package.json index 6bc94bc..e2d78e8 100644 --- a/packages/evlog/package.json +++ b/packages/evlog/package.json @@ -74,7 +74,8 @@ "typecheck": "echo 'Typecheck handled by build'" }, "dependencies": { - "@nuxt/kit": "^4.3.0" + "@nuxt/kit": "^4.3.0", + "ufo": "^1.6.3" }, "devDependencies": { "@nuxt/devtools": "^3.1.1", @@ -86,8 +87,7 @@ "nuxt": "^4.3.0", "typescript": "^5.9.3", "unbuild": "^3.6.1", - "nitro": "^3.0.1-alpha.2", - "ufo": "^1.6.3" + "nitro": "^3.0.1-alpha.2" }, "peerDependencies": { "h3": "^1.15.5", diff --git a/packages/evlog/src/nitrov3/plugin.ts b/packages/evlog/src/nitro-v3/plugin.ts similarity index 100% rename from packages/evlog/src/nitrov3/plugin.ts rename to packages/evlog/src/nitro-v3/plugin.ts From 90e2c4551d6beb2780c5287e2b50850bffad2830 Mon Sep 17 00:00:00 2001 From: schplitt Date: Sat, 31 Jan 2026 13:56:55 +0100 Subject: [PATCH 12/15] feat(nitro-v3): align EvlogError with Nitro v3 HTTPError contract --- .../1.getting-started/1.introduction.md | 2 + .../1.getting-started/2.installation.md | 2 +- .../1.getting-started/3.quick-start.md | 6 +- .../2.core-concepts/2.structured-errors.md | 6 +- packages/evlog/src/nitro-v3/error.ts | 116 ++++++++++++++++++ packages/evlog/src/nitro-v3/plugin.ts | 2 + 6 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 packages/evlog/src/nitro-v3/error.ts diff --git a/apps/docs/content/1.getting-started/1.introduction.md b/apps/docs/content/1.getting-started/1.introduction.md index 30c268d..b075a61 100644 --- a/apps/docs/content/1.getting-started/1.introduction.md +++ b/apps/docs/content/1.getting-started/1.introduction.md @@ -97,6 +97,8 @@ Structured errors provide actionable context: ::code-group ```typescript [Code] // server/api/checkout.post.ts +import { createError } from 'evlog' // Use 'evlog/nitro/v3' for Nitro v3 + throw createError({ message: 'Payment failed', status: 402, diff --git a/apps/docs/content/1.getting-started/2.installation.md b/apps/docs/content/1.getting-started/2.installation.md index 1186432..757a451 100644 --- a/apps/docs/content/1.getting-started/2.installation.md +++ b/apps/docs/content/1.getting-started/2.installation.md @@ -62,7 +62,7 @@ export default defineNitroConfig({ ``` ::callout{icon="i-lucide-info" color="info"} -For early Nitro v3 support, use `evlog/nitro/v3` instead of `evlog/nitro`. +For early Nitro v3 support, use `evlog/nitro/v3` instead of `evlog/nitro`. When using Nitro v3, import `createError` from `evlog/nitro/v3` instead of `evlog`. :: ## Standalone TypeScript diff --git a/apps/docs/content/1.getting-started/3.quick-start.md b/apps/docs/content/1.getting-started/3.quick-start.md index 4885af0..9b7e5bb 100644 --- a/apps/docs/content/1.getting-started/3.quick-start.md +++ b/apps/docs/content/1.getting-started/3.quick-start.md @@ -37,10 +37,14 @@ The logger automatically emits when the request ends. No manual `emit()` call ne Use `createError()` to throw errors with actionable context: +::callout{icon="i-lucide-info" color="info"} +For Nitro v3, import from `evlog/nitro/v3` instead of `evlog`. +:: + ::code-group ```typescript [Code] // server/api/checkout.post.ts -import { createError } from 'evlog' +import { createError } from 'evlog' // Use 'evlog/nitro/v3' for Nitro v3 throw createError({ message: 'Payment failed', diff --git a/apps/docs/content/2.core-concepts/2.structured-errors.md b/apps/docs/content/2.core-concepts/2.structured-errors.md index 33812a4..4cd0e17 100644 --- a/apps/docs/content/2.core-concepts/2.structured-errors.md +++ b/apps/docs/content/2.core-concepts/2.structured-errors.md @@ -5,6 +5,10 @@ description: Create errors that explain why they occurred and how to fix them. evlog provides a `createError()` function that creates errors with rich, actionable context. +::callout{icon="i-lucide-info" color="info"} +For Nitro v3, import `createError` from `evlog/nitro/v3` instead of `evlog`. +:: + ## Why Structured Errors? Traditional errors are often unhelpful: @@ -60,7 +64,7 @@ throw createError({ ::code-group ```typescript [Code] // server/api/users/[id].get.ts -import { createError } from 'evlog' +import { createError } from 'evlog' // Use 'evlog/nitro/v3' for Nitro v3 throw createError({ message: 'User not found', diff --git a/packages/evlog/src/nitro-v3/error.ts b/packages/evlog/src/nitro-v3/error.ts new file mode 100644 index 0000000..65f1dbe --- /dev/null +++ b/packages/evlog/src/nitro-v3/error.ts @@ -0,0 +1,116 @@ +import { HTTPError } from 'nitro/h3' +import type { ErrorOptions } from '../types' +import { colors, isServer } from '../utils' + +/** + * Structured error with context for better debugging + * + * @example + * ```ts + * throw new EvlogError({ + * message: 'Failed to sync repository', + * status: 503, + * why: 'GitHub API rate limit exceeded', + * fix: 'Wait 1 hour or use a different token', + * link: 'https://docs.github.com/en/rest/rate-limit', + * cause: originalError, + * }) + * ``` + */ +export class EvlogError extends HTTPError { + + readonly status: number + readonly why?: string + readonly fix?: string + readonly link?: string + + override get name(): string { + return 'EvlogError' + } + + constructor(options: ErrorOptions | string) { + const opts = typeof options === 'string' ? { message: options } : options + + const body = opts.why || opts.fix || opts.link + ? { why: opts.why, fix: opts.fix, link: opts.link } + : undefined + + super(opts.message, { cause: opts.cause, body }) + + this.status = opts.status ?? 500 + this.why = opts.why + this.fix = opts.fix + this.link = opts.link + + // Maintain proper stack trace in V8 + if (Error.captureStackTrace) { + Error.captureStackTrace(this, EvlogError) + } + } + + get statusCode(): number { + return this.status + } + + override toString(): string { + // Use colors only on server (terminal) + const useColors = isServer() + + const red = useColors ? colors.red : '' + const yellow = useColors ? colors.yellow : '' + const cyan = useColors ? colors.cyan : '' + const dim = useColors ? colors.dim : '' + const reset = useColors ? colors.reset : '' + const bold = useColors ? colors.bold : '' + + const lines: string[] = [] + + lines.push(`${red}${bold}Error:${reset} ${this.message}`) + + if (this.why) { + lines.push(`${yellow}Why:${reset} ${this.why}`) + } + + if (this.fix) { + lines.push(`${cyan}Fix:${reset} ${this.fix}`) + } + + if (this.link) { + lines.push(`${dim}More info:${reset} ${this.link}`) + } + + if (this.cause) { + lines.push(`${dim}Caused by:${reset} ${(this.cause as Error).message}`) + } + + return lines.join('\n') + } + +} + +/** + * Create a structured error with context for debugging and user-facing messages. + * + * @param options - Error message string or full options object + * @returns EvlogError instance compatible with Nitro's error handling + * + * @example + * ```ts + * // Simple error + * throw createError('Something went wrong') + * + * // Structured error with context + * throw createError({ + * message: 'Payment failed', + * status: 402, + * why: 'Card declined by issuer', + * fix: 'Try a different payment method', + * link: 'https://docs.example.com/payments', + * }) + * ``` + */ +export function createError(options: ErrorOptions | string): EvlogError { + return new EvlogError(options) +} + +export const createEvlogError = createError diff --git a/packages/evlog/src/nitro-v3/plugin.ts b/packages/evlog/src/nitro-v3/plugin.ts index 4e896a6..0b5d63f 100644 --- a/packages/evlog/src/nitro-v3/plugin.ts +++ b/packages/evlog/src/nitro-v3/plugin.ts @@ -7,6 +7,8 @@ import { createRequestLogger, initLogger } from '../logger' import { shouldLog } from '../nitro' import type { RequestLogger } from '../types' +export * from './error' + interface EvlogConfig { env?: Record pretty?: boolean From 23c32cde26df882ae3b5486806fa288bcd3b71e3 Mon Sep 17 00:00:00 2001 From: schplitt Date: Sat, 31 Jan 2026 14:29:23 +0100 Subject: [PATCH 13/15] nitro/v3 feature parity --- packages/evlog/src/nitro-v3/plugin.ts | 87 ++++++++++++++++++++++++--- packages/evlog/src/nitro.ts | 13 +--- 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/packages/evlog/src/nitro-v3/plugin.ts b/packages/evlog/src/nitro-v3/plugin.ts index 0b5d63f..93327bd 100644 --- a/packages/evlog/src/nitro-v3/plugin.ts +++ b/packages/evlog/src/nitro-v3/plugin.ts @@ -5,7 +5,7 @@ import type { HTTPEvent } from 'nitro/h3' import { parseURL } from 'ufo' import { createRequestLogger, initLogger } from '../logger' import { shouldLog } from '../nitro' -import type { RequestLogger } from '../types' +import type { RequestLogger, SamplingConfig, TailSamplingContext, WideEvent } from '../types' export * from './error' @@ -13,6 +13,7 @@ interface EvlogConfig { env?: Record pretty?: boolean include?: string[] + sampling?: SamplingConfig } // currently nitro/v3 doesnt export hook types correctly @@ -22,6 +23,8 @@ interface NitroRuntimeHooks { error: CaptureError; request: (event: HTTPEvent) => void | Promise; response: (res: Response, event: HTTPEvent) => void | Promise; + 'evlog:emit:keep': (ctx: TailSamplingContext) => void | Promise; + 'evlog:drain': (ctx: { event: WideEvent; request?: { method?: string; path: string; requestId?: string } }) => void | Promise; } // Hookable core type not available so we build it our self type Hooks = { @@ -38,6 +41,7 @@ export default definePlugin((nitroApp) => { initLogger({ env: evlogConfig?.env, pretty: evlogConfig?.pretty, + sampling: evlogConfig?.sampling, }) const hooks = nitroApp.hooks as Hooks @@ -67,22 +71,89 @@ export default definePlugin((nitroApp) => { e.req.context = {} } e.req.context.log = log + // Store start time for duration calculation in tail sampling + e.req.context._evlogStartTime = Date.now() }) - hooks.hook('response', (res, event) => { + hooks.hook('response', async (res, event) => { const e = event + // Skip if already emitted by error hook + if (e.req.context?._evlogEmitted) return + const log = e.req.context?.log as RequestLogger | undefined - if (log) { - log.set({ status: res.status }) - log.emit() + if (log && e.req.context) { + const { status } = res + log.set({ status }) + + const { pathname } = parseURL(e.req.url) + const startTime = e.req.context._evlogStartTime as number | undefined + const durationMs = startTime ? Date.now() - startTime : undefined + + const tailCtx: TailSamplingContext = { + status, + duration: durationMs, + path: pathname, + method: e.req.method, + context: log.getContext(), + shouldKeep: false, + } + + await nitroApp.hooks.callHook('evlog:emit:keep', tailCtx) + + const emittedEvent = log.emit({ _forceKeep: tailCtx.shouldKeep }) + + // Drain hook integration + if (emittedEvent) { + (nitroApp.hooks as any).callHook('evlog:drain', { + event: emittedEvent, + request: { method: e.req.method, path: pathname, requestId: e.req.context.requestId as string | undefined }, + }).catch((err: Error) => { + console.error('[evlog] drain failed:', err) + }) + } } }) - hooks.hook('error', (error, { event }) => { + hooks.hook('error', async (error, { event }) => { const e = event - const log = e?.req.context?.log as RequestLogger | undefined - if (log) { + if (!e) return + + const log = e.req.context?.log as RequestLogger | undefined + if (log && e.req.context) { log.error(error as Error) + + // Get the actual error status code + const errorStatus = (error as { statusCode?: number }).statusCode ?? 500 + log.set({ status: errorStatus }) + + const { pathname } = parseURL(e.req.url) + const startTime = e.req.context._evlogStartTime as number | undefined + const durationMs = startTime ? Date.now() - startTime : undefined + + const tailCtx: TailSamplingContext = { + status: errorStatus, + duration: durationMs, + path: pathname, + method: e.req.method, + context: log.getContext(), + shouldKeep: false, + } + + await nitroApp.hooks.callHook('evlog:emit:keep', tailCtx) + + e.req.context._evlogEmitted = true + + const emittedEvent = log.emit({ _forceKeep: tailCtx.shouldKeep }) + + // Drain hook integration + if (emittedEvent) { + await nitroApp.hooks.callHook('evlog:drain', { + event: emittedEvent, + request: { method: e.req.method, path: pathname, requestId: e.req.context.requestId as string | undefined }, + }).catch((err: Error) => { + console.error('[evlog] drain failed:', err) + }) + } } }) }) diff --git a/packages/evlog/src/nitro.ts b/packages/evlog/src/nitro.ts index 9322d74..cb985c9 100644 --- a/packages/evlog/src/nitro.ts +++ b/packages/evlog/src/nitro.ts @@ -1,15 +1,4 @@ -function matchesPattern(path: string, pattern: string): boolean { - // Convert glob pattern to regex - const regexPattern = pattern - .replace(/[.+^${}()|[\]\\]/g, '\\$&') // Escape special regex chars except * and ? - .replace(/\*\*/g, '{{GLOBSTAR}}') // Temp placeholder for ** - .replace(/\*/g, '[^/]*') // * matches anything except / - .replace(/{{GLOBSTAR}}/g, '.*') // ** matches anything including / - .replace(/\?/g, '[^/]') // ? matches single char except / - - const regex = new RegExp(`^${regexPattern}$`) - return regex.test(path) -} +import { matchesPattern } from './utils' export function shouldLog(path: string, include?: string[]): boolean { // If no include patterns, log everything From 2bd17f62c794ee3cf433a33393f248597421df5d Mon Sep 17 00:00:00 2001 From: schplitt Date: Sat, 31 Jan 2026 17:43:47 +0100 Subject: [PATCH 14/15] fix: error handling/logging --- .../routes/api/test/update.put.ts | 3 ++- packages/evlog/src/nitro-v3/error.ts | 10 ++++---- packages/evlog/src/nitro-v3/plugin.ts | 24 +++++++++++-------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/apps/nitro-v3-playground/routes/api/test/update.put.ts b/apps/nitro-v3-playground/routes/api/test/update.put.ts index c40f5f3..52bd014 100644 --- a/apps/nitro-v3-playground/routes/api/test/update.put.ts +++ b/apps/nitro-v3-playground/routes/api/test/update.put.ts @@ -1,5 +1,6 @@ import { defineHandler, readBody } from 'nitro/h3' -import { useLogger, createError } from 'evlog' +import { useLogger } from 'evlog' +import { createError } from 'evlog/nitro/v3' export default defineHandler(async (event) => { const log = useLogger(event) diff --git a/packages/evlog/src/nitro-v3/error.ts b/packages/evlog/src/nitro-v3/error.ts index 65f1dbe..1cfc6dc 100644 --- a/packages/evlog/src/nitro-v3/error.ts +++ b/packages/evlog/src/nitro-v3/error.ts @@ -24,10 +24,6 @@ export class EvlogError extends HTTPError { readonly fix?: string readonly link?: string - override get name(): string { - return 'EvlogError' - } - constructor(options: ErrorOptions | string) { const opts = typeof options === 'string' ? { message: options } : options @@ -35,9 +31,11 @@ export class EvlogError extends HTTPError { ? { why: opts.why, fix: opts.fix, link: opts.link } : undefined - super(opts.message, { cause: opts.cause, body }) + const statusCode = opts.status ?? 500 + + super(opts.message, { cause: opts.cause, body, statusCode }) - this.status = opts.status ?? 500 + this.status = statusCode this.why = opts.why this.fix = opts.fix this.link = opts.link diff --git a/packages/evlog/src/nitro-v3/plugin.ts b/packages/evlog/src/nitro-v3/plugin.ts index 93327bd..53f14ed 100644 --- a/packages/evlog/src/nitro-v3/plugin.ts +++ b/packages/evlog/src/nitro-v3/plugin.ts @@ -104,12 +104,14 @@ export default definePlugin((nitroApp) => { // Drain hook integration if (emittedEvent) { - (nitroApp.hooks as any).callHook('evlog:drain', { - event: emittedEvent, - request: { method: e.req.method, path: pathname, requestId: e.req.context.requestId as string | undefined }, - }).catch((err: Error) => { + try { + await nitroApp.hooks.callHook('evlog:drain', { + event: emittedEvent, + request: { method: e.req.method, path: pathname, requestId: e.req.context.requestId as string | undefined }, + }) + } catch (err) { console.error('[evlog] drain failed:', err) - }) + } } } }) @@ -147,12 +149,14 @@ export default definePlugin((nitroApp) => { // Drain hook integration if (emittedEvent) { - await nitroApp.hooks.callHook('evlog:drain', { - event: emittedEvent, - request: { method: e.req.method, path: pathname, requestId: e.req.context.requestId as string | undefined }, - }).catch((err: Error) => { + try { + await nitroApp.hooks.callHook('evlog:drain', { + event: emittedEvent, + request: { method: e.req.method, path: pathname, requestId: e.req.context.requestId as string | undefined }, + }) + } catch (err) { console.error('[evlog] drain failed:', err) - }) + } } } }) From 4d7b5e41b54615d5e8298858ca96052459aa5f63 Mon Sep 17 00:00:00 2001 From: schplitt Date: Sat, 31 Jan 2026 17:50:36 +0100 Subject: [PATCH 15/15] nitrov3 respect exclude config --- packages/evlog/src/nitro-v3/plugin.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/evlog/src/nitro-v3/plugin.ts b/packages/evlog/src/nitro-v3/plugin.ts index 53f14ed..7272044 100644 --- a/packages/evlog/src/nitro-v3/plugin.ts +++ b/packages/evlog/src/nitro-v3/plugin.ts @@ -13,6 +13,7 @@ interface EvlogConfig { env?: Record pretty?: boolean include?: string[] + exclude?: string[] sampling?: SamplingConfig } @@ -57,8 +58,8 @@ export default definePlugin((nitroApp) => { pathname } = parseURL(e.req.url) - // Skip logging for routes not matching include patterns - if (!shouldLog(pathname, evlogConfig?.include)) { + // Skip logging for routes not matching include/exclude patterns + if (!shouldLog(pathname, evlogConfig?.include, evlogConfig?.exclude)) { return }