tokenmeter 0.9.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 (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +346 -0
  3. package/dist/__tests__/context.test.d.ts +2 -0
  4. package/dist/__tests__/context.test.d.ts.map +1 -0
  5. package/dist/__tests__/context.test.js +94 -0
  6. package/dist/__tests__/context.test.js.map +1 -0
  7. package/dist/__tests__/elevenlabs.test.d.ts +2 -0
  8. package/dist/__tests__/elevenlabs.test.d.ts.map +1 -0
  9. package/dist/__tests__/elevenlabs.test.js +108 -0
  10. package/dist/__tests__/elevenlabs.test.js.map +1 -0
  11. package/dist/__tests__/fal.test.d.ts +2 -0
  12. package/dist/__tests__/fal.test.d.ts.map +1 -0
  13. package/dist/__tests__/fal.test.js +153 -0
  14. package/dist/__tests__/fal.test.js.map +1 -0
  15. package/dist/__tests__/pricing.test.d.ts +2 -0
  16. package/dist/__tests__/pricing.test.d.ts.map +1 -0
  17. package/dist/__tests__/pricing.test.js +76 -0
  18. package/dist/__tests__/pricing.test.js.map +1 -0
  19. package/dist/__tests__/recorder.test.d.ts +2 -0
  20. package/dist/__tests__/recorder.test.d.ts.map +1 -0
  21. package/dist/__tests__/recorder.test.js +133 -0
  22. package/dist/__tests__/recorder.test.js.map +1 -0
  23. package/dist/__tests__/storage.test.d.ts +2 -0
  24. package/dist/__tests__/storage.test.d.ts.map +1 -0
  25. package/dist/__tests__/storage.test.js +106 -0
  26. package/dist/__tests__/storage.test.js.map +1 -0
  27. package/dist/client/index.d.ts +8 -0
  28. package/dist/client/index.d.ts.map +1 -0
  29. package/dist/client/index.js +7 -0
  30. package/dist/client/index.js.map +1 -0
  31. package/dist/config.d.ts +92 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +166 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/context.d.ts +80 -0
  36. package/dist/context.d.ts.map +1 -0
  37. package/dist/context.js +131 -0
  38. package/dist/context.js.map +1 -0
  39. package/dist/exporter/PostgresExporter.d.ts +82 -0
  40. package/dist/exporter/PostgresExporter.d.ts.map +1 -0
  41. package/dist/exporter/PostgresExporter.js +237 -0
  42. package/dist/exporter/PostgresExporter.js.map +1 -0
  43. package/dist/exporter/index.d.ts +8 -0
  44. package/dist/exporter/index.d.ts.map +1 -0
  45. package/dist/exporter/index.js +7 -0
  46. package/dist/exporter/index.js.map +1 -0
  47. package/dist/index.d.ts +31 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +37 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/instrumentation/proxy.d.ts +26 -0
  52. package/dist/instrumentation/proxy.d.ts.map +1 -0
  53. package/dist/instrumentation/proxy.js +337 -0
  54. package/dist/instrumentation/proxy.js.map +1 -0
  55. package/dist/instrumentation/strategies/index.d.ts +55 -0
  56. package/dist/instrumentation/strategies/index.d.ts.map +1 -0
  57. package/dist/instrumentation/strategies/index.js +429 -0
  58. package/dist/instrumentation/strategies/index.js.map +1 -0
  59. package/dist/integrations/express/index.d.ts +137 -0
  60. package/dist/integrations/express/index.d.ts.map +1 -0
  61. package/dist/integrations/express/index.js +186 -0
  62. package/dist/integrations/express/index.js.map +1 -0
  63. package/dist/integrations/inngest/index.d.ts +222 -0
  64. package/dist/integrations/inngest/index.d.ts.map +1 -0
  65. package/dist/integrations/inngest/index.js +223 -0
  66. package/dist/integrations/inngest/index.js.map +1 -0
  67. package/dist/integrations/langfuse/index.d.ts +170 -0
  68. package/dist/integrations/langfuse/index.d.ts.map +1 -0
  69. package/dist/integrations/langfuse/index.js +225 -0
  70. package/dist/integrations/langfuse/index.js.map +1 -0
  71. package/dist/integrations/next/index.d.ts +138 -0
  72. package/dist/integrations/next/index.d.ts.map +1 -0
  73. package/dist/integrations/next/index.js +170 -0
  74. package/dist/integrations/next/index.js.map +1 -0
  75. package/dist/integrations/nextjs/index.d.ts +198 -0
  76. package/dist/integrations/nextjs/index.d.ts.map +1 -0
  77. package/dist/integrations/nextjs/index.js +181 -0
  78. package/dist/integrations/nextjs/index.js.map +1 -0
  79. package/dist/integrations/vercel-ai/index.d.ts +288 -0
  80. package/dist/integrations/vercel-ai/index.d.ts.map +1 -0
  81. package/dist/integrations/vercel-ai/index.js +260 -0
  82. package/dist/integrations/vercel-ai/index.js.map +1 -0
  83. package/dist/logger.d.ts +58 -0
  84. package/dist/logger.d.ts.map +1 -0
  85. package/dist/logger.js +89 -0
  86. package/dist/logger.js.map +1 -0
  87. package/dist/pricing/catalog.d.ts +10 -0
  88. package/dist/pricing/catalog.d.ts.map +1 -0
  89. package/dist/pricing/catalog.js +297 -0
  90. package/dist/pricing/catalog.js.map +1 -0
  91. package/dist/pricing/index.d.ts +77 -0
  92. package/dist/pricing/index.d.ts.map +1 -0
  93. package/dist/pricing/index.js +251 -0
  94. package/dist/pricing/index.js.map +1 -0
  95. package/dist/pricing/manifest.d.ts +156 -0
  96. package/dist/pricing/manifest.d.ts.map +1 -0
  97. package/dist/pricing/manifest.js +381 -0
  98. package/dist/pricing/manifest.js.map +1 -0
  99. package/dist/pricing/manifest.json +12786 -0
  100. package/dist/pricing/providers/anthropic.json +253 -0
  101. package/dist/pricing/providers/bedrock.json +341 -0
  102. package/dist/pricing/providers/bfl.json +220 -0
  103. package/dist/pricing/providers/elevenlabs.json +142 -0
  104. package/dist/pricing/providers/fal.json +15866 -0
  105. package/dist/pricing/providers/google.json +346 -0
  106. package/dist/pricing/providers/openai.json +1035 -0
  107. package/dist/pricing/schema.d.ts +102 -0
  108. package/dist/pricing/schema.d.ts.map +1 -0
  109. package/dist/pricing/schema.js +56 -0
  110. package/dist/pricing/schema.js.map +1 -0
  111. package/dist/processor/TokenMeterProcessor.d.ts +55 -0
  112. package/dist/processor/TokenMeterProcessor.d.ts.map +1 -0
  113. package/dist/processor/TokenMeterProcessor.js +132 -0
  114. package/dist/processor/TokenMeterProcessor.js.map +1 -0
  115. package/dist/query/client.d.ts +61 -0
  116. package/dist/query/client.d.ts.map +1 -0
  117. package/dist/query/client.js +206 -0
  118. package/dist/query/client.js.map +1 -0
  119. package/dist/query/index.d.ts +8 -0
  120. package/dist/query/index.d.ts.map +1 -0
  121. package/dist/query/index.js +7 -0
  122. package/dist/query/index.js.map +1 -0
  123. package/dist/recorder.d.ts +74 -0
  124. package/dist/recorder.d.ts.map +1 -0
  125. package/dist/recorder.js +227 -0
  126. package/dist/recorder.js.map +1 -0
  127. package/dist/sdks/anthropic.d.ts +21 -0
  128. package/dist/sdks/anthropic.d.ts.map +1 -0
  129. package/dist/sdks/anthropic.js +258 -0
  130. package/dist/sdks/anthropic.js.map +1 -0
  131. package/dist/sdks/elevenlabs.d.ts +59 -0
  132. package/dist/sdks/elevenlabs.d.ts.map +1 -0
  133. package/dist/sdks/elevenlabs.js +192 -0
  134. package/dist/sdks/elevenlabs.js.map +1 -0
  135. package/dist/sdks/fal.d.ts +102 -0
  136. package/dist/sdks/fal.d.ts.map +1 -0
  137. package/dist/sdks/fal.js +306 -0
  138. package/dist/sdks/fal.js.map +1 -0
  139. package/dist/sdks/openai.d.ts +17 -0
  140. package/dist/sdks/openai.d.ts.map +1 -0
  141. package/dist/sdks/openai.js +191 -0
  142. package/dist/sdks/openai.js.map +1 -0
  143. package/dist/storage/interface.d.ts +15 -0
  144. package/dist/storage/interface.d.ts.map +1 -0
  145. package/dist/storage/interface.js +53 -0
  146. package/dist/storage/interface.js.map +1 -0
  147. package/dist/storage/prisma.d.ts +15 -0
  148. package/dist/storage/prisma.d.ts.map +1 -0
  149. package/dist/storage/prisma.js +135 -0
  150. package/dist/storage/prisma.js.map +1 -0
  151. package/dist/types.d.ts +206 -0
  152. package/dist/types.d.ts.map +1 -0
  153. package/dist/types.js +45 -0
  154. package/dist/types.js.map +1 -0
  155. package/dist/vercel-ai/index.d.ts +89 -0
  156. package/dist/vercel-ai/index.d.ts.map +1 -0
  157. package/dist/vercel-ai/index.js +298 -0
  158. package/dist/vercel-ai/index.js.map +1 -0
  159. package/package.json +119 -0
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Next.js Integration
3
+ *
4
+ * Provides helpers for App Router route handlers to automatically
5
+ * set up cost tracking context.
6
+ */
7
+ import { withAttributes } from "../../context.js";
8
+ /**
9
+ * Default context extractor that reads from common headers
10
+ */
11
+ function defaultContextExtractor(request, options) {
12
+ const userIdHeader = options.userIdHeader ?? "x-user-id";
13
+ const orgIdHeader = options.orgIdHeader ?? "x-org-id";
14
+ const workflowIdHeader = options.workflowIdHeader ?? "x-request-id";
15
+ return {
16
+ userId: request.headers.get(userIdHeader) ?? undefined,
17
+ orgId: request.headers.get(orgIdHeader) ?? undefined,
18
+ workflowId: request.headers.get(workflowIdHeader) ?? crypto.randomUUID(),
19
+ };
20
+ }
21
+ /**
22
+ * Convert TokenMeterContext to attributes
23
+ */
24
+ function contextToAttributes(ctx) {
25
+ const attrs = {};
26
+ if (ctx.userId) {
27
+ attrs["user.id"] = ctx.userId;
28
+ }
29
+ if (ctx.orgId) {
30
+ attrs["org.id"] = ctx.orgId;
31
+ }
32
+ if (ctx.workflowId) {
33
+ attrs["workflow.id"] = ctx.workflowId;
34
+ }
35
+ if (ctx.metadata) {
36
+ for (const [key, value] of Object.entries(ctx.metadata)) {
37
+ attrs[key] = value;
38
+ }
39
+ }
40
+ return attrs;
41
+ }
42
+ /**
43
+ * Wrap a Next.js App Router route handler with tokenmeter context.
44
+ *
45
+ * All AI calls made with `monitor()`-wrapped clients within the handler
46
+ * will automatically be attributed to the user/org extracted from the request.
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * // app/api/chat/route.ts
51
+ * import { withTokenmeter } from 'tokenmeter/next';
52
+ * import { monitor } from 'tokenmeter';
53
+ * import OpenAI from 'openai';
54
+ *
55
+ * const openai = monitor(new OpenAI());
56
+ *
57
+ * export const POST = withTokenmeter(async (req) => {
58
+ * const { message } = await req.json();
59
+ *
60
+ * // This call is automatically attributed to the user
61
+ * const result = await openai.chat.completions.create({
62
+ * model: 'gpt-4o',
63
+ * messages: [{ role: 'user', content: message }],
64
+ * });
65
+ *
66
+ * return Response.json({ reply: result.choices[0].message.content });
67
+ * });
68
+ * ```
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * // With custom context extraction (e.g., from auth)
73
+ * import { auth } from '@clerk/nextjs/server';
74
+ *
75
+ * export const POST = withTokenmeter(
76
+ * async (req) => {
77
+ * // Handler code
78
+ * },
79
+ * {
80
+ * getContext: async (req) => {
81
+ * const { userId, orgId } = await auth();
82
+ * return { userId, orgId };
83
+ * },
84
+ * }
85
+ * );
86
+ * ```
87
+ */
88
+ export function withTokenmeter(handler, options = {}) {
89
+ return async (request, routeContext) => {
90
+ // Extract context
91
+ let ctx;
92
+ if (options.getContext) {
93
+ ctx = await options.getContext(request);
94
+ }
95
+ else {
96
+ ctx = defaultContextExtractor(request, options);
97
+ }
98
+ // Convert to attributes
99
+ const attrs = contextToAttributes(ctx);
100
+ // Execute handler within context
101
+ return withAttributes(attrs, async () => {
102
+ return handler(request, routeContext);
103
+ });
104
+ };
105
+ }
106
+ /**
107
+ * Create a reusable tokenmeter wrapper with preset options.
108
+ *
109
+ * Useful when you have common context extraction logic across multiple routes.
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * // lib/tokenmeter.ts
114
+ * import { createTokenmeterWrapper } from 'tokenmeter/next';
115
+ * import { auth } from '@clerk/nextjs/server';
116
+ *
117
+ * export const withCostTracking = createTokenmeterWrapper({
118
+ * getContext: async (req) => {
119
+ * const { userId, orgId } = await auth();
120
+ * return { userId, orgId };
121
+ * },
122
+ * });
123
+ *
124
+ * // app/api/chat/route.ts
125
+ * import { withCostTracking } from '@/lib/tokenmeter';
126
+ *
127
+ * export const POST = withCostTracking(async (req) => {
128
+ * // ...
129
+ * });
130
+ * ```
131
+ */
132
+ export function createTokenmeterWrapper(defaultOptions) {
133
+ return (handler, options) => {
134
+ return withTokenmeter(handler, { ...defaultOptions, ...options });
135
+ };
136
+ }
137
+ /**
138
+ * Helper to extract common headers from a request
139
+ */
140
+ export const headerExtractors = {
141
+ /**
142
+ * Extract user ID from x-user-id header
143
+ */
144
+ userId: (request) => {
145
+ return request.headers.get("x-user-id") ?? undefined;
146
+ },
147
+ /**
148
+ * Extract org ID from x-org-id header
149
+ */
150
+ orgId: (request) => {
151
+ return request.headers.get("x-org-id") ?? undefined;
152
+ },
153
+ /**
154
+ * Extract API key from Authorization header (Bearer token)
155
+ */
156
+ apiKey: (request) => {
157
+ const auth = request.headers.get("authorization");
158
+ if (auth?.startsWith("Bearer ")) {
159
+ return auth.slice(7);
160
+ }
161
+ return undefined;
162
+ },
163
+ /**
164
+ * Extract request ID from x-request-id header
165
+ */
166
+ requestId: (request) => {
167
+ return request.headers.get("x-request-id") ?? undefined;
168
+ },
169
+ };
170
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/integrations/next/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,198 @@
1
+ import type { CostTraceOptions } from "../../types.js";
2
+ /**
3
+ * Minimal type definitions for Next.js server types.
4
+ * These are defined inline to avoid requiring Next.js as a hard dependency.
5
+ */
6
+ /** Minimal NextRequest interface */
7
+ export interface NextRequest {
8
+ headers: Headers;
9
+ nextUrl: {
10
+ pathname: string;
11
+ searchParams: URLSearchParams;
12
+ };
13
+ method: string;
14
+ url: string;
15
+ }
16
+ /** Minimal NextResponse static methods */
17
+ export interface NextResponseStatic {
18
+ next: (init?: {
19
+ headers?: Headers;
20
+ }) => NextResponse;
21
+ redirect: (url: string | URL, status?: number) => NextResponse;
22
+ rewrite: (url: string | URL) => NextResponse;
23
+ json: (body: unknown, init?: ResponseInit) => NextResponse;
24
+ }
25
+ /** Minimal NextResponse interface */
26
+ export interface NextResponse extends Response {
27
+ cookies: {
28
+ set: (name: string, value: string, options?: unknown) => void;
29
+ delete: (name: string) => void;
30
+ };
31
+ }
32
+ /** Next.js middleware function type */
33
+ export type NextMiddleware = (request: NextRequest) => Promise<NextResponse | Response | undefined> | NextResponse | Response | undefined;
34
+ /**
35
+ * Configuration for the Next.js middleware
36
+ */
37
+ export interface TokenmeterMiddlewareConfig {
38
+ /**
39
+ * Extract the identifier from the request.
40
+ * This is required and should return a user ID, org ID, or other billing identifier.
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * getIdentifier: (req) => req.headers.get('x-user-id') || 'anonymous'
45
+ * ```
46
+ */
47
+ getIdentifier: (req: NextRequest) => string | null | undefined | Promise<string | null | undefined>;
48
+ /**
49
+ * Optional: Extract a secondary identifier from the request.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * getSecondaryIdentifier: (req) => req.headers.get('x-org-id')
54
+ * ```
55
+ */
56
+ getSecondaryIdentifier?: (req: NextRequest) => string | null | undefined | Promise<string | null | undefined>;
57
+ /**
58
+ * Optional: Extract or generate a workflow ID from the request.
59
+ * Defaults to using the x-request-id header or generating a UUID.
60
+ */
61
+ getWorkflowId?: (req: NextRequest) => string | null | undefined | Promise<string | null | undefined>;
62
+ /**
63
+ * Optional: Extract or specify a workflow type from the request.
64
+ */
65
+ getWorkflowType?: (req: NextRequest) => string | null | undefined | Promise<string | null | undefined>;
66
+ /**
67
+ * Optional: Extract additional metadata from the request.
68
+ */
69
+ getMetadata?: (req: NextRequest) => Record<string, unknown> | undefined | Promise<Record<string, unknown> | undefined>;
70
+ /**
71
+ * Optional: Filter which routes should have cost tracking enabled.
72
+ * Return true to enable tracking for the request, false to skip.
73
+ * Defaults to tracking all routes.
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * shouldTrack: (req) => req.nextUrl.pathname.startsWith('/api/')
78
+ * ```
79
+ */
80
+ shouldTrack?: (req: NextRequest) => boolean;
81
+ }
82
+ /**
83
+ * Wrap a Next.js middleware function with cost tracking context.
84
+ *
85
+ * This is the recommended way to add tokenmeter to Next.js middleware.
86
+ * It wraps your existing middleware and sets up cost tracking context
87
+ * before your middleware runs.
88
+ *
89
+ * @param middleware - Your existing Next.js middleware function
90
+ * @param config - Configuration for extracting identifiers and metadata
91
+ * @returns A wrapped middleware function
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * // middleware.ts
96
+ * import { NextResponse } from 'next/server';
97
+ * import type { NextRequest } from 'next/server';
98
+ * import { wrapMiddleware } from 'tokenmeter/nextjs';
99
+ *
100
+ * function middleware(request: NextRequest) {
101
+ * // Your middleware logic here
102
+ * return NextResponse.next();
103
+ * }
104
+ *
105
+ * export default wrapMiddleware(middleware, {
106
+ * getIdentifier: (req) => req.headers.get('x-user-id'),
107
+ * shouldTrack: (req) => req.nextUrl.pathname.startsWith('/api/'),
108
+ * });
109
+ * ```
110
+ */
111
+ export declare function wrapMiddleware(middleware: NextMiddleware, config: TokenmeterMiddlewareConfig): NextMiddleware;
112
+ /**
113
+ * Create a standalone Next.js middleware for cost tracking.
114
+ *
115
+ * Use this when you want tokenmeter to be the only middleware,
116
+ * or when composing middleware manually.
117
+ *
118
+ * NOTE: This middleware only sets up the tracking context. The actual
119
+ * AI calls must be made in API routes that run in the same request context.
120
+ * Due to Next.js Edge Runtime limitations, the context may not propagate
121
+ * to API routes. For API routes, use `withTokenmeter` instead.
122
+ *
123
+ * @param config - Configuration for extracting identifiers and metadata
124
+ * @param NextResponse - The NextResponse class from 'next/server'
125
+ * @returns A Next.js middleware function
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * // middleware.ts
130
+ * import { NextResponse } from 'next/server';
131
+ * import { createTokenmeterMiddleware } from 'tokenmeter/nextjs';
132
+ *
133
+ * export default createTokenmeterMiddleware({
134
+ * getIdentifier: (req) => req.headers.get('x-user-id'),
135
+ * shouldTrack: (req) => req.nextUrl.pathname.startsWith('/api/'),
136
+ * }, NextResponse);
137
+ * ```
138
+ */
139
+ export declare function createTokenmeterMiddleware(config: TokenmeterMiddlewareConfig, NextResponse: NextResponseStatic): NextMiddleware;
140
+ /**
141
+ * Higher-order function to wrap a Next.js API route handler with cost tracking.
142
+ *
143
+ * Use this for App Router route handlers when you need more control than middleware.
144
+ * This is the RECOMMENDED approach for tracking AI costs in API routes.
145
+ *
146
+ * @param handler - The route handler function
147
+ * @param getOptions - Function to extract trace options from the request
148
+ * @returns A wrapped route handler
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * // app/api/chat/route.ts
153
+ * import { withTokenmeter } from 'tokenmeter/nextjs';
154
+ * import { auth } from '@/auth';
155
+ *
156
+ * async function handler(req: NextRequest) {
157
+ * // Your AI calls here are automatically tracked
158
+ * const result = await openai.chat.completions.create({ ... });
159
+ * return Response.json({ result });
160
+ * }
161
+ *
162
+ * export const POST = withTokenmeter(handler, async (req) => {
163
+ * const session = await auth();
164
+ * return {
165
+ * identifier: session?.user?.id || 'anonymous',
166
+ * workflowType: 'chat',
167
+ * };
168
+ * });
169
+ * ```
170
+ */
171
+ export declare function withTokenmeter<T extends NextRequest>(handler: (req: T, ...args: unknown[]) => Promise<Response>, getOptions: (req: T) => CostTraceOptions | Promise<CostTraceOptions>): (req: T, ...args: unknown[]) => Promise<Response>;
172
+ /**
173
+ * Helper to extract common identifiers from Next.js request headers.
174
+ */
175
+ export declare const headerExtractors: {
176
+ /**
177
+ * Get identifier from x-user-id header
178
+ */
179
+ userId: (req: NextRequest) => string | null;
180
+ /**
181
+ * Get identifier from x-org-id header
182
+ */
183
+ orgId: (req: NextRequest) => string | null;
184
+ /**
185
+ * Get identifier from x-api-key header
186
+ */
187
+ apiKey: (req: NextRequest) => string | null;
188
+ /**
189
+ * Get identifier from Authorization header (Bearer token)
190
+ */
191
+ bearerToken: (req: NextRequest) => string | null;
192
+ /**
193
+ * Get request ID from common headers
194
+ */
195
+ requestId: (req: NextRequest) => string | null;
196
+ };
197
+ export default wrapMiddleware;
198
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/nextjs/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,181 @@
1
+ import { withCostTrace } from "../../context.js";
2
+ import { isInitialized } from "../../config.js";
3
+ /**
4
+ * Wrap a Next.js middleware function with cost tracking context.
5
+ *
6
+ * This is the recommended way to add tokenmeter to Next.js middleware.
7
+ * It wraps your existing middleware and sets up cost tracking context
8
+ * before your middleware runs.
9
+ *
10
+ * @param middleware - Your existing Next.js middleware function
11
+ * @param config - Configuration for extracting identifiers and metadata
12
+ * @returns A wrapped middleware function
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * // middleware.ts
17
+ * import { NextResponse } from 'next/server';
18
+ * import type { NextRequest } from 'next/server';
19
+ * import { wrapMiddleware } from 'tokenmeter/nextjs';
20
+ *
21
+ * function middleware(request: NextRequest) {
22
+ * // Your middleware logic here
23
+ * return NextResponse.next();
24
+ * }
25
+ *
26
+ * export default wrapMiddleware(middleware, {
27
+ * getIdentifier: (req) => req.headers.get('x-user-id'),
28
+ * shouldTrack: (req) => req.nextUrl.pathname.startsWith('/api/'),
29
+ * });
30
+ * ```
31
+ */
32
+ export function wrapMiddleware(middleware, config) {
33
+ return async function tokenmeterMiddleware(request) {
34
+ // Check if tokenmeter is initialized
35
+ if (!isInitialized()) {
36
+ console.warn("[tokenmeter] Not initialized. Call init() before using middleware.");
37
+ return middleware(request);
38
+ }
39
+ // Check if we should track this request
40
+ if (config.shouldTrack && !config.shouldTrack(request)) {
41
+ return middleware(request);
42
+ }
43
+ // Get identifier (may be async)
44
+ const identifier = await config.getIdentifier(request);
45
+ if (!identifier) {
46
+ // No identifier - skip tracking but continue request
47
+ return middleware(request);
48
+ }
49
+ // Build trace options (await any async getters)
50
+ const traceOptions = {
51
+ identifier,
52
+ secondaryIdentifier: (await config.getSecondaryIdentifier?.(request)) ?? undefined,
53
+ workflowId: (await config.getWorkflowId?.(request)) ??
54
+ request.headers.get("x-request-id") ??
55
+ crypto.randomUUID(),
56
+ workflowType: (await config.getWorkflowType?.(request)) ?? undefined,
57
+ requestId: request.headers.get("x-request-id") ?? undefined,
58
+ metadata: {
59
+ ...(await config.getMetadata?.(request)),
60
+ path: request.nextUrl.pathname,
61
+ method: request.method,
62
+ },
63
+ };
64
+ // Wrap the middleware execution in a cost trace context
65
+ return withCostTrace(traceOptions, async () => {
66
+ const result = await middleware(request);
67
+ return result;
68
+ });
69
+ };
70
+ }
71
+ /**
72
+ * Create a standalone Next.js middleware for cost tracking.
73
+ *
74
+ * Use this when you want tokenmeter to be the only middleware,
75
+ * or when composing middleware manually.
76
+ *
77
+ * NOTE: This middleware only sets up the tracking context. The actual
78
+ * AI calls must be made in API routes that run in the same request context.
79
+ * Due to Next.js Edge Runtime limitations, the context may not propagate
80
+ * to API routes. For API routes, use `withTokenmeter` instead.
81
+ *
82
+ * @param config - Configuration for extracting identifiers and metadata
83
+ * @param NextResponse - The NextResponse class from 'next/server'
84
+ * @returns A Next.js middleware function
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * // middleware.ts
89
+ * import { NextResponse } from 'next/server';
90
+ * import { createTokenmeterMiddleware } from 'tokenmeter/nextjs';
91
+ *
92
+ * export default createTokenmeterMiddleware({
93
+ * getIdentifier: (req) => req.headers.get('x-user-id'),
94
+ * shouldTrack: (req) => req.nextUrl.pathname.startsWith('/api/'),
95
+ * }, NextResponse);
96
+ * ```
97
+ */
98
+ export function createTokenmeterMiddleware(config, NextResponse) {
99
+ return wrapMiddleware(() => NextResponse.next(), config);
100
+ }
101
+ /**
102
+ * Higher-order function to wrap a Next.js API route handler with cost tracking.
103
+ *
104
+ * Use this for App Router route handlers when you need more control than middleware.
105
+ * This is the RECOMMENDED approach for tracking AI costs in API routes.
106
+ *
107
+ * @param handler - The route handler function
108
+ * @param getOptions - Function to extract trace options from the request
109
+ * @returns A wrapped route handler
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * // app/api/chat/route.ts
114
+ * import { withTokenmeter } from 'tokenmeter/nextjs';
115
+ * import { auth } from '@/auth';
116
+ *
117
+ * async function handler(req: NextRequest) {
118
+ * // Your AI calls here are automatically tracked
119
+ * const result = await openai.chat.completions.create({ ... });
120
+ * return Response.json({ result });
121
+ * }
122
+ *
123
+ * export const POST = withTokenmeter(handler, async (req) => {
124
+ * const session = await auth();
125
+ * return {
126
+ * identifier: session?.user?.id || 'anonymous',
127
+ * workflowType: 'chat',
128
+ * };
129
+ * });
130
+ * ```
131
+ */
132
+ export function withTokenmeter(handler, getOptions) {
133
+ return async (req, ...args) => {
134
+ if (!isInitialized()) {
135
+ console.warn("[tokenmeter] Not initialized. Call init() before using withTokenmeter.");
136
+ return handler(req, ...args);
137
+ }
138
+ const options = await getOptions(req);
139
+ if (!options.identifier) {
140
+ return handler(req, ...args);
141
+ }
142
+ return withCostTrace(options, async () => {
143
+ return handler(req, ...args);
144
+ });
145
+ };
146
+ }
147
+ /**
148
+ * Helper to extract common identifiers from Next.js request headers.
149
+ */
150
+ export const headerExtractors = {
151
+ /**
152
+ * Get identifier from x-user-id header
153
+ */
154
+ userId: (req) => req.headers.get("x-user-id"),
155
+ /**
156
+ * Get identifier from x-org-id header
157
+ */
158
+ orgId: (req) => req.headers.get("x-org-id"),
159
+ /**
160
+ * Get identifier from x-api-key header
161
+ */
162
+ apiKey: (req) => req.headers.get("x-api-key"),
163
+ /**
164
+ * Get identifier from Authorization header (Bearer token)
165
+ */
166
+ bearerToken: (req) => {
167
+ const auth = req.headers.get("authorization");
168
+ if (auth?.startsWith("Bearer ")) {
169
+ return auth.slice(7);
170
+ }
171
+ return null;
172
+ },
173
+ /**
174
+ * Get request ID from common headers
175
+ */
176
+ requestId: (req) => req.headers.get("x-request-id") ||
177
+ req.headers.get("x-correlation-id") ||
178
+ req.headers.get("x-trace-id"),
179
+ };
180
+ export default wrapMiddleware;
181
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/integrations/nextjs/index.ts"],"names":[],"mappings":"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"}