error-mom 0.4.1 → 0.5.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/dist/cli.js +56 -2
- package/package.json +8 -8
- package/LICENSE +0 -21
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { execFileSync } from "child_process";
|
|
5
|
-
import { chmod, mkdir, readFile, writeFile } from "fs/promises";
|
|
5
|
+
import { chmod, mkdir, readFile, readdir, stat, writeFile } from "fs/promises";
|
|
6
6
|
import { existsSync } from "fs";
|
|
7
7
|
import { homedir } from "os";
|
|
8
8
|
import { basename, join } from "path";
|
|
@@ -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.
|
|
13
|
+
var VERSION = "0.5.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);
|
|
@@ -132,6 +132,42 @@ program.command("init").description("Create/select a project, install the SDK, a
|
|
|
132
132
|
nextAction: `Wire it up: ${framework.wiring} If the app routes caught errors through a central handler or error-broadcast function, call errorMom.captureError(err) inside it \u2014 that is where framework-caught and LLM errors surface. For handlers where a framework catches errors itself (queue/cron jobs, webhooks, MCP tools), wrap each with errorMom.wrap(fn, { culprit: "<name>" }). The setup file has the write-only project key baked in (safe to commit; ERROR_MOM_* env vars override when set), so production builds report without any configuration. Then run error-mom doctor --project-key ${project.ingestKey}.`
|
|
133
133
|
});
|
|
134
134
|
});
|
|
135
|
+
program.command("sourcemaps").description("Upload production source maps so minified stacks symbolicate on ingest").argument("<dir>", "Build output directory containing *.map files (e.g. dist)").requiredOption("--release <release>", "Release the maps belong to (must match the SDK release)").requiredOption("--project <id-or-slug>", "Project id or slug").action(async (dir, options) => {
|
|
136
|
+
const config = await loadConfig();
|
|
137
|
+
const mapFiles = await findMapFiles(dir);
|
|
138
|
+
if (mapFiles.length === 0) {
|
|
139
|
+
throw new Error(`No .map files found under ${dir}. Build with source maps enabled first.`);
|
|
140
|
+
}
|
|
141
|
+
const uploaded = [];
|
|
142
|
+
const skipped = [];
|
|
143
|
+
for (const mapFile of mapFiles) {
|
|
144
|
+
const info = await stat(mapFile);
|
|
145
|
+
if (info.size > 20 * 1024 * 1024) {
|
|
146
|
+
skipped.push({ file: mapFile, reason: "larger than 20 MB" });
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
let map;
|
|
150
|
+
try {
|
|
151
|
+
map = JSON.parse(await readFile(mapFile, "utf8"));
|
|
152
|
+
} catch {
|
|
153
|
+
skipped.push({ file: mapFile, reason: "not valid JSON" });
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const fileName = basename(mapFile).replace(/\.map$/, "");
|
|
157
|
+
try {
|
|
158
|
+
await request(config.server, config.adminToken, "/api/v1/sourcemaps", {
|
|
159
|
+
body: { projectId: options.project, release: options.release, fileName, map }
|
|
160
|
+
});
|
|
161
|
+
uploaded.push(fileName);
|
|
162
|
+
} catch (error) {
|
|
163
|
+
skipped.push({
|
|
164
|
+
file: mapFile,
|
|
165
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
print({ release: options.release, project: options.project, uploaded, skipped });
|
|
170
|
+
});
|
|
135
171
|
program.command("mcp").description("Run Error Mom tools over MCP stdio for coding agents").action(async () => {
|
|
136
172
|
await runMcpServer();
|
|
137
173
|
});
|
|
@@ -474,6 +510,24 @@ function syntheticEvent() {
|
|
|
474
510
|
context: {}
|
|
475
511
|
};
|
|
476
512
|
}
|
|
513
|
+
async function findMapFiles(dir) {
|
|
514
|
+
const found = [];
|
|
515
|
+
let entries;
|
|
516
|
+
try {
|
|
517
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
518
|
+
} catch {
|
|
519
|
+
throw new Error(`Cannot read directory ${dir}.`);
|
|
520
|
+
}
|
|
521
|
+
for (const entry of entries) {
|
|
522
|
+
const fullPath = join(dir, entry.name);
|
|
523
|
+
if (entry.isDirectory() && entry.name !== "node_modules") {
|
|
524
|
+
found.push(...await findMapFiles(fullPath));
|
|
525
|
+
} else if (entry.isFile() && entry.name.endsWith(".map")) {
|
|
526
|
+
found.push(fullPath);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return found.sort();
|
|
530
|
+
}
|
|
477
531
|
function normalizeServer(server) {
|
|
478
532
|
return server.replace(/\/$/, "");
|
|
479
533
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "error-mom",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Agent-first CLI and MCP tools for self-hosted Error Mom",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
"dist",
|
|
12
12
|
"README.md"
|
|
13
13
|
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsup src/cli.ts --format esm --dts --clean",
|
|
16
|
+
"check": "tsc --noEmit",
|
|
17
|
+
"test": "vitest run --passWithNoTests"
|
|
18
|
+
},
|
|
14
19
|
"dependencies": {
|
|
15
20
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
16
21
|
"commander": "^15.0.0",
|
|
@@ -23,10 +28,5 @@
|
|
|
23
28
|
"publishConfig": {
|
|
24
29
|
"access": "public"
|
|
25
30
|
},
|
|
26
|
-
"license": "MIT"
|
|
27
|
-
|
|
28
|
-
"build": "tsup src/cli.ts --format esm --dts --clean",
|
|
29
|
-
"check": "tsc --noEmit",
|
|
30
|
-
"test": "vitest run --passWithNoTests"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
31
|
+
"license": "MIT"
|
|
32
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Ken Kai
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|