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.
- package/LICENSE +21 -0
- package/README.md +346 -0
- package/dist/__tests__/context.test.d.ts +2 -0
- package/dist/__tests__/context.test.d.ts.map +1 -0
- package/dist/__tests__/context.test.js +94 -0
- package/dist/__tests__/context.test.js.map +1 -0
- package/dist/__tests__/elevenlabs.test.d.ts +2 -0
- package/dist/__tests__/elevenlabs.test.d.ts.map +1 -0
- package/dist/__tests__/elevenlabs.test.js +108 -0
- package/dist/__tests__/elevenlabs.test.js.map +1 -0
- package/dist/__tests__/fal.test.d.ts +2 -0
- package/dist/__tests__/fal.test.d.ts.map +1 -0
- package/dist/__tests__/fal.test.js +153 -0
- package/dist/__tests__/fal.test.js.map +1 -0
- package/dist/__tests__/pricing.test.d.ts +2 -0
- package/dist/__tests__/pricing.test.d.ts.map +1 -0
- package/dist/__tests__/pricing.test.js +76 -0
- package/dist/__tests__/pricing.test.js.map +1 -0
- package/dist/__tests__/recorder.test.d.ts +2 -0
- package/dist/__tests__/recorder.test.d.ts.map +1 -0
- package/dist/__tests__/recorder.test.js +133 -0
- package/dist/__tests__/recorder.test.js.map +1 -0
- package/dist/__tests__/storage.test.d.ts +2 -0
- package/dist/__tests__/storage.test.d.ts.map +1 -0
- package/dist/__tests__/storage.test.js +106 -0
- package/dist/__tests__/storage.test.js.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -0
- package/dist/config.d.ts +92 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +166 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +80 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +131 -0
- package/dist/context.js.map +1 -0
- package/dist/exporter/PostgresExporter.d.ts +82 -0
- package/dist/exporter/PostgresExporter.d.ts.map +1 -0
- package/dist/exporter/PostgresExporter.js +237 -0
- package/dist/exporter/PostgresExporter.js.map +1 -0
- package/dist/exporter/index.d.ts +8 -0
- package/dist/exporter/index.d.ts.map +1 -0
- package/dist/exporter/index.js +7 -0
- package/dist/exporter/index.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumentation/proxy.d.ts +26 -0
- package/dist/instrumentation/proxy.d.ts.map +1 -0
- package/dist/instrumentation/proxy.js +337 -0
- package/dist/instrumentation/proxy.js.map +1 -0
- package/dist/instrumentation/strategies/index.d.ts +55 -0
- package/dist/instrumentation/strategies/index.d.ts.map +1 -0
- package/dist/instrumentation/strategies/index.js +429 -0
- package/dist/instrumentation/strategies/index.js.map +1 -0
- package/dist/integrations/express/index.d.ts +137 -0
- package/dist/integrations/express/index.d.ts.map +1 -0
- package/dist/integrations/express/index.js +186 -0
- package/dist/integrations/express/index.js.map +1 -0
- package/dist/integrations/inngest/index.d.ts +222 -0
- package/dist/integrations/inngest/index.d.ts.map +1 -0
- package/dist/integrations/inngest/index.js +223 -0
- package/dist/integrations/inngest/index.js.map +1 -0
- package/dist/integrations/langfuse/index.d.ts +170 -0
- package/dist/integrations/langfuse/index.d.ts.map +1 -0
- package/dist/integrations/langfuse/index.js +225 -0
- package/dist/integrations/langfuse/index.js.map +1 -0
- package/dist/integrations/next/index.d.ts +138 -0
- package/dist/integrations/next/index.d.ts.map +1 -0
- package/dist/integrations/next/index.js +170 -0
- package/dist/integrations/next/index.js.map +1 -0
- package/dist/integrations/nextjs/index.d.ts +198 -0
- package/dist/integrations/nextjs/index.d.ts.map +1 -0
- package/dist/integrations/nextjs/index.js +181 -0
- package/dist/integrations/nextjs/index.js.map +1 -0
- package/dist/integrations/vercel-ai/index.d.ts +288 -0
- package/dist/integrations/vercel-ai/index.d.ts.map +1 -0
- package/dist/integrations/vercel-ai/index.js +260 -0
- package/dist/integrations/vercel-ai/index.js.map +1 -0
- package/dist/logger.d.ts +58 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +89 -0
- package/dist/logger.js.map +1 -0
- package/dist/pricing/catalog.d.ts +10 -0
- package/dist/pricing/catalog.d.ts.map +1 -0
- package/dist/pricing/catalog.js +297 -0
- package/dist/pricing/catalog.js.map +1 -0
- package/dist/pricing/index.d.ts +77 -0
- package/dist/pricing/index.d.ts.map +1 -0
- package/dist/pricing/index.js +251 -0
- package/dist/pricing/index.js.map +1 -0
- package/dist/pricing/manifest.d.ts +156 -0
- package/dist/pricing/manifest.d.ts.map +1 -0
- package/dist/pricing/manifest.js +381 -0
- package/dist/pricing/manifest.js.map +1 -0
- package/dist/pricing/manifest.json +12786 -0
- package/dist/pricing/providers/anthropic.json +253 -0
- package/dist/pricing/providers/bedrock.json +341 -0
- package/dist/pricing/providers/bfl.json +220 -0
- package/dist/pricing/providers/elevenlabs.json +142 -0
- package/dist/pricing/providers/fal.json +15866 -0
- package/dist/pricing/providers/google.json +346 -0
- package/dist/pricing/providers/openai.json +1035 -0
- package/dist/pricing/schema.d.ts +102 -0
- package/dist/pricing/schema.d.ts.map +1 -0
- package/dist/pricing/schema.js +56 -0
- package/dist/pricing/schema.js.map +1 -0
- package/dist/processor/TokenMeterProcessor.d.ts +55 -0
- package/dist/processor/TokenMeterProcessor.d.ts.map +1 -0
- package/dist/processor/TokenMeterProcessor.js +132 -0
- package/dist/processor/TokenMeterProcessor.js.map +1 -0
- package/dist/query/client.d.ts +61 -0
- package/dist/query/client.d.ts.map +1 -0
- package/dist/query/client.js +206 -0
- package/dist/query/client.js.map +1 -0
- package/dist/query/index.d.ts +8 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +7 -0
- package/dist/query/index.js.map +1 -0
- package/dist/recorder.d.ts +74 -0
- package/dist/recorder.d.ts.map +1 -0
- package/dist/recorder.js +227 -0
- package/dist/recorder.js.map +1 -0
- package/dist/sdks/anthropic.d.ts +21 -0
- package/dist/sdks/anthropic.d.ts.map +1 -0
- package/dist/sdks/anthropic.js +258 -0
- package/dist/sdks/anthropic.js.map +1 -0
- package/dist/sdks/elevenlabs.d.ts +59 -0
- package/dist/sdks/elevenlabs.d.ts.map +1 -0
- package/dist/sdks/elevenlabs.js +192 -0
- package/dist/sdks/elevenlabs.js.map +1 -0
- package/dist/sdks/fal.d.ts +102 -0
- package/dist/sdks/fal.d.ts.map +1 -0
- package/dist/sdks/fal.js +306 -0
- package/dist/sdks/fal.js.map +1 -0
- package/dist/sdks/openai.d.ts +17 -0
- package/dist/sdks/openai.d.ts.map +1 -0
- package/dist/sdks/openai.js +191 -0
- package/dist/sdks/openai.js.map +1 -0
- package/dist/storage/interface.d.ts +15 -0
- package/dist/storage/interface.d.ts.map +1 -0
- package/dist/storage/interface.js +53 -0
- package/dist/storage/interface.js.map +1 -0
- package/dist/storage/prisma.d.ts +15 -0
- package/dist/storage/prisma.d.ts.map +1 -0
- package/dist/storage/prisma.js +135 -0
- package/dist/storage/prisma.js.map +1 -0
- package/dist/types.d.ts +206 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +45 -0
- package/dist/types.js.map +1 -0
- package/dist/vercel-ai/index.d.ts +89 -0
- package/dist/vercel-ai/index.d.ts.map +1 -0
- package/dist/vercel-ai/index.js +298 -0
- package/dist/vercel-ai/index.js.map +1 -0
- 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":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA+GhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,cAAc,CAC5B,UAA0B,EAC1B,MAAkC;IAElC,OAAO,KAAK,UAAU,oBAAoB,CACxC,OAAoB;QAEpB,qCAAqC;QACrC,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CACV,oEAAoE,CACrE,CAAC;YACF,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAED,wCAAwC;QACxC,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YACvD,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAED,gCAAgC;QAChC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACvD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,qDAAqD;YACrD,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAED,gDAAgD;QAChD,MAAM,YAAY,GAAqB;YACrC,UAAU;YACV,mBAAmB,EACjB,CAAC,MAAM,MAAM,CAAC,sBAAsB,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,SAAS;YAC/D,UAAU,EACR,CAAC,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,CAAC;gBACvC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;gBACnC,MAAM,CAAC,UAAU,EAAE;YACrB,YAAY,EAAE,CAAC,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,SAAS;YACpE,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,SAAS;YAC3D,QAAQ,EAAE;gBACR,GAAG,CAAC,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,CAAC;gBACxC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ;gBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB;SACF,CAAC;QAEF,wDAAwD;QACxD,OAAO,aAAa,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;YAC5C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;YACzC,OAAO,MAAM,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAAkC,EAClC,YAAgC;IAEhC,OAAO,cAAc,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,cAAc,CAC5B,OAA0D,EAC1D,UAAoE;IAEpE,OAAO,KAAK,EAAE,GAAM,EAAE,GAAG,IAAe,EAAqB,EAAE;QAC7D,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CACV,wEAAwE,CACzE,CAAC;YACF,OAAO,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;QAEtC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACxB,OAAO,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC/B,CAAC;QAED,OAAO,aAAa,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;YACvC,OAAO,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B;;OAEG;IACH,MAAM,EAAE,CAAC,GAAgB,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IAE1D;;OAEG;IACH,KAAK,EAAE,CAAC,GAAgB,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;IAExD;;OAEG;IACH,MAAM,EAAE,CAAC,GAAgB,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;IAE1D;;OAEG;IACH,WAAW,EAAE,CAAC,GAAgB,EAAE,EAAE;QAChC,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC9C,IAAI,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,SAAS,EAAE,CAAC,GAAgB,EAAE,EAAE,CAC9B,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAC/B,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;QACnC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;CAChC,CAAC;AAEF,eAAe,cAAc,CAAC"}
|