@glasstrace/sdk 0.0.1 → 0.1.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 +22 -0
- package/README.md +13 -0
- package/dist/adapters/drizzle.cjs +87 -0
- package/dist/adapters/drizzle.cjs.map +1 -0
- package/dist/adapters/drizzle.d.cts +28 -0
- package/dist/adapters/drizzle.d.ts +28 -0
- package/dist/adapters/drizzle.js +62 -0
- package/dist/adapters/drizzle.js.map +1 -0
- package/dist/chunk-BKMITIEZ.js +169 -0
- package/dist/chunk-BKMITIEZ.js.map +1 -0
- package/dist/cli/init.cjs +537 -0
- package/dist/cli/init.cjs.map +1 -0
- package/dist/cli/init.d.cts +21 -0
- package/dist/cli/init.d.ts +21 -0
- package/dist/cli/init.js +343 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/index.cjs +1407 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +357 -0
- package/dist/index.d.ts +357 -0
- package/dist/index.js +1191 -0
- package/dist/index.js.map +1 -0
- package/package.json +91 -8
- package/index.js +0 -1
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { SdkDiagnosticCode, GlasstraceEnvVars, GlasstraceOptions, SessionId, AnonApiKey, CaptureConfig, SdkInitResponse, ImportGraphPayload, SdkHealthReport, SourceMapUploadResponse } from '@glasstrace/protocol';
|
|
2
|
+
import { Context } from '@opentelemetry/api';
|
|
3
|
+
import { SpanProcessor, Span, ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
4
|
+
import { ExportResult } from '@opentelemetry/core';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal SDK error class with a typed diagnostic code.
|
|
8
|
+
* Caught at the boundary and converted to a log message + diagnostic entry.
|
|
9
|
+
* Never thrown to the developer.
|
|
10
|
+
*/
|
|
11
|
+
declare class SdkError extends Error {
|
|
12
|
+
readonly code: SdkDiagnosticCode;
|
|
13
|
+
constructor(code: SdkDiagnosticCode, message: string, cause?: Error);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Resolved configuration after merging explicit options with environment variables.
|
|
18
|
+
*/
|
|
19
|
+
interface ResolvedConfig {
|
|
20
|
+
apiKey: string | undefined;
|
|
21
|
+
endpoint: string;
|
|
22
|
+
forceEnable: boolean;
|
|
23
|
+
verbose: boolean;
|
|
24
|
+
environment: string | undefined;
|
|
25
|
+
coverageMapEnabled: boolean;
|
|
26
|
+
nodeEnv: string | undefined;
|
|
27
|
+
vercelEnv: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Reads all recognized Glasstrace environment variables from process.env.
|
|
31
|
+
* Returns undefined for any variable not set. Never throws.
|
|
32
|
+
*/
|
|
33
|
+
declare function readEnvVars(): GlasstraceEnvVars;
|
|
34
|
+
/**
|
|
35
|
+
* Merges explicit GlasstraceOptions with environment variables.
|
|
36
|
+
* Explicit options take precedence over environment variables.
|
|
37
|
+
*/
|
|
38
|
+
declare function resolveConfig(options?: GlasstraceOptions): ResolvedConfig;
|
|
39
|
+
/**
|
|
40
|
+
* Returns true when the SDK should be inactive (production detected without force-enable).
|
|
41
|
+
* Logic order:
|
|
42
|
+
* 1. forceEnable === true → return false (override)
|
|
43
|
+
* 2. NODE_ENV === 'production' → return true
|
|
44
|
+
* 3. VERCEL_ENV === 'production' → return true
|
|
45
|
+
* 4. Otherwise → return false
|
|
46
|
+
*/
|
|
47
|
+
declare function isProductionDisabled(config: ResolvedConfig): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Returns true when no API key is configured (anonymous mode).
|
|
50
|
+
* Treats undefined, empty string, whitespace-only, and gt_anon_* keys as anonymous.
|
|
51
|
+
*/
|
|
52
|
+
declare function isAnonymousMode(config: ResolvedConfig): boolean;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Derives a deterministic session ID from the given inputs using SHA-256.
|
|
56
|
+
* The hash is truncated to 16 hex characters and parsed through SessionIdSchema.
|
|
57
|
+
*
|
|
58
|
+
* @param apiKey - The project's API key (or anonymous placeholder).
|
|
59
|
+
* @param origin - The origin string identifying the deployment environment.
|
|
60
|
+
* @param date - UTC date as YYYY-MM-DD.
|
|
61
|
+
* @param windowIndex - Zero-based index of the 4-hour activity window within the day.
|
|
62
|
+
* @returns A 16-character hex SessionId.
|
|
63
|
+
*/
|
|
64
|
+
declare function deriveSessionId(apiKey: string, origin: string, date: string, windowIndex: number): SessionId;
|
|
65
|
+
/**
|
|
66
|
+
* Returns the origin string for the current process.
|
|
67
|
+
* If GLASSTRACE_ENV is set, returns that value.
|
|
68
|
+
* Otherwise returns `localhost:{PORT}` (PORT defaults to 3000).
|
|
69
|
+
*
|
|
70
|
+
* @returns The origin string used as a session derivation input.
|
|
71
|
+
*/
|
|
72
|
+
declare function getOrigin(): string;
|
|
73
|
+
/**
|
|
74
|
+
* Returns the current UTC date as a YYYY-MM-DD string.
|
|
75
|
+
*
|
|
76
|
+
* @returns The UTC date formatted as "YYYY-MM-DD".
|
|
77
|
+
*/
|
|
78
|
+
declare function getDateString(): string;
|
|
79
|
+
/**
|
|
80
|
+
* Tracks the current session state with 4-hour window tracking.
|
|
81
|
+
* Instantiated once by the orchestrator.
|
|
82
|
+
*/
|
|
83
|
+
declare class SessionManager {
|
|
84
|
+
private windowIndex;
|
|
85
|
+
private lastActivityTimestamp;
|
|
86
|
+
private lastDate;
|
|
87
|
+
private lastApiKey;
|
|
88
|
+
private currentSessionId;
|
|
89
|
+
/**
|
|
90
|
+
* Returns the current session ID, deriving a new one if:
|
|
91
|
+
* - More than 4 hours have elapsed since last activity
|
|
92
|
+
* - The UTC date has changed (resets window index to 0)
|
|
93
|
+
* - The API key has changed (e.g., deferred anonymous key swap)
|
|
94
|
+
* - This is the first call
|
|
95
|
+
*
|
|
96
|
+
* @param apiKey - The project's API key used in session derivation.
|
|
97
|
+
* @returns The current or newly derived SessionId.
|
|
98
|
+
*/
|
|
99
|
+
getSessionId(apiKey: string): SessionId;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The set of recognized fetch target categories.
|
|
104
|
+
*/
|
|
105
|
+
type FetchTarget = "supabase" | "stripe" | "internal" | "unknown";
|
|
106
|
+
/**
|
|
107
|
+
* Classifies an outbound fetch target URL into a known category.
|
|
108
|
+
* Classification is case-insensitive and based on the URL hostname.
|
|
109
|
+
* Uses dot-boundary matching to avoid false positives (e.g. evilstripe.com).
|
|
110
|
+
*
|
|
111
|
+
* Returns one of: 'supabase', 'stripe', 'internal', or 'unknown'.
|
|
112
|
+
*/
|
|
113
|
+
declare function classifyFetchTarget(url: string): FetchTarget;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Reads an existing anonymous key from the filesystem.
|
|
117
|
+
* Returns the key if valid, or null if:
|
|
118
|
+
* - The file does not exist
|
|
119
|
+
* - The file content is invalid
|
|
120
|
+
* - An I/O error occurs
|
|
121
|
+
*/
|
|
122
|
+
declare function readAnonKey(projectRoot?: string): Promise<AnonApiKey | null>;
|
|
123
|
+
/**
|
|
124
|
+
* Gets an existing anonymous key from the filesystem, or creates a new one.
|
|
125
|
+
*
|
|
126
|
+
* - If file exists and contains a valid key, returns it
|
|
127
|
+
* - If file does not exist or content is invalid, generates a new key via createAnonApiKey()
|
|
128
|
+
* - Writes the new key to `.glasstrace/anon_key`, creating the directory if needed
|
|
129
|
+
* - On file write failure: logs a warning, caches an ephemeral in-memory key so
|
|
130
|
+
* repeated calls in the same process return the same key
|
|
131
|
+
*/
|
|
132
|
+
declare function getOrCreateAnonKey(projectRoot?: string): Promise<AnonApiKey>;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Reads and validates a cached config file from `.glasstrace/config`.
|
|
136
|
+
* Returns the parsed `SdkInitResponse` or `null` on any failure.
|
|
137
|
+
*/
|
|
138
|
+
declare function loadCachedConfig(projectRoot?: string): SdkInitResponse | null;
|
|
139
|
+
/**
|
|
140
|
+
* Persists the init response to `.glasstrace/config`.
|
|
141
|
+
* On failure, logs a warning and continues.
|
|
142
|
+
*/
|
|
143
|
+
declare function saveCachedConfig(response: SdkInitResponse, projectRoot?: string): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* Sends a POST request to `/v1/sdk/init`.
|
|
146
|
+
* Validates the response against `SdkInitResponseSchema`.
|
|
147
|
+
*/
|
|
148
|
+
declare function sendInitRequest(config: ResolvedConfig, anonKey: AnonApiKey | null, sdkVersion: string, importGraph?: ImportGraphPayload, healthReport?: SdkHealthReport, diagnostics?: Array<{
|
|
149
|
+
code: SdkDiagnosticCode;
|
|
150
|
+
message: string;
|
|
151
|
+
timestamp: number;
|
|
152
|
+
}>, signal?: AbortSignal): Promise<SdkInitResponse>;
|
|
153
|
+
/**
|
|
154
|
+
* Orchestrates the full init flow: send request, update config, cache result.
|
|
155
|
+
* This function MUST NOT throw.
|
|
156
|
+
*/
|
|
157
|
+
declare function performInit(config: ResolvedConfig, anonKey: AnonApiKey | null, sdkVersion: string): Promise<void>;
|
|
158
|
+
/**
|
|
159
|
+
* Returns the current capture config from the three-tier fallback chain:
|
|
160
|
+
* 1. In-memory config from latest init response
|
|
161
|
+
* 2. File cache
|
|
162
|
+
* 3. DEFAULT_CAPTURE_CONFIG
|
|
163
|
+
*/
|
|
164
|
+
declare function getActiveConfig(): CaptureConfig;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Lightweight SpanProcessor that delegates to a wrapped processor.
|
|
168
|
+
*
|
|
169
|
+
* All glasstrace.* attribute enrichment has been moved to {@link GlasstraceExporter}
|
|
170
|
+
* (see enriching-exporter.ts), which enriches spans at export time. This resolves:
|
|
171
|
+
* - Cold-start spans are buffered in the exporter, not dropped
|
|
172
|
+
* - Vercel's CompositeSpanProcessor skips onEnding(); the exporter doesn't need it
|
|
173
|
+
* - Session ID is computed at export time with the resolved API key
|
|
174
|
+
*
|
|
175
|
+
* This class is retained for backward compatibility. New code should use
|
|
176
|
+
* GlasstraceExporter directly.
|
|
177
|
+
*
|
|
178
|
+
* @deprecated Use GlasstraceExporter for span enrichment. This processor is now a pass-through.
|
|
179
|
+
*/
|
|
180
|
+
declare class GlasstraceSpanProcessor implements SpanProcessor {
|
|
181
|
+
private readonly wrappedProcessor;
|
|
182
|
+
constructor(wrappedProcessor: SpanProcessor, _sessionManager?: SessionManager, _apiKey?: string | (() => string), _getConfig?: () => CaptureConfig, _environment?: string);
|
|
183
|
+
onStart(span: Span, parentContext: Context): void;
|
|
184
|
+
onEnd(readableSpan: ReadableSpan): void;
|
|
185
|
+
shutdown(): Promise<void>;
|
|
186
|
+
forceFlush(): Promise<void>;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Options for constructing a {@link GlasstraceExporter}.
|
|
191
|
+
*/
|
|
192
|
+
interface GlasstraceExporterOptions {
|
|
193
|
+
getApiKey: () => string;
|
|
194
|
+
sessionManager: SessionManager;
|
|
195
|
+
getConfig: () => CaptureConfig;
|
|
196
|
+
environment: string | undefined;
|
|
197
|
+
endpointUrl: string;
|
|
198
|
+
createDelegate: ((url: string, headers: Record<string, string>) => SpanExporter) | null;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* A SpanExporter that enriches spans with glasstrace.* attributes at export
|
|
202
|
+
* time, then delegates to a real OTLP exporter.
|
|
203
|
+
*
|
|
204
|
+
* This design resolves three issues:
|
|
205
|
+
* - Spans emitted before the API key resolves are buffered (not dropped)
|
|
206
|
+
* and flushed once the key is available.
|
|
207
|
+
* - Enrichment happens in the exporter (not onEnding), so it works
|
|
208
|
+
* on Vercel where CompositeSpanProcessor does not forward onEnding().
|
|
209
|
+
* - Session ID is computed at export time using the resolved API key,
|
|
210
|
+
* not the "pending" placeholder.
|
|
211
|
+
*/
|
|
212
|
+
declare class GlasstraceExporter implements SpanExporter {
|
|
213
|
+
private readonly getApiKey;
|
|
214
|
+
private readonly sessionManager;
|
|
215
|
+
private readonly getConfig;
|
|
216
|
+
private readonly environment;
|
|
217
|
+
private readonly endpointUrl;
|
|
218
|
+
private readonly createDelegateFn;
|
|
219
|
+
private delegate;
|
|
220
|
+
private pendingBatches;
|
|
221
|
+
private pendingSpanCount;
|
|
222
|
+
private overflowLogged;
|
|
223
|
+
constructor(options: GlasstraceExporterOptions);
|
|
224
|
+
export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
|
|
225
|
+
/**
|
|
226
|
+
* Called when the API key transitions from "pending" to a resolved value.
|
|
227
|
+
* Creates the delegate exporter and flushes all buffered spans.
|
|
228
|
+
*/
|
|
229
|
+
notifyKeyResolved(): void;
|
|
230
|
+
shutdown(): Promise<void>;
|
|
231
|
+
forceFlush(): Promise<void>;
|
|
232
|
+
/**
|
|
233
|
+
* Enriches a ReadableSpan with all glasstrace.* attributes.
|
|
234
|
+
* Returns a new ReadableSpan wrapper; the original span is not mutated.
|
|
235
|
+
* Each attribute derivation is wrapped in its own try-catch for partial
|
|
236
|
+
* enrichment resilience.
|
|
237
|
+
*/
|
|
238
|
+
private enrichSpan;
|
|
239
|
+
/**
|
|
240
|
+
* Lazily creates the delegate OTLP exporter once the API key is resolved.
|
|
241
|
+
*/
|
|
242
|
+
private ensureDelegate;
|
|
243
|
+
/**
|
|
244
|
+
* Buffers enriched spans while the API key is pending.
|
|
245
|
+
* Evicts oldest batches if the buffer exceeds MAX_PENDING_SPANS.
|
|
246
|
+
*/
|
|
247
|
+
private bufferSpans;
|
|
248
|
+
/**
|
|
249
|
+
* Flushes all buffered spans through the delegate exporter.
|
|
250
|
+
* Called when the API key resolves.
|
|
251
|
+
*/
|
|
252
|
+
private flushPending;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Creates a request handler for the `/__glasstrace/config` discovery endpoint.
|
|
257
|
+
*
|
|
258
|
+
* The returned handler checks if the request URL path is `/__glasstrace/config`.
|
|
259
|
+
* If not, returns `null` (pass-through). If it matches, returns a `DiscoveryResponse`
|
|
260
|
+
* with the anonymous key and current session ID.
|
|
261
|
+
*
|
|
262
|
+
* The triple guard (anonymous + dev + active) is enforced by the caller,
|
|
263
|
+
* not by this module. If the handler is registered, it serves.
|
|
264
|
+
*/
|
|
265
|
+
declare function createDiscoveryHandler(getAnonKey: () => Promise<AnonApiKey | null>, getSessionId: () => SessionId): (request: Request) => Promise<Response | null>;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* The primary SDK entry point called by developers in their `instrumentation.ts`.
|
|
269
|
+
* Orchestrates OTel setup, span processor, init client, anon key, and discovery endpoint.
|
|
270
|
+
*
|
|
271
|
+
* This function is synchronous and MUST NOT throw. The developer's server is never blocked.
|
|
272
|
+
* Background work (key resolution, init call) happens via fire-and-forget promises.
|
|
273
|
+
*
|
|
274
|
+
* @param options - Optional SDK configuration. Environment variables are used as fallbacks.
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* ```ts
|
|
278
|
+
* // instrumentation.ts
|
|
279
|
+
* import { registerGlasstrace } from "@glasstrace/sdk";
|
|
280
|
+
* registerGlasstrace(); // uses env vars
|
|
281
|
+
* ```
|
|
282
|
+
*/
|
|
283
|
+
declare function registerGlasstrace(options?: GlasstraceOptions): void;
|
|
284
|
+
/**
|
|
285
|
+
* Returns the registered discovery handler, or null if not registered.
|
|
286
|
+
*/
|
|
287
|
+
declare function getDiscoveryHandler(): ((request: Request) => Promise<Response | null>) | null;
|
|
288
|
+
|
|
289
|
+
type NextConfig = Record<string, unknown>;
|
|
290
|
+
/**
|
|
291
|
+
* Wraps the developer's Next.js config to enable source map generation
|
|
292
|
+
* and upload .map files to the ingestion API at build time.
|
|
293
|
+
*
|
|
294
|
+
* The build NEVER fails because of Glasstrace — all errors are caught
|
|
295
|
+
* and logged as warnings.
|
|
296
|
+
*
|
|
297
|
+
* @param nextConfig - The developer's existing Next.js configuration object.
|
|
298
|
+
* @returns A new config object with source map generation and upload enabled.
|
|
299
|
+
*/
|
|
300
|
+
declare function withGlasstraceConfig(nextConfig: NextConfig): NextConfig;
|
|
301
|
+
|
|
302
|
+
interface SourceMapEntry {
|
|
303
|
+
filePath: string;
|
|
304
|
+
content: string;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Recursively finds all .map files in the given build directory.
|
|
308
|
+
* Returns relative paths and file contents.
|
|
309
|
+
*/
|
|
310
|
+
declare function collectSourceMaps(buildDir: string): Promise<SourceMapEntry[]>;
|
|
311
|
+
/**
|
|
312
|
+
* Computes a build hash for source map uploads.
|
|
313
|
+
*
|
|
314
|
+
* First tries `git rev-parse HEAD` to get the git commit SHA.
|
|
315
|
+
* On failure, falls back to a deterministic content hash:
|
|
316
|
+
* sort source map file paths alphabetically, concatenate each as
|
|
317
|
+
* `{relativePath}\n{fileLength}\n{fileContent}`, then SHA-256 the result.
|
|
318
|
+
*/
|
|
319
|
+
declare function computeBuildHash(maps?: SourceMapEntry[]): Promise<string>;
|
|
320
|
+
/**
|
|
321
|
+
* Uploads source maps to the ingestion API.
|
|
322
|
+
*
|
|
323
|
+
* POSTs to `{endpoint}/v1/source-maps` with the API key, build hash,
|
|
324
|
+
* and file entries. Validates the response against SourceMapUploadResponseSchema.
|
|
325
|
+
*/
|
|
326
|
+
declare function uploadSourceMaps(apiKey: string, endpoint: string, buildHash: string, maps: SourceMapEntry[]): Promise<SourceMapUploadResponse>;
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Discovers test files by scanning the project directory for conventional
|
|
330
|
+
* test file patterns. Also reads vitest/jest config files for custom include
|
|
331
|
+
* patterns and merges them with the defaults. Excludes node_modules/ and .next/.
|
|
332
|
+
*
|
|
333
|
+
* @param projectRoot - Absolute path to the project root directory.
|
|
334
|
+
* @returns Relative POSIX paths from projectRoot, capped at {@link MAX_TEST_FILES}.
|
|
335
|
+
*/
|
|
336
|
+
declare function discoverTestFiles(projectRoot: string): Promise<string[]>;
|
|
337
|
+
/**
|
|
338
|
+
* Extracts import paths from file content using regex.
|
|
339
|
+
* Handles ES module imports, CommonJS requires, and dynamic imports.
|
|
340
|
+
*
|
|
341
|
+
* @param fileContent - The full text content of a TypeScript/JavaScript file.
|
|
342
|
+
* @returns An array of import path strings as written in the source (e.g. "./foo", "react").
|
|
343
|
+
*/
|
|
344
|
+
declare function extractImports(fileContent: string): string[];
|
|
345
|
+
/**
|
|
346
|
+
* Builds an import graph mapping test file paths to their imported module paths.
|
|
347
|
+
*
|
|
348
|
+
* Discovers test files, reads each, extracts imports, and builds a graph.
|
|
349
|
+
* Computes a deterministic buildHash from the serialized graph content.
|
|
350
|
+
* Individual file read failures are silently skipped.
|
|
351
|
+
*
|
|
352
|
+
* @param projectRoot - Absolute path to the project root directory.
|
|
353
|
+
* @returns An {@link ImportGraphPayload} containing the graph and a deterministic buildHash.
|
|
354
|
+
*/
|
|
355
|
+
declare function buildImportGraph(projectRoot: string): Promise<ImportGraphPayload>;
|
|
356
|
+
|
|
357
|
+
export { type FetchTarget, GlasstraceExporter, type GlasstraceExporterOptions, GlasstraceSpanProcessor, type ResolvedConfig, SdkError, SessionManager, type SourceMapEntry, buildImportGraph, classifyFetchTarget, collectSourceMaps, computeBuildHash, createDiscoveryHandler, deriveSessionId, discoverTestFiles, extractImports, getActiveConfig, getDateString, getDiscoveryHandler, getOrCreateAnonKey, getOrigin, isAnonymousMode, isProductionDisabled, loadCachedConfig, performInit, readAnonKey, readEnvVars, registerGlasstrace, resolveConfig, saveCachedConfig, sendInitRequest, uploadSourceMaps, withGlasstraceConfig };
|