@glasstrace/sdk 0.14.1 → 0.15.1

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 (40) hide show
  1. package/dist/{chunk-ERGEG4ZQ.js → chunk-2LDBR3F3.js} +16 -3
  2. package/dist/chunk-2LDBR3F3.js.map +1 -0
  3. package/dist/chunk-A2AZL6MZ.js +309 -0
  4. package/dist/chunk-A2AZL6MZ.js.map +1 -0
  5. package/dist/{chunk-ARAOZCZT.js → chunk-ROFOJQWN.js} +118 -16
  6. package/dist/chunk-ROFOJQWN.js.map +1 -0
  7. package/dist/{chunk-WV3NIPWJ.js → chunk-ZNOD6FC7.js} +18 -276
  8. package/dist/chunk-ZNOD6FC7.js.map +1 -0
  9. package/dist/cli/init.cjs +458 -115
  10. package/dist/cli/init.cjs.map +1 -1
  11. package/dist/cli/init.d.cts +33 -1
  12. package/dist/cli/init.d.ts +33 -1
  13. package/dist/cli/init.js +144 -42
  14. package/dist/cli/init.js.map +1 -1
  15. package/dist/cli/mcp-add.cjs.map +1 -1
  16. package/dist/cli/mcp-add.js +4 -2
  17. package/dist/cli/mcp-add.js.map +1 -1
  18. package/dist/cli/uninit.cjs +181 -60
  19. package/dist/cli/uninit.cjs.map +1 -1
  20. package/dist/cli/uninit.d.cts +38 -8
  21. package/dist/cli/uninit.d.ts +38 -8
  22. package/dist/cli/uninit.js +6 -3
  23. package/dist/cli/validate.cjs +135 -0
  24. package/dist/cli/validate.cjs.map +1 -0
  25. package/dist/cli/validate.d.cts +60 -0
  26. package/dist/cli/validate.d.ts +60 -0
  27. package/dist/cli/validate.js +103 -0
  28. package/dist/cli/validate.js.map +1 -0
  29. package/dist/index.cjs +123 -47
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +45 -5
  32. package/dist/index.d.ts +45 -5
  33. package/dist/index.js +109 -46
  34. package/dist/index.js.map +1 -1
  35. package/dist/{source-map-uploader-W6VPGY26.js → source-map-uploader-3GWUQDTS.js} +6 -2
  36. package/package.json +6 -4
  37. package/dist/chunk-ARAOZCZT.js.map +0 -1
  38. package/dist/chunk-ERGEG4ZQ.js.map +0 -1
  39. package/dist/chunk-WV3NIPWJ.js.map +0 -1
  40. /package/dist/{source-map-uploader-W6VPGY26.js.map → source-map-uploader-3GWUQDTS.js.map} +0 -0
package/dist/index.d.cts CHANGED
@@ -278,9 +278,15 @@ declare function getOrCreateAnonKey(projectRoot?: string): Promise<AnonApiKey>;
278
278
  */
279
279
  declare function loadCachedConfig(projectRoot?: string): SdkInitResponse | null;
280
280
  /**
281
- * Persists the init response to `.glasstrace/config`.
282
- * Silently skipped when `node:fs` is unavailable (non-Node environments).
283
- * On I/O failure, logs a warning and continues.
281
+ * Persists the init response to `.glasstrace/config` using atomic
282
+ * write-temp + rename semantics. Silently skipped when `node:fs` is
283
+ * unavailable (non-Node environments). On I/O failure, logs a warning.
284
+ *
285
+ * Atomicity: the payload is written to `.glasstrace/config.tmp` and then
286
+ * renamed into place. `rename` is atomic on POSIX filesystems, so readers
287
+ * either see the previous valid config or the new valid config — never a
288
+ * truncated or partially-written file (DISC-1247 Scenario 5). If the
289
+ * rename fails, the temp file is cleaned up on a best-effort basis.
284
290
  */
285
291
  declare function saveCachedConfig(response: SdkInitResponse, projectRoot?: string): Promise<void>;
286
292
  /**
@@ -488,7 +494,25 @@ declare function registerGlasstrace(options?: GlasstraceOptions): void;
488
494
  */
489
495
  declare function getDiscoveryHandler(): ((request: Request) => Promise<Response | null>) | null;
490
496
 
491
- type NextConfig = Record<string, unknown>;
497
+ /**
498
+ * Structural view of Next.js's `NextConfig`. The SDK does not import Next's
499
+ * type directly because Next is not a peer dependency — this wrapper must
500
+ * type-check regardless of which Next.js version the consumer has installed.
501
+ *
502
+ * The constraint is `object` rather than `Record<string, unknown>` because
503
+ * Next's actual `NextConfig` is an interface *without* a string index
504
+ * signature. Requiring `[key: string]: unknown` would fail the assignability
505
+ * check that caused DISC-1256, reported by Next 16 consumers as:
506
+ * > Argument of type 'NextConfig' is not assignable to parameter of type
507
+ * > 'NextConfig'. Index signature for type 'string' is missing in type
508
+ * > 'NextConfig'.
509
+ *
510
+ * `object` accepts every non-primitive value, which is what the wrapper
511
+ * actually handles at runtime (it shallow-copies the input and reads a few
512
+ * known properties defensively). Combined with the generic signature on
513
+ * `withGlasstraceConfig`, callers preserve their exact config subtype.
514
+ */
515
+ type NextConfig = object;
492
516
  /**
493
517
  * Wraps the developer's Next.js config to enable source map generation
494
518
  * and upload .map files to the ingestion API at build time.
@@ -496,10 +520,26 @@ type NextConfig = Record<string, unknown>;
496
520
  * The build NEVER fails because of Glasstrace — all errors are caught
497
521
  * and logged as warnings.
498
522
  *
523
+ * ## Turbopack
524
+ *
525
+ * Next.js 16 made Turbopack the default bundler for `next build`, and Next
526
+ * rejects configs that set `webpack` without also setting `turbopack`. This
527
+ * wrapper therefore seeds an empty `turbopack: {}` when the user has not set
528
+ * one themselves, preserving existing behaviour for explicit Turbopack configs.
529
+ *
530
+ * **Source-map upload is currently webpack-only.** Under Turbopack the build
531
+ * succeeds, but the afterEmit hook that collects and uploads `.map` files does
532
+ * not fire. Run `next build --webpack` to get source-map uploads, or wait for
533
+ * a follow-up release that ports the plugin to Turbopack.
534
+ *
499
535
  * @param nextConfig - The developer's existing Next.js configuration object.
500
536
  * @returns A new config object with source map generation and upload enabled.
537
+ * The return type mirrors the input type so that caller-side config
538
+ * properties are preserved. The `object` constraint (rather than
539
+ * `Record<string, unknown>`) is what makes the wrapper accept Next's
540
+ * real `NextConfig` interface (DISC-1256).
501
541
  */
502
- declare function withGlasstraceConfig(nextConfig: NextConfig): NextConfig;
542
+ declare function withGlasstraceConfig<T extends NextConfig>(nextConfig: T): T;
503
543
 
504
544
  /**
505
545
  * Returns true when the SDK is in ACTIVE or ACTIVE_DEGRADED state.
package/dist/index.d.ts CHANGED
@@ -278,9 +278,15 @@ declare function getOrCreateAnonKey(projectRoot?: string): Promise<AnonApiKey>;
278
278
  */
279
279
  declare function loadCachedConfig(projectRoot?: string): SdkInitResponse | null;
280
280
  /**
281
- * Persists the init response to `.glasstrace/config`.
282
- * Silently skipped when `node:fs` is unavailable (non-Node environments).
283
- * On I/O failure, logs a warning and continues.
281
+ * Persists the init response to `.glasstrace/config` using atomic
282
+ * write-temp + rename semantics. Silently skipped when `node:fs` is
283
+ * unavailable (non-Node environments). On I/O failure, logs a warning.
284
+ *
285
+ * Atomicity: the payload is written to `.glasstrace/config.tmp` and then
286
+ * renamed into place. `rename` is atomic on POSIX filesystems, so readers
287
+ * either see the previous valid config or the new valid config — never a
288
+ * truncated or partially-written file (DISC-1247 Scenario 5). If the
289
+ * rename fails, the temp file is cleaned up on a best-effort basis.
284
290
  */
285
291
  declare function saveCachedConfig(response: SdkInitResponse, projectRoot?: string): Promise<void>;
286
292
  /**
@@ -488,7 +494,25 @@ declare function registerGlasstrace(options?: GlasstraceOptions): void;
488
494
  */
489
495
  declare function getDiscoveryHandler(): ((request: Request) => Promise<Response | null>) | null;
490
496
 
491
- type NextConfig = Record<string, unknown>;
497
+ /**
498
+ * Structural view of Next.js's `NextConfig`. The SDK does not import Next's
499
+ * type directly because Next is not a peer dependency — this wrapper must
500
+ * type-check regardless of which Next.js version the consumer has installed.
501
+ *
502
+ * The constraint is `object` rather than `Record<string, unknown>` because
503
+ * Next's actual `NextConfig` is an interface *without* a string index
504
+ * signature. Requiring `[key: string]: unknown` would fail the assignability
505
+ * check that caused DISC-1256, reported by Next 16 consumers as:
506
+ * > Argument of type 'NextConfig' is not assignable to parameter of type
507
+ * > 'NextConfig'. Index signature for type 'string' is missing in type
508
+ * > 'NextConfig'.
509
+ *
510
+ * `object` accepts every non-primitive value, which is what the wrapper
511
+ * actually handles at runtime (it shallow-copies the input and reads a few
512
+ * known properties defensively). Combined with the generic signature on
513
+ * `withGlasstraceConfig`, callers preserve their exact config subtype.
514
+ */
515
+ type NextConfig = object;
492
516
  /**
493
517
  * Wraps the developer's Next.js config to enable source map generation
494
518
  * and upload .map files to the ingestion API at build time.
@@ -496,10 +520,26 @@ type NextConfig = Record<string, unknown>;
496
520
  * The build NEVER fails because of Glasstrace — all errors are caught
497
521
  * and logged as warnings.
498
522
  *
523
+ * ## Turbopack
524
+ *
525
+ * Next.js 16 made Turbopack the default bundler for `next build`, and Next
526
+ * rejects configs that set `webpack` without also setting `turbopack`. This
527
+ * wrapper therefore seeds an empty `turbopack: {}` when the user has not set
528
+ * one themselves, preserving existing behaviour for explicit Turbopack configs.
529
+ *
530
+ * **Source-map upload is currently webpack-only.** Under Turbopack the build
531
+ * succeeds, but the afterEmit hook that collects and uploads `.map` files does
532
+ * not fire. Run `next build --webpack` to get source-map uploads, or wait for
533
+ * a follow-up release that ports the plugin to Turbopack.
534
+ *
499
535
  * @param nextConfig - The developer's existing Next.js configuration object.
500
536
  * @returns A new config object with source map generation and upload enabled.
537
+ * The return type mirrors the input type so that caller-side config
538
+ * properties are preserved. The `object` constraint (rather than
539
+ * `Record<string, unknown>`) is what makes the wrapper accept Next's
540
+ * real `NextConfig` interface (DISC-1256).
501
541
  */
502
- declare function withGlasstraceConfig(nextConfig: NextConfig): NextConfig;
542
+ declare function withGlasstraceConfig<T extends NextConfig>(nextConfig: T): T;
503
543
 
504
544
  /**
505
545
  * Returns true when the SDK is in ACTIVE or ACTIVE_DEGRADED state.
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  uploadSourceMaps,
14
14
  uploadSourceMapsAuto,
15
15
  uploadSourceMapsPresigned
16
- } from "./chunk-ERGEG4ZQ.js";
16
+ } from "./chunk-2LDBR3F3.js";
17
17
  import {
18
18
  buildImportGraph,
19
19
  discoverTestFiles,
@@ -304,6 +304,7 @@ async function saveCachedConfig(response, projectRoot) {
304
304
  const root = projectRoot ?? process.cwd();
305
305
  const dirPath = modules.path.join(root, GLASSTRACE_DIR);
306
306
  const configPath = modules.path.join(dirPath, CONFIG_FILE);
307
+ const tmpPath = `${configPath}.tmp`;
307
308
  try {
308
309
  await modules.fs.mkdir(dirPath, { recursive: true, mode: 448 });
309
310
  await modules.fs.chmod(dirPath, 448);
@@ -311,7 +312,20 @@ async function saveCachedConfig(response, projectRoot) {
311
312
  response,
312
313
  cachedAt: Date.now()
313
314
  };
314
- await modules.fs.writeFile(configPath, JSON.stringify(cached), { encoding: "utf-8", mode: 384 });
315
+ await modules.fs.writeFile(tmpPath, JSON.stringify(cached), {
316
+ encoding: "utf-8",
317
+ mode: 384
318
+ });
319
+ try {
320
+ await modules.fs.chmod(tmpPath, 384);
321
+ await modules.fs.rename(tmpPath, configPath);
322
+ } catch (renameErr) {
323
+ try {
324
+ await modules.fs.unlink(tmpPath);
325
+ } catch {
326
+ }
327
+ throw renameErr;
328
+ }
315
329
  await modules.fs.chmod(configPath, 384);
316
330
  } catch (err) {
317
331
  console.warn(
@@ -4430,7 +4444,6 @@ async function configureOtel(config, sessionManager) {
4430
4444
  await provider.shutdown();
4431
4445
  }
4432
4446
  });
4433
- registerSignalHandlers();
4434
4447
  registerBeforeExitTrigger();
4435
4448
  const prismaModule = await tryImport("@prisma/instrumentation");
4436
4449
  if (prismaModule) {
@@ -4485,12 +4498,15 @@ var HEARTBEAT_INTERVAL_MS = 5 * 60 * 1e3;
4485
4498
  var BACKOFF_BASE_MS = HEARTBEAT_INTERVAL_MS;
4486
4499
  var BACKOFF_MAX_MS = 30 * 60 * 1e3;
4487
4500
  var BACKOFF_JITTER = 0.2;
4501
+ var HEARTBEAT_SHUTDOWN_PRIORITY = 10;
4502
+ var SHUTDOWN_MARKER_RELPATH = ".glasstrace/shutdown-requested";
4488
4503
  var heartbeatTimer = null;
4489
4504
  var heartbeatGeneration = 0;
4490
4505
  var backoffAttempts = 0;
4491
4506
  var backoffUntil = 0;
4492
4507
  var tickInProgress = false;
4493
- var _shutdownHandler = null;
4508
+ var shutdownHookRegistered = false;
4509
+ var shutdownFired = false;
4494
4510
  function startHeartbeat(config, anonKey, sdkVersion, generation, onClaimTransition) {
4495
4511
  if (heartbeatTimer !== null) return;
4496
4512
  heartbeatGeneration = generation;
@@ -4498,7 +4514,7 @@ function startHeartbeat(config, anonKey, sdkVersion, generation, onClaimTransiti
4498
4514
  void heartbeatTick(config, anonKey, sdkVersion, generation, onClaimTransition);
4499
4515
  }, HEARTBEAT_INTERVAL_MS);
4500
4516
  heartbeatTimer.unref();
4501
- registerShutdownHandlers(config, anonKey, sdkVersion);
4517
+ registerHeartbeatShutdownHook(config, anonKey, sdkVersion);
4502
4518
  if (config.verbose) {
4503
4519
  sdkLog("info", "[glasstrace] Heartbeat started (5-minute interval).");
4504
4520
  }
@@ -4508,7 +4524,26 @@ function stopHeartbeat() {
4508
4524
  clearInterval(heartbeatTimer);
4509
4525
  heartbeatTimer = null;
4510
4526
  }
4511
- removeShutdownHandlers();
4527
+ }
4528
+ function checkShutdownMarker(projectRoot) {
4529
+ let fsSync = null;
4530
+ let pathSync = null;
4531
+ try {
4532
+ fsSync = __require("fs");
4533
+ pathSync = __require("path");
4534
+ } catch {
4535
+ return { triggered: false };
4536
+ }
4537
+ const root = projectRoot ?? (typeof process !== "undefined" ? process.cwd() : ".");
4538
+ const markerPath = pathSync.join(root, SHUTDOWN_MARKER_RELPATH);
4539
+ if (!fsSync.existsSync(markerPath)) return { triggered: false };
4540
+ try {
4541
+ fsSync.unlinkSync(markerPath);
4542
+ } catch {
4543
+ }
4544
+ const shutdown = executeShutdown().catch(() => {
4545
+ });
4546
+ return { triggered: true, shutdown };
4512
4547
  }
4513
4548
  async function heartbeatTick(config, anonKey, sdkVersion, generation, onClaimTransition) {
4514
4549
  if (tickInProgress) return;
@@ -4518,6 +4553,14 @@ async function heartbeatTick(config, anonKey, sdkVersion, generation, onClaimTra
4518
4553
  stopHeartbeat();
4519
4554
  return;
4520
4555
  }
4556
+ const markerResult = checkShutdownMarker();
4557
+ if (markerResult.triggered) {
4558
+ stopHeartbeat();
4559
+ if (markerResult.shutdown) {
4560
+ await markerResult.shutdown;
4561
+ }
4562
+ return;
4563
+ }
4521
4564
  if (Date.now() < backoffUntil) {
4522
4565
  if (config.verbose) {
4523
4566
  sdkLog("info", "[glasstrace] Heartbeat skipped (rate-limit backoff).");
@@ -4552,35 +4595,26 @@ async function heartbeatTick(config, anonKey, sdkVersion, generation, onClaimTra
4552
4595
  tickInProgress = false;
4553
4596
  }
4554
4597
  }
4555
- function registerShutdownHandlers(config, anonKey, sdkVersion) {
4556
- if (typeof process === "undefined" || typeof process.once !== "function") {
4557
- return;
4558
- }
4559
- let shutdownFired = false;
4560
- const handler = (signal) => {
4561
- if (shutdownFired) return;
4562
- shutdownFired = true;
4563
- if (heartbeatTimer !== null) {
4564
- clearInterval(heartbeatTimer);
4565
- heartbeatTimer = null;
4598
+ function registerHeartbeatShutdownHook(config, anonKey, sdkVersion) {
4599
+ if (shutdownHookRegistered) return;
4600
+ shutdownHookRegistered = true;
4601
+ registerShutdownHook({
4602
+ name: "heartbeat-final-report",
4603
+ priority: HEARTBEAT_SHUTDOWN_PRIORITY,
4604
+ fn: async () => {
4605
+ if (shutdownFired) return;
4606
+ shutdownFired = true;
4607
+ if (heartbeatTimer !== null) {
4608
+ clearInterval(heartbeatTimer);
4609
+ heartbeatTimer = null;
4610
+ }
4611
+ try {
4612
+ const healthReport = collectHealthReport(sdkVersion);
4613
+ await performInit(config, anonKey, sdkVersion, healthReport);
4614
+ } catch {
4615
+ }
4566
4616
  }
4567
- const healthReport = collectHealthReport(sdkVersion);
4568
- void performInit(config, anonKey, sdkVersion, healthReport).catch(() => {
4569
- }).finally(() => {
4570
- removeShutdownHandlers();
4571
- process.kill(process.pid, signal);
4572
- });
4573
- };
4574
- _shutdownHandler = handler;
4575
- process.once("SIGTERM", _shutdownHandler);
4576
- process.once("SIGINT", _shutdownHandler);
4577
- }
4578
- function removeShutdownHandlers() {
4579
- if (_shutdownHandler && typeof process !== "undefined") {
4580
- process.removeListener("SIGTERM", _shutdownHandler);
4581
- process.removeListener("SIGINT", _shutdownHandler);
4582
- _shutdownHandler = null;
4583
- }
4617
+ });
4584
4618
  }
4585
4619
 
4586
4620
  // src/runtime-state.ts
@@ -4681,7 +4715,7 @@ function registerGlasstrace(options) {
4681
4715
  setCoreState(CoreState.REGISTERING);
4682
4716
  startRuntimeStateWriter({
4683
4717
  projectRoot: process.cwd(),
4684
- sdkVersion: "0.14.1"
4718
+ sdkVersion: "0.15.1"
4685
4719
  });
4686
4720
  const config = resolveConfig(options);
4687
4721
  if (config.verbose) {
@@ -4697,6 +4731,11 @@ function registerGlasstrace(options) {
4697
4731
  if (config.verbose) {
4698
4732
  console.info("[glasstrace] Not production-disabled.");
4699
4733
  }
4734
+ const existingProbe = trace.getTracerProvider().getTracer("glasstrace-probe");
4735
+ const anotherProviderRegistered = existingProbe.constructor.name !== "ProxyTracer";
4736
+ if (!anotherProviderRegistered) {
4737
+ registerSignalHandlers();
4738
+ }
4700
4739
  const anonymous = isAnonymousMode(config);
4701
4740
  let effectiveKey = config.apiKey;
4702
4741
  initAuthState(anonymous ? AuthState.ANONYMOUS : AuthState.AUTHENTICATED);
@@ -4727,8 +4766,6 @@ function registerGlasstrace(options) {
4727
4766
  }
4728
4767
  setCoreState(CoreState.KEY_PENDING);
4729
4768
  const currentGeneration = registrationGeneration;
4730
- const existingProbe = trace.getTracerProvider().getTracer("glasstrace-probe");
4731
- const anotherProviderRegistered = existingProbe.constructor.name !== "ProxyTracer";
4732
4769
  if (anotherProviderRegistered) {
4733
4770
  if (config.verbose) {
4734
4771
  console.info("[glasstrace] Another OTel provider detected \u2014 using existing context manager.");
@@ -4843,8 +4880,8 @@ async function backgroundInit(config, anonKeyForInit, generation) {
4843
4880
  if (config.verbose) {
4844
4881
  console.info("[glasstrace] Background init firing.");
4845
4882
  }
4846
- const healthReport = collectHealthReport("0.14.1");
4847
- const initResult = await performInit(config, anonKeyForInit, "0.14.1", healthReport);
4883
+ const healthReport = collectHealthReport("0.15.1");
4884
+ const initResult = await performInit(config, anonKeyForInit, "0.15.1", healthReport);
4848
4885
  if (generation !== registrationGeneration) return;
4849
4886
  const currentState = getCoreState();
4850
4887
  if (currentState === CoreState.SHUTTING_DOWN || currentState === CoreState.SHUTDOWN) {
@@ -4867,7 +4904,7 @@ async function backgroundInit(config, anonKeyForInit, generation) {
4867
4904
  }
4868
4905
  maybeInstallConsoleCapture();
4869
4906
  if (didLastInitSucceed()) {
4870
- startHeartbeat(config, anonKeyForInit, "0.14.1", generation, (newApiKey, accountId) => {
4907
+ startHeartbeat(config, anonKeyForInit, "0.15.1", generation, (newApiKey, accountId) => {
4871
4908
  setAuthState(AuthState.CLAIMING);
4872
4909
  emitLifecycleEvent("auth:claim_started", { accountId });
4873
4910
  setResolvedApiKey(newApiKey);
@@ -4898,16 +4935,34 @@ function isDiscoveryEnabled(config) {
4898
4935
 
4899
4936
  // src/config-wrapper.ts
4900
4937
  init_esm_shims();
4938
+ function isTurbopackBuild() {
4939
+ if (typeof process === "undefined") return false;
4940
+ const argv = Array.isArray(process.argv) ? process.argv : [];
4941
+ if (argv.includes("--webpack")) return false;
4942
+ if (argv.includes("--turbopack")) return true;
4943
+ if (process.env?.TURBOPACK === "1") return true;
4944
+ return false;
4945
+ }
4901
4946
  function withGlasstraceConfig(nextConfig) {
4902
4947
  if (typeof process === "undefined" || typeof process.versions?.node !== "string") {
4903
4948
  return nextConfig != null ? { ...nextConfig } : {};
4904
4949
  }
4905
4950
  const config = nextConfig != null ? { ...nextConfig } : {};
4906
- const existingExperimental = config.experimental ?? {};
4907
- config.experimental = { ...existingExperimental, serverSourceMaps: true };
4908
- const distDir = typeof config.distDir === "string" ? config.distDir : ".next";
4909
- const existingWebpack = config.webpack;
4910
- config.webpack = (webpackConfig, context2) => {
4951
+ const bag = config;
4952
+ const existingExperimental = bag.experimental ?? {};
4953
+ bag.experimental = {
4954
+ ...existingExperimental,
4955
+ serverSourceMaps: true
4956
+ };
4957
+ if (bag.turbopack == null) {
4958
+ bag.turbopack = {};
4959
+ }
4960
+ if (isTurbopackBuild()) {
4961
+ warnTurbopackLimitationOnce();
4962
+ }
4963
+ const distDir = typeof bag.distDir === "string" ? bag.distDir : ".next";
4964
+ const existingWebpack = bag.webpack;
4965
+ bag.webpack = (webpackConfig, context2) => {
4911
4966
  let result = webpackConfig;
4912
4967
  if (typeof existingWebpack === "function") {
4913
4968
  result = existingWebpack(webpackConfig, context2);
@@ -4934,6 +4989,14 @@ function withGlasstraceConfig(nextConfig) {
4934
4989
  };
4935
4990
  return config;
4936
4991
  }
4992
+ var _turbopackWarningEmitted = false;
4993
+ function warnTurbopackLimitationOnce() {
4994
+ if (_turbopackWarningEmitted) return;
4995
+ _turbopackWarningEmitted = true;
4996
+ console.warn(
4997
+ "[glasstrace] Turbopack detected. Source-map upload currently runs only under webpack \u2014 run `next build --webpack` to upload source maps, or wait for the Turbopack port in a future SDK release."
4998
+ );
4999
+ }
4937
5000
  async function handleSourceMapUpload(distDir) {
4938
5001
  try {
4939
5002
  const apiKey = process.env.GLASSTRACE_API_KEY;
@@ -4944,7 +5007,7 @@ async function handleSourceMapUpload(distDir) {
4944
5007
  );
4945
5008
  return;
4946
5009
  }
4947
- const { discoverSourceMapFiles: discoverSourceMapFiles2, computeBuildHash: computeBuildHash2, uploadSourceMaps: uploadSourceMaps2 } = await import("./source-map-uploader-W6VPGY26.js");
5010
+ const { discoverSourceMapFiles: discoverSourceMapFiles2, computeBuildHash: computeBuildHash2, uploadSourceMaps: uploadSourceMaps2 } = await import("./source-map-uploader-3GWUQDTS.js");
4948
5011
  const files = await discoverSourceMapFiles2(distDir);
4949
5012
  if (files.length === 0) {
4950
5013
  console.info("[glasstrace] No source map files found. Skipping upload.");