@vestig/next 0.11.4 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/client/error-boundary.d.ts +22 -0
  2. package/dist/client/error-boundary.d.ts.map +1 -1
  3. package/dist/client/error-boundary.js +89 -2
  4. package/dist/client/error-boundary.js.map +1 -1
  5. package/dist/client/provider.d.ts +2 -0
  6. package/dist/client/provider.d.ts.map +1 -1
  7. package/dist/client/provider.js +16 -2
  8. package/dist/client/provider.js.map +1 -1
  9. package/dist/db/index.d.ts +1 -1
  10. package/dist/db/index.d.ts.map +1 -1
  11. package/dist/db/index.js +1 -1
  12. package/dist/db/index.js.map +1 -1
  13. package/dist/db/query-logger.d.ts +6 -0
  14. package/dist/db/query-logger.d.ts.map +1 -1
  15. package/dist/db/query-logger.js +77 -7
  16. package/dist/db/query-logger.js.map +1 -1
  17. package/dist/wide-events/context.d.ts +73 -0
  18. package/dist/wide-events/context.d.ts.map +1 -0
  19. package/dist/wide-events/context.js +86 -0
  20. package/dist/wide-events/context.js.map +1 -0
  21. package/dist/wide-events/helpers.d.ts +138 -0
  22. package/dist/wide-events/helpers.d.ts.map +1 -0
  23. package/dist/wide-events/helpers.js +182 -0
  24. package/dist/wide-events/helpers.js.map +1 -0
  25. package/dist/wide-events/index.d.ts +63 -0
  26. package/dist/wide-events/index.d.ts.map +1 -0
  27. package/dist/wide-events/index.js +67 -0
  28. package/dist/wide-events/index.js.map +1 -0
  29. package/dist/wide-events/middleware.d.ts +65 -0
  30. package/dist/wide-events/middleware.d.ts.map +1 -0
  31. package/dist/wide-events/middleware.js +160 -0
  32. package/dist/wide-events/middleware.js.map +1 -0
  33. package/dist/wide-events/server-action.d.ts +91 -0
  34. package/dist/wide-events/server-action.d.ts.map +1 -0
  35. package/dist/wide-events/server-action.js +158 -0
  36. package/dist/wide-events/server-action.js.map +1 -0
  37. package/package.json +9 -2
@@ -0,0 +1,160 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { createCorrelationContext, createLogger, createTraceparent, createWideEvent, parseTraceparent, } from 'vestig';
3
+ import { CORRELATION_HEADERS } from '../utils/headers';
4
+ import { runWithWideEvent } from './context';
5
+ const DEFAULT_OPTIONS = {
6
+ level: 'info',
7
+ enabled: true,
8
+ sanitize: 'default',
9
+ skipPaths: ['/_next', '/favicon.ico', '/api/vestig'],
10
+ requestIdHeader: CORRELATION_HEADERS.REQUEST_ID,
11
+ structured: true,
12
+ };
13
+ // Cached logger per middleware instance
14
+ const loggerCache = new WeakMap();
15
+ function getOrCreateLogger(options) {
16
+ const cached = loggerCache.get(options);
17
+ if (cached)
18
+ return cached;
19
+ const logger = createLogger({
20
+ level: options.level,
21
+ enabled: options.enabled,
22
+ sanitize: options.sanitize,
23
+ structured: options.structured,
24
+ tailSampling: options.tailSampling,
25
+ });
26
+ loggerCache.set(options, logger);
27
+ return logger;
28
+ }
29
+ /**
30
+ * Create wide event middleware for Next.js
31
+ *
32
+ * This middleware automatically creates a wide event for each request
33
+ * and populates it with HTTP context. The wide event is available
34
+ * throughout the request lifecycle via `getWideEvent()`.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * // middleware.ts
39
+ * import { createWideEventMiddleware } from '@vestig/next/wide-events'
40
+ *
41
+ * export const middleware = createWideEventMiddleware({
42
+ * skipPaths: ['/health', '/metrics'],
43
+ * tailSampling: {
44
+ * enabled: true,
45
+ * alwaysKeepStatuses: ['error'],
46
+ * slowThresholdMs: 2000,
47
+ * successSampleRate: 0.1,
48
+ * },
49
+ * })
50
+ *
51
+ * export const config = {
52
+ * matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
53
+ * }
54
+ * ```
55
+ */
56
+ export function createWideEventMiddleware(options = {}) {
57
+ const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
58
+ return async function wideEventMiddleware(request) {
59
+ // Skip configured paths
60
+ const pathname = request.nextUrl.pathname;
61
+ const skipPaths = mergedOptions.skipPaths ?? DEFAULT_OPTIONS.skipPaths ?? [];
62
+ if (skipPaths.some((p) => pathname.startsWith(p))) {
63
+ return NextResponse.next();
64
+ }
65
+ const logger = getOrCreateLogger(mergedOptions);
66
+ const startTime = performance.now();
67
+ // Extract or generate correlation context
68
+ const requestIdHeader = mergedOptions.requestIdHeader ??
69
+ DEFAULT_OPTIONS.requestIdHeader ??
70
+ CORRELATION_HEADERS.REQUEST_ID;
71
+ const existingRequestId = request.headers.get(requestIdHeader) ?? undefined;
72
+ const traceparent = request.headers.get(CORRELATION_HEADERS.TRACEPARENT);
73
+ const parsed = traceparent ? parseTraceparent(traceparent) : null;
74
+ const ctx = createCorrelationContext({
75
+ requestId: existingRequestId,
76
+ traceId: parsed?.traceId,
77
+ spanId: parsed?.spanId,
78
+ });
79
+ // Create wide event for this request
80
+ const event = createWideEvent({
81
+ type: 'http.request',
82
+ context: {
83
+ requestId: ctx.requestId,
84
+ traceId: ctx.traceId,
85
+ spanId: ctx.spanId,
86
+ },
87
+ });
88
+ // Populate initial HTTP context
89
+ event.merge('http', {
90
+ method: request.method,
91
+ path: pathname,
92
+ search: request.nextUrl.search || undefined,
93
+ host: request.headers.get('host'),
94
+ });
95
+ // Add user context from headers if available
96
+ const userAgent = request.headers.get('user-agent');
97
+ const ip = request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ??
98
+ request.headers.get('x-real-ip');
99
+ if (userAgent || ip) {
100
+ event.merge('client', {
101
+ userAgent: userAgent?.slice(0, 200),
102
+ ip,
103
+ });
104
+ }
105
+ // Create request context
106
+ const eventContext = {
107
+ event,
108
+ startTime,
109
+ };
110
+ // Run middleware with wide event context
111
+ // These are guaranteed to exist from createCorrelationContext
112
+ const requestId = ctx.requestId ?? '';
113
+ const traceId = ctx.traceId ?? '';
114
+ const spanId = ctx.spanId ?? '';
115
+ return runWithWideEvent(eventContext, () => {
116
+ // Create new headers with correlation IDs
117
+ const requestHeaders = new Headers(request.headers);
118
+ requestHeaders.set(CORRELATION_HEADERS.REQUEST_ID, requestId);
119
+ requestHeaders.set(CORRELATION_HEADERS.TRACE_ID, traceId);
120
+ requestHeaders.set(CORRELATION_HEADERS.SPAN_ID, spanId);
121
+ requestHeaders.set(CORRELATION_HEADERS.TRACEPARENT, createTraceparent(traceId, spanId));
122
+ // Create response with updated headers
123
+ const response = NextResponse.next({
124
+ request: {
125
+ headers: requestHeaders,
126
+ },
127
+ });
128
+ // Add correlation headers to response
129
+ response.headers.set(CORRELATION_HEADERS.REQUEST_ID, requestId);
130
+ response.headers.set(CORRELATION_HEADERS.TRACE_ID, traceId);
131
+ // Complete the wide event
132
+ const duration = performance.now() - startTime;
133
+ // Add final timing
134
+ event.set('performance', 'duration_ms', duration);
135
+ // End and emit the wide event
136
+ const completedEvent = event.end({
137
+ status: 'success',
138
+ level: 'info',
139
+ });
140
+ // Emit through the logger (applies tail sampling if configured)
141
+ logger.emitWideEvent(completedEvent);
142
+ return response;
143
+ });
144
+ };
145
+ }
146
+ /**
147
+ * Pre-configured wide event middleware for direct export
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * // middleware.ts
152
+ * export { wideEventMiddleware as middleware } from '@vestig/next/wide-events'
153
+ *
154
+ * export const config = {
155
+ * matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
156
+ * }
157
+ * ```
158
+ */
159
+ export const wideEventMiddleware = createWideEventMiddleware();
160
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/wide-events/middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ import { type LogLevel, type SanitizePreset, type TailSamplingConfig, createWideEvent } from 'vestig';
2
+ /**
3
+ * Options for wide event server actions
4
+ */
5
+ export interface WideEventActionOptions {
6
+ /** Action name (used as event type) */
7
+ name?: string;
8
+ /** Log level */
9
+ level?: LogLevel;
10
+ /** Enable/disable wide event emission */
11
+ enabled?: boolean;
12
+ /** PII sanitization preset */
13
+ sanitize?: SanitizePreset;
14
+ /** Use structured JSON output */
15
+ structured?: boolean;
16
+ /** Tail sampling configuration */
17
+ tailSampling?: TailSamplingConfig;
18
+ }
19
+ /**
20
+ * Context provided to wide event actions
21
+ */
22
+ export interface WideEventActionContext {
23
+ /** The wide event builder for this action */
24
+ event: ReturnType<typeof createWideEvent>;
25
+ }
26
+ /**
27
+ * Server action handler type with wide event context
28
+ */
29
+ export type WideEventServerAction<TInput, TResult> = (input: TInput, ctx: WideEventActionContext) => Promise<TResult>;
30
+ /**
31
+ * Wrap a server action with wide event tracking.
32
+ *
33
+ * If called within an existing wide event context (e.g., from middleware),
34
+ * it will enrich that event. Otherwise, it creates a new wide event.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * // app/actions/user.ts
39
+ * 'use server'
40
+ *
41
+ * import { withWideEvent } from '@vestig/next/wide-events'
42
+ *
43
+ * export const createUser = withWideEvent(
44
+ * async (data: CreateUserInput, { event }) => {
45
+ * event.set('action', 'type', 'user.create')
46
+ * event.set('user', 'email', data.email)
47
+ *
48
+ * const user = await db.users.create({ data })
49
+ *
50
+ * event.set('user', 'id', user.id)
51
+ * return user
52
+ * },
53
+ * { name: 'action.user.create' }
54
+ * )
55
+ * ```
56
+ */
57
+ export declare function withWideEvent<TInput, TResult>(handler: WideEventServerAction<TInput, TResult>, options?: WideEventActionOptions): (input: TInput) => Promise<TResult>;
58
+ /**
59
+ * Create a factory for wide event server actions with shared options.
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * // app/actions/index.ts
64
+ * import { createWideEventAction } from '@vestig/next/wide-events'
65
+ *
66
+ * const action = createWideEventAction({
67
+ * tailSampling: {
68
+ * enabled: true,
69
+ * successSampleRate: 0.1,
70
+ * },
71
+ * })
72
+ *
73
+ * export const createUser = action(
74
+ * async (data, { event }) => {
75
+ * event.set('user', 'email', data.email)
76
+ * return await db.users.create({ data })
77
+ * },
78
+ * { name: 'action.user.create' }
79
+ * )
80
+ *
81
+ * export const updateUser = action(
82
+ * async ({ id, data }, { event }) => {
83
+ * event.set('user', 'id', id)
84
+ * return await db.users.update({ where: { id }, data })
85
+ * },
86
+ * { name: 'action.user.update' }
87
+ * )
88
+ * ```
89
+ */
90
+ export declare function createWideEventAction(defaultOptions?: WideEventActionOptions): <TInput, TResult>(handler: WideEventServerAction<TInput, TResult>, options?: WideEventActionOptions) => ((input: TInput) => Promise<TResult>);
91
+ //# sourceMappingURL=server-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-action.d.ts","sourceRoot":"","sources":["../../src/wide-events/server-action.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,QAAQ,EAEb,KAAK,cAAc,EACnB,KAAK,kBAAkB,EAEvB,eAAe,EACf,MAAM,QAAQ,CAAA;AAGf;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gBAAgB;IAChB,KAAK,CAAC,EAAE,QAAQ,CAAA;IAChB,yCAAyC;IACzC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,iCAAiC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,kCAAkC;IAClC,YAAY,CAAC,EAAE,kBAAkB,CAAA;CACjC;AAgCD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,6CAA6C;IAC7C,KAAK,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAA;CACzC;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,CAAC,MAAM,EAAE,OAAO,IAAI,CACpD,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,sBAAsB,KACvB,OAAO,CAAC,OAAO,CAAC,CAAA;AAErB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,EAC5C,OAAO,EAAE,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/C,OAAO,GAAE,sBAA2B,GAClC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAmFrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,qBAAqB,CAAC,cAAc,GAAE,sBAA2B,IACxE,MAAM,EAAE,OAAO,EACtB,SAAS,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/C,UAAS,sBAA2B,KAClC,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAExC"}
@@ -0,0 +1,158 @@
1
+ import { createLogger, createWideEvent, } from 'vestig';
2
+ import { getWideEvent, runWithWideEventAsync } from './context';
3
+ const DEFAULT_OPTIONS = {
4
+ level: 'info',
5
+ enabled: true,
6
+ sanitize: 'default',
7
+ structured: true,
8
+ };
9
+ // Cached logger
10
+ let cachedLogger = null;
11
+ function getOrCreateLogger(options) {
12
+ if (cachedLogger && options === DEFAULT_OPTIONS) {
13
+ return cachedLogger;
14
+ }
15
+ const logger = createLogger({
16
+ level: options.level,
17
+ enabled: options.enabled,
18
+ sanitize: options.sanitize,
19
+ structured: options.structured,
20
+ tailSampling: options.tailSampling,
21
+ });
22
+ if (options === DEFAULT_OPTIONS) {
23
+ cachedLogger = logger;
24
+ }
25
+ return logger;
26
+ }
27
+ /**
28
+ * Wrap a server action with wide event tracking.
29
+ *
30
+ * If called within an existing wide event context (e.g., from middleware),
31
+ * it will enrich that event. Otherwise, it creates a new wide event.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * // app/actions/user.ts
36
+ * 'use server'
37
+ *
38
+ * import { withWideEvent } from '@vestig/next/wide-events'
39
+ *
40
+ * export const createUser = withWideEvent(
41
+ * async (data: CreateUserInput, { event }) => {
42
+ * event.set('action', 'type', 'user.create')
43
+ * event.set('user', 'email', data.email)
44
+ *
45
+ * const user = await db.users.create({ data })
46
+ *
47
+ * event.set('user', 'id', user.id)
48
+ * return user
49
+ * },
50
+ * { name: 'action.user.create' }
51
+ * )
52
+ * ```
53
+ */
54
+ export function withWideEvent(handler, options = {}) {
55
+ const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
56
+ return async (input) => {
57
+ const startTime = performance.now();
58
+ const logger = getOrCreateLogger(mergedOptions);
59
+ // Check if we're already in a wide event context
60
+ const existingEvent = getWideEvent();
61
+ if (existingEvent) {
62
+ // Enrich existing event with action context
63
+ const actionName = mergedOptions.name ?? 'server-action';
64
+ existingEvent.set('action', 'name', actionName);
65
+ existingEvent.set('action', 'start_ms', performance.now() - startTime);
66
+ try {
67
+ const result = await handler(input, { event: existingEvent });
68
+ existingEvent.set('action', 'duration_ms', performance.now() - startTime);
69
+ existingEvent.set('action', 'status', 'success');
70
+ return result;
71
+ }
72
+ catch (error) {
73
+ existingEvent.set('action', 'duration_ms', performance.now() - startTime);
74
+ existingEvent.set('action', 'status', 'error');
75
+ existingEvent.merge('error', {
76
+ name: error instanceof Error ? error.name : 'Error',
77
+ message: error instanceof Error ? error.message : String(error),
78
+ });
79
+ throw error;
80
+ }
81
+ }
82
+ // Create new wide event for this action
83
+ const actionName = mergedOptions.name ?? 'server-action';
84
+ const event = createWideEvent({
85
+ type: actionName,
86
+ });
87
+ event.set('action', 'name', actionName);
88
+ const eventContext = {
89
+ event,
90
+ startTime,
91
+ };
92
+ return runWithWideEventAsync(eventContext, async () => {
93
+ try {
94
+ const result = await handler(input, { event });
95
+ // Complete and emit the wide event
96
+ const duration = performance.now() - startTime;
97
+ event.set('performance', 'duration_ms', duration);
98
+ const completedEvent = event.end({
99
+ status: 'success',
100
+ level: 'info',
101
+ });
102
+ logger.emitWideEvent(completedEvent);
103
+ return result;
104
+ }
105
+ catch (error) {
106
+ const duration = performance.now() - startTime;
107
+ event.set('performance', 'duration_ms', duration);
108
+ event.merge('error', {
109
+ name: error instanceof Error ? error.name : 'Error',
110
+ message: error instanceof Error ? error.message : String(error),
111
+ });
112
+ const completedEvent = event.end({
113
+ status: 'error',
114
+ error: error instanceof Error ? error : new Error(String(error)),
115
+ level: 'error',
116
+ });
117
+ logger.emitWideEvent(completedEvent);
118
+ throw error;
119
+ }
120
+ });
121
+ };
122
+ }
123
+ /**
124
+ * Create a factory for wide event server actions with shared options.
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * // app/actions/index.ts
129
+ * import { createWideEventAction } from '@vestig/next/wide-events'
130
+ *
131
+ * const action = createWideEventAction({
132
+ * tailSampling: {
133
+ * enabled: true,
134
+ * successSampleRate: 0.1,
135
+ * },
136
+ * })
137
+ *
138
+ * export const createUser = action(
139
+ * async (data, { event }) => {
140
+ * event.set('user', 'email', data.email)
141
+ * return await db.users.create({ data })
142
+ * },
143
+ * { name: 'action.user.create' }
144
+ * )
145
+ *
146
+ * export const updateUser = action(
147
+ * async ({ id, data }, { event }) => {
148
+ * event.set('user', 'id', id)
149
+ * return await db.users.update({ where: { id }, data })
150
+ * },
151
+ * { name: 'action.user.update' }
152
+ * )
153
+ * ```
154
+ */
155
+ export function createWideEventAction(defaultOptions = {}) {
156
+ return (handler, options = {}) => withWideEvent(handler, { ...defaultOptions, ...options });
157
+ }
158
+ //# sourceMappingURL=server-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-action.js","sourceRoot":"","sources":["../../src/wide-events/server-action.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vestig/next",
3
- "version": "0.11.4",
3
+ "version": "0.13.0",
4
4
  "description": "First-class Next.js 15+ integration for vestig logging library. Zero boilerplate, automatic request correlation, full type safety.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -45,6 +45,10 @@
45
45
  "./db": {
46
46
  "types": "./dist/db/index.d.ts",
47
47
  "import": "./dist/db/index.js"
48
+ },
49
+ "./wide-events": {
50
+ "types": "./dist/wide-events/index.d.ts",
51
+ "import": "./dist/wide-events/index.js"
48
52
  }
49
53
  },
50
54
  "files": ["dist"],
@@ -70,7 +74,10 @@
70
74
  "typescript",
71
75
  "request-correlation",
72
76
  "tracing",
73
- "observability"
77
+ "observability",
78
+ "wide-events",
79
+ "canonical-log-lines",
80
+ "tail-sampling"
74
81
  ],
75
82
  "author": "Arakiss",
76
83
  "license": "MIT",