error-mom 0.2.0 → 0.3.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.
Files changed (2) hide show
  1. package/dist/cli.js +133 -22
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ import { Command } from "commander";
10
10
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
11
11
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12
12
  import { z } from "zod";
13
- var VERSION = "0.2.0";
13
+ var VERSION = "0.3.0";
14
14
  var CONFIG_DIR = join(homedir(), ".error-mom");
15
15
  var CONFIG_FILE = join(CONFIG_DIR, "config.json");
16
16
  var program = new Command().name("error-mom").description("Query and operate a self-hosted Error Mom incident desk").version(VERSION);
@@ -112,17 +112,18 @@ program.command("init").description("Create/select a project, install the SDK, a
112
112
  const setupPath = await writeSetup(framework);
113
113
  await writeFile(
114
114
  join(process.cwd(), ".error-mom.json"),
115
- `${JSON.stringify({ server: config.server, projectId: project.id, projectName: project.name, framework }, null, 2)}
115
+ `${JSON.stringify({ server: config.server, projectId: project.id, projectName: project.name, framework: framework.id }, null, 2)}
116
116
  `
117
117
  );
118
118
  await appendEnvironment(framework, config.server, project.ingestKey);
119
119
  print({
120
120
  installed: !options.skipInstall,
121
121
  project: { id: project.id, name: project.name, slug: project.slug },
122
- framework,
122
+ framework: framework.id,
123
123
  setupFile: setupPath,
124
124
  verified: false,
125
- nextAction: framework === "next" ? `Import ${setupPath} from the root layout for client errors; instrumentation.ts already reports server errors. For jobs/handlers that catch errors themselves (queues, webhooks, MCP tools), wrap them with errorMom.wrap(fn). Then run error-mom doctor --project-key <key>.` : `Import ${setupPath} from the earliest ${framework} entry point. For code where a framework catches errors itself (job runners, webhooks, MCP tools), wrap handlers with errorMom.wrap(fn). Then run error-mom doctor --project-key <key>.`
125
+ wiring: framework.wiring,
126
+ nextAction: `Wire it up: ${framework.wiring} For handlers where a framework catches errors itself (queue/cron jobs, webhooks, MCP tools), wrap each with errorMom.wrap(fn, { culprit: "<name>" }). Then run error-mom doctor --project-key <key>.`
126
127
  });
127
128
  });
128
129
  program.command("mcp").description("Run Error Mom tools over MCP stdio for coding agents").action(async () => {
@@ -243,14 +244,125 @@ async function readPackageJson(cwd) {
243
244
  );
244
245
  }
245
246
  }
247
+ var FRAMEWORKS = [
248
+ [
249
+ "next",
250
+ {
251
+ id: "next",
252
+ envStyle: "next",
253
+ wiring: "Import the setup file from the root layout for client errors; the generated instrumentation.ts already reports server errors (API routes, SSR, server actions)."
254
+ }
255
+ ],
256
+ [
257
+ "@tauri-apps/api",
258
+ {
259
+ id: "tauri",
260
+ envStyle: "vite",
261
+ wiring: "Import the setup file first in the webview entry (main.tsx or equivalent). If the app spawns Node sidecar processes, also call initErrorMom from @kenkaiiii/error-mom/node at each sidecar entry so backend/LLM errors are reported too. Rust-side panics are not captured."
262
+ }
263
+ ],
264
+ [
265
+ "electron",
266
+ {
267
+ id: "electron",
268
+ envStyle: "node",
269
+ wiring: "Call initErrorMom from @kenkaiiii/error-mom/node at the TOP of the main process entry, and import @kenkaiiii/error-mom (browser build) first in each renderer entry. Both report to the same project."
270
+ }
271
+ ],
272
+ [
273
+ "astro",
274
+ {
275
+ id: "astro",
276
+ envStyle: "vite",
277
+ wiring: "Load the setup file as a client script in the base layout so it runs on every page. For SSR/API routes, add src/middleware.ts that wraps next() with errorMom.wrap using @kenkaiiii/error-mom/node."
278
+ }
279
+ ],
280
+ [
281
+ "@sveltejs/kit",
282
+ {
283
+ id: "sveltekit",
284
+ envStyle: "vite",
285
+ wiring: "Import the setup file in hooks.client.ts and export handleError from BOTH hooks.client.ts and hooks.server.ts calling errorMom.captureError(error); the server hook uses @kenkaiiii/error-mom/node. SvelteKit catches load/endpoint errors, so handleError is its official reporting hook."
286
+ }
287
+ ],
288
+ [
289
+ "nuxt",
290
+ {
291
+ id: "nuxt",
292
+ envStyle: "vite",
293
+ wiring: "Create a client plugin (plugins/error-mom.client.ts) importing the setup file, and a nitro plugin hooking 'error' with @kenkaiiii/error-mom/node for server-side errors."
294
+ }
295
+ ],
296
+ [
297
+ "@remix-run/react",
298
+ {
299
+ id: "remix",
300
+ envStyle: "node",
301
+ wiring: "Import the setup file in entry.client.tsx, and export handleError from entry.server.tsx calling errorMom.captureError(error). Remix catches loader/action errors and handleError is its official reporting hook."
302
+ }
303
+ ],
304
+ [
305
+ "@angular/core",
306
+ {
307
+ id: "angular",
308
+ envStyle: "node",
309
+ wiring: "Import the setup file in main.ts and provide a custom ErrorHandler that calls errorMom.captureError(error). Angular catches component errors in its own handler."
310
+ }
311
+ ],
312
+ [
313
+ "express",
314
+ {
315
+ id: "express",
316
+ envStyle: "node",
317
+ wiring: "Import the setup file at the TOP of the server entry, and add a final error middleware: (err, req, res, next) => { errorMom.captureError(err, { culprit: `${req.method} ${req.path}` }); next(err); }. Express catches route errors, so the middleware is where they surface."
318
+ }
319
+ ],
320
+ [
321
+ "fastify",
322
+ {
323
+ id: "fastify",
324
+ envStyle: "node",
325
+ wiring: "Import the setup file at the TOP of the server entry, and call errorMom.captureError(error) inside setErrorHandler before replying. Fastify catches handler errors there."
326
+ }
327
+ ],
328
+ [
329
+ "hono",
330
+ {
331
+ id: "hono",
332
+ envStyle: "node",
333
+ wiring: "Import the setup file at the TOP of the server entry, and call errorMom.captureError(err) inside app.onError. Hono catches handler errors there."
334
+ }
335
+ ],
336
+ [
337
+ "@nestjs/core",
338
+ {
339
+ id: "nestjs",
340
+ envStyle: "node",
341
+ wiring: "Import the setup file at the TOP of main.ts, and add a global exception filter that calls errorMom.captureError(exception) before delegating to the base filter."
342
+ }
343
+ ],
344
+ [
345
+ "vite",
346
+ {
347
+ id: "vite",
348
+ envStyle: "vite",
349
+ wiring: "Import the setup file first in the app entry (main.tsx or equivalent)."
350
+ }
351
+ ]
352
+ ];
246
353
  function detectFramework(packageJson) {
247
354
  const dependencies = {
248
355
  ...packageJson.dependencies ?? {},
249
356
  ...packageJson.devDependencies ?? {}
250
357
  };
251
- if (dependencies.next) return "next";
252
- if (dependencies.vite) return "vite";
253
- return "node";
358
+ for (const [dependency, info] of FRAMEWORKS) {
359
+ if (dependencies[dependency]) return info;
360
+ }
361
+ return {
362
+ id: "node",
363
+ envStyle: "node",
364
+ wiring: "Import the setup file at the TOP of the main entry point, before anything else."
365
+ };
254
366
  }
255
367
  function detectPackageManager(cwd) {
256
368
  if (existsSync(join(cwd, "pnpm-lock.yaml"))) return "pnpm";
@@ -271,25 +383,24 @@ function installSdk(packageManager) {
271
383
  async function writeSetup(framework) {
272
384
  const sourceDirectory = existsSync(join(process.cwd(), "src")) ? "src" : ".";
273
385
  const relativePath = join(sourceDirectory, "error-mom.ts");
274
- if (framework === "next") await writeNextInstrumentation(sourceDirectory);
275
- const environment = framework === "next" ? "process.env.NEXT_PUBLIC_" : framework === "vite" ? "import.meta.env.VITE_" : "process.env.";
276
- const moduleName = framework === "node" ? "@kenkaiiii/error-mom/node" : "@kenkaiiii/error-mom";
277
- const contents = `${framework === "next" ? '"use client";\n\n' : ""}import { initErrorMom } from "${moduleName}";
386
+ if (framework.id === "next") await writeNextInstrumentation(sourceDirectory);
387
+ const environment = framework.envStyle === "next" ? "process.env.NEXT_PUBLIC_" : framework.envStyle === "vite" ? "import.meta.env.VITE_" : "process.env.";
388
+ const moduleName = framework.envStyle === "node" ? "@kenkaiiii/error-mom/node" : "@kenkaiiii/error-mom";
389
+ const contents = `${framework.id === "next" ? '"use client";\n\n' : ""}import { initErrorMom } from "${moduleName}";
278
390
 
279
391
  const server = ${environment}ERROR_MOM_SERVER;
280
392
  const projectKey = ${environment}ERROR_MOM_PROJECT_KEY;
281
393
  const release = ${environment}ERROR_MOM_RELEASE;
282
394
 
283
- if (!server || !projectKey) {
284
- throw new Error("ERROR_MOM_SERVER and ERROR_MOM_PROJECT_KEY are required");
285
- }
286
-
287
- initErrorMom({
288
- server,
289
- projectKey,
290
- environment: ${environment}ERROR_MOM_ENVIRONMENT ?? "production",
291
- ...(release ? { release } : {}),
292
- });
395
+ export const errorMom =
396
+ server && projectKey
397
+ ? initErrorMom({
398
+ server,
399
+ projectKey,
400
+ environment: ${environment}ERROR_MOM_ENVIRONMENT ?? "production",
401
+ ...(release ? { release } : {}),
402
+ })
403
+ : undefined;
293
404
  `;
294
405
  await writeFile(join(process.cwd(), relativePath), contents);
295
406
  return relativePath;
@@ -324,7 +435,7 @@ export const onRequestError: Instrumentation.onRequestError = async (
324
435
  await writeFile(file, contents);
325
436
  }
326
437
  async function appendEnvironment(framework, server, key) {
327
- const prefix = framework === "next" ? "NEXT_PUBLIC_" : framework === "vite" ? "VITE_" : "";
438
+ const prefix = framework.envStyle === "next" ? "NEXT_PUBLIC_" : framework.envStyle === "vite" ? "VITE_" : "";
328
439
  const file = join(process.cwd(), ".env.local");
329
440
  const existing = existsSync(file) ? await readFile(file, "utf8") : "";
330
441
  const lines = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "error-mom",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Agent-first CLI and MCP tools for self-hosted Error Mom",
5
5
  "type": "module",
6
6
  "bin": {