@glasstrace/sdk 1.1.1 → 1.1.3

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 (49) hide show
  1. package/README.md +78 -1
  2. package/dist/{chunk-DIM4JRXM.js → chunk-2M57EO6U.js} +2 -2
  3. package/dist/{chunk-Y26HJUPD.js → chunk-FGDS33I2.js} +138 -12
  4. package/dist/chunk-FGDS33I2.js.map +1 -0
  5. package/dist/{chunk-MXDZHFJQ.js → chunk-JKI4OCFV.js} +4 -14
  6. package/dist/chunk-JKI4OCFV.js.map +1 -0
  7. package/dist/{chunk-7SZQN6IU.js → chunk-NB7GJE4S.js} +2 -2
  8. package/dist/chunk-NB7GJE4S.js.map +1 -0
  9. package/dist/{chunk-ZRDQ6ZKI.js → chunk-TWHCJKRS.js} +101 -481
  10. package/dist/chunk-TWHCJKRS.js.map +1 -0
  11. package/dist/{chunk-P22UQ2OJ.js → chunk-TWTWRJ25.js} +233 -9
  12. package/dist/chunk-TWTWRJ25.js.map +1 -0
  13. package/dist/cli/init.cjs +2494 -2332
  14. package/dist/cli/init.cjs.map +1 -1
  15. package/dist/cli/init.js +434 -63
  16. package/dist/cli/init.js.map +1 -1
  17. package/dist/cli/mcp-add.cjs +14 -2
  18. package/dist/cli/mcp-add.cjs.map +1 -1
  19. package/dist/cli/mcp-add.js +17 -5
  20. package/dist/cli/mcp-add.js.map +1 -1
  21. package/dist/cli/status.cjs.map +1 -1
  22. package/dist/cli/status.js +1 -3
  23. package/dist/cli/status.js.map +1 -1
  24. package/dist/cli/uninit.cjs +116 -14
  25. package/dist/cli/uninit.cjs.map +1 -1
  26. package/dist/cli/uninit.js +3 -3
  27. package/dist/cli/validate.cjs +14162 -2
  28. package/dist/cli/validate.cjs.map +1 -1
  29. package/dist/cli/validate.d.cts +7 -3
  30. package/dist/cli/validate.d.ts +7 -3
  31. package/dist/cli/validate.js +25 -2
  32. package/dist/cli/validate.js.map +1 -1
  33. package/dist/index.cjs +339 -28
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +12 -9
  36. package/dist/index.d.ts +12 -9
  37. package/dist/index.js +3 -3
  38. package/dist/{monorepo-GSL6JD3G.js → monorepo-PFVNPQ6X.js} +3 -5
  39. package/dist/node-entry.cjs +339 -28
  40. package/dist/node-entry.cjs.map +1 -1
  41. package/dist/node-entry.js +3 -3
  42. package/package.json +1 -1
  43. package/dist/chunk-7SZQN6IU.js.map +0 -1
  44. package/dist/chunk-MXDZHFJQ.js.map +0 -1
  45. package/dist/chunk-P22UQ2OJ.js.map +0 -1
  46. package/dist/chunk-Y26HJUPD.js.map +0 -1
  47. package/dist/chunk-ZRDQ6ZKI.js.map +0 -1
  48. /package/dist/{chunk-DIM4JRXM.js.map → chunk-2M57EO6U.js.map} +0 -0
  49. /package/dist/{monorepo-GSL6JD3G.js.map → monorepo-PFVNPQ6X.js.map} +0 -0
@@ -1,426 +1,55 @@
1
1
  import {
2
- NEXT_CONFIG_NAMES
3
- } from "./chunk-7SZQN6IU.js";
4
- import {
2
+ atomicWriteFileSync,
3
+ atomicWriteFileSyncWithTmp,
4
+ fsyncParentDirSync,
5
5
  isDevApiKey,
6
- readEnvLocalApiKey
7
- } from "./chunk-P22UQ2OJ.js";
6
+ readEnvLocalApiKey,
7
+ writeAndFsyncTempSync
8
+ } from "./chunk-TWTWRJ25.js";
8
9
  import {
9
10
  AnonApiKeySchema
10
11
  } from "./chunk-X5MAXP5T.js";
12
+ import {
13
+ NEXT_CONFIG_NAMES
14
+ } from "./chunk-NB7GJE4S.js";
11
15
 
12
16
  // src/cli/uninit.ts
13
- import * as fs3 from "node:fs";
17
+ import * as fs2 from "node:fs";
14
18
  import * as os from "node:os";
15
- import * as path3 from "node:path";
19
+ import * as path2 from "node:path";
16
20
 
17
- // src/cli/scaffolder.ts
21
+ // src/cli/discovery-file.ts
18
22
  import * as fs from "node:fs";
19
23
  import * as path from "node:path";
20
- function hasRegisterGlasstraceCall(content) {
21
- return content.split("\n").some((line) => {
22
- const uncommented = line.replace(/\/\/.*$/, "");
23
- return /\bregisterGlasstrace\s*\(/.test(uncommented);
24
- });
25
- }
26
- function injectRegisterGlasstrace(content) {
27
- if (hasRegisterGlasstraceCall(content)) {
28
- return { injected: false, content };
29
- }
30
- const registerFnRegex = /export\s+(?:async\s+)?function\s+register\s*\([^)]*\)\s*\{/;
31
- const match = registerFnRegex.exec(content);
32
- if (!match) {
33
- return { injected: false, content };
34
- }
35
- const afterBrace = content.slice(match.index + match[0].length);
36
- const indentMatch = /\n([ \t]+)/.exec(afterBrace);
37
- const indent = indentMatch ? indentMatch[1] : " ";
38
- const importLine = 'import { registerGlasstrace } from "@glasstrace/sdk";\n';
39
- const hasGlasstraceImport = content.includes("@glasstrace/sdk");
40
- const insertPoint = match.index + match[0].length;
41
- const callInjection = `
42
- ${indent}// Glasstrace must be registered before other instrumentation
43
- ${indent}registerGlasstrace();
44
- `;
45
- let modified;
46
- if (hasGlasstraceImport) {
47
- const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']@glasstrace\/sdk["']/;
48
- const importMatch = importRegex.exec(content);
49
- if (importMatch) {
50
- const specifiers = importMatch[1];
51
- const alreadyImported = specifiers.split(",").some((s) => s.trim() === "registerGlasstrace");
52
- if (alreadyImported) {
53
- modified = content.slice(0, insertPoint) + callInjection + content.slice(insertPoint);
54
- } else {
55
- const existingImports = specifiers.trimEnd();
56
- const separator = existingImports.endsWith(",") ? " " : ", ";
57
- const updatedImport = `import { ${existingImports.trim()}${separator}registerGlasstrace } from "@glasstrace/sdk"`;
58
- modified = content.replace(importMatch[0], updatedImport);
59
- const newMatch = registerFnRegex.exec(modified);
60
- if (newMatch) {
61
- const newInsertPoint = newMatch.index + newMatch[0].length;
62
- modified = modified.slice(0, newInsertPoint) + callInjection + modified.slice(newInsertPoint);
63
- }
64
- }
65
- } else {
66
- modified = importLine + content;
67
- const newMatch = registerFnRegex.exec(modified);
68
- if (newMatch) {
69
- const newInsertPoint = newMatch.index + newMatch[0].length;
70
- modified = modified.slice(0, newInsertPoint) + callInjection + modified.slice(newInsertPoint);
71
- }
72
- }
73
- } else {
74
- modified = importLine + content.slice(0, insertPoint) + callInjection + content.slice(insertPoint);
75
- }
76
- return { injected: true, content: modified };
77
- }
78
- var INSTRUMENTATION_FILENAMES = [
79
- "instrumentation.ts",
80
- "instrumentation.js",
81
- "instrumentation.mjs"
82
- ];
83
- function resolveInstrumentationTarget(projectRoot) {
84
- const rootExisting = [];
85
- const srcExisting = [];
86
- for (const name of INSTRUMENTATION_FILENAMES) {
87
- const rootPath = path.join(projectRoot, name);
88
- if (isRegularFile(rootPath)) {
89
- rootExisting.push(rootPath);
90
- }
91
- const srcPath = path.join(projectRoot, "src", name);
92
- if (isRegularFile(srcPath)) {
93
- srcExisting.push(srcPath);
94
- }
95
- }
96
- const existing = [...rootExisting, ...srcExisting];
97
- if (rootExisting.length > 0 && srcExisting.length > 0) {
98
- return {
99
- target: null,
100
- layout: null,
101
- existing,
102
- rootExisting,
103
- srcExisting,
104
- conflict: true
105
- };
106
- }
107
- if (srcExisting.length > 0) {
108
- return {
109
- target: srcExisting[0],
110
- layout: "src",
111
- existing,
112
- rootExisting,
113
- srcExisting,
114
- conflict: false
115
- };
116
- }
117
- if (rootExisting.length > 0) {
118
- return {
119
- target: rootExisting[0],
120
- layout: "root",
121
- existing,
122
- rootExisting,
123
- srcExisting,
124
- conflict: false
125
- };
126
- }
127
- const srcDir = path.join(projectRoot, "src");
128
- const layout = isDirectory(srcDir) ? "src" : "root";
129
- const target = layout === "src" ? path.join(projectRoot, "src", "instrumentation.ts") : path.join(projectRoot, "instrumentation.ts");
130
- return {
131
- target,
132
- layout,
133
- existing,
134
- rootExisting,
135
- srcExisting,
136
- conflict: false
137
- };
138
- }
139
- function isDirectory(p) {
140
- try {
141
- return fs.statSync(p).isDirectory();
142
- } catch {
143
- return false;
144
- }
145
- }
146
- function isRegularFile(p) {
147
- try {
148
- const stat = fs.lstatSync(p);
149
- if (stat.isSymbolicLink()) {
150
- return fs.statSync(p).isFile();
151
- }
152
- return stat.isFile();
153
- } catch {
154
- return false;
155
- }
156
- }
157
- function appendRegisterFunction(content) {
158
- const importLine = 'import { registerGlasstrace } from "@glasstrace/sdk";\n';
159
- const functionBlock = "\nexport async function register() {\n // Glasstrace must be registered before Prisma instrumentation\n // to ensure all ORM spans are captured correctly.\n // If you use @prisma/instrumentation, import it after this call.\n registerGlasstrace();\n}\n";
160
- let withImport = content;
161
- const hasGlasstraceImport = content.includes("@glasstrace/sdk");
162
- if (!hasGlasstraceImport) {
163
- withImport = importLine + content;
164
- } else {
165
- const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']@glasstrace\/sdk["']/;
166
- const importMatch = importRegex.exec(content);
167
- if (importMatch) {
168
- const specifiers = importMatch[1];
169
- const alreadyImported = specifiers.split(",").some((s) => s.trim() === "registerGlasstrace");
170
- if (!alreadyImported) {
171
- const existingImports = specifiers.trimEnd();
172
- const separator = existingImports.endsWith(",") ? " " : ", ";
173
- const updatedImport = `import { ${existingImports.trim()}${separator}registerGlasstrace } from "@glasstrace/sdk"`;
174
- withImport = content.replace(importMatch[0], updatedImport);
175
- }
176
- } else {
177
- withImport = importLine + content;
178
- }
179
- }
180
- const trailingNewline = withImport.endsWith("\n") ? "" : "\n";
181
- return withImport + trailingNewline + functionBlock;
182
- }
183
- async function defaultInstrumentationPrompt(question, defaultValue) {
184
- if (!process.stdin.isTTY) return defaultValue;
185
- const readline = await import("node:readline");
186
- const rl = readline.createInterface({
187
- input: process.stdin,
188
- output: process.stdout
189
- });
190
- return new Promise((resolve) => {
191
- const suffix = defaultValue ? " [Y/n] " : " [y/N] ";
192
- rl.question(question + suffix, (answer) => {
193
- rl.close();
194
- const trimmed = answer.trim().toLowerCase();
195
- if (trimmed === "") {
196
- resolve(defaultValue);
197
- return;
198
- }
199
- resolve(trimmed === "y" || trimmed === "yes");
200
- });
201
- });
202
- }
203
- async function scaffoldInstrumentation(projectRoot, options = {}) {
204
- const target = resolveInstrumentationTarget(projectRoot);
205
- if (target.conflict) {
206
- return {
207
- action: "conflict",
208
- // Point the user at the `src/` variant — modern Next.js apps with a
209
- // `src/` directory load from there, so that's the merge target. The
210
- // competing path is reported separately for the error message.
211
- filePath: target.srcExisting[0],
212
- conflictingPath: target.rootExisting[0]
213
- };
214
- }
215
- const filePath = target.target;
216
- const layout = target.layout;
217
- if (filePath === null || layout === null) {
218
- return { action: "unrecognized" };
219
- }
220
- const force = options.force === true;
221
- const prompt = options.prompt ?? defaultInstrumentationPrompt;
222
- if (!fs.existsSync(filePath)) {
223
- const content = `import { registerGlasstrace } from "@glasstrace/sdk";
224
-
225
- export async function register() {
226
- // Glasstrace must be registered before Prisma instrumentation
227
- // to ensure all ORM spans are captured correctly.
228
- // If you use @prisma/instrumentation, import it after this call.
229
- registerGlasstrace();
230
- }
231
- `;
232
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
233
- fs.writeFileSync(filePath, content, "utf-8");
234
- return { action: "created", filePath, layout };
235
- }
236
- const existing = fs.readFileSync(filePath, "utf-8");
237
- if (hasRegisterGlasstraceCall(existing)) {
238
- return { action: "already-registered", filePath, layout };
239
- }
240
- if (!force) {
241
- const approved = await prompt(
242
- `Merge registerGlasstrace() into ${path.relative(projectRoot, filePath)}?`,
243
- false
244
- );
245
- if (!approved) {
246
- return { action: "skipped", filePath, layout };
247
- }
248
- }
249
- const injectResult = injectRegisterGlasstrace(existing);
250
- if (injectResult.injected) {
251
- fs.writeFileSync(filePath, injectResult.content, "utf-8");
252
- return { action: "injected", filePath, layout };
253
- }
254
- const appended = appendRegisterFunction(existing);
255
- fs.writeFileSync(filePath, appended, "utf-8");
256
- return { action: "appended", filePath, layout };
257
- }
258
- async function scaffoldNextConfig(projectRoot) {
259
- let configPath;
260
- let configName;
261
- for (const name of NEXT_CONFIG_NAMES) {
262
- const candidate = path.join(projectRoot, name);
263
- if (fs.existsSync(candidate)) {
264
- configPath = candidate;
265
- configName = name;
266
- break;
267
- }
268
- }
269
- if (configPath === void 0 || configName === void 0) {
270
- return null;
271
- }
272
- const existing = fs.readFileSync(configPath, "utf-8");
273
- if (existing.trim().length === 0) {
274
- return { modified: false, reason: "empty-file" };
275
- }
276
- if (existing.includes("withGlasstraceConfig")) {
277
- return { modified: false, reason: "already-wrapped" };
278
- }
279
- const isESM = configName.endsWith(".ts") || configName.endsWith(".mjs");
280
- if (isESM) {
281
- const importLine = 'import { withGlasstraceConfig } from "@glasstrace/sdk";\n';
282
- const wrapResult2 = wrapExport(existing);
283
- if (!wrapResult2.wrapped) {
284
- return { modified: false, reason: "no-export" };
285
- }
286
- const modified2 = importLine + "\n" + wrapResult2.content;
287
- fs.writeFileSync(configPath, modified2, "utf-8");
288
- return { modified: true };
289
- }
290
- const requireLine = 'const { withGlasstraceConfig } = require("@glasstrace/sdk");\n';
291
- const wrapResult = wrapCJSExport(existing);
292
- if (!wrapResult.wrapped) {
293
- return { modified: false, reason: "no-export" };
294
- }
295
- const modified = requireLine + "\n" + wrapResult.content;
296
- fs.writeFileSync(configPath, modified, "utf-8");
297
- return { modified: true };
298
- }
299
- function wrapExport(content) {
300
- const marker = "export default";
301
- const idx = content.lastIndexOf(marker);
302
- if (idx === -1) {
303
- return { content, wrapped: false };
304
- }
305
- const preamble = content.slice(0, idx);
306
- const exprRaw = content.slice(idx + marker.length);
307
- const expr = exprRaw.trim().replace(/;?\s*$/, "");
308
- if (expr.length === 0) {
309
- return { content, wrapped: false };
310
- }
311
- return {
312
- content: preamble + `export default withGlasstraceConfig(${expr});
313
- `,
314
- wrapped: true
315
- };
316
- }
317
- function wrapCJSExport(content) {
318
- const cjsMarker = "module.exports";
319
- const cjsIdx = content.lastIndexOf(cjsMarker);
320
- if (cjsIdx === -1) {
321
- return { content, wrapped: false };
322
- }
323
- const preamble = content.slice(0, cjsIdx);
324
- const afterMarker = content.slice(cjsIdx + cjsMarker.length);
325
- const eqMatch = /^\s*=\s*/.exec(afterMarker);
326
- if (!eqMatch) {
327
- return { content, wrapped: false };
328
- }
329
- const exprRaw = afterMarker.slice(eqMatch[0].length);
330
- const expr = exprRaw.trim().replace(/;?\s*$/, "");
331
- if (expr.length === 0) {
332
- return { content, wrapped: false };
333
- }
334
- return {
335
- content: preamble + `module.exports = withGlasstraceConfig(${expr});
336
- `,
337
- wrapped: true
338
- };
339
- }
340
- async function scaffoldEnvLocal(projectRoot) {
341
- const filePath = path.join(projectRoot, ".env.local");
342
- if (fs.existsSync(filePath)) {
343
- const existing = fs.readFileSync(filePath, "utf-8");
344
- if (/^\s*#?\s*GLASSTRACE_API_KEY\s*=/m.test(existing)) {
345
- return false;
346
- }
347
- const separator = existing.endsWith("\n") ? "" : "\n";
348
- fs.writeFileSync(filePath, existing + separator + "# GLASSTRACE_API_KEY=your_key_here\n", "utf-8");
349
- return true;
350
- }
351
- fs.writeFileSync(filePath, "# GLASSTRACE_API_KEY=your_key_here\n", "utf-8");
352
- return true;
353
- }
354
- async function addCoverageMapEnv(projectRoot) {
355
- const filePath = path.join(projectRoot, ".env.local");
356
- if (!fs.existsSync(filePath)) {
357
- fs.writeFileSync(filePath, "GLASSTRACE_COVERAGE_MAP=true\n", "utf-8");
358
- return true;
359
- }
360
- const existing = fs.readFileSync(filePath, "utf-8");
361
- const keyRegex = /^(\s*GLASSTRACE_COVERAGE_MAP\s*=\s*)(.*)$/m;
362
- const keyMatch = keyRegex.exec(existing);
363
- if (keyMatch) {
364
- const currentValue = keyMatch[2].trim();
365
- if (currentValue === "true") {
366
- return false;
367
- }
368
- const updated = existing.replace(keyRegex, `${keyMatch[1]}true`);
369
- fs.writeFileSync(filePath, updated, "utf-8");
370
- return true;
371
- }
372
- const separator = existing.endsWith("\n") ? "" : "\n";
373
- fs.writeFileSync(filePath, existing + separator + "GLASSTRACE_COVERAGE_MAP=true\n", "utf-8");
374
- return true;
375
- }
376
- async function scaffoldGitignore(projectRoot) {
377
- const filePath = path.join(projectRoot, ".gitignore");
378
- if (fs.existsSync(filePath)) {
379
- const existing = fs.readFileSync(filePath, "utf-8");
380
- const lines = existing.split("\n").map((l) => l.trim());
381
- if (lines.includes(".glasstrace/")) {
382
- return false;
383
- }
384
- const separator = existing.endsWith("\n") ? "" : "\n";
385
- fs.writeFileSync(filePath, existing + separator + ".glasstrace/\n", "utf-8");
386
- return true;
387
- }
388
- fs.writeFileSync(filePath, ".glasstrace/\n", "utf-8");
389
- return true;
390
- }
391
-
392
- // src/cli/discovery-file.ts
393
- import * as fs2 from "node:fs";
394
- import * as path2 from "node:path";
395
24
  var WELL_KNOWN_GLASSTRACE_PATH = ".well-known/glasstrace.json";
396
25
  var DISCOVERY_FILE_VERSION = 1;
397
26
  function resolveStaticRoot(projectRoot) {
398
27
  if (isSvelteKitProject(projectRoot)) {
399
28
  return {
400
- absolutePath: path2.join(projectRoot, "static"),
29
+ absolutePath: path.join(projectRoot, "static"),
401
30
  layout: "static"
402
31
  };
403
32
  }
404
33
  return {
405
- absolutePath: path2.join(projectRoot, "public"),
34
+ absolutePath: path.join(projectRoot, "public"),
406
35
  layout: "public"
407
36
  };
408
37
  }
409
38
  function isSvelteKitProject(projectRoot) {
410
- const pkgPath = path2.join(projectRoot, "package.json");
39
+ const pkgPath = path.join(projectRoot, "package.json");
411
40
  let isEsm = false;
412
41
  try {
413
- const pkgContent = fs2.readFileSync(pkgPath, "utf-8");
42
+ const pkgContent = fs.readFileSync(pkgPath, "utf-8");
414
43
  const parsed = JSON.parse(pkgContent);
415
44
  isEsm = parsed.type === "module";
416
45
  } catch {
417
46
  return false;
418
47
  }
419
48
  if (!isEsm) return false;
420
- const svelteConfigJs = path2.join(projectRoot, "svelte.config.js");
421
- const svelteConfigTs = path2.join(projectRoot, "svelte.config.ts");
422
- const appHtml = path2.join(projectRoot, "src", "app.html");
423
- return fs2.existsSync(svelteConfigJs) || fs2.existsSync(svelteConfigTs) || fs2.existsSync(appHtml);
49
+ const svelteConfigJs = path.join(projectRoot, "svelte.config.js");
50
+ const svelteConfigTs = path.join(projectRoot, "svelte.config.ts");
51
+ const appHtml = path.join(projectRoot, "src", "app.html");
52
+ return fs.existsSync(svelteConfigJs) || fs.existsSync(svelteConfigTs) || fs.existsSync(appHtml);
424
53
  }
425
54
  function relativeDiscoveryPath(layout) {
426
55
  const rootDir = layout === "static" ? "static" : "public";
@@ -429,7 +58,7 @@ function relativeDiscoveryPath(layout) {
429
58
  function readExistingDiscoveryFile(filePath) {
430
59
  let raw;
431
60
  try {
432
- raw = fs2.readFileSync(filePath, "utf-8");
61
+ raw = fs.readFileSync(filePath, "utf-8");
433
62
  } catch {
434
63
  return null;
435
64
  }
@@ -468,11 +97,11 @@ function serializeDiscoveryPayload(key, extras) {
468
97
  }
469
98
  function writeDiscoveryFile(projectRoot, anonKey) {
470
99
  const { absolutePath: staticRoot, layout } = resolveStaticRoot(projectRoot);
471
- const wellKnownDir = path2.join(staticRoot, ".well-known");
472
- const filePath = path2.join(wellKnownDir, "glasstrace.json");
100
+ const wellKnownDir = path.join(staticRoot, ".well-known");
101
+ const filePath = path.join(wellKnownDir, "glasstrace.json");
473
102
  let existingAction;
474
103
  let extras = {};
475
- if (fs2.existsSync(filePath)) {
104
+ if (fs.existsSync(filePath)) {
476
105
  const existing = readExistingDiscoveryFile(filePath);
477
106
  if (existing === null) {
478
107
  existingAction = "skipped-foreign";
@@ -490,35 +119,42 @@ function writeDiscoveryFile(projectRoot, anonKey) {
490
119
  existingAction = "created";
491
120
  }
492
121
  const tmpPath = `${filePath}.tmp-${process.pid}`;
493
- const needsWindowsReplace = process.platform === "win32" && fs2.existsSync(filePath);
122
+ const needsWindowsReplace = process.platform === "win32" && fs.existsSync(filePath);
494
123
  const backupPath = needsWindowsReplace ? `${filePath}.bak-${process.pid}` : null;
495
124
  try {
496
- fs2.mkdirSync(wellKnownDir, { recursive: true });
125
+ fs.mkdirSync(wellKnownDir, { recursive: true });
497
126
  const payload = serializeDiscoveryPayload(anonKey, extras);
498
- fs2.writeFileSync(tmpPath, payload, { encoding: "utf-8" });
499
127
  if (backupPath !== null) {
500
- fs2.renameSync(filePath, backupPath);
128
+ writeAndFsyncTempSync(tmpPath, payload, {
129
+ encoding: "utf-8",
130
+ mode: 420
131
+ });
132
+ fs.renameSync(filePath, backupPath);
501
133
  try {
502
- fs2.renameSync(tmpPath, filePath);
134
+ fs.renameSync(tmpPath, filePath);
503
135
  } catch (renameErr) {
504
136
  try {
505
- fs2.renameSync(backupPath, filePath);
137
+ fs.renameSync(backupPath, filePath);
506
138
  } catch {
507
139
  }
508
140
  throw renameErr;
509
141
  }
142
+ fsyncParentDirSync(filePath);
510
143
  try {
511
- fs2.unlinkSync(backupPath);
144
+ fs.unlinkSync(backupPath);
512
145
  } catch {
513
146
  }
514
147
  } else {
515
- fs2.renameSync(tmpPath, filePath);
148
+ atomicWriteFileSyncWithTmp(filePath, tmpPath, payload, {
149
+ encoding: "utf-8",
150
+ mode: 420
151
+ });
516
152
  }
517
153
  return { action: existingAction, filePath, layout };
518
154
  } catch (err) {
519
155
  try {
520
- if (fs2.existsSync(tmpPath)) {
521
- fs2.unlinkSync(tmpPath);
156
+ if (fs.existsSync(tmpPath)) {
157
+ fs.unlinkSync(tmpPath);
522
158
  }
523
159
  } catch {
524
160
  }
@@ -535,13 +171,13 @@ function removeDiscoveryFile(projectRoot) {
535
171
  const layouts = ["public", "static"];
536
172
  const outcomes = [];
537
173
  for (const layout of layouts) {
538
- const staticRoot = path2.join(projectRoot, layout);
539
- const wellKnownDir = path2.join(staticRoot, ".well-known");
540
- const filePath = path2.join(wellKnownDir, "glasstrace.json");
174
+ const staticRoot = path.join(projectRoot, layout);
175
+ const wellKnownDir = path.join(staticRoot, ".well-known");
176
+ const filePath = path.join(wellKnownDir, "glasstrace.json");
541
177
  let removed = false;
542
178
  try {
543
- if (fs2.existsSync(filePath)) {
544
- fs2.unlinkSync(filePath);
179
+ if (fs.existsSync(filePath)) {
180
+ fs.unlinkSync(filePath);
545
181
  removed = true;
546
182
  }
547
183
  } catch (err) {
@@ -556,10 +192,10 @@ function removeDiscoveryFile(projectRoot) {
556
192
  let directoryRemoved = false;
557
193
  if (removed) {
558
194
  try {
559
- if (fs2.existsSync(wellKnownDir)) {
560
- const entries = fs2.readdirSync(wellKnownDir);
195
+ if (fs.existsSync(wellKnownDir)) {
196
+ const entries = fs.readdirSync(wellKnownDir);
561
197
  if (entries.length === 0) {
562
- fs2.rmdirSync(wellKnownDir);
198
+ fs.rmdirSync(wellKnownDir);
563
199
  directoryRemoved = true;
564
200
  }
565
201
  }
@@ -892,26 +528,16 @@ function processTomlMcpConfig(content) {
892
528
  return { action: "removed-section", content: result + "\n" };
893
529
  }
894
530
  function writeShutdownMarker(projectRoot) {
895
- const dirPath = path3.join(projectRoot, ".glasstrace");
896
- if (!fs3.existsSync(dirPath)) {
531
+ const dirPath = path2.join(projectRoot, ".glasstrace");
532
+ if (!fs2.existsSync(dirPath)) {
897
533
  return false;
898
534
  }
899
- const markerPath = path3.join(dirPath, "shutdown-requested");
900
- const tmpPath = `${markerPath}.tmp`;
535
+ const markerPath = path2.join(dirPath, "shutdown-requested");
901
536
  const body = JSON.stringify({ requestedAt: (/* @__PURE__ */ new Date()).toISOString() });
902
537
  try {
903
- fs3.writeFileSync(tmpPath, body, { encoding: "utf-8", mode: 384 });
904
- try {
905
- fs3.chmodSync(tmpPath, 384);
906
- } catch {
907
- }
908
- fs3.renameSync(tmpPath, markerPath);
538
+ atomicWriteFileSync(markerPath, body, { encoding: "utf-8", mode: 384 });
909
539
  return true;
910
540
  } catch {
911
- try {
912
- fs3.unlinkSync(tmpPath);
913
- } catch {
914
- }
915
541
  return false;
916
542
  }
917
543
  }
@@ -950,8 +576,8 @@ async function runUninit(options) {
950
576
  summary.push("Wrote .glasstrace/shutdown-requested marker");
951
577
  }
952
578
  } else {
953
- const dirPath = path3.join(projectRoot, ".glasstrace");
954
- if (fs3.existsSync(dirPath)) {
579
+ const dirPath = path2.join(projectRoot, ".glasstrace");
580
+ if (fs2.existsSync(dirPath)) {
955
581
  summary.push(`${prefix}Would write .glasstrace/shutdown-requested marker`);
956
582
  }
957
583
  }
@@ -963,11 +589,11 @@ async function runUninit(options) {
963
589
  try {
964
590
  let configHandled = false;
965
591
  for (const name of NEXT_CONFIG_NAMES) {
966
- const configPath = path3.join(projectRoot, name);
967
- if (!fs3.existsSync(configPath)) {
592
+ const configPath = path2.join(projectRoot, name);
593
+ if (!fs2.existsSync(configPath)) {
968
594
  continue;
969
595
  }
970
- const content = fs3.readFileSync(configPath, "utf-8");
596
+ const content = fs2.readFileSync(configPath, "utf-8");
971
597
  if (!content.includes("withGlasstraceConfig")) {
972
598
  continue;
973
599
  }
@@ -977,7 +603,7 @@ async function runUninit(options) {
977
603
  const cleaned = removeGlasstraceConfigImport(unwrapResult.content);
978
604
  const final = cleanLeadingBlankLines(cleaned);
979
605
  if (!dryRun) {
980
- fs3.writeFileSync(configPath, final, "utf-8");
606
+ fs2.writeFileSync(configPath, final, "utf-8");
981
607
  }
982
608
  summary.push(`${prefix}Unwrapped withGlasstraceConfig from ${name}`);
983
609
  configHandled = true;
@@ -998,20 +624,20 @@ async function runUninit(options) {
998
624
  );
999
625
  }
1000
626
  try {
1001
- const instrPath = path3.join(projectRoot, "instrumentation.ts");
1002
- if (fs3.existsSync(instrPath)) {
1003
- const content = fs3.readFileSync(instrPath, "utf-8");
627
+ const instrPath = path2.join(projectRoot, "instrumentation.ts");
628
+ if (fs2.existsSync(instrPath)) {
629
+ const content = fs2.readFileSync(instrPath, "utf-8");
1004
630
  if (content.includes("registerGlasstrace") || content.includes("@glasstrace/sdk")) {
1005
631
  if (isInitCreatedInstrumentation(content)) {
1006
632
  if (!dryRun) {
1007
- fs3.unlinkSync(instrPath);
633
+ fs2.unlinkSync(instrPath);
1008
634
  }
1009
635
  summary.push(`${prefix}Deleted instrumentation.ts (init-created)`);
1010
636
  } else {
1011
637
  const cleaned = removeRegisterGlasstrace(content);
1012
638
  if (cleaned !== content) {
1013
639
  if (!dryRun) {
1014
- fs3.writeFileSync(instrPath, cleaned, "utf-8");
640
+ fs2.writeFileSync(instrPath, cleaned, "utf-8");
1015
641
  }
1016
642
  summary.push(
1017
643
  `${prefix}Removed registerGlasstrace() from instrumentation.ts`
@@ -1026,10 +652,10 @@ async function runUninit(options) {
1026
652
  );
1027
653
  }
1028
654
  try {
1029
- const glasstraceDir = path3.join(projectRoot, ".glasstrace");
1030
- if (fs3.existsSync(glasstraceDir)) {
655
+ const glasstraceDir = path2.join(projectRoot, ".glasstrace");
656
+ if (fs2.existsSync(glasstraceDir)) {
1031
657
  if (!dryRun) {
1032
- fs3.rmSync(glasstraceDir, { recursive: true, force: true });
658
+ fs2.rmSync(glasstraceDir, { recursive: true, force: true });
1033
659
  }
1034
660
  summary.push(`${prefix}Removed .glasstrace/ directory`);
1035
661
  }
@@ -1042,8 +668,8 @@ async function runUninit(options) {
1042
668
  if (dryRun) {
1043
669
  for (const previewLayout of ["public", "static"]) {
1044
670
  const relPath = relativeDiscoveryPath(previewLayout);
1045
- const absPath = path3.join(projectRoot, relPath);
1046
- if (fs3.existsSync(absPath)) {
671
+ const absPath = path2.join(projectRoot, relPath);
672
+ if (fs2.existsSync(absPath)) {
1047
673
  summary.push(`${prefix}Would remove ${relPath}`);
1048
674
  }
1049
675
  }
@@ -1068,9 +694,9 @@ async function runUninit(options) {
1068
694
  );
1069
695
  }
1070
696
  try {
1071
- const envPath = path3.join(projectRoot, ".env.local");
1072
- if (fs3.existsSync(envPath)) {
1073
- const content = fs3.readFileSync(envPath, "utf-8");
697
+ const envPath = path2.join(projectRoot, ".env.local");
698
+ if (fs2.existsSync(envPath)) {
699
+ const content = fs2.readFileSync(envPath, "utf-8");
1074
700
  const existingKey = readEnvLocalApiKey(content);
1075
701
  const hasDevKey = isDevApiKey(existingKey);
1076
702
  let proceed = true;
@@ -1103,12 +729,12 @@ async function runUninit(options) {
1103
729
  const result = filtered.join("\n");
1104
730
  if (result.trim().length === 0) {
1105
731
  if (!dryRun) {
1106
- fs3.unlinkSync(envPath);
732
+ fs2.unlinkSync(envPath);
1107
733
  }
1108
734
  summary.push(`${prefix}Deleted .env.local (no remaining entries)`);
1109
735
  } else {
1110
736
  if (!dryRun) {
1111
- fs3.writeFileSync(envPath, result, "utf-8");
737
+ fs2.writeFileSync(envPath, result, "utf-8");
1112
738
  }
1113
739
  let devKeyAnnotation = "";
1114
740
  if (devKeyPath === "interactive-confirmed") {
@@ -1131,9 +757,9 @@ async function runUninit(options) {
1131
757
  );
1132
758
  }
1133
759
  try {
1134
- const gitignorePath = path3.join(projectRoot, ".gitignore");
1135
- if (fs3.existsSync(gitignorePath)) {
1136
- const content = fs3.readFileSync(gitignorePath, "utf-8");
760
+ const gitignorePath = path2.join(projectRoot, ".gitignore");
761
+ if (fs2.existsSync(gitignorePath)) {
762
+ const content = fs2.readFileSync(gitignorePath, "utf-8");
1137
763
  const lines = content.split("\n");
1138
764
  const mcpGitignoreEntries = /* @__PURE__ */ new Set([
1139
765
  ".glasstrace/",
@@ -1149,12 +775,12 @@ async function runUninit(options) {
1149
775
  const result = filtered.join("\n");
1150
776
  if (result.trim().length === 0) {
1151
777
  if (!dryRun) {
1152
- fs3.unlinkSync(gitignorePath);
778
+ fs2.unlinkSync(gitignorePath);
1153
779
  }
1154
780
  summary.push(`${prefix}Deleted .gitignore (no remaining entries)`);
1155
781
  } else {
1156
782
  if (!dryRun) {
1157
- fs3.writeFileSync(gitignorePath, result, "utf-8");
783
+ fs2.writeFileSync(gitignorePath, result, "utf-8");
1158
784
  }
1159
785
  summary.push(`${prefix}Removed Glasstrace entries from .gitignore`);
1160
786
  }
@@ -1167,63 +793,63 @@ async function runUninit(options) {
1167
793
  }
1168
794
  try {
1169
795
  for (const configFile of MCP_CONFIG_FILES) {
1170
- const configPath = path3.join(projectRoot, configFile);
1171
- if (!fs3.existsSync(configPath)) {
796
+ const configPath = path2.join(projectRoot, configFile);
797
+ if (!fs2.existsSync(configPath)) {
1172
798
  continue;
1173
799
  }
1174
- const content = fs3.readFileSync(configPath, "utf-8");
800
+ const content = fs2.readFileSync(configPath, "utf-8");
1175
801
  const result = processJsonMcpConfig(content);
1176
802
  if (result.action === "deleted") {
1177
803
  if (!dryRun) {
1178
- fs3.unlinkSync(configPath);
804
+ fs2.unlinkSync(configPath);
1179
805
  }
1180
806
  summary.push(`${prefix}Deleted ${configFile}`);
1181
807
  } else if (result.action === "removed-key" && result.content !== void 0) {
1182
808
  if (!dryRun) {
1183
- fs3.writeFileSync(configPath, result.content, "utf-8");
809
+ fs2.writeFileSync(configPath, result.content, "utf-8");
1184
810
  }
1185
811
  summary.push(`${prefix}Removed glasstrace from ${configFile}`);
1186
812
  }
1187
813
  }
1188
- const codexConfigPath = path3.join(projectRoot, ".codex", "config.toml");
1189
- if (fs3.existsSync(codexConfigPath)) {
1190
- const content = fs3.readFileSync(codexConfigPath, "utf-8");
814
+ const codexConfigPath = path2.join(projectRoot, ".codex", "config.toml");
815
+ if (fs2.existsSync(codexConfigPath)) {
816
+ const content = fs2.readFileSync(codexConfigPath, "utf-8");
1191
817
  const tomlResult = processTomlMcpConfig(content);
1192
818
  if (tomlResult.action === "deleted") {
1193
819
  if (!dryRun) {
1194
- fs3.unlinkSync(codexConfigPath);
820
+ fs2.unlinkSync(codexConfigPath);
1195
821
  }
1196
822
  summary.push(`${prefix}Deleted .codex/config.toml`);
1197
823
  } else if (tomlResult.action === "removed-section" && tomlResult.content !== void 0) {
1198
824
  if (!dryRun) {
1199
- fs3.writeFileSync(codexConfigPath, tomlResult.content, "utf-8");
825
+ fs2.writeFileSync(codexConfigPath, tomlResult.content, "utf-8");
1200
826
  }
1201
827
  summary.push(`${prefix}Removed glasstrace from .codex/config.toml`);
1202
828
  }
1203
829
  }
1204
- const hasWindsurfMarkers = fs3.existsSync(path3.join(projectRoot, ".windsurfrules")) || fs3.existsSync(path3.join(projectRoot, ".windsurf"));
830
+ const hasWindsurfMarkers = fs2.existsSync(path2.join(projectRoot, ".windsurfrules")) || fs2.existsSync(path2.join(projectRoot, ".windsurf"));
1205
831
  if (hasWindsurfMarkers) {
1206
- const windsurfConfigPath = path3.join(
832
+ const windsurfConfigPath = path2.join(
1207
833
  os.homedir(),
1208
834
  ".codeium",
1209
835
  "windsurf",
1210
836
  "mcp_config.json"
1211
837
  );
1212
- if (fs3.existsSync(windsurfConfigPath)) {
1213
- const content = fs3.readFileSync(windsurfConfigPath, "utf-8");
838
+ if (fs2.existsSync(windsurfConfigPath)) {
839
+ const content = fs2.readFileSync(windsurfConfigPath, "utf-8");
1214
840
  const windsurfResult = processJsonMcpConfig(content);
1215
841
  const home = os.homedir();
1216
842
  const displayPath = windsurfConfigPath.startsWith(home) ? "~" + windsurfConfigPath.slice(home.length) : windsurfConfigPath;
1217
843
  if (windsurfResult.action === "deleted") {
1218
844
  if (!dryRun) {
1219
- fs3.unlinkSync(windsurfConfigPath);
845
+ fs2.unlinkSync(windsurfConfigPath);
1220
846
  }
1221
847
  summary.push(
1222
848
  `${prefix}Deleted global Windsurf config (${displayPath})`
1223
849
  );
1224
850
  } else if (windsurfResult.action === "removed-key" && windsurfResult.content !== void 0) {
1225
851
  if (!dryRun) {
1226
- fs3.writeFileSync(windsurfConfigPath, windsurfResult.content, "utf-8");
852
+ fs2.writeFileSync(windsurfConfigPath, windsurfResult.content, "utf-8");
1227
853
  }
1228
854
  summary.push(
1229
855
  `${prefix}Removed glasstrace from global Windsurf config (${displayPath})`
@@ -1238,21 +864,21 @@ async function runUninit(options) {
1238
864
  }
1239
865
  try {
1240
866
  for (const infoFile of AGENT_INFO_FILES) {
1241
- const filePath = path3.join(projectRoot, infoFile);
1242
- if (!fs3.existsSync(filePath)) {
867
+ const filePath = path2.join(projectRoot, infoFile);
868
+ if (!fs2.existsSync(filePath)) {
1243
869
  continue;
1244
870
  }
1245
- const content = fs3.readFileSync(filePath, "utf-8");
871
+ const content = fs2.readFileSync(filePath, "utf-8");
1246
872
  const result = removeMarkerSection(content);
1247
873
  if (result.removed) {
1248
874
  if (result.content.trim().length === 0) {
1249
875
  if (!dryRun) {
1250
- fs3.unlinkSync(filePath);
876
+ fs2.unlinkSync(filePath);
1251
877
  }
1252
878
  summary.push(`${prefix}Deleted ${infoFile} (only contained Glasstrace section)`);
1253
879
  } else {
1254
880
  if (!dryRun) {
1255
- fs3.writeFileSync(filePath, result.content, "utf-8");
881
+ fs2.writeFileSync(filePath, result.content, "utf-8");
1256
882
  }
1257
883
  summary.push(`${prefix}Removed Glasstrace section from ${infoFile}`);
1258
884
  }
@@ -1270,12 +896,6 @@ async function runUninit(options) {
1270
896
  }
1271
897
 
1272
898
  export {
1273
- resolveInstrumentationTarget,
1274
- scaffoldInstrumentation,
1275
- scaffoldNextConfig,
1276
- scaffoldEnvLocal,
1277
- addCoverageMapEnv,
1278
- scaffoldGitignore,
1279
899
  resolveStaticRoot,
1280
900
  relativeDiscoveryPath,
1281
901
  writeDiscoveryFile,
@@ -1294,4 +914,4 @@ export {
1294
914
  writeShutdownMarker,
1295
915
  runUninit
1296
916
  };
1297
- //# sourceMappingURL=chunk-ZRDQ6ZKI.js.map
917
+ //# sourceMappingURL=chunk-TWHCJKRS.js.map