brakit 0.9.0 → 0.9.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.
- package/dist/api.d.ts +2 -0
- package/dist/api.js +10 -4
- package/dist/bin/brakit.js +156 -23
- package/dist/dashboard-client.global.js +30 -30
- package/dist/dashboard.html +30 -30
- package/dist/mcp/server.js +1 -1
- package/dist/runtime/index.js +178 -67
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -348,10 +348,12 @@ declare function detectProject(rootDir: string): Promise<DetectedProject>;
|
|
|
348
348
|
declare class AdapterRegistry {
|
|
349
349
|
private adapters;
|
|
350
350
|
private active;
|
|
351
|
+
private failed;
|
|
351
352
|
register(adapter: BrakitAdapter): void;
|
|
352
353
|
patchAll(emit: (event: TelemetryEvent) => void): void;
|
|
353
354
|
unpatchAll(): void;
|
|
354
355
|
getActive(): readonly BrakitAdapter[];
|
|
356
|
+
getFailed(): readonly string[];
|
|
355
357
|
}
|
|
356
358
|
|
|
357
359
|
interface AnalysisUpdate {
|
package/dist/api.js
CHANGED
|
@@ -54,6 +54,7 @@ var BASELINE_MIN_SESSIONS = 2;
|
|
|
54
54
|
var BASELINE_MIN_REQUESTS_PER_SESSION = 3;
|
|
55
55
|
var ISSUES_FILE = "issues.json";
|
|
56
56
|
var ISSUES_FLUSH_INTERVAL_MS = 1e4;
|
|
57
|
+
var DETAIL_PREVIEW_LENGTH = 120;
|
|
57
58
|
|
|
58
59
|
// src/utils/log.ts
|
|
59
60
|
var PREFIX = "[brakit]";
|
|
@@ -429,6 +430,7 @@ var AdapterRegistry = class {
|
|
|
429
430
|
constructor() {
|
|
430
431
|
this.adapters = [];
|
|
431
432
|
this.active = [];
|
|
433
|
+
this.failed = [];
|
|
432
434
|
}
|
|
433
435
|
register(adapter) {
|
|
434
436
|
this.adapters.push(adapter);
|
|
@@ -441,6 +443,7 @@ var AdapterRegistry = class {
|
|
|
441
443
|
this.active.push(adapter);
|
|
442
444
|
}
|
|
443
445
|
} catch {
|
|
446
|
+
this.failed.push(adapter.name);
|
|
444
447
|
}
|
|
445
448
|
}
|
|
446
449
|
}
|
|
@@ -456,6 +459,9 @@ var AdapterRegistry = class {
|
|
|
456
459
|
getActive() {
|
|
457
460
|
return this.active;
|
|
458
461
|
}
|
|
462
|
+
getFailed() {
|
|
463
|
+
return this.failed;
|
|
464
|
+
}
|
|
459
465
|
};
|
|
460
466
|
|
|
461
467
|
// src/utils/response.ts
|
|
@@ -774,7 +780,7 @@ var stackTraceLeakRule = {
|
|
|
774
780
|
title: "Stack Trace Leaked to Client",
|
|
775
781
|
desc: `${ep} \u2014 response exposes internal stack trace`,
|
|
776
782
|
hint: this.hint,
|
|
777
|
-
detail: firstLine ? `Stack trace: ${firstLine.slice(0,
|
|
783
|
+
detail: firstLine ? `Stack trace: ${firstLine.slice(0, DETAIL_PREVIEW_LENGTH)}` : void 0,
|
|
778
784
|
endpoint: ep,
|
|
779
785
|
count: 1
|
|
780
786
|
}
|
|
@@ -1664,7 +1670,7 @@ var n1Rule = {
|
|
|
1664
1670
|
title: "N+1 Query Pattern",
|
|
1665
1671
|
desc: `${endpoint} runs ${shapeGroup.count}x ${info.op} ${info.table} with different params in a single request`,
|
|
1666
1672
|
hint: "This typically happens when fetching related data in a loop. Use a batch query, JOIN, or include/eager-load to fetch all records at once.",
|
|
1667
|
-
detail: `${shapeGroup.count} queries with ${shapeGroup.distinctSql.size} distinct param variations. Example: ${[...shapeGroup.distinctSql][0]?.slice(0,
|
|
1673
|
+
detail: `${shapeGroup.count} queries with ${shapeGroup.distinctSql.size} distinct param variations. Example: ${[...shapeGroup.distinctSql][0]?.slice(0, DETAIL_PREVIEW_LENGTH) ?? info.op + " " + info.table}`
|
|
1668
1674
|
});
|
|
1669
1675
|
}
|
|
1670
1676
|
}
|
|
@@ -1703,7 +1709,7 @@ var redundantQueryRule = {
|
|
|
1703
1709
|
title: "Redundant Query",
|
|
1704
1710
|
desc: `${label} runs ${entry.count}x with identical params in ${endpoint}.`,
|
|
1705
1711
|
hint: "The exact same query with identical parameters runs multiple times in one request. Cache the first result or lift the query to a shared function.",
|
|
1706
|
-
detail: entry.first.sql ? `Query: ${entry.first.sql.slice(0,
|
|
1712
|
+
detail: entry.first.sql ? `Query: ${entry.first.sql.slice(0, DETAIL_PREVIEW_LENGTH)}` : void 0
|
|
1707
1713
|
});
|
|
1708
1714
|
}
|
|
1709
1715
|
}
|
|
@@ -2235,7 +2241,7 @@ var AnalysisEngine = class {
|
|
|
2235
2241
|
};
|
|
2236
2242
|
|
|
2237
2243
|
// src/index.ts
|
|
2238
|
-
var VERSION = "0.9.
|
|
2244
|
+
var VERSION = "0.9.1";
|
|
2239
2245
|
export {
|
|
2240
2246
|
AdapterRegistry,
|
|
2241
2247
|
AnalysisEngine,
|
package/dist/bin/brakit.js
CHANGED
|
@@ -10,7 +10,7 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/constants/config.ts
|
|
13
|
-
var PROJECT_HASH_LENGTH, SECRET_SCAN_ARRAY_LIMIT, PII_SCAN_ARRAY_LIMIT, MIN_SECRET_VALUE_LENGTH, FULL_RECORD_MIN_FIELDS, LIST_PII_MIN_ITEMS, MAX_OBJECT_SCAN_DEPTH, ISSUE_PRUNE_TTL_MS, OVERFETCH_UNWRAP_MIN_SIZE, STALE_ISSUE_TTL_MS, METRICS_DIR, PORT_FILE, VALID_ISSUE_STATES, VALID_AI_FIX_STATUSES, VALID_SECURITY_SEVERITIES;
|
|
13
|
+
var PROJECT_HASH_LENGTH, SECRET_SCAN_ARRAY_LIMIT, PII_SCAN_ARRAY_LIMIT, MIN_SECRET_VALUE_LENGTH, FULL_RECORD_MIN_FIELDS, LIST_PII_MIN_ITEMS, MAX_OBJECT_SCAN_DEPTH, ISSUE_PRUNE_TTL_MS, OVERFETCH_UNWRAP_MIN_SIZE, STALE_ISSUE_TTL_MS, METRICS_DIR, PORT_FILE, VALID_ISSUE_STATES, VALID_AI_FIX_STATUSES, VALID_SECURITY_SEVERITIES, TELEMETRY_EVENT_CLI_INVOKED, TELEMETRY_EVENT_CLI_UNINSTALL, DETAIL_PREVIEW_LENGTH;
|
|
14
14
|
var init_config = __esm({
|
|
15
15
|
"src/constants/config.ts"() {
|
|
16
16
|
"use strict";
|
|
@@ -29,6 +29,9 @@ var init_config = __esm({
|
|
|
29
29
|
VALID_ISSUE_STATES = /* @__PURE__ */ new Set(["open", "fixing", "resolved", "stale", "regressed"]);
|
|
30
30
|
VALID_AI_FIX_STATUSES = /* @__PURE__ */ new Set(["fixed", "wont_fix"]);
|
|
31
31
|
VALID_SECURITY_SEVERITIES = /* @__PURE__ */ new Set(["critical", "warning"]);
|
|
32
|
+
TELEMETRY_EVENT_CLI_INVOKED = "cli_invoked";
|
|
33
|
+
TELEMETRY_EVENT_CLI_UNINSTALL = "cli_uninstall";
|
|
34
|
+
DETAIL_PREVIEW_LENGTH = 120;
|
|
32
35
|
}
|
|
33
36
|
});
|
|
34
37
|
|
|
@@ -70,7 +73,7 @@ var init_type_guards = __esm({
|
|
|
70
73
|
});
|
|
71
74
|
|
|
72
75
|
// src/constants/labels.ts
|
|
73
|
-
var DASHBOARD_PREFIX, DASHBOARD_API_REQUESTS, DASHBOARD_API_EVENTS, DASHBOARD_API_FLOWS, DASHBOARD_API_CLEAR, DASHBOARD_API_LOGS, DASHBOARD_API_FETCHES, DASHBOARD_API_ERRORS, DASHBOARD_API_QUERIES, DASHBOARD_API_INGEST, DASHBOARD_API_METRICS, DASHBOARD_API_ACTIVITY, DASHBOARD_API_METRICS_LIVE, DASHBOARD_API_INSIGHTS, DASHBOARD_API_SECURITY, DASHBOARD_API_TAB, DASHBOARD_API_FINDINGS, DASHBOARD_API_FINDINGS_REPORT, VALID_TABS_TUPLE, VALID_TABS;
|
|
76
|
+
var DASHBOARD_PREFIX, DASHBOARD_API_REQUESTS, DASHBOARD_API_EVENTS, DASHBOARD_API_FLOWS, DASHBOARD_API_CLEAR, DASHBOARD_API_LOGS, DASHBOARD_API_FETCHES, DASHBOARD_API_ERRORS, DASHBOARD_API_QUERIES, DASHBOARD_API_INGEST, DASHBOARD_API_METRICS, DASHBOARD_API_ACTIVITY, DASHBOARD_API_METRICS_LIVE, DASHBOARD_API_INSIGHTS, DASHBOARD_API_SECURITY, DASHBOARD_API_TAB, DASHBOARD_API_FINDINGS, DASHBOARD_API_FINDINGS_REPORT, VALID_TABS_TUPLE, VALID_TABS, POSTHOG_HOST, POSTHOG_CAPTURE_PATH, POSTHOG_REQUEST_TIMEOUT_MS;
|
|
74
77
|
var init_labels = __esm({
|
|
75
78
|
"src/constants/labels.ts"() {
|
|
76
79
|
"use strict";
|
|
@@ -104,11 +107,14 @@ var init_labels = __esm({
|
|
|
104
107
|
"security"
|
|
105
108
|
];
|
|
106
109
|
VALID_TABS = new Set(VALID_TABS_TUPLE);
|
|
110
|
+
POSTHOG_HOST = "https://us.i.posthog.com";
|
|
111
|
+
POSTHOG_CAPTURE_PATH = "/i/v0/e/";
|
|
112
|
+
POSTHOG_REQUEST_TIMEOUT_MS = 3e3;
|
|
107
113
|
}
|
|
108
114
|
});
|
|
109
115
|
|
|
110
116
|
// src/constants/features.ts
|
|
111
|
-
var SUPPORTED_SOURCE_EXTENSIONS, BUILD_CACHE_DIRS, FALLBACK_SCAN_DIRS, MCP_SERVER_NAME, INITIAL_DISCOVERY_TIMEOUT_MS, LAZY_DISCOVERY_TIMEOUT_MS, CLIENT_FETCH_TIMEOUT_MS, HEALTH_CHECK_TIMEOUT_MS, DISCOVERY_POLL_INTERVAL_MS, MAX_DISCOVERY_DEPTH, MAX_TIMELINE_EVENTS, MAX_RESOLVED_DISPLAY, ENRICHMENT_SEVERITY_FILTER, MCP_SERVER_VERSION, RECOVERY_WINDOW_MS, PORT_MIN, PORT_MAX;
|
|
117
|
+
var SUPPORTED_SOURCE_EXTENSIONS, BUILD_CACHE_DIRS, FALLBACK_SCAN_DIRS, MCP_SERVER_NAME, INITIAL_DISCOVERY_TIMEOUT_MS, LAZY_DISCOVERY_TIMEOUT_MS, CLIENT_FETCH_TIMEOUT_MS, HEALTH_CHECK_TIMEOUT_MS, DISCOVERY_POLL_INTERVAL_MS, MAX_DISCOVERY_DEPTH, MAX_TIMELINE_EVENTS, MAX_RESOLVED_DISPLAY, ENRICHMENT_SEVERITY_FILTER, MCP_SERVER_VERSION, RECOVERY_WINDOW_MS, PORT_MIN, PORT_MAX, DIR_MODE_OWNER_ONLY, FILE_MODE_OWNER_ONLY;
|
|
112
118
|
var init_features = __esm({
|
|
113
119
|
"src/constants/features.ts"() {
|
|
114
120
|
"use strict";
|
|
@@ -132,10 +138,12 @@ var init_features = __esm({
|
|
|
132
138
|
MAX_TIMELINE_EVENTS = 20;
|
|
133
139
|
MAX_RESOLVED_DISPLAY = 5;
|
|
134
140
|
ENRICHMENT_SEVERITY_FILTER = ["critical", "warning"];
|
|
135
|
-
MCP_SERVER_VERSION = "0.9.
|
|
141
|
+
MCP_SERVER_VERSION = "0.9.1";
|
|
136
142
|
RECOVERY_WINDOW_MS = 5 * 60 * 1e3;
|
|
137
143
|
PORT_MIN = 1;
|
|
138
144
|
PORT_MAX = 65535;
|
|
145
|
+
DIR_MODE_OWNER_ONLY = 448;
|
|
146
|
+
FILE_MODE_OWNER_ONLY = 384;
|
|
139
147
|
}
|
|
140
148
|
});
|
|
141
149
|
|
|
@@ -307,8 +315,8 @@ async function searchForPort(startDir) {
|
|
|
307
315
|
}
|
|
308
316
|
return null;
|
|
309
317
|
}
|
|
310
|
-
async function discoverBrakitPort(
|
|
311
|
-
const port = await searchForPort(
|
|
318
|
+
async function discoverBrakitPort(cwd2) {
|
|
319
|
+
const port = await searchForPort(cwd2 ?? process.cwd());
|
|
312
320
|
if (!port) {
|
|
313
321
|
throw new Error(
|
|
314
322
|
"Brakit is not running. Start your app with brakit enabled first."
|
|
@@ -316,11 +324,11 @@ async function discoverBrakitPort(cwd) {
|
|
|
316
324
|
}
|
|
317
325
|
return { port, baseUrl: `http://localhost:${port}` };
|
|
318
326
|
}
|
|
319
|
-
async function waitForBrakit(
|
|
327
|
+
async function waitForBrakit(cwd2, timeoutMs = 1e4, pollMs = DISCOVERY_POLL_INTERVAL_MS) {
|
|
320
328
|
const deadline = Date.now() + timeoutMs;
|
|
321
329
|
while (Date.now() < deadline) {
|
|
322
330
|
try {
|
|
323
|
-
const result = await discoverBrakitPort(
|
|
331
|
+
const result = await discoverBrakitPort(cwd2);
|
|
324
332
|
const res = await fetch(`${result.baseUrl}${DASHBOARD_API_REQUESTS}?limit=1`);
|
|
325
333
|
if (res.ok) return result;
|
|
326
334
|
} catch {
|
|
@@ -1047,6 +1055,8 @@ var init_server = __esm({
|
|
|
1047
1055
|
|
|
1048
1056
|
// bin/brakit.ts
|
|
1049
1057
|
import { runMain } from "citty";
|
|
1058
|
+
import { existsSync as existsSync7 } from "fs";
|
|
1059
|
+
import { resolve as resolve6 } from "path";
|
|
1050
1060
|
|
|
1051
1061
|
// src/cli/commands/install.ts
|
|
1052
1062
|
import { defineCommand } from "citty";
|
|
@@ -1563,7 +1573,7 @@ var stackTraceLeakRule = {
|
|
|
1563
1573
|
title: "Stack Trace Leaked to Client",
|
|
1564
1574
|
desc: `${ep} \u2014 response exposes internal stack trace`,
|
|
1565
1575
|
hint: this.hint,
|
|
1566
|
-
detail: firstLine ? `Stack trace: ${firstLine.slice(0,
|
|
1576
|
+
detail: firstLine ? `Stack trace: ${firstLine.slice(0, DETAIL_PREVIEW_LENGTH)}` : void 0,
|
|
1567
1577
|
endpoint: ep,
|
|
1568
1578
|
count: 1
|
|
1569
1579
|
}
|
|
@@ -1802,7 +1812,7 @@ init_constants();
|
|
|
1802
1812
|
init_endpoint();
|
|
1803
1813
|
|
|
1804
1814
|
// src/index.ts
|
|
1805
|
-
var VERSION = "0.9.
|
|
1815
|
+
var VERSION = "0.9.1";
|
|
1806
1816
|
|
|
1807
1817
|
// src/cli/commands/install.ts
|
|
1808
1818
|
init_constants();
|
|
@@ -2014,8 +2024,8 @@ async function setupNuxt(rootDir) {
|
|
|
2014
2024
|
}
|
|
2015
2025
|
const content = BRAKIT_TEMPLATES.nuxt + "\n";
|
|
2016
2026
|
const dir = join3(rootDir, "server/plugins");
|
|
2017
|
-
const { mkdirSync:
|
|
2018
|
-
|
|
2027
|
+
const { mkdirSync: mkdirSync4 } = await import("fs");
|
|
2028
|
+
mkdirSync4(dir, { recursive: true });
|
|
2019
2029
|
await writeFile3(absPath, content);
|
|
2020
2030
|
return { action: "created", file: relPath, content };
|
|
2021
2031
|
}
|
|
@@ -2114,13 +2124,118 @@ function printManualInstructions(framework) {
|
|
|
2114
2124
|
|
|
2115
2125
|
// src/cli/commands/uninstall.ts
|
|
2116
2126
|
import { defineCommand as defineCommand2 } from "citty";
|
|
2117
|
-
import { resolve as resolve4, join as
|
|
2127
|
+
import { resolve as resolve4, join as join5, relative as relative2 } from "path";
|
|
2118
2128
|
import { readFile as readFile5, writeFile as writeFile4, unlink, rm, readdir as readdir2 } from "fs/promises";
|
|
2119
2129
|
import { execSync as execSync2 } from "child_process";
|
|
2120
2130
|
import pc2 from "picocolors";
|
|
2121
2131
|
init_constants();
|
|
2122
2132
|
init_log();
|
|
2123
2133
|
init_type_guards();
|
|
2134
|
+
|
|
2135
|
+
// src/telemetry/index.ts
|
|
2136
|
+
import { platform as platform2, release, arch } from "os";
|
|
2137
|
+
import { spawn } from "child_process";
|
|
2138
|
+
|
|
2139
|
+
// src/telemetry/config.ts
|
|
2140
|
+
init_features();
|
|
2141
|
+
import { homedir as homedir2, platform } from "os";
|
|
2142
|
+
import { join as join4 } from "path";
|
|
2143
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
|
|
2144
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2145
|
+
var IS_WINDOWS = platform() === "win32";
|
|
2146
|
+
var CONFIG_DIR = join4(homedir2(), ".brakit");
|
|
2147
|
+
var CONFIG_PATH = join4(CONFIG_DIR, "config.json");
|
|
2148
|
+
function readConfig() {
|
|
2149
|
+
try {
|
|
2150
|
+
if (!existsSync6(CONFIG_PATH)) return null;
|
|
2151
|
+
return JSON.parse(readFileSync3(CONFIG_PATH, "utf-8"));
|
|
2152
|
+
} catch {
|
|
2153
|
+
return null;
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
function writeConfig(config) {
|
|
2157
|
+
try {
|
|
2158
|
+
if (!existsSync6(CONFIG_DIR))
|
|
2159
|
+
mkdirSync3(CONFIG_DIR, { recursive: true, ...IS_WINDOWS ? {} : { mode: DIR_MODE_OWNER_ONLY } });
|
|
2160
|
+
writeFileSync3(
|
|
2161
|
+
CONFIG_PATH,
|
|
2162
|
+
JSON.stringify(config, null, 2) + "\n",
|
|
2163
|
+
IS_WINDOWS ? {} : { mode: FILE_MODE_OWNER_ONLY }
|
|
2164
|
+
);
|
|
2165
|
+
} catch (err) {
|
|
2166
|
+
if (process.env.BRAKIT_DEBUG) {
|
|
2167
|
+
process.stderr.write(`[brakit] config write failed: ${err?.message ?? err}
|
|
2168
|
+
`);
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
function getOrCreateConfig() {
|
|
2173
|
+
const existing = readConfig();
|
|
2174
|
+
if (existing && typeof existing.telemetry === "boolean" && existing.anonymousId) {
|
|
2175
|
+
return existing;
|
|
2176
|
+
}
|
|
2177
|
+
const config = { telemetry: true, anonymousId: randomUUID2() };
|
|
2178
|
+
writeConfig(config);
|
|
2179
|
+
return config;
|
|
2180
|
+
}
|
|
2181
|
+
var cachedEnabled = null;
|
|
2182
|
+
function isTelemetryEnabled() {
|
|
2183
|
+
if (cachedEnabled !== null) return cachedEnabled;
|
|
2184
|
+
const env = process.env.BRAKIT_TELEMETRY;
|
|
2185
|
+
if (env !== void 0) {
|
|
2186
|
+
cachedEnabled = env !== "false" && env !== "0" && env !== "off";
|
|
2187
|
+
return cachedEnabled;
|
|
2188
|
+
}
|
|
2189
|
+
cachedEnabled = readConfig()?.telemetry ?? true;
|
|
2190
|
+
return cachedEnabled;
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
// src/telemetry/index.ts
|
|
2194
|
+
init_labels();
|
|
2195
|
+
init_config();
|
|
2196
|
+
var POSTHOG_KEY = "phc_E9TwydCGnSfPLIUhNxChpeg32TSowjk31KiPhnLPP0x";
|
|
2197
|
+
function commonProperties() {
|
|
2198
|
+
return {
|
|
2199
|
+
brakit_version: VERSION,
|
|
2200
|
+
node_version: process.version,
|
|
2201
|
+
os: `${platform2()}-${release()}`,
|
|
2202
|
+
arch: arch(),
|
|
2203
|
+
$lib: "brakit",
|
|
2204
|
+
$process_person_profile: false,
|
|
2205
|
+
$geoip_disable: true
|
|
2206
|
+
};
|
|
2207
|
+
}
|
|
2208
|
+
function sendToPosthog(event, properties) {
|
|
2209
|
+
if (!isTelemetryEnabled()) return;
|
|
2210
|
+
const config = getOrCreateConfig();
|
|
2211
|
+
const payload = {
|
|
2212
|
+
api_key: POSTHOG_KEY,
|
|
2213
|
+
event,
|
|
2214
|
+
distinct_id: config.anonymousId,
|
|
2215
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2216
|
+
properties: { ...commonProperties(), ...properties }
|
|
2217
|
+
};
|
|
2218
|
+
try {
|
|
2219
|
+
const body = JSON.stringify(payload);
|
|
2220
|
+
const url = `${POSTHOG_HOST}${POSTHOG_CAPTURE_PATH}`;
|
|
2221
|
+
const child = spawn(
|
|
2222
|
+
process.execPath,
|
|
2223
|
+
[
|
|
2224
|
+
"-e",
|
|
2225
|
+
`fetch(${JSON.stringify(url)},{method:"POST",headers:{"content-type":"application/json"},body:${JSON.stringify(body)},signal:AbortSignal.timeout(${POSTHOG_REQUEST_TIMEOUT_MS})}).catch(()=>{})`
|
|
2226
|
+
],
|
|
2227
|
+
{ detached: true, stdio: "ignore" }
|
|
2228
|
+
);
|
|
2229
|
+
child.unref();
|
|
2230
|
+
} catch {
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
function trackEvent(event, properties) {
|
|
2234
|
+
sendToPosthog(event, { sdk: "node", ...properties });
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
// src/cli/commands/uninstall.ts
|
|
2238
|
+
init_config();
|
|
2124
2239
|
var PREPENDED_FILES = [
|
|
2125
2240
|
"app/entry.server.tsx",
|
|
2126
2241
|
"app/entry.server.ts",
|
|
@@ -2155,16 +2270,20 @@ var uninstall_default = defineCommand2({
|
|
|
2155
2270
|
console.log();
|
|
2156
2271
|
console.log(pc2.bold(" \u25C6 brakit uninstall"));
|
|
2157
2272
|
console.log();
|
|
2273
|
+
let anyInstrumentationRemoved = false;
|
|
2274
|
+
let anyPackageRemoved = false;
|
|
2158
2275
|
for (const project of projects) {
|
|
2159
2276
|
const suffix = projects.length > 1 ? ` in ${relative2(rootDir, project.dir) || "."}` : "";
|
|
2160
2277
|
const removed = await removeInstrumentation(project.dir);
|
|
2161
2278
|
if (removed) {
|
|
2279
|
+
anyInstrumentationRemoved = true;
|
|
2162
2280
|
console.log(pc2.green(` \u2713 ${removed}${suffix}`));
|
|
2163
2281
|
} else {
|
|
2164
2282
|
console.log(pc2.dim(` No brakit instrumentation files found${suffix}.`));
|
|
2165
2283
|
}
|
|
2166
2284
|
const uninstalled = await uninstallPackage(project.dir, project.pm);
|
|
2167
2285
|
if (uninstalled === true) {
|
|
2286
|
+
anyPackageRemoved = true;
|
|
2168
2287
|
console.log(pc2.green(` \u2713 Removed brakit from devDependencies${suffix}`));
|
|
2169
2288
|
} else if (uninstalled === "failed") {
|
|
2170
2289
|
}
|
|
@@ -2185,6 +2304,12 @@ var uninstall_default = defineCommand2({
|
|
|
2185
2304
|
if (cacheCleared) {
|
|
2186
2305
|
console.log(pc2.green(" \u2713 Cleared build cache"));
|
|
2187
2306
|
}
|
|
2307
|
+
trackEvent(TELEMETRY_EVENT_CLI_UNINSTALL, {
|
|
2308
|
+
instrumentation_removed: anyInstrumentationRemoved,
|
|
2309
|
+
package_removed: anyPackageRemoved,
|
|
2310
|
+
mcp_removed: mcpRemoved,
|
|
2311
|
+
data_removed: dataRemoved
|
|
2312
|
+
});
|
|
2188
2313
|
console.log();
|
|
2189
2314
|
}
|
|
2190
2315
|
});
|
|
@@ -2195,7 +2320,7 @@ async function removeInstrumentation(projectDir) {
|
|
|
2195
2320
|
}
|
|
2196
2321
|
const candidates = [...PREPENDED_FILES];
|
|
2197
2322
|
try {
|
|
2198
|
-
const pkgRaw = await readFile5(
|
|
2323
|
+
const pkgRaw = await readFile5(join5(projectDir, "package.json"), "utf-8");
|
|
2199
2324
|
const pkg = JSON.parse(pkgRaw);
|
|
2200
2325
|
if (pkg.main) candidates.unshift(pkg.main);
|
|
2201
2326
|
} catch (err) {
|
|
@@ -2210,7 +2335,7 @@ async function removeInstrumentation(projectDir) {
|
|
|
2210
2335
|
return null;
|
|
2211
2336
|
}
|
|
2212
2337
|
async function tryRemoveBrakitFromFile(projectDir, relPath) {
|
|
2213
|
-
const absPath =
|
|
2338
|
+
const absPath = join5(projectDir, relPath);
|
|
2214
2339
|
if (!await fileExists(absPath)) return null;
|
|
2215
2340
|
const content = await readFile5(absPath, "utf-8");
|
|
2216
2341
|
if (!content.includes("brakit")) return null;
|
|
@@ -2227,7 +2352,7 @@ async function tryRemoveBrakitFromFile(projectDir, relPath) {
|
|
|
2227
2352
|
return null;
|
|
2228
2353
|
}
|
|
2229
2354
|
async function tryRemoveImportLine(projectDir, relPath) {
|
|
2230
|
-
const absPath =
|
|
2355
|
+
const absPath = join5(projectDir, relPath);
|
|
2231
2356
|
if (!await fileExists(absPath)) return null;
|
|
2232
2357
|
const content = await readFile5(absPath, "utf-8");
|
|
2233
2358
|
if (!content.includes(IMPORT_LINE)) return null;
|
|
@@ -2238,7 +2363,7 @@ async function tryRemoveImportLine(projectDir, relPath) {
|
|
|
2238
2363
|
async function fallbackSearchAndRemove(projectDir) {
|
|
2239
2364
|
const dirsToScan = FALLBACK_SCAN_DIRS;
|
|
2240
2365
|
for (const dir of dirsToScan) {
|
|
2241
|
-
const absDir =
|
|
2366
|
+
const absDir = join5(projectDir, dir);
|
|
2242
2367
|
if (!await fileExists(absDir)) continue;
|
|
2243
2368
|
let entries;
|
|
2244
2369
|
try {
|
|
@@ -2251,7 +2376,7 @@ async function fallbackSearchAndRemove(projectDir) {
|
|
|
2251
2376
|
const ext = entry.slice(entry.lastIndexOf("."));
|
|
2252
2377
|
if (!SUPPORTED_SOURCE_EXTENSIONS.has(ext)) continue;
|
|
2253
2378
|
const relPath = dir === "." ? entry : `${dir}/${entry}`;
|
|
2254
|
-
const absPath =
|
|
2379
|
+
const absPath = join5(projectDir, relPath);
|
|
2255
2380
|
try {
|
|
2256
2381
|
const content = await readFile5(absPath, "utf-8");
|
|
2257
2382
|
if (!containsBrakitImport(content)) continue;
|
|
@@ -2274,7 +2399,7 @@ async function fallbackSearchAndRemove(projectDir) {
|
|
|
2274
2399
|
return null;
|
|
2275
2400
|
}
|
|
2276
2401
|
async function removeMcpConfig(rootDir) {
|
|
2277
|
-
const mcpPath =
|
|
2402
|
+
const mcpPath = join5(rootDir, ".mcp.json");
|
|
2278
2403
|
if (!await fileExists(mcpPath)) return false;
|
|
2279
2404
|
try {
|
|
2280
2405
|
const raw = await readFile5(mcpPath, "utf-8");
|
|
@@ -2294,7 +2419,7 @@ async function removeMcpConfig(rootDir) {
|
|
|
2294
2419
|
}
|
|
2295
2420
|
async function uninstallPackage(rootDir, pm) {
|
|
2296
2421
|
try {
|
|
2297
|
-
const pkgRaw = await readFile5(
|
|
2422
|
+
const pkgRaw = await readFile5(join5(rootDir, "package.json"), "utf-8");
|
|
2298
2423
|
const pkg = JSON.parse(pkgRaw);
|
|
2299
2424
|
if (!pkg.devDependencies?.brakit && !pkg.dependencies?.brakit) return false;
|
|
2300
2425
|
} catch (err) {
|
|
@@ -2318,7 +2443,7 @@ async function uninstallPackage(rootDir, pm) {
|
|
|
2318
2443
|
}
|
|
2319
2444
|
async function removeBrakitData(rootDir) {
|
|
2320
2445
|
let removed = false;
|
|
2321
|
-
const projectDir =
|
|
2446
|
+
const projectDir = join5(rootDir, METRICS_DIR);
|
|
2322
2447
|
if (await fileExists(projectDir)) {
|
|
2323
2448
|
try {
|
|
2324
2449
|
await rm(projectDir, { recursive: true, force: true });
|
|
@@ -2339,7 +2464,7 @@ async function removeBrakitData(rootDir) {
|
|
|
2339
2464
|
return removed;
|
|
2340
2465
|
}
|
|
2341
2466
|
async function cleanGitignore(rootDir) {
|
|
2342
|
-
const gitignorePath =
|
|
2467
|
+
const gitignorePath = join5(rootDir, ".gitignore");
|
|
2343
2468
|
if (!await fileExists(gitignorePath)) return false;
|
|
2344
2469
|
try {
|
|
2345
2470
|
const content = await readFile5(gitignorePath, "utf-8");
|
|
@@ -2356,7 +2481,7 @@ async function cleanGitignore(rootDir) {
|
|
|
2356
2481
|
async function clearBuildCaches(rootDir) {
|
|
2357
2482
|
let cleared = false;
|
|
2358
2483
|
for (const dir of BUILD_CACHE_DIRS) {
|
|
2359
|
-
const absDir =
|
|
2484
|
+
const absDir = join5(rootDir, dir);
|
|
2360
2485
|
if (!await fileExists(absDir)) continue;
|
|
2361
2486
|
try {
|
|
2362
2487
|
await rm(absDir, { recursive: true, force: true });
|
|
@@ -2369,7 +2494,15 @@ async function clearBuildCaches(rootDir) {
|
|
|
2369
2494
|
}
|
|
2370
2495
|
|
|
2371
2496
|
// bin/brakit.ts
|
|
2497
|
+
init_config();
|
|
2372
2498
|
var sub = process.argv[2];
|
|
2499
|
+
var command = sub === "uninstall" ? "uninstall" : sub === "mcp" ? "mcp" : "install";
|
|
2500
|
+
var cwd = process.cwd();
|
|
2501
|
+
trackEvent(TELEMETRY_EVENT_CLI_INVOKED, {
|
|
2502
|
+
command,
|
|
2503
|
+
has_package_json: existsSync7(resolve6(cwd, "package.json")),
|
|
2504
|
+
cwd_has_node_modules: existsSync7(resolve6(cwd, "node_modules"))
|
|
2505
|
+
});
|
|
2373
2506
|
if (sub === "uninstall") {
|
|
2374
2507
|
process.argv.splice(2, 1);
|
|
2375
2508
|
runMain(uninstall_default);
|