snapfail 0.0.17 → 0.0.19

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.js CHANGED
@@ -164,6 +164,14 @@ async function fetchIncident(config, id) {
164
164
  });
165
165
  return data;
166
166
  }
167
+ async function deleteGroup(config, id) {
168
+ const url = `${config.endpoint}/api/incidents/${id}`;
169
+ const data = await apiFetch(url, {
170
+ method: "DELETE",
171
+ headers: { "X-Project-Key": config.projectKey }
172
+ });
173
+ return data !== null;
174
+ }
167
175
  async function fetchSample(config, groupId, sampleIndex) {
168
176
  const url = `${config.endpoint}/api/incidents/${groupId}/samples/${sampleIndex}`;
169
177
  const data = await apiFetch(url, {
@@ -237,6 +245,13 @@ function formatIncidentDetail(group, sample) {
237
245
  for (const f of sample.stackFrames.slice(0, 6)) {
238
246
  const fn = f.fn ? `${cyan(f.fn)} ` : "";
239
247
  lines.push(` ${fn}${dim(f.file + ":" + f.line)}`);
248
+ if (f.codeSnippet) {
249
+ for (const snippetLine of f.codeSnippet.split(`
250
+ `)) {
251
+ const isError = snippetLine.startsWith("\u25BA");
252
+ lines.push(isError ? ` ${bold(snippetLine)}` : ` ${dim(snippetLine)}`);
253
+ }
254
+ }
240
255
  }
241
256
  }
242
257
  if (sample.consoleEntries.length > 0) {
@@ -287,6 +302,20 @@ async function runIncidents(opts) {
287
302
  // src/commands/incident.ts
288
303
  async function runIncident(opts) {
289
304
  const config = loadConfig();
305
+ if (opts.delete) {
306
+ const ok = await deleteGroup(config, opts.id);
307
+ if (!ok) {
308
+ console.error(`Incident group ${opts.id} not found.`);
309
+ process.exit(1);
310
+ }
311
+ if (opts.json) {
312
+ process.stdout.write(JSON.stringify({ ok: true, deleted: opts.id }) + `
313
+ `);
314
+ } else {
315
+ console.log(`Deleted incident group ${opts.id} and all related data.`);
316
+ }
317
+ return;
318
+ }
290
319
  if (opts.sample != null) {
291
320
  const s = await fetchSample(config, opts.id, opts.sample);
292
321
  if (!s) {
@@ -2056,6 +2085,34 @@ function injectAstroAdapter(configPath) {
2056
2085
  }
2057
2086
  writeFileSync3(configPath, src, "utf-8");
2058
2087
  }
2088
+ function injectNextConfig(cwd) {
2089
+ const candidates = ["next.config.ts", "next.config.mjs", "next.config.js"];
2090
+ const cfgFile = candidates.find((n2) => existsSync3(resolve2(cwd, n2)));
2091
+ if (!cfgFile)
2092
+ return;
2093
+ const cfgPath = resolve2(cwd, cfgFile);
2094
+ let src = readFileSync3(cfgPath, "utf-8");
2095
+ if (src.includes("withSnapfail"))
2096
+ return;
2097
+ const isEsm = cfgFile.endsWith(".mjs") || cfgFile.endsWith(".ts");
2098
+ const projectKeyExpr = isEsm ? `import.meta.env?.NEXT_PUBLIC_SNAPFAIL_PROJECT_KEY ?? process.env.NEXT_PUBLIC_SNAPFAIL_PROJECT_KEY ?? ""` : `process.env.NEXT_PUBLIC_SNAPFAIL_PROJECT_KEY ?? ""`;
2099
+ if (isEsm) {
2100
+ src = `import { withSnapfail } from "@snapfail/next";
2101
+ ` + src;
2102
+ src = src.replace(/export\s+default\s+(\w+);/, `export default withSnapfail(${projectKeyExpr})($1);`);
2103
+ if (!src.includes("withSnapfail(")) {
2104
+ src = src.replace(/export\s+default\s+(\{)/, `export default withSnapfail(${projectKeyExpr})($1`);
2105
+ }
2106
+ } else {
2107
+ src = `const { withSnapfail } = require("@snapfail/next");
2108
+ ` + src;
2109
+ src = src.replace(/module\.exports\s*=\s*(\w+);/, `module.exports = withSnapfail(${projectKeyExpr})($1);`);
2110
+ if (!src.includes("withSnapfail(")) {
2111
+ src = src.replace(/module\.exports\s*=\s*(\{)/, `module.exports = withSnapfail(${projectKeyExpr})($1`);
2112
+ }
2113
+ }
2114
+ writeFileSync3(cfgPath, src, "utf-8");
2115
+ }
2059
2116
  function injectNextProvider(cwd) {
2060
2117
  const providerSrc = `"use client";
2061
2118
  import { useEffect } from "react";
@@ -2065,7 +2122,9 @@ export function SnapfailProvider() {
2065
2122
  useEffect(() => {
2066
2123
  initSnapfail({
2067
2124
  projectKey: process.env.NEXT_PUBLIC_SNAPFAIL_PROJECT_KEY ?? "",
2125
+ endpoint: process.env.NEXT_PUBLIC_SNAPFAIL_ENDPOINT ?? "https://app.snapfail.com",
2068
2126
  environment: process.env.NODE_ENV === "production" ? "prod" : "dev",
2127
+ buildId: process.env.NEXT_PUBLIC_SNAPFAIL_BUILD_ID,
2069
2128
  });
2070
2129
  }, []);
2071
2130
  return null;
@@ -2210,6 +2269,8 @@ async function runInit(cwd = process.cwd()) {
2210
2269
  } catch {
2211
2270
  spinner2.stop("Skipping install (not yet on npm).");
2212
2271
  }
2272
+ injectNextConfig(cwd);
2273
+ log.success("Injected withSnapfail into next.config");
2213
2274
  injectNextProvider(cwd);
2214
2275
  log.success("Created snapfail-provider.tsx");
2215
2276
  log.warn("Add <SnapfailProvider /> to your root layout.");
@@ -2242,7 +2303,8 @@ async function fetchDiagnosis(config, id, force) {
2242
2303
  try {
2243
2304
  res = await fetch(url.toString(), {
2244
2305
  method: "POST",
2245
- headers: { "X-Project-Key": config.projectKey }
2306
+ headers: { "X-Project-Key": config.projectKey, "Content-Type": "application/json" },
2307
+ body: "{}"
2246
2308
  });
2247
2309
  } catch (err) {
2248
2310
  throw new Error(`Network error: ${err instanceof Error ? err.message : String(err)}`);
@@ -2318,7 +2380,7 @@ function parseArgs(argv) {
2318
2380
  }
2319
2381
  return { command, args, flags };
2320
2382
  }
2321
- var VERSION = "0.0.17";
2383
+ var VERSION = "0.0.18";
2322
2384
  async function main() {
2323
2385
  const { command, args, flags } = parseArgs(process.argv);
2324
2386
  const json = flags["json"] === true;
@@ -2348,7 +2410,7 @@ async function main() {
2348
2410
  }
2349
2411
  const sampleFlag = flags["sample"];
2350
2412
  const sample = typeof sampleFlag === "string" ? parseInt(sampleFlag) : undefined;
2351
- await runIncident({ id, sample, json });
2413
+ await runIncident({ id, sample, json, delete: flags["delete"] === true });
2352
2414
  return;
2353
2415
  }
2354
2416
  if (command === "explain") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snapfail",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "type": "module",
5
5
  "description": "CLI for snapfail — project setup, incident inspection and AI diagnostics",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -30,7 +30,7 @@ function parseArgs(argv: string[]): {
30
30
  return { command, args, flags };
31
31
  }
32
32
 
33
- const VERSION = "0.0.17";
33
+ const VERSION = "0.0.18";
34
34
 
35
35
  async function main(): Promise<void> {
36
36
  const { command, args, flags } = parseArgs(process.argv);
@@ -66,7 +66,7 @@ async function main(): Promise<void> {
66
66
  const sampleFlag = flags["sample"];
67
67
  const sample =
68
68
  typeof sampleFlag === "string" ? parseInt(sampleFlag) : undefined;
69
- await runIncident({ id, sample, json });
69
+ await runIncident({ id, sample, json, delete: flags["delete"] === true });
70
70
  return;
71
71
  }
72
72