@teja-app/api-client 0.0.1-dev.20260124115708.06e82a3 → 0.0.1-dev.20260125152414.0c955c4

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/dist/index.d.ts CHANGED
@@ -4,6 +4,8 @@
4
4
  * Type-safe API client generated from OpenAPI specification.
5
5
  * Provides full TypeScript support for all API endpoints.
6
6
  *
7
+ * ## Basic Usage
8
+ *
7
9
  * @example
8
10
  * ```typescript
9
11
  * import { OpenAPI, ClientsService, isApiError, getErrorMessage } from '@teja-app/api-client';
@@ -14,15 +16,55 @@
14
16
  *
15
17
  * // Make typed API calls with error handling
16
18
  * try {
17
- * const clients = await ClientsService.listClients({ limit: 10 });
19
+ * const clients = await ClientsService.getClients({ status: 'active' });
18
20
  * } catch (error) {
19
21
  * if (isApiError(error)) {
20
22
  * console.error('API Error:', getErrorMessage(error));
21
23
  * }
22
24
  * }
23
25
  * ```
26
+ *
27
+ * ## Telemetry Integration
28
+ *
29
+ * The API client supports OpenTelemetry integration for distributed tracing.
30
+ * Configure it once at app initialization to automatically add trace context
31
+ * headers to all API requests.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * import {
36
+ * OpenAPI,
37
+ * configureTelemetry,
38
+ * setupInterceptors
39
+ * } from '@teja-app/api-client';
40
+ * import { trace } from '@opentelemetry/api';
41
+ *
42
+ * // 1. Configure API client
43
+ * OpenAPI.BASE = import.meta.env.VITE_API_URL;
44
+ * OpenAPI.TOKEN = () => getAccessToken();
45
+ *
46
+ * // 2. Configure telemetry with your trace context provider
47
+ * configureTelemetry({
48
+ * enabled: true,
49
+ * getTraceContext: () => {
50
+ * const span = trace.getActiveSpan();
51
+ * if (!span) return null;
52
+ * const ctx = span.spanContext();
53
+ * return {
54
+ * traceId: ctx.traceId,
55
+ * spanId: ctx.spanId,
56
+ * traceFlags: ctx.traceFlags,
57
+ * };
58
+ * },
59
+ * });
60
+ *
61
+ * // 3. Enable interceptors (adds traceparent header to requests)
62
+ * setupInterceptors();
63
+ * ```
24
64
  */
25
65
  export * from "./generated";
26
66
  export * from "./errors";
27
67
  export * from "./interceptors";
68
+ export * from "./telemetry";
69
+ export * from "./request-with-interceptors";
28
70
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,cAAc,aAAa,CAAC;AAG5B,cAAc,UAAU,CAAC;AAGzB,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAGH,cAAc,aAAa,CAAC;AAG5B,cAAc,UAAU,CAAC;AAGzB,cAAc,gBAAgB,CAAC;AAG/B,cAAc,aAAa,CAAC;AAG5B,cAAc,6BAA6B,CAAC"}
package/dist/index.js CHANGED
@@ -4,6 +4,8 @@
4
4
  * Type-safe API client generated from OpenAPI specification.
5
5
  * Provides full TypeScript support for all API endpoints.
6
6
  *
7
+ * ## Basic Usage
8
+ *
7
9
  * @example
8
10
  * ```typescript
9
11
  * import { OpenAPI, ClientsService, isApiError, getErrorMessage } from '@teja-app/api-client';
@@ -14,13 +16,51 @@
14
16
  *
15
17
  * // Make typed API calls with error handling
16
18
  * try {
17
- * const clients = await ClientsService.listClients({ limit: 10 });
19
+ * const clients = await ClientsService.getClients({ status: 'active' });
18
20
  * } catch (error) {
19
21
  * if (isApiError(error)) {
20
22
  * console.error('API Error:', getErrorMessage(error));
21
23
  * }
22
24
  * }
23
25
  * ```
26
+ *
27
+ * ## Telemetry Integration
28
+ *
29
+ * The API client supports OpenTelemetry integration for distributed tracing.
30
+ * Configure it once at app initialization to automatically add trace context
31
+ * headers to all API requests.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * import {
36
+ * OpenAPI,
37
+ * configureTelemetry,
38
+ * setupInterceptors
39
+ * } from '@teja-app/api-client';
40
+ * import { trace } from '@opentelemetry/api';
41
+ *
42
+ * // 1. Configure API client
43
+ * OpenAPI.BASE = import.meta.env.VITE_API_URL;
44
+ * OpenAPI.TOKEN = () => getAccessToken();
45
+ *
46
+ * // 2. Configure telemetry with your trace context provider
47
+ * configureTelemetry({
48
+ * enabled: true,
49
+ * getTraceContext: () => {
50
+ * const span = trace.getActiveSpan();
51
+ * if (!span) return null;
52
+ * const ctx = span.spanContext();
53
+ * return {
54
+ * traceId: ctx.traceId,
55
+ * spanId: ctx.spanId,
56
+ * traceFlags: ctx.traceFlags,
57
+ * };
58
+ * },
59
+ * });
60
+ *
61
+ * // 3. Enable interceptors (adds traceparent header to requests)
62
+ * setupInterceptors();
63
+ * ```
24
64
  */
25
65
  // Re-export everything from generated code
26
66
  export * from "./generated";
@@ -28,4 +68,8 @@ export * from "./generated";
28
68
  export * from "./errors";
29
69
  // Export interceptors
30
70
  export * from "./interceptors";
71
+ // Export telemetry utilities
72
+ export * from "./telemetry";
73
+ // Export interceptor setup utilities
74
+ export * from "./request-with-interceptors";
31
75
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,2CAA2C;AAC3C,cAAc,aAAa,CAAC;AAE5B,yBAAyB;AACzB,cAAc,UAAU,CAAC;AAEzB,sBAAsB;AACtB,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAEH,2CAA2C;AAC3C,cAAc,aAAa,CAAC;AAE5B,yBAAyB;AACzB,cAAc,UAAU,CAAC;AAEzB,sBAAsB;AACtB,cAAc,gBAAgB,CAAC;AAE/B,6BAA6B;AAC7B,cAAc,aAAa,CAAC;AAE5B,qCAAqC;AACrC,cAAc,6BAA6B,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Enhanced request function with interceptor support
3
+ *
4
+ * This module provides a way to integrate interceptors with the generated
5
+ * request function. Since the generated code can't be modified, apps need
6
+ * to configure the OpenAPI object to use the enhanced request behavior.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { setupInterceptors } from '@teja-app/api-client';
11
+ *
12
+ * // Call this once at app initialization
13
+ * setupInterceptors();
14
+ *
15
+ * // Now all API calls will run through interceptors
16
+ * ```
17
+ */
18
+ /**
19
+ * Setup interceptors to work with the generated API client
20
+ *
21
+ * This patches the OpenAPI.HEADERS configuration to run request interceptors.
22
+ * Call this once at application startup after configuring telemetry.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * import { configureTelemetry, setupInterceptors, OpenAPI } from '@teja-app/api-client';
27
+ * import { trace } from '@opentelemetry/api';
28
+ *
29
+ * // 1. Configure the API client
30
+ * OpenAPI.BASE = 'https://api.example.com';
31
+ * OpenAPI.TOKEN = () => getAccessToken();
32
+ *
33
+ * // 2. Configure telemetry
34
+ * configureTelemetry({
35
+ * enabled: true,
36
+ * getTraceContext: () => {
37
+ * const span = trace.getActiveSpan();
38
+ * if (!span) return null;
39
+ * const ctx = span.spanContext();
40
+ * return { traceId: ctx.traceId, spanId: ctx.spanId, traceFlags: ctx.traceFlags };
41
+ * },
42
+ * });
43
+ *
44
+ * // 3. Setup interceptors (enables telemetry header injection)
45
+ * setupInterceptors();
46
+ * ```
47
+ */
48
+ export declare function setupInterceptors(): void;
49
+ /**
50
+ * Remove interceptor integration and restore original configuration
51
+ */
52
+ export declare function teardownInterceptors(): void;
53
+ /**
54
+ * Check if interceptors are currently set up
55
+ */
56
+ export declare function areInterceptorsSetup(): boolean;
57
+ //# sourceMappingURL=request-with-interceptors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-with-interceptors.d.ts","sourceRoot":"","sources":["../src/request-with-interceptors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AASH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CA8BxC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Enhanced request function with interceptor support
3
+ *
4
+ * This module provides a way to integrate interceptors with the generated
5
+ * request function. Since the generated code can't be modified, apps need
6
+ * to configure the OpenAPI object to use the enhanced request behavior.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { setupInterceptors } from '@teja-app/api-client';
11
+ *
12
+ * // Call this once at app initialization
13
+ * setupInterceptors();
14
+ *
15
+ * // Now all API calls will run through interceptors
16
+ * ```
17
+ */
18
+ import { OpenAPI } from "./generated/core/OpenAPI";
19
+ import { interceptors } from "./interceptors";
20
+ // Store the original HEADERS resolver
21
+ let originalHeaders = undefined;
22
+ /**
23
+ * Setup interceptors to work with the generated API client
24
+ *
25
+ * This patches the OpenAPI.HEADERS configuration to run request interceptors.
26
+ * Call this once at application startup after configuring telemetry.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * import { configureTelemetry, setupInterceptors, OpenAPI } from '@teja-app/api-client';
31
+ * import { trace } from '@opentelemetry/api';
32
+ *
33
+ * // 1. Configure the API client
34
+ * OpenAPI.BASE = 'https://api.example.com';
35
+ * OpenAPI.TOKEN = () => getAccessToken();
36
+ *
37
+ * // 2. Configure telemetry
38
+ * configureTelemetry({
39
+ * enabled: true,
40
+ * getTraceContext: () => {
41
+ * const span = trace.getActiveSpan();
42
+ * if (!span) return null;
43
+ * const ctx = span.spanContext();
44
+ * return { traceId: ctx.traceId, spanId: ctx.spanId, traceFlags: ctx.traceFlags };
45
+ * },
46
+ * });
47
+ *
48
+ * // 3. Setup interceptors (enables telemetry header injection)
49
+ * setupInterceptors();
50
+ * ```
51
+ */
52
+ export function setupInterceptors() {
53
+ // Store original HEADERS configuration
54
+ originalHeaders = OpenAPI.HEADERS;
55
+ // Patch HEADERS to run interceptors
56
+ OpenAPI.HEADERS = async (options) => {
57
+ // Get base headers from original configuration
58
+ let baseHeaders = {};
59
+ if (typeof originalHeaders === "function") {
60
+ baseHeaders = (await originalHeaders(options)) || {};
61
+ }
62
+ else if (originalHeaders) {
63
+ baseHeaders = originalHeaders;
64
+ }
65
+ // Create a temporary options object with current headers
66
+ const optionsWithHeaders = {
67
+ ...options,
68
+ headers: baseHeaders,
69
+ };
70
+ // Run through request interceptors
71
+ const interceptedOptions = await interceptors.runRequestInterceptors(optionsWithHeaders);
72
+ // Return the headers (which may have been modified by interceptors)
73
+ return interceptedOptions.headers || {};
74
+ };
75
+ }
76
+ /**
77
+ * Remove interceptor integration and restore original configuration
78
+ */
79
+ export function teardownInterceptors() {
80
+ if (originalHeaders !== undefined) {
81
+ OpenAPI.HEADERS = originalHeaders;
82
+ originalHeaders = undefined;
83
+ }
84
+ }
85
+ /**
86
+ * Check if interceptors are currently set up
87
+ */
88
+ export function areInterceptorsSetup() {
89
+ return originalHeaders !== undefined;
90
+ }
91
+ //# sourceMappingURL=request-with-interceptors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-with-interceptors.js","sourceRoot":"","sources":["../src/request-with-interceptors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,sCAAsC;AACtC,IAAI,eAAe,GAA2B,SAAS,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,iBAAiB;IAChC,uCAAuC;IACvC,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IAElC,oCAAoC;IACpC,OAAO,CAAC,OAAO,GAAG,KAAK,EACtB,OAA0B,EACQ,EAAE;QACpC,+CAA+C;QAC/C,IAAI,WAAW,GAA2B,EAAE,CAAC;QAE7C,IAAI,OAAO,eAAe,KAAK,UAAU,EAAE,CAAC;YAC3C,WAAW,GAAG,CAAC,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QACtD,CAAC;aAAM,IAAI,eAAe,EAAE,CAAC;YAC5B,WAAW,GAAG,eAAyC,CAAC;QACzD,CAAC;QAED,yDAAyD;QACzD,MAAM,kBAAkB,GAAsB;YAC7C,GAAG,OAAO;YACV,OAAO,EAAE,WAAW;SACpB,CAAC;QAEF,mCAAmC;QACnC,MAAM,kBAAkB,GACvB,MAAM,YAAY,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;QAE/D,oEAAoE;QACpE,OAAQ,kBAAkB,CAAC,OAAkC,IAAI,EAAE,CAAC;IACrE,CAAC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB;IACnC,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;QACnC,OAAO,CAAC,OAAO,GAAG,eAAe,CAAC;QAClC,eAAe,GAAG,SAAS,CAAC;IAC7B,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB;IACnC,OAAO,eAAe,KAAK,SAAS,CAAC;AACtC,CAAC"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Telemetry support for the API client
3
+ *
4
+ * This module provides lightweight telemetry integration that works with
5
+ * OpenTelemetry or any W3C Trace Context compatible tracing system.
6
+ *
7
+ * The api-client doesn't include OpenTelemetry as a dependency - apps
8
+ * provide the trace context through configuration or interceptors.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { configureTelemetry, createTelemetryInterceptor } from '@teja-app/api-client';
13
+ * import { trace } from '@opentelemetry/api';
14
+ *
15
+ * // Option 1: Configure with a trace context provider
16
+ * configureTelemetry({
17
+ * enabled: true,
18
+ * getTraceContext: () => {
19
+ * const span = trace.getActiveSpan();
20
+ * if (!span) return null;
21
+ * const ctx = span.spanContext();
22
+ * return {
23
+ * traceId: ctx.traceId,
24
+ * spanId: ctx.spanId,
25
+ * traceFlags: ctx.traceFlags,
26
+ * };
27
+ * },
28
+ * });
29
+ *
30
+ * // Option 2: Use the request interceptor directly
31
+ * import { interceptors } from '@teja-app/api-client';
32
+ * interceptors.addRequestInterceptor(createTelemetryInterceptor());
33
+ * ```
34
+ */
35
+ import type { ApiRequestOptions } from "./generated/core/ApiRequestOptions";
36
+ /**
37
+ * W3C Trace Context format
38
+ * @see https://www.w3.org/TR/trace-context/
39
+ */
40
+ export interface TraceContext {
41
+ /** 32-character hex trace ID */
42
+ traceId: string;
43
+ /** 16-character hex span/parent ID */
44
+ spanId: string;
45
+ /** Trace flags (1 = sampled) */
46
+ traceFlags?: number;
47
+ /** Optional trace state for vendor-specific data */
48
+ traceState?: string;
49
+ }
50
+ /**
51
+ * Function that returns the current trace context
52
+ */
53
+ export type TraceContextProvider = () => TraceContext | null;
54
+ /**
55
+ * Telemetry configuration options
56
+ */
57
+ export interface TelemetryConfig {
58
+ /** Enable/disable telemetry header injection */
59
+ enabled: boolean;
60
+ /** Function that returns current trace context */
61
+ getTraceContext?: TraceContextProvider;
62
+ /** Custom header name for trace parent (default: 'traceparent') */
63
+ traceParentHeader?: string;
64
+ /** Custom header name for trace state (default: 'tracestate') */
65
+ traceStateHeader?: string;
66
+ /** Include span attributes in request metadata */
67
+ includeAttributes?: boolean;
68
+ }
69
+ /**
70
+ * Request metadata with telemetry info
71
+ */
72
+ export interface RequestTelemetryMetadata {
73
+ traceId: string | null;
74
+ spanId: string | null;
75
+ startTime: number;
76
+ }
77
+ /**
78
+ * Configure telemetry for the API client
79
+ *
80
+ * @param config - Telemetry configuration options
81
+ * @returns Cleanup function to remove the telemetry interceptor
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * import { configureTelemetry } from '@teja-app/api-client';
86
+ * import { trace } from '@opentelemetry/api';
87
+ *
88
+ * const cleanup = configureTelemetry({
89
+ * enabled: true,
90
+ * getTraceContext: () => {
91
+ * const span = trace.getActiveSpan();
92
+ * if (!span) return null;
93
+ * const ctx = span.spanContext();
94
+ * return { traceId: ctx.traceId, spanId: ctx.spanId, traceFlags: ctx.traceFlags };
95
+ * },
96
+ * });
97
+ *
98
+ * // Later, to disable:
99
+ * cleanup();
100
+ * ```
101
+ */
102
+ export declare function configureTelemetry(config: TelemetryConfig): () => void;
103
+ /**
104
+ * Get the current telemetry configuration
105
+ */
106
+ export declare function getTelemetryConfig(): Readonly<TelemetryConfig>;
107
+ /**
108
+ * Check if telemetry is enabled
109
+ */
110
+ export declare function isTelemetryEnabled(): boolean;
111
+ /**
112
+ * Format trace context as W3C traceparent header value
113
+ * Format: {version}-{trace-id}-{parent-id}-{trace-flags}
114
+ *
115
+ * @see https://www.w3.org/TR/trace-context/#traceparent-header
116
+ */
117
+ export declare function formatTraceParent(context: TraceContext): string;
118
+ /**
119
+ * Parse a W3C traceparent header value
120
+ *
121
+ * @param header - The traceparent header value
122
+ * @returns Parsed trace context or null if invalid
123
+ */
124
+ export declare function parseTraceParent(header: string): TraceContext | null;
125
+ /**
126
+ * Create a request interceptor that adds W3C trace context headers
127
+ *
128
+ * @param config - Optional config override (uses global config if not provided)
129
+ * @returns Request interceptor function
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * import { interceptors, createTelemetryInterceptor } from '@teja-app/api-client';
134
+ *
135
+ * interceptors.addRequestInterceptor(
136
+ * createTelemetryInterceptor({
137
+ * enabled: true,
138
+ * getTraceContext: () => ({ traceId: '...', spanId: '...' }),
139
+ * })
140
+ * );
141
+ * ```
142
+ */
143
+ export declare function createTelemetryInterceptor(config?: Partial<TelemetryConfig>): (options: ApiRequestOptions) => ApiRequestOptions;
144
+ /**
145
+ * Get request metadata for a given request (for response correlation)
146
+ */
147
+ export declare function getRequestMetadata(method: string, url: string): RequestTelemetryMetadata | undefined;
148
+ /**
149
+ * Generate a random trace ID (32 hex characters)
150
+ * Use this if you need to create a new trace without OpenTelemetry
151
+ */
152
+ export declare function generateTraceId(): string;
153
+ /**
154
+ * Generate a random span ID (16 hex characters)
155
+ * Use this if you need to create a new span without OpenTelemetry
156
+ */
157
+ export declare function generateSpanId(): string;
158
+ /**
159
+ * Create a simple trace context without OpenTelemetry
160
+ * Useful for basic tracing when full OpenTelemetry is not needed
161
+ */
162
+ export declare function createSimpleTraceContext(): TraceContext;
163
+ /**
164
+ * Span attribute keys for consistent tagging
165
+ * These match OpenTelemetry semantic conventions
166
+ */
167
+ export declare const SpanAttributeKeys: {
168
+ readonly HTTP_METHOD: "http.method";
169
+ readonly HTTP_URL: "http.url";
170
+ readonly HTTP_STATUS_CODE: "http.status_code";
171
+ readonly HTTP_ROUTE: "http.route";
172
+ readonly API_SERVICE: "api.service";
173
+ readonly API_OPERATION: "api.operation";
174
+ readonly CLIENT_ID: "client.id";
175
+ readonly TENANT_ID: "tenant.id";
176
+ readonly USER_ID: "user.id";
177
+ readonly USER_ROLE: "user.role";
178
+ readonly ERROR_TYPE: "error.type";
179
+ readonly ERROR_MESSAGE: "error.message";
180
+ readonly ERROR_CODE: "error.code";
181
+ readonly MUTATION_TYPE: "mutation.type";
182
+ readonly MUTATION_ENTITY: "mutation.entity";
183
+ readonly MUTATION_KEY: "mutation.key";
184
+ };
185
+ export type SpanAttributeKey = (typeof SpanAttributeKeys)[keyof typeof SpanAttributeKeys];
186
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAG5E;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,YAAY,GAAG,IAAI,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kDAAkD;IAClD,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACxC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CAClB;AAUD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,IAAI,CAkBtE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,QAAQ,CAAC,eAAe,CAAC,CAE9D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAI/D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAiBpE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,0BAA0B,CACzC,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAC/B,CAAC,OAAO,EAAE,iBAAiB,KAAK,iBAAiB,CA6CnD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACT,wBAAwB,GAAG,SAAS,CAOtC;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAMxC;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,YAAY,CAMvD;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;CA0BpB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAC3B,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,CAAC"}
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Telemetry support for the API client
3
+ *
4
+ * This module provides lightweight telemetry integration that works with
5
+ * OpenTelemetry or any W3C Trace Context compatible tracing system.
6
+ *
7
+ * The api-client doesn't include OpenTelemetry as a dependency - apps
8
+ * provide the trace context through configuration or interceptors.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { configureTelemetry, createTelemetryInterceptor } from '@teja-app/api-client';
13
+ * import { trace } from '@opentelemetry/api';
14
+ *
15
+ * // Option 1: Configure with a trace context provider
16
+ * configureTelemetry({
17
+ * enabled: true,
18
+ * getTraceContext: () => {
19
+ * const span = trace.getActiveSpan();
20
+ * if (!span) return null;
21
+ * const ctx = span.spanContext();
22
+ * return {
23
+ * traceId: ctx.traceId,
24
+ * spanId: ctx.spanId,
25
+ * traceFlags: ctx.traceFlags,
26
+ * };
27
+ * },
28
+ * });
29
+ *
30
+ * // Option 2: Use the request interceptor directly
31
+ * import { interceptors } from '@teja-app/api-client';
32
+ * interceptors.addRequestInterceptor(createTelemetryInterceptor());
33
+ * ```
34
+ */
35
+ import { interceptors } from "./interceptors";
36
+ // Global telemetry configuration
37
+ let telemetryConfig = {
38
+ enabled: false,
39
+ };
40
+ // Store for request metadata (keyed by request URL + method)
41
+ const requestMetadata = new Map();
42
+ /**
43
+ * Configure telemetry for the API client
44
+ *
45
+ * @param config - Telemetry configuration options
46
+ * @returns Cleanup function to remove the telemetry interceptor
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { configureTelemetry } from '@teja-app/api-client';
51
+ * import { trace } from '@opentelemetry/api';
52
+ *
53
+ * const cleanup = configureTelemetry({
54
+ * enabled: true,
55
+ * getTraceContext: () => {
56
+ * const span = trace.getActiveSpan();
57
+ * if (!span) return null;
58
+ * const ctx = span.spanContext();
59
+ * return { traceId: ctx.traceId, spanId: ctx.spanId, traceFlags: ctx.traceFlags };
60
+ * },
61
+ * });
62
+ *
63
+ * // Later, to disable:
64
+ * cleanup();
65
+ * ```
66
+ */
67
+ export function configureTelemetry(config) {
68
+ telemetryConfig = { ...config };
69
+ if (config.enabled && config.getTraceContext) {
70
+ // Add the telemetry interceptor
71
+ const removeInterceptor = interceptors.addRequestInterceptor(createTelemetryInterceptor(config));
72
+ return () => {
73
+ telemetryConfig = { enabled: false };
74
+ removeInterceptor();
75
+ };
76
+ }
77
+ return () => {
78
+ telemetryConfig = { enabled: false };
79
+ };
80
+ }
81
+ /**
82
+ * Get the current telemetry configuration
83
+ */
84
+ export function getTelemetryConfig() {
85
+ return telemetryConfig;
86
+ }
87
+ /**
88
+ * Check if telemetry is enabled
89
+ */
90
+ export function isTelemetryEnabled() {
91
+ return telemetryConfig.enabled;
92
+ }
93
+ /**
94
+ * Format trace context as W3C traceparent header value
95
+ * Format: {version}-{trace-id}-{parent-id}-{trace-flags}
96
+ *
97
+ * @see https://www.w3.org/TR/trace-context/#traceparent-header
98
+ */
99
+ export function formatTraceParent(context) {
100
+ const version = "00";
101
+ const traceFlags = (context.traceFlags ?? 1).toString(16).padStart(2, "0");
102
+ return `${version}-${context.traceId}-${context.spanId}-${traceFlags}`;
103
+ }
104
+ /**
105
+ * Parse a W3C traceparent header value
106
+ *
107
+ * @param header - The traceparent header value
108
+ * @returns Parsed trace context or null if invalid
109
+ */
110
+ export function parseTraceParent(header) {
111
+ const parts = header.split("-");
112
+ if (parts.length !== 4)
113
+ return null;
114
+ const [version, traceId, spanId, flags] = parts;
115
+ // Validate format
116
+ if (version !== "00")
117
+ return null;
118
+ if (traceId.length !== 32)
119
+ return null;
120
+ if (spanId.length !== 16)
121
+ return null;
122
+ if (flags.length !== 2)
123
+ return null;
124
+ return {
125
+ traceId,
126
+ spanId,
127
+ traceFlags: parseInt(flags, 16),
128
+ };
129
+ }
130
+ /**
131
+ * Create a request interceptor that adds W3C trace context headers
132
+ *
133
+ * @param config - Optional config override (uses global config if not provided)
134
+ * @returns Request interceptor function
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * import { interceptors, createTelemetryInterceptor } from '@teja-app/api-client';
139
+ *
140
+ * interceptors.addRequestInterceptor(
141
+ * createTelemetryInterceptor({
142
+ * enabled: true,
143
+ * getTraceContext: () => ({ traceId: '...', spanId: '...' }),
144
+ * })
145
+ * );
146
+ * ```
147
+ */
148
+ export function createTelemetryInterceptor(config) {
149
+ return (options) => {
150
+ const effectiveConfig = config
151
+ ? { ...telemetryConfig, ...config }
152
+ : telemetryConfig;
153
+ if (!effectiveConfig.enabled || !effectiveConfig.getTraceContext) {
154
+ return options;
155
+ }
156
+ const traceContext = effectiveConfig.getTraceContext();
157
+ if (!traceContext) {
158
+ return options;
159
+ }
160
+ const traceParentHeader = effectiveConfig.traceParentHeader ?? "traceparent";
161
+ const traceStateHeader = effectiveConfig.traceStateHeader ?? "tracestate";
162
+ // Build headers with trace context
163
+ const headers = {
164
+ ...options.headers,
165
+ [traceParentHeader]: formatTraceParent(traceContext),
166
+ };
167
+ // Add tracestate if provided
168
+ if (traceContext.traceState) {
169
+ headers[traceStateHeader] = traceContext.traceState;
170
+ }
171
+ // Store metadata for response correlation
172
+ if (effectiveConfig.includeAttributes) {
173
+ const requestKey = `${options.method}:${options.url}`;
174
+ requestMetadata.set(requestKey, {
175
+ traceId: traceContext.traceId,
176
+ spanId: traceContext.spanId,
177
+ startTime: Date.now(),
178
+ });
179
+ }
180
+ return {
181
+ ...options,
182
+ headers,
183
+ };
184
+ };
185
+ }
186
+ /**
187
+ * Get request metadata for a given request (for response correlation)
188
+ */
189
+ export function getRequestMetadata(method, url) {
190
+ const key = `${method}:${url}`;
191
+ const metadata = requestMetadata.get(key);
192
+ if (metadata) {
193
+ requestMetadata.delete(key); // Clean up after retrieval
194
+ }
195
+ return metadata;
196
+ }
197
+ /**
198
+ * Generate a random trace ID (32 hex characters)
199
+ * Use this if you need to create a new trace without OpenTelemetry
200
+ */
201
+ export function generateTraceId() {
202
+ const bytes = new Uint8Array(16);
203
+ crypto.getRandomValues(bytes);
204
+ return Array.from(bytes)
205
+ .map((b) => b.toString(16).padStart(2, "0"))
206
+ .join("");
207
+ }
208
+ /**
209
+ * Generate a random span ID (16 hex characters)
210
+ * Use this if you need to create a new span without OpenTelemetry
211
+ */
212
+ export function generateSpanId() {
213
+ const bytes = new Uint8Array(8);
214
+ crypto.getRandomValues(bytes);
215
+ return Array.from(bytes)
216
+ .map((b) => b.toString(16).padStart(2, "0"))
217
+ .join("");
218
+ }
219
+ /**
220
+ * Create a simple trace context without OpenTelemetry
221
+ * Useful for basic tracing when full OpenTelemetry is not needed
222
+ */
223
+ export function createSimpleTraceContext() {
224
+ return {
225
+ traceId: generateTraceId(),
226
+ spanId: generateSpanId(),
227
+ traceFlags: 1, // Sampled
228
+ };
229
+ }
230
+ /**
231
+ * Span attribute keys for consistent tagging
232
+ * These match OpenTelemetry semantic conventions
233
+ */
234
+ export const SpanAttributeKeys = {
235
+ // HTTP semantic conventions
236
+ HTTP_METHOD: "http.method",
237
+ HTTP_URL: "http.url",
238
+ HTTP_STATUS_CODE: "http.status_code",
239
+ HTTP_ROUTE: "http.route",
240
+ // API client specific
241
+ API_SERVICE: "api.service",
242
+ API_OPERATION: "api.operation",
243
+ // Application context
244
+ CLIENT_ID: "client.id",
245
+ TENANT_ID: "tenant.id",
246
+ USER_ID: "user.id",
247
+ USER_ROLE: "user.role",
248
+ // Error context
249
+ ERROR_TYPE: "error.type",
250
+ ERROR_MESSAGE: "error.message",
251
+ ERROR_CODE: "error.code",
252
+ // Mutation context (for React Query integration)
253
+ MUTATION_TYPE: "mutation.type",
254
+ MUTATION_ENTITY: "mutation.entity",
255
+ MUTATION_KEY: "mutation.key",
256
+ };
257
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teja-app/api-client",
3
- "version": "0.0.1-dev.20260124115708.06e82a3",
3
+ "version": "0.0.1-dev.20260125152414.0c955c4",
4
4
  "description": "TypeScript SDK for the Teja API",
5
5
  "author": "Teja App",
6
6
  "license": "MIT",