@massu/core 1.6.0 → 1.6.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/cli.js +255 -1451
- package/dist/hooks/session-start.js +10 -15
- package/docs/AUTHORING-ADAPTERS.md +41 -0
- package/docs/SECURITY.md +39 -0
- package/package.json +3 -3
- package/src/security/registry-pubkey.generated.ts +1 -1
package/dist/cli.js
CHANGED
|
@@ -11159,1239 +11159,43 @@ var init_python_flask = __esm({
|
|
|
11159
11159
|
}
|
|
11160
11160
|
});
|
|
11161
11161
|
|
|
11162
|
-
//
|
|
11163
|
-
import {
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
readdirSync as readdirSync9,
|
|
11168
|
-
readFileSync as readFileSync9,
|
|
11169
|
-
writeFileSync as writeFileSync2,
|
|
11170
|
-
renameSync as renameSync3,
|
|
11171
|
-
unlinkSync as unlinkSync2,
|
|
11172
|
-
lstatSync as lstatSync4,
|
|
11173
|
-
chmodSync as chmodSync2,
|
|
11174
|
-
utimesSync as utimesSync2
|
|
11175
|
-
} from "fs";
|
|
11176
|
-
import { homedir as homedir3 } from "os";
|
|
11177
|
-
import { dirname as dirname5, join as join9 } from "path";
|
|
11178
|
-
import { Language as Language2, Parser as Parser7 } from "web-tree-sitter";
|
|
11179
|
-
function compileQuery2(language, source, queryName) {
|
|
11180
|
-
let perLang = queryCache2.get(language);
|
|
11181
|
-
if (!perLang) {
|
|
11182
|
-
perLang = /* @__PURE__ */ new Map();
|
|
11183
|
-
queryCache2.set(language, perLang);
|
|
11184
|
-
}
|
|
11185
|
-
const cached = perLang.get(source);
|
|
11186
|
-
if (cached) return cached;
|
|
11187
|
-
let q2;
|
|
11188
|
-
try {
|
|
11189
|
-
q2 = new Query2(language, source);
|
|
11190
|
-
} catch (e2) {
|
|
11191
|
-
throw new InvalidQueryError2(queryName, source, e2);
|
|
11192
|
-
}
|
|
11193
|
-
perLang.set(source, q2);
|
|
11194
|
-
return q2;
|
|
11195
|
-
}
|
|
11196
|
-
function runQuery2(parser, source, queryText, queryName, filePath) {
|
|
11197
|
-
const language = parser.language;
|
|
11198
|
-
if (!language) {
|
|
11199
|
-
throw new InvalidQueryError2(
|
|
11200
|
-
queryName,
|
|
11201
|
-
queryText,
|
|
11202
|
-
new Error("Parser has no language assigned")
|
|
11203
|
-
);
|
|
11204
|
-
}
|
|
11205
|
-
const query = compileQuery2(language, queryText, queryName);
|
|
11206
|
-
const tree = parser.parse(source);
|
|
11207
|
-
if (!tree) return [];
|
|
11208
|
-
let matches;
|
|
11209
|
-
try {
|
|
11210
|
-
matches = query.matches(tree.rootNode);
|
|
11211
|
-
} catch (e2) {
|
|
11212
|
-
throw new InvalidQueryError2(queryName, queryText, e2);
|
|
11213
|
-
}
|
|
11214
|
-
const out = [];
|
|
11215
|
-
for (const match of matches) {
|
|
11216
|
-
if (!match.captures || match.captures.length === 0) continue;
|
|
11217
|
-
const captures = {};
|
|
11218
|
-
let earliestLine = Number.POSITIVE_INFINITY;
|
|
11219
|
-
for (const cap of match.captures) {
|
|
11220
|
-
const node = cap.node;
|
|
11221
|
-
captures[cap.name] = node.text;
|
|
11222
|
-
if (node.startPosition.row + 1 < earliestLine) {
|
|
11223
|
-
earliestLine = node.startPosition.row + 1;
|
|
11224
|
-
}
|
|
11225
|
-
}
|
|
11226
|
-
out.push({
|
|
11227
|
-
captures,
|
|
11228
|
-
file: filePath,
|
|
11229
|
-
line: Number.isFinite(earliestLine) ? earliestLine : 1,
|
|
11230
|
-
queryName
|
|
11231
|
-
});
|
|
11232
|
-
}
|
|
11233
|
-
try {
|
|
11234
|
-
tree.delete();
|
|
11235
|
-
} catch {
|
|
11236
|
-
}
|
|
11237
|
-
return out;
|
|
11238
|
-
}
|
|
11239
|
-
function getCacheDir2() {
|
|
11240
|
-
return process.env.MASSU_WASM_CACHE_DIR ?? join9(homedir3(), ".massu", "wasm-cache");
|
|
11241
|
-
}
|
|
11242
|
-
function getCachedPath2(language, sha) {
|
|
11243
|
-
return join9(getCacheDir2(), `${language}-${sha}.wasm`);
|
|
11244
|
-
}
|
|
11245
|
-
function getCacheRetainCount2() {
|
|
11246
|
-
const env = process.env.MASSU_WASM_CACHE_RETAIN;
|
|
11247
|
-
if (env) {
|
|
11248
|
-
const n = Number(env);
|
|
11249
|
-
if (Number.isFinite(n) && n >= 1 && n <= 1024) return Math.floor(n);
|
|
11250
|
-
}
|
|
11251
|
-
return DEFAULT_CACHE_RETAIN_COUNT2;
|
|
11252
|
-
}
|
|
11253
|
-
function touchCacheFile2(path) {
|
|
11254
|
-
try {
|
|
11255
|
-
const now = /* @__PURE__ */ new Date();
|
|
11256
|
-
utimesSync2(path, now, now);
|
|
11257
|
-
} catch {
|
|
11258
|
-
}
|
|
11259
|
-
}
|
|
11260
|
-
function evictBeyondRetainCount2(retain = getCacheRetainCount2()) {
|
|
11261
|
-
const dir = getCacheDir2();
|
|
11262
|
-
let entries;
|
|
11263
|
-
try {
|
|
11264
|
-
entries = readdirSync9(dir);
|
|
11265
|
-
} catch {
|
|
11266
|
-
return;
|
|
11267
|
-
}
|
|
11268
|
-
const candidates = [];
|
|
11269
|
-
for (const name of entries) {
|
|
11270
|
-
if (!name.endsWith(".wasm")) continue;
|
|
11271
|
-
const path = join9(dir, name);
|
|
11272
|
-
let stat;
|
|
11273
|
-
try {
|
|
11274
|
-
stat = lstatSync4(path);
|
|
11275
|
-
} catch {
|
|
11276
|
-
continue;
|
|
11277
|
-
}
|
|
11278
|
-
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
11279
|
-
console.error(
|
|
11280
|
-
`[tree-sitter-loader] cache eviction skipped non-regular file: ${path} (possible symlink attack \u2014 see Phase 3.5 finding F-008).`
|
|
11281
|
-
);
|
|
11282
|
-
continue;
|
|
11283
|
-
}
|
|
11284
|
-
candidates.push({ path, mtimeMs: stat.mtimeMs });
|
|
11285
|
-
}
|
|
11286
|
-
if (candidates.length <= retain) return;
|
|
11287
|
-
candidates.sort((a2, b2) => b2.mtimeMs - a2.mtimeMs);
|
|
11288
|
-
for (const victim of candidates.slice(retain)) {
|
|
11289
|
-
try {
|
|
11290
|
-
unlinkSync2(victim.path);
|
|
11291
|
-
} catch {
|
|
11292
|
-
}
|
|
11293
|
-
}
|
|
11294
|
-
}
|
|
11295
|
-
function sha2562(bytes) {
|
|
11296
|
-
return createHash3("sha256").update(bytes).digest("hex");
|
|
11297
|
-
}
|
|
11298
|
-
async function ensureParserInitialized2() {
|
|
11299
|
-
if (parserInitPromise2) return parserInitPromise2;
|
|
11300
|
-
parserInitPromise2 = Parser7.init();
|
|
11301
|
-
return parserInitPromise2;
|
|
11302
|
-
}
|
|
11303
|
-
async function loadGrammar2(language, options = {}) {
|
|
11304
|
-
await ensureParserInitialized2();
|
|
11305
|
-
const cached = loadedGrammars2.get(language);
|
|
11306
|
-
if (cached) return cached;
|
|
11307
|
-
const manifest = options.manifestOverride?.[language] ?? GRAMMAR_MANIFEST2[language];
|
|
11308
|
-
if (!manifest) {
|
|
11309
|
-
throw new GrammarUnavailableError2(
|
|
11310
|
-
language,
|
|
11311
|
-
new Error(`No manifest entry for language "${language}". v1 supports: ${Object.keys(GRAMMAR_MANIFEST2).join(", ")}.`)
|
|
11312
|
-
);
|
|
11313
|
-
}
|
|
11314
|
-
const cachePath = getCachedPath2(language, manifest.sha256);
|
|
11315
|
-
let cacheLstat;
|
|
11316
|
-
try {
|
|
11317
|
-
cacheLstat = lstatSync4(cachePath);
|
|
11318
|
-
} catch {
|
|
11319
|
-
cacheLstat = null;
|
|
11320
|
-
}
|
|
11321
|
-
if (cacheLstat) {
|
|
11322
|
-
if (cacheLstat.isSymbolicLink() || !cacheLstat.isFile()) {
|
|
11323
|
-
throw new GrammarCacheSymlinkError2(cachePath);
|
|
11324
|
-
}
|
|
11325
|
-
let bytes;
|
|
11326
|
-
try {
|
|
11327
|
-
bytes = readFileSync9(cachePath);
|
|
11328
|
-
} catch (e2) {
|
|
11329
|
-
bytes = new Uint8Array(0);
|
|
11330
|
-
}
|
|
11331
|
-
if (bytes.byteLength > 0) {
|
|
11332
|
-
const actualSha = sha2562(bytes);
|
|
11333
|
-
if (actualSha !== manifest.sha256) {
|
|
11334
|
-
throw new GrammarSHAMismatchError2(language, manifest.sha256, actualSha);
|
|
11335
|
-
}
|
|
11336
|
-
const lang2 = await Language2.load(bytes);
|
|
11337
|
-
loadedGrammars2.set(language, lang2);
|
|
11338
|
-
touchCacheFile2(cachePath);
|
|
11339
|
-
return lang2;
|
|
11340
|
-
}
|
|
11341
|
-
}
|
|
11342
|
-
if (!/^https:\/\//i.test(manifest.url)) {
|
|
11343
|
-
throw new GrammarUrlNotHttpsError2(manifest.url);
|
|
11344
|
-
}
|
|
11345
|
-
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
11346
|
-
if (!fetchImpl) {
|
|
11347
|
-
throw new GrammarUnavailableError2(
|
|
11348
|
-
language,
|
|
11349
|
-
new Error("No fetch implementation available (Node < 18?)")
|
|
11350
|
-
);
|
|
11351
|
-
}
|
|
11352
|
-
let body;
|
|
11353
|
-
try {
|
|
11354
|
-
const res = await fetchImpl(manifest.url);
|
|
11355
|
-
if (!res.ok) {
|
|
11356
|
-
throw new Error(`HTTP ${res.status ?? "unknown"} from ${manifest.url}`);
|
|
11357
|
-
}
|
|
11358
|
-
body = new Uint8Array(await res.arrayBuffer());
|
|
11359
|
-
} catch (e2) {
|
|
11360
|
-
throw new GrammarUnavailableError2(language, e2);
|
|
11361
|
-
}
|
|
11362
|
-
const downloadedSha = sha2562(body);
|
|
11363
|
-
if (downloadedSha !== manifest.sha256) {
|
|
11364
|
-
throw new GrammarSHAMismatchError2(language, manifest.sha256, downloadedSha);
|
|
11365
|
-
}
|
|
11366
|
-
try {
|
|
11367
|
-
mkdirSync4(dirname5(cachePath), { recursive: true, mode: 448 });
|
|
11368
|
-
try {
|
|
11369
|
-
chmodSync2(dirname5(cachePath), 448);
|
|
11370
|
-
} catch {
|
|
11371
|
-
}
|
|
11372
|
-
const tmpPath = `${cachePath}.tmp.${process.pid}`;
|
|
11373
|
-
writeFileSync2(tmpPath, body, { mode: 384 });
|
|
11374
|
-
try {
|
|
11375
|
-
chmodSync2(tmpPath, 384);
|
|
11376
|
-
} catch {
|
|
11377
|
-
}
|
|
11378
|
-
try {
|
|
11379
|
-
renameSync3(tmpPath, cachePath);
|
|
11380
|
-
try {
|
|
11381
|
-
chmodSync2(cachePath, 384);
|
|
11382
|
-
} catch {
|
|
11383
|
-
}
|
|
11384
|
-
} catch (e2) {
|
|
11385
|
-
try {
|
|
11386
|
-
unlinkSync2(tmpPath);
|
|
11387
|
-
} catch {
|
|
11388
|
-
}
|
|
11389
|
-
throw e2;
|
|
11390
|
-
}
|
|
11391
|
-
evictBeyondRetainCount2();
|
|
11392
|
-
} catch (e2) {
|
|
11393
|
-
console.error(
|
|
11394
|
-
`[tree-sitter-loader] cache write failed for ${language}: ${e2 instanceof Error ? e2.message : String(e2)} \u2014 loading directly from memory.`
|
|
11395
|
-
);
|
|
11396
|
-
}
|
|
11397
|
-
const lang = await Language2.load(body);
|
|
11398
|
-
loadedGrammars2.set(language, lang);
|
|
11399
|
-
return lang;
|
|
11400
|
-
}
|
|
11401
|
-
function isParsableSource2(source, sizeBytes) {
|
|
11402
|
-
const bytes = sizeBytes ?? Buffer.byteLength(source, "utf-8");
|
|
11403
|
-
if (bytes > MAX_AST_FILE_BYTES2) {
|
|
11404
|
-
return {
|
|
11405
|
-
reason: "size-cap",
|
|
11406
|
-
detail: `${bytes} bytes > ${MAX_AST_FILE_BYTES2} cap`
|
|
11407
|
-
};
|
|
11408
|
-
}
|
|
11409
|
-
let depth = 0;
|
|
11410
|
-
let maxDepth = 0;
|
|
11411
|
-
for (let i = 0; i < source.length; i++) {
|
|
11412
|
-
const c2 = source.charCodeAt(i);
|
|
11413
|
-
if (c2 === 0) {
|
|
11414
|
-
return { reason: "control-bytes", detail: "NUL byte at offset " + i };
|
|
11415
|
-
}
|
|
11416
|
-
if (c2 === 40 || c2 === 91 || c2 === 123) {
|
|
11417
|
-
depth++;
|
|
11418
|
-
if (depth > maxDepth) maxDepth = depth;
|
|
11419
|
-
if (depth > MAX_AST_PARSE_DEPTH2) {
|
|
11420
|
-
return {
|
|
11421
|
-
reason: "depth-cap",
|
|
11422
|
-
detail: `nesting depth exceeded ${MAX_AST_PARSE_DEPTH2}`
|
|
11423
|
-
};
|
|
11424
|
-
}
|
|
11425
|
-
} else if (c2 === 41 || c2 === 93 || c2 === 125) {
|
|
11426
|
-
depth = depth > 0 ? depth - 1 : 0;
|
|
11427
|
-
}
|
|
11428
|
-
}
|
|
11429
|
-
return null;
|
|
11430
|
-
}
|
|
11431
|
-
var InvalidQueryError2, queryCache2, GrammarSHAMismatchError2, GrammarUnavailableError2, GrammarCacheSymlinkError2, GrammarUrlNotHttpsError2, GRAMMAR_MANIFEST2, DEFAULT_CACHE_RETAIN_COUNT2, parserInitPromise2, loadedGrammars2, MAX_AST_FILE_BYTES2, MAX_AST_PARSE_DEPTH2;
|
|
11432
|
-
var init_adapter = __esm({
|
|
11433
|
-
"dist/adapter.js"() {
|
|
11434
|
-
"use strict";
|
|
11435
|
-
InvalidQueryError2 = class extends Error {
|
|
11436
|
-
queryName;
|
|
11437
|
-
querySource;
|
|
11438
|
-
cause;
|
|
11439
|
-
constructor(queryName, querySource, cause) {
|
|
11440
|
-
const causeMsg = cause instanceof Error ? cause.message : String(cause);
|
|
11441
|
-
super(
|
|
11442
|
-
`[query-helpers] Invalid Tree-sitter query "${queryName}": ${causeMsg}
|
|
11443
|
-
Query source:
|
|
11444
|
-
${querySource}`
|
|
11445
|
-
);
|
|
11446
|
-
this.name = "InvalidQueryError";
|
|
11447
|
-
this.queryName = queryName;
|
|
11448
|
-
this.querySource = querySource;
|
|
11449
|
-
this.cause = cause;
|
|
11450
|
-
}
|
|
11451
|
-
};
|
|
11452
|
-
queryCache2 = /* @__PURE__ */ new WeakMap();
|
|
11453
|
-
GrammarSHAMismatchError2 = class extends Error {
|
|
11454
|
-
language;
|
|
11455
|
-
expected;
|
|
11456
|
-
actual;
|
|
11457
|
-
constructor(language, expected, actual) {
|
|
11458
|
-
super(
|
|
11459
|
-
`[tree-sitter-loader] SHA-256 mismatch for grammar "${language}". Expected ${expected}, got ${actual}. REFUSING to load \u2014 see Phase 3.5 audit attack vector #3.`
|
|
11460
|
-
);
|
|
11461
|
-
this.name = "GrammarSHAMismatchError";
|
|
11462
|
-
this.language = language;
|
|
11463
|
-
this.expected = expected;
|
|
11464
|
-
this.actual = actual;
|
|
11465
|
-
}
|
|
11466
|
-
};
|
|
11467
|
-
GrammarUnavailableError2 = class extends Error {
|
|
11468
|
-
language;
|
|
11469
|
-
cause;
|
|
11470
|
-
constructor(language, cause) {
|
|
11471
|
-
const causeMsg = cause instanceof Error ? cause.message : cause ? String(cause) : "no cached grammar and download failed";
|
|
11472
|
-
super(
|
|
11473
|
-
`[tree-sitter-loader] Grammar for "${language}" is unavailable: ${causeMsg}. Falling back to regex introspection for files in ${language}.`
|
|
11474
|
-
);
|
|
11475
|
-
this.name = "GrammarUnavailableError";
|
|
11476
|
-
this.language = language;
|
|
11477
|
-
this.cause = cause;
|
|
11478
|
-
}
|
|
11479
|
-
};
|
|
11480
|
-
GrammarCacheSymlinkError2 = class extends Error {
|
|
11481
|
-
cachePath;
|
|
11482
|
-
constructor(cachePath) {
|
|
11483
|
-
super(
|
|
11484
|
-
`[tree-sitter-loader] Refusing to load grammar \u2014 cache path "${cachePath}" is a symlink or non-regular file. (Phase 3.5 finding #3 \u2014 symlink attack vector.)`
|
|
11485
|
-
);
|
|
11486
|
-
this.name = "GrammarCacheSymlinkError";
|
|
11487
|
-
this.cachePath = cachePath;
|
|
11488
|
-
}
|
|
11489
|
-
};
|
|
11490
|
-
GrammarUrlNotHttpsError2 = class extends Error {
|
|
11491
|
-
url;
|
|
11492
|
-
constructor(url) {
|
|
11493
|
-
super(
|
|
11494
|
-
`[tree-sitter-loader] Refusing to download grammar from non-HTTPS URL: ${url}. Only https:// URLs are accepted. (Phase 3.5 finding #3.)`
|
|
11495
|
-
);
|
|
11496
|
-
this.name = "GrammarUrlNotHttpsError";
|
|
11497
|
-
this.url = url;
|
|
11498
|
-
}
|
|
11499
|
-
};
|
|
11500
|
-
GRAMMAR_MANIFEST2 = {
|
|
11501
|
-
python: {
|
|
11502
|
-
url: "https://unpkg.com/tree-sitter-wasms@0.1.13/out/tree-sitter-python.wasm",
|
|
11503
|
-
sha256: "9056d0fb0c337810d019fae350e8167786119da98f0f282aceae7ab89ee8253b",
|
|
11504
|
-
version: "0.1.13"
|
|
11505
|
-
},
|
|
11506
|
-
typescript: {
|
|
11507
|
-
url: "https://unpkg.com/tree-sitter-wasms@0.1.13/out/tree-sitter-typescript.wasm",
|
|
11508
|
-
sha256: "8515404dceed38e1ed86aa34b09fcf3379fff1b4ff9dd3967bcd6d1eb5ac3d8f",
|
|
11509
|
-
version: "0.1.13"
|
|
11510
|
-
},
|
|
11511
|
-
javascript: {
|
|
11512
|
-
url: "https://unpkg.com/tree-sitter-wasms@0.1.13/out/tree-sitter-javascript.wasm",
|
|
11513
|
-
sha256: "63812b9e275d26851264734868d27a1656bd44a2ef6eb3e85e6b03728c595ab5",
|
|
11514
|
-
version: "0.1.13"
|
|
11515
|
-
},
|
|
11516
|
-
swift: {
|
|
11517
|
-
url: "https://unpkg.com/tree-sitter-wasms@0.1.13/out/tree-sitter-swift.wasm",
|
|
11518
|
-
sha256: "41c4fdb2249a3aa6d87eed0d383081ff09725c2248b4977043a43825980ffcc7",
|
|
11519
|
-
version: "0.1.13"
|
|
11520
|
-
},
|
|
11521
|
-
// ----------------------------------------------------------------
|
|
11522
|
-
// Plan 3c Phase 7 expansion (2026-05-07):
|
|
11523
|
-
//
|
|
11524
|
-
// Six additional grammars to support the registry-verified framework
|
|
11525
|
-
// adapters (go-chi, rails, aspnet, spring, ktor, phoenix) plus the
|
|
11526
|
-
// bundled adapters in the same language families (gin/echo/fiber,
|
|
11527
|
-
// sinatra, etc.). All entries use the SAME pinned tree-sitter-wasms
|
|
11528
|
-
// version (0.1.13) as the v1 four to keep the dependency surface
|
|
11529
|
-
// single-source.
|
|
11530
|
-
//
|
|
11531
|
-
// SHA-256s computed 2026-05-07 via:
|
|
11532
|
-
// curl -fsSL <url> | shasum -a 256
|
|
11533
|
-
//
|
|
11534
|
-
// The unpkg filename for C# uses an underscore (`c_sharp`) while the
|
|
11535
|
-
// TreeSitterLanguage identifier uses no separator (`csharp`); the map
|
|
11536
|
-
// key is the type identifier, the URL is the storage path — they do
|
|
11537
|
-
// NOT need to match, the same as how `python` maps to `tree-sitter-
|
|
11538
|
-
// python.wasm`. This is intentional and validated by the manifest
|
|
11539
|
-
// shape test in tree-sitter-loader-manifest.test.ts.
|
|
11540
|
-
// ----------------------------------------------------------------
|
|
11541
|
-
go: {
|
|
11542
|
-
url: "https://unpkg.com/tree-sitter-wasms@0.1.13/out/tree-sitter-go.wasm",
|
|
11543
|
-
sha256: "9963ca89b616eaf04b08a43bc1fb0f07b85395bec313330851f1f1ead2f755b6",
|
|
11544
|
-
version: "0.1.13"
|
|
11545
|
-
},
|
|
11546
|
-
ruby: {
|
|
11547
|
-
url: "https://unpkg.com/tree-sitter-wasms@0.1.13/out/tree-sitter-ruby.wasm",
|
|
11548
|
-
sha256: "93a5022855314cdb45458c7bb026a24a0ebc3a5ff6439e542e881f14dfa13a39",
|
|
11549
|
-
version: "0.1.13"
|
|
11550
|
-
},
|
|
11551
|
-
csharp: {
|
|
11552
|
-
url: "https://unpkg.com/tree-sitter-wasms@0.1.13/out/tree-sitter-c_sharp.wasm",
|
|
11553
|
-
sha256: "6266a7e32d68a3459104d994dc848df15d5672b0ea8e86d327274b694f8e6991",
|
|
11554
|
-
version: "0.1.13"
|
|
11555
|
-
},
|
|
11556
|
-
java: {
|
|
11557
|
-
url: "https://unpkg.com/tree-sitter-wasms@0.1.13/out/tree-sitter-java.wasm",
|
|
11558
|
-
sha256: "637aac4415fb39a211a4f4292d63c66b5ce9c32fa2cd35464af4f681d91b9a1f",
|
|
11559
|
-
version: "0.1.13"
|
|
11560
|
-
},
|
|
11561
|
-
kotlin: {
|
|
11562
|
-
url: "https://unpkg.com/tree-sitter-wasms@0.1.13/out/tree-sitter-kotlin.wasm",
|
|
11563
|
-
sha256: "b5cb00c8d06ed0f10f1dbe497205b437809d7e87db1f638721a8cfb30e044449",
|
|
11564
|
-
version: "0.1.13"
|
|
11565
|
-
},
|
|
11566
|
-
elixir: {
|
|
11567
|
-
url: "https://unpkg.com/tree-sitter-wasms@0.1.13/out/tree-sitter-elixir.wasm",
|
|
11568
|
-
sha256: "82e91b9759ddca30d8978ebbfa8e347b4451b64c931f9ae62112e6db9b8fac20",
|
|
11569
|
-
version: "0.1.13"
|
|
11570
|
-
}
|
|
11571
|
-
};
|
|
11572
|
-
DEFAULT_CACHE_RETAIN_COUNT2 = 16;
|
|
11573
|
-
parserInitPromise2 = null;
|
|
11574
|
-
loadedGrammars2 = /* @__PURE__ */ new Map();
|
|
11575
|
-
MAX_AST_FILE_BYTES2 = 1 * 1024 * 1024;
|
|
11576
|
-
MAX_AST_PARSE_DEPTH2 = 5e3;
|
|
11577
|
-
}
|
|
11578
|
-
});
|
|
11579
|
-
|
|
11580
|
-
// ../adapter-go-chi/dist/index.js
|
|
11581
|
-
import { Parser as Parser8 } from "web-tree-sitter";
|
|
11582
|
-
function extractPrefixBase4(prefix3) {
|
|
11583
|
-
if (!prefix3.startsWith("/"))
|
|
11584
|
-
return null;
|
|
11585
|
-
const stripped = prefix3.replace(/^\/+/, "");
|
|
11586
|
-
const firstSeg = stripped.split("/")[0];
|
|
11587
|
-
if (!firstSeg)
|
|
11588
|
-
return null;
|
|
11589
|
-
return "/" + firstSeg;
|
|
11590
|
-
}
|
|
11591
|
-
var ROUTE_METHOD_QUERY, MOUNT_PREFIX_QUERY, MIDDLEWARE_USE_QUERY, goChiAdapter;
|
|
11592
|
-
var init_dist = __esm({
|
|
11593
|
-
"../adapter-go-chi/dist/index.js"() {
|
|
11594
|
-
"use strict";
|
|
11595
|
-
init_adapter();
|
|
11596
|
-
ROUTE_METHOD_QUERY = `
|
|
11597
|
-
(call_expression
|
|
11598
|
-
function: (selector_expression
|
|
11599
|
-
field: (field_identifier) @method (#match? @method "^(Get|Post|Put|Delete|Patch|Head|Options|Connect|Trace)$"))
|
|
11600
|
-
arguments: (argument_list
|
|
11601
|
-
.
|
|
11602
|
-
(interpreted_string_literal) @route_path))
|
|
11603
|
-
`;
|
|
11604
|
-
MOUNT_PREFIX_QUERY = `
|
|
11605
|
-
(call_expression
|
|
11606
|
-
function: (selector_expression
|
|
11607
|
-
field: (field_identifier) @_field (#eq? @_field "Mount"))
|
|
11608
|
-
arguments: (argument_list
|
|
11609
|
-
.
|
|
11610
|
-
(interpreted_string_literal) @mount_path))
|
|
11611
|
-
`;
|
|
11612
|
-
MIDDLEWARE_USE_QUERY = `
|
|
11613
|
-
(call_expression
|
|
11614
|
-
function: (selector_expression
|
|
11615
|
-
field: (field_identifier) @_use (#eq? @_use "Use"))
|
|
11616
|
-
arguments: (argument_list
|
|
11617
|
-
.
|
|
11618
|
-
(selector_expression
|
|
11619
|
-
operand: (identifier) @_pkg (#eq? @_pkg "middleware")
|
|
11620
|
-
field: (field_identifier) @middleware_name)))
|
|
11621
|
-
`;
|
|
11622
|
-
goChiAdapter = {
|
|
11623
|
-
id: "go-chi",
|
|
11624
|
-
languages: ["go"],
|
|
11625
|
-
matches(signals) {
|
|
11626
|
-
if (!signals.goMod)
|
|
11627
|
-
return false;
|
|
11628
|
-
if (/github\.com\/go-chi\/chi/i.test(signals.goMod))
|
|
11629
|
-
return true;
|
|
11630
|
-
return false;
|
|
11631
|
-
},
|
|
11632
|
-
async introspect(files, _rootDir) {
|
|
11633
|
-
if (files.length === 0) {
|
|
11634
|
-
return { conventions: {}, provenance: [], confidence: "none" };
|
|
11635
|
-
}
|
|
11636
|
-
let language;
|
|
11637
|
-
try {
|
|
11638
|
-
language = await loadGrammar2("go");
|
|
11639
|
-
} catch (e2) {
|
|
11640
|
-
return { conventions: {}, provenance: [], confidence: "none" };
|
|
11641
|
-
}
|
|
11642
|
-
const parser = new Parser8();
|
|
11643
|
-
parser.setLanguage(language);
|
|
11644
|
-
const routeMethods = /* @__PURE__ */ new Map();
|
|
11645
|
-
const mountBases = /* @__PURE__ */ new Map();
|
|
11646
|
-
const middlewareNames = /* @__PURE__ */ new Map();
|
|
11647
|
-
try {
|
|
11648
|
-
for (const file of files) {
|
|
11649
|
-
const skip = isParsableSource2(file.content, file.size);
|
|
11650
|
-
if (skip) {
|
|
11651
|
-
process.stderr.write(`[massu/ast] WARN: go-chi skipping ${file.path}: ${skip.reason} (${skip.detail}). Cap=${MAX_AST_FILE_BYTES2}. (Phase 3.5 mitigation)
|
|
11652
|
-
`);
|
|
11653
|
-
continue;
|
|
11654
|
-
}
|
|
11655
|
-
try {
|
|
11656
|
-
for (const hit of runQuery2(parser, file.content, ROUTE_METHOD_QUERY, "chi-route-method", file.path)) {
|
|
11657
|
-
const method = hit.captures.method;
|
|
11658
|
-
if (method && !routeMethods.has(method)) {
|
|
11659
|
-
routeMethods.set(method, { line: hit.line, file: file.path });
|
|
11660
|
-
}
|
|
11661
|
-
}
|
|
11662
|
-
for (const hit of runQuery2(parser, file.content, MOUNT_PREFIX_QUERY, "chi-mount-prefix", file.path)) {
|
|
11663
|
-
const raw = hit.captures.mount_path;
|
|
11664
|
-
if (!raw)
|
|
11665
|
-
continue;
|
|
11666
|
-
const literal = raw.replace(/^["`]/, "").replace(/["`]$/, "");
|
|
11667
|
-
const base = extractPrefixBase4(literal);
|
|
11668
|
-
if (base && !mountBases.has(base)) {
|
|
11669
|
-
mountBases.set(base, { line: hit.line, file: file.path });
|
|
11670
|
-
}
|
|
11671
|
-
}
|
|
11672
|
-
for (const hit of runQuery2(parser, file.content, MIDDLEWARE_USE_QUERY, "chi-middleware-use", file.path)) {
|
|
11673
|
-
const name = hit.captures.middleware_name;
|
|
11674
|
-
if (name && !middlewareNames.has(name)) {
|
|
11675
|
-
middlewareNames.set(name, { line: hit.line, file: file.path });
|
|
11676
|
-
}
|
|
11677
|
-
}
|
|
11678
|
-
} catch (e2) {
|
|
11679
|
-
if (e2 instanceof InvalidQueryError2) {
|
|
11680
|
-
throw e2;
|
|
11681
|
-
}
|
|
11682
|
-
continue;
|
|
11683
|
-
}
|
|
11684
|
-
}
|
|
11685
|
-
} finally {
|
|
11686
|
-
try {
|
|
11687
|
-
parser.delete();
|
|
11688
|
-
} catch {
|
|
11689
|
-
}
|
|
11690
|
-
}
|
|
11691
|
-
const conventions = {};
|
|
11692
|
-
const provenance = [];
|
|
11693
|
-
if (routeMethods.size === 1) {
|
|
11694
|
-
const [name, { line, file }] = routeMethods.entries().next().value;
|
|
11695
|
-
conventions.route_method = name;
|
|
11696
|
-
provenance.push({ field: "route_method", sourceFile: file, line, query: "chi-route-method" });
|
|
11697
|
-
} else if (routeMethods.size >= 2) {
|
|
11698
|
-
const [name, { line, file }] = routeMethods.entries().next().value;
|
|
11699
|
-
conventions.route_method = name;
|
|
11700
|
-
provenance.push({ field: "route_method", sourceFile: file, line, query: "chi-route-method" });
|
|
11701
|
-
}
|
|
11702
|
-
if (mountBases.size >= 1) {
|
|
11703
|
-
const [base, { line, file }] = mountBases.entries().next().value;
|
|
11704
|
-
conventions.mount_prefix_base = base;
|
|
11705
|
-
provenance.push({ field: "mount_prefix_base", sourceFile: file, line, query: "chi-mount-prefix" });
|
|
11706
|
-
}
|
|
11707
|
-
if (middlewareNames.size >= 1) {
|
|
11708
|
-
const [name, { line, file }] = middlewareNames.entries().next().value;
|
|
11709
|
-
conventions.middleware_name = name;
|
|
11710
|
-
provenance.push({ field: "middleware_name", sourceFile: file, line, query: "chi-middleware-use" });
|
|
11711
|
-
}
|
|
11712
|
-
let confidence;
|
|
11713
|
-
if (Object.keys(conventions).length === 0) {
|
|
11714
|
-
confidence = "none";
|
|
11715
|
-
} else if (routeMethods.size === 1) {
|
|
11716
|
-
confidence = "high";
|
|
11717
|
-
} else if (routeMethods.size >= 2) {
|
|
11718
|
-
confidence = "low";
|
|
11719
|
-
} else {
|
|
11720
|
-
confidence = "medium";
|
|
11721
|
-
}
|
|
11722
|
-
return { conventions, provenance, confidence };
|
|
11723
|
-
}
|
|
11724
|
-
};
|
|
11725
|
-
}
|
|
11726
|
-
});
|
|
11727
|
-
|
|
11728
|
-
// src/detect/adapters/go-chi.ts
|
|
11729
|
-
var init_go_chi = __esm({
|
|
11730
|
-
"src/detect/adapters/go-chi.ts"() {
|
|
11731
|
-
"use strict";
|
|
11732
|
-
init_dist();
|
|
11733
|
-
}
|
|
11734
|
-
});
|
|
11735
|
-
|
|
11736
|
-
// ../adapter-rails/dist/index.js
|
|
11737
|
-
import { Parser as Parser9 } from "web-tree-sitter";
|
|
11738
|
-
function extractRootController(target) {
|
|
11739
|
-
const idx = target.indexOf("#");
|
|
11740
|
-
if (idx <= 0)
|
|
11741
|
-
return null;
|
|
11742
|
-
const controller = target.slice(0, idx).trim();
|
|
11743
|
-
return controller || null;
|
|
11744
|
-
}
|
|
11745
|
-
var ROUTE_METHOD_QUERY2, NAMESPACE_QUERY, ROOT_ROUTE_QUERY, railsAdapter;
|
|
11746
|
-
var init_dist2 = __esm({
|
|
11747
|
-
"../adapter-rails/dist/index.js"() {
|
|
11748
|
-
"use strict";
|
|
11749
|
-
init_adapter();
|
|
11750
|
-
ROUTE_METHOD_QUERY2 = `
|
|
11751
|
-
(call
|
|
11752
|
-
method: (identifier) @method (#match? @method "^(get|post|put|patch|delete|options|head)$")
|
|
11753
|
-
arguments: (argument_list
|
|
11754
|
-
.
|
|
11755
|
-
(string) @route_path))
|
|
11756
|
-
`;
|
|
11757
|
-
NAMESPACE_QUERY = `
|
|
11758
|
-
(call
|
|
11759
|
-
method: (identifier) @_method (#eq? @_method "namespace")
|
|
11760
|
-
arguments: (argument_list
|
|
11761
|
-
.
|
|
11762
|
-
[
|
|
11763
|
-
(simple_symbol) @namespace_symbol
|
|
11764
|
-
(string) @namespace_string
|
|
11765
|
-
]))
|
|
11766
|
-
`;
|
|
11767
|
-
ROOT_ROUTE_QUERY = `
|
|
11768
|
-
(call
|
|
11769
|
-
method: (identifier) @_method (#eq? @_method "root")
|
|
11770
|
-
arguments: (argument_list
|
|
11771
|
-
.
|
|
11772
|
-
(string) @root_target))
|
|
11773
|
-
|
|
11774
|
-
(call
|
|
11775
|
-
method: (identifier) @_method (#eq? @_method "root")
|
|
11776
|
-
arguments: (argument_list
|
|
11777
|
-
(pair
|
|
11778
|
-
key: (hash_key_symbol) @_key (#eq? @_key "to")
|
|
11779
|
-
value: (string) @root_target)))
|
|
11780
|
-
`;
|
|
11781
|
-
railsAdapter = {
|
|
11782
|
-
id: "rails",
|
|
11783
|
-
languages: ["ruby"],
|
|
11784
|
-
matches(signals) {
|
|
11785
|
-
if (!signals.gemfile)
|
|
11786
|
-
return false;
|
|
11787
|
-
return /^\s*gem\s+['"]rails['"]/im.test(signals.gemfile);
|
|
11788
|
-
},
|
|
11789
|
-
async introspect(files, _rootDir) {
|
|
11790
|
-
if (files.length === 0) {
|
|
11791
|
-
return { conventions: {}, provenance: [], confidence: "none" };
|
|
11792
|
-
}
|
|
11793
|
-
let language;
|
|
11794
|
-
try {
|
|
11795
|
-
language = await loadGrammar2("ruby");
|
|
11796
|
-
} catch (e2) {
|
|
11797
|
-
return { conventions: {}, provenance: [], confidence: "none" };
|
|
11798
|
-
}
|
|
11799
|
-
const parser = new Parser9();
|
|
11800
|
-
parser.setLanguage(language);
|
|
11801
|
-
const routeMethods = /* @__PURE__ */ new Map();
|
|
11802
|
-
const namespaces = /* @__PURE__ */ new Map();
|
|
11803
|
-
const rootControllers = /* @__PURE__ */ new Map();
|
|
11804
|
-
try {
|
|
11805
|
-
for (const file of files) {
|
|
11806
|
-
const skip = isParsableSource2(file.content, file.size);
|
|
11807
|
-
if (skip) {
|
|
11808
|
-
process.stderr.write(`[massu/ast] WARN: rails skipping ${file.path}: ${skip.reason} (${skip.detail}). Cap=${MAX_AST_FILE_BYTES2}. (Phase 3.5 mitigation)
|
|
11809
|
-
`);
|
|
11810
|
-
continue;
|
|
11811
|
-
}
|
|
11812
|
-
try {
|
|
11813
|
-
for (const hit of runQuery2(parser, file.content, ROUTE_METHOD_QUERY2, "rails-route-method", file.path)) {
|
|
11814
|
-
const method = hit.captures.method;
|
|
11815
|
-
if (method && !routeMethods.has(method)) {
|
|
11816
|
-
routeMethods.set(method, { line: hit.line, file: file.path });
|
|
11817
|
-
}
|
|
11818
|
-
}
|
|
11819
|
-
for (const hit of runQuery2(parser, file.content, NAMESPACE_QUERY, "rails-namespace", file.path)) {
|
|
11820
|
-
const symbolRaw = hit.captures.namespace_symbol;
|
|
11821
|
-
const stringRaw = hit.captures.namespace_string;
|
|
11822
|
-
const name = symbolRaw ? symbolRaw.replace(/^:/, "") : stringRaw ? stringRaw.replace(/^['"]/, "").replace(/['"]$/, "") : null;
|
|
11823
|
-
if (!name)
|
|
11824
|
-
continue;
|
|
11825
|
-
const path = "/" + name;
|
|
11826
|
-
if (!namespaces.has(path)) {
|
|
11827
|
-
namespaces.set(path, { line: hit.line, file: file.path });
|
|
11828
|
-
}
|
|
11829
|
-
}
|
|
11830
|
-
for (const hit of runQuery2(parser, file.content, ROOT_ROUTE_QUERY, "rails-root", file.path)) {
|
|
11831
|
-
const raw = hit.captures.root_target;
|
|
11832
|
-
if (!raw)
|
|
11833
|
-
continue;
|
|
11834
|
-
const literal = raw.replace(/^['"]/, "").replace(/['"]$/, "");
|
|
11835
|
-
const controller = extractRootController(literal);
|
|
11836
|
-
if (controller && !rootControllers.has(controller)) {
|
|
11837
|
-
rootControllers.set(controller, { line: hit.line, file: file.path });
|
|
11838
|
-
}
|
|
11839
|
-
}
|
|
11840
|
-
} catch (e2) {
|
|
11841
|
-
if (e2 instanceof InvalidQueryError2) {
|
|
11842
|
-
throw e2;
|
|
11843
|
-
}
|
|
11844
|
-
continue;
|
|
11845
|
-
}
|
|
11846
|
-
}
|
|
11847
|
-
} finally {
|
|
11848
|
-
try {
|
|
11849
|
-
parser.delete();
|
|
11850
|
-
} catch {
|
|
11851
|
-
}
|
|
11852
|
-
}
|
|
11853
|
-
const conventions = {};
|
|
11854
|
-
const provenance = [];
|
|
11855
|
-
if (routeMethods.size === 1) {
|
|
11856
|
-
const [name, { line, file }] = routeMethods.entries().next().value;
|
|
11857
|
-
conventions.route_method = name;
|
|
11858
|
-
provenance.push({ field: "route_method", sourceFile: file, line, query: "rails-route-method" });
|
|
11859
|
-
} else if (routeMethods.size >= 2) {
|
|
11860
|
-
const [name, { line, file }] = routeMethods.entries().next().value;
|
|
11861
|
-
conventions.route_method = name;
|
|
11862
|
-
provenance.push({ field: "route_method", sourceFile: file, line, query: "rails-route-method" });
|
|
11863
|
-
}
|
|
11864
|
-
if (namespaces.size >= 1) {
|
|
11865
|
-
const [path, { line, file }] = namespaces.entries().next().value;
|
|
11866
|
-
conventions.api_namespace = path;
|
|
11867
|
-
provenance.push({ field: "api_namespace", sourceFile: file, line, query: "rails-namespace" });
|
|
11868
|
-
}
|
|
11869
|
-
if (rootControllers.size >= 1) {
|
|
11870
|
-
const [name, { line, file }] = rootControllers.entries().next().value;
|
|
11871
|
-
conventions.root_controller = name;
|
|
11872
|
-
provenance.push({ field: "root_controller", sourceFile: file, line, query: "rails-root" });
|
|
11873
|
-
}
|
|
11874
|
-
let confidence;
|
|
11875
|
-
if (Object.keys(conventions).length === 0) {
|
|
11876
|
-
confidence = "none";
|
|
11877
|
-
} else if (routeMethods.size === 1) {
|
|
11878
|
-
confidence = "high";
|
|
11879
|
-
} else if (routeMethods.size >= 2) {
|
|
11880
|
-
confidence = "low";
|
|
11881
|
-
} else {
|
|
11882
|
-
confidence = "medium";
|
|
11883
|
-
}
|
|
11884
|
-
return { conventions, provenance, confidence };
|
|
11885
|
-
}
|
|
11886
|
-
};
|
|
11887
|
-
}
|
|
11888
|
-
});
|
|
11889
|
-
|
|
11890
|
-
// src/detect/adapters/rails.ts
|
|
11891
|
-
var init_rails = __esm({
|
|
11892
|
-
"src/detect/adapters/rails.ts"() {
|
|
11893
|
-
"use strict";
|
|
11894
|
-
init_dist2();
|
|
11895
|
-
}
|
|
11896
|
-
});
|
|
11897
|
-
|
|
11898
|
-
// ../adapter-phoenix/dist/index.js
|
|
11899
|
-
import { Parser as Parser10 } from "web-tree-sitter";
|
|
11900
|
-
function extractPrefixBase5(prefix3) {
|
|
11901
|
-
if (!prefix3.startsWith("/"))
|
|
11902
|
-
return null;
|
|
11903
|
-
const stripped = prefix3.replace(/^\/+/, "");
|
|
11904
|
-
const firstSeg = stripped.split("/")[0];
|
|
11905
|
-
if (!firstSeg)
|
|
11906
|
-
return null;
|
|
11907
|
-
return "/" + firstSeg;
|
|
11908
|
-
}
|
|
11909
|
-
var ROUTE_METHOD_QUERY3, SCOPE_PATH_QUERY, ROUTER_MODULE_QUERY, phoenixAdapter;
|
|
11910
|
-
var init_dist3 = __esm({
|
|
11911
|
-
"../adapter-phoenix/dist/index.js"() {
|
|
11912
|
-
"use strict";
|
|
11913
|
-
init_adapter();
|
|
11914
|
-
ROUTE_METHOD_QUERY3 = `
|
|
11915
|
-
(call
|
|
11916
|
-
(identifier) @method (#match? @method "^(get|post|put|patch|delete|options|head)$")
|
|
11917
|
-
(arguments
|
|
11918
|
-
.
|
|
11919
|
-
(string) @route_path))
|
|
11920
|
-
`;
|
|
11921
|
-
SCOPE_PATH_QUERY = `
|
|
11922
|
-
(call
|
|
11923
|
-
(identifier) @_method (#eq? @_method "scope")
|
|
11924
|
-
(arguments
|
|
11925
|
-
.
|
|
11926
|
-
(string) @scope_path)
|
|
11927
|
-
(do_block))
|
|
11928
|
-
`;
|
|
11929
|
-
ROUTER_MODULE_QUERY = `
|
|
11930
|
-
(call
|
|
11931
|
-
(identifier) @_method (#eq? @_method "defmodule")
|
|
11932
|
-
(arguments
|
|
11933
|
-
.
|
|
11934
|
-
(alias) @module_name (#match? @module_name "Router$"))
|
|
11935
|
-
(do_block))
|
|
11936
|
-
`;
|
|
11937
|
-
phoenixAdapter = {
|
|
11938
|
-
id: "phoenix",
|
|
11939
|
-
languages: ["elixir"],
|
|
11940
|
-
matches(signals) {
|
|
11941
|
-
if (!signals.mixExs)
|
|
11942
|
-
return false;
|
|
11943
|
-
return /\{\s*:phoenix\b(?!_)/.test(signals.mixExs);
|
|
11944
|
-
},
|
|
11945
|
-
async introspect(files, _rootDir) {
|
|
11946
|
-
if (files.length === 0) {
|
|
11947
|
-
return { conventions: {}, provenance: [], confidence: "none" };
|
|
11948
|
-
}
|
|
11949
|
-
let language;
|
|
11950
|
-
try {
|
|
11951
|
-
language = await loadGrammar2("elixir");
|
|
11952
|
-
} catch (e2) {
|
|
11953
|
-
return { conventions: {}, provenance: [], confidence: "none" };
|
|
11954
|
-
}
|
|
11955
|
-
const parser = new Parser10();
|
|
11956
|
-
parser.setLanguage(language);
|
|
11957
|
-
const routeMethods = /* @__PURE__ */ new Map();
|
|
11958
|
-
const scopePaths = /* @__PURE__ */ new Map();
|
|
11959
|
-
const routerModules = /* @__PURE__ */ new Map();
|
|
11960
|
-
try {
|
|
11961
|
-
for (const file of files) {
|
|
11962
|
-
const skip = isParsableSource2(file.content, file.size);
|
|
11963
|
-
if (skip) {
|
|
11964
|
-
process.stderr.write(`[massu/ast] WARN: phoenix skipping ${file.path}: ${skip.reason} (${skip.detail}). Cap=${MAX_AST_FILE_BYTES2}. (Phase 3.5 mitigation)
|
|
11965
|
-
`);
|
|
11966
|
-
continue;
|
|
11967
|
-
}
|
|
11968
|
-
try {
|
|
11969
|
-
for (const hit of runQuery2(parser, file.content, ROUTE_METHOD_QUERY3, "phoenix-route-method", file.path)) {
|
|
11970
|
-
const method = hit.captures.method;
|
|
11971
|
-
if (method && !routeMethods.has(method)) {
|
|
11972
|
-
routeMethods.set(method, { line: hit.line, file: file.path });
|
|
11973
|
-
}
|
|
11974
|
-
}
|
|
11975
|
-
for (const hit of runQuery2(parser, file.content, SCOPE_PATH_QUERY, "phoenix-scope-path", file.path)) {
|
|
11976
|
-
const raw = hit.captures.scope_path;
|
|
11977
|
-
if (!raw)
|
|
11978
|
-
continue;
|
|
11979
|
-
const literal = raw.replace(/^["']/, "").replace(/["']$/, "");
|
|
11980
|
-
const base = extractPrefixBase5(literal);
|
|
11981
|
-
if (base && !scopePaths.has(base)) {
|
|
11982
|
-
scopePaths.set(base, { line: hit.line, file: file.path });
|
|
11983
|
-
}
|
|
11984
|
-
}
|
|
11985
|
-
for (const hit of runQuery2(parser, file.content, ROUTER_MODULE_QUERY, "phoenix-router-module", file.path)) {
|
|
11986
|
-
const name = hit.captures.module_name;
|
|
11987
|
-
if (name && !routerModules.has(name)) {
|
|
11988
|
-
routerModules.set(name, { line: hit.line, file: file.path });
|
|
11989
|
-
}
|
|
11990
|
-
}
|
|
11991
|
-
} catch (e2) {
|
|
11992
|
-
if (e2 instanceof InvalidQueryError2) {
|
|
11993
|
-
throw e2;
|
|
11994
|
-
}
|
|
11995
|
-
continue;
|
|
11996
|
-
}
|
|
11997
|
-
}
|
|
11998
|
-
} finally {
|
|
11999
|
-
try {
|
|
12000
|
-
parser.delete();
|
|
12001
|
-
} catch {
|
|
12002
|
-
}
|
|
12003
|
-
}
|
|
12004
|
-
const conventions = {};
|
|
12005
|
-
const provenance = [];
|
|
12006
|
-
if (routeMethods.size === 1) {
|
|
12007
|
-
const [name, { line, file }] = routeMethods.entries().next().value;
|
|
12008
|
-
conventions.route_method = name;
|
|
12009
|
-
provenance.push({ field: "route_method", sourceFile: file, line, query: "phoenix-route-method" });
|
|
12010
|
-
} else if (routeMethods.size >= 2) {
|
|
12011
|
-
const [name, { line, file }] = routeMethods.entries().next().value;
|
|
12012
|
-
conventions.route_method = name;
|
|
12013
|
-
provenance.push({ field: "route_method", sourceFile: file, line, query: "phoenix-route-method" });
|
|
12014
|
-
}
|
|
12015
|
-
if (scopePaths.size >= 1) {
|
|
12016
|
-
const [base, { line, file }] = scopePaths.entries().next().value;
|
|
12017
|
-
conventions.scope_prefix_base = base;
|
|
12018
|
-
provenance.push({ field: "scope_prefix_base", sourceFile: file, line, query: "phoenix-scope-path" });
|
|
12019
|
-
}
|
|
12020
|
-
if (routerModules.size >= 1) {
|
|
12021
|
-
const [name, { line, file }] = routerModules.entries().next().value;
|
|
12022
|
-
conventions.router_module = name;
|
|
12023
|
-
provenance.push({ field: "router_module", sourceFile: file, line, query: "phoenix-router-module" });
|
|
12024
|
-
}
|
|
12025
|
-
let confidence;
|
|
12026
|
-
if (Object.keys(conventions).length === 0) {
|
|
12027
|
-
confidence = "none";
|
|
12028
|
-
} else if (routeMethods.size === 1) {
|
|
12029
|
-
confidence = "high";
|
|
12030
|
-
} else if (routeMethods.size >= 2) {
|
|
12031
|
-
confidence = "low";
|
|
12032
|
-
} else {
|
|
12033
|
-
confidence = "medium";
|
|
12034
|
-
}
|
|
12035
|
-
return { conventions, provenance, confidence };
|
|
12036
|
-
}
|
|
12037
|
-
};
|
|
11162
|
+
// src/detect/adapters/go-chi.ts
|
|
11163
|
+
import { goChiAdapter } from "@massu/adapter-go-chi";
|
|
11164
|
+
var init_go_chi = __esm({
|
|
11165
|
+
"src/detect/adapters/go-chi.ts"() {
|
|
11166
|
+
"use strict";
|
|
12038
11167
|
}
|
|
12039
11168
|
});
|
|
12040
11169
|
|
|
12041
|
-
// src/detect/adapters/
|
|
12042
|
-
|
|
12043
|
-
|
|
11170
|
+
// src/detect/adapters/rails.ts
|
|
11171
|
+
import { railsAdapter } from "@massu/adapter-rails";
|
|
11172
|
+
var init_rails = __esm({
|
|
11173
|
+
"src/detect/adapters/rails.ts"() {
|
|
12044
11174
|
"use strict";
|
|
12045
|
-
init_dist3();
|
|
12046
11175
|
}
|
|
12047
11176
|
});
|
|
12048
11177
|
|
|
12049
|
-
//
|
|
12050
|
-
import {
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
const firstSeg = stripped.split("/")[0];
|
|
12054
|
-
if (!firstSeg)
|
|
12055
|
-
return null;
|
|
12056
|
-
return "/" + firstSeg;
|
|
12057
|
-
}
|
|
12058
|
-
var MAP_VERB_QUERY, HTTP_ATTR_QUERY, ROUTE_ATTR_QUERY, CONTROLLER_CLASS_QUERY, aspnetAdapter;
|
|
12059
|
-
var init_dist4 = __esm({
|
|
12060
|
-
"../adapter-aspnet/dist/index.js"() {
|
|
11178
|
+
// src/detect/adapters/phoenix.ts
|
|
11179
|
+
import { phoenixAdapter } from "@massu/adapter-phoenix";
|
|
11180
|
+
var init_phoenix = __esm({
|
|
11181
|
+
"src/detect/adapters/phoenix.ts"() {
|
|
12061
11182
|
"use strict";
|
|
12062
|
-
init_adapter();
|
|
12063
|
-
MAP_VERB_QUERY = `
|
|
12064
|
-
(invocation_expression
|
|
12065
|
-
function: (member_access_expression
|
|
12066
|
-
name: (identifier) @method (#match? @method "^Map(Get|Post|Put|Patch|Delete|Head|Options)$"))
|
|
12067
|
-
arguments: (argument_list
|
|
12068
|
-
.
|
|
12069
|
-
(argument (string_literal) @route_path)))
|
|
12070
|
-
`;
|
|
12071
|
-
HTTP_ATTR_QUERY = `
|
|
12072
|
-
(attribute
|
|
12073
|
-
name: (identifier) @attr_name (#match? @attr_name "^Http(Get|Post|Put|Patch|Delete|Head|Options)$"))
|
|
12074
|
-
`;
|
|
12075
|
-
ROUTE_ATTR_QUERY = `
|
|
12076
|
-
(attribute
|
|
12077
|
-
name: (identifier) @_attr_name (#eq? @_attr_name "Route")
|
|
12078
|
-
(attribute_argument_list
|
|
12079
|
-
(attribute_argument (string_literal) @route_template)))
|
|
12080
|
-
`;
|
|
12081
|
-
CONTROLLER_CLASS_QUERY = `
|
|
12082
|
-
(class_declaration
|
|
12083
|
-
name: (identifier) @class_name (#match? @class_name "Controller$"))
|
|
12084
|
-
`;
|
|
12085
|
-
aspnetAdapter = {
|
|
12086
|
-
id: "aspnet",
|
|
12087
|
-
languages: ["csharp"],
|
|
12088
|
-
matches(signals) {
|
|
12089
|
-
if (!signals.csproj)
|
|
12090
|
-
return false;
|
|
12091
|
-
if (/Sdk\s*=\s*["']Microsoft\.NET\.Sdk\.Web["']/i.test(signals.csproj))
|
|
12092
|
-
return true;
|
|
12093
|
-
if (/Microsoft\.AspNetCore\.App/i.test(signals.csproj))
|
|
12094
|
-
return true;
|
|
12095
|
-
return false;
|
|
12096
|
-
},
|
|
12097
|
-
async introspect(files, _rootDir) {
|
|
12098
|
-
if (files.length === 0) {
|
|
12099
|
-
return { conventions: {}, provenance: [], confidence: "none" };
|
|
12100
|
-
}
|
|
12101
|
-
let language;
|
|
12102
|
-
try {
|
|
12103
|
-
language = await loadGrammar2("csharp");
|
|
12104
|
-
} catch (e2) {
|
|
12105
|
-
return { conventions: {}, provenance: [], confidence: "none" };
|
|
12106
|
-
}
|
|
12107
|
-
const parser = new Parser11();
|
|
12108
|
-
parser.setLanguage(language);
|
|
12109
|
-
const routeMethods = /* @__PURE__ */ new Map();
|
|
12110
|
-
const prefixBases = /* @__PURE__ */ new Map();
|
|
12111
|
-
const controllerClasses = /* @__PURE__ */ new Map();
|
|
12112
|
-
try {
|
|
12113
|
-
for (const file of files) {
|
|
12114
|
-
const skip = isParsableSource2(file.content, file.size);
|
|
12115
|
-
if (skip) {
|
|
12116
|
-
process.stderr.write(`[massu/ast] WARN: aspnet skipping ${file.path}: ${skip.reason} (${skip.detail}). Cap=${MAX_AST_FILE_BYTES2}. (Phase 3.5 mitigation)
|
|
12117
|
-
`);
|
|
12118
|
-
continue;
|
|
12119
|
-
}
|
|
12120
|
-
try {
|
|
12121
|
-
for (const hit of runQuery2(parser, file.content, MAP_VERB_QUERY, "aspnet-map-verb", file.path)) {
|
|
12122
|
-
const methodRaw = hit.captures.method;
|
|
12123
|
-
if (!methodRaw)
|
|
12124
|
-
continue;
|
|
12125
|
-
const verb = methodRaw.replace(/^Map/, "");
|
|
12126
|
-
if (!routeMethods.has(verb)) {
|
|
12127
|
-
routeMethods.set(verb, { line: hit.line, file: file.path });
|
|
12128
|
-
}
|
|
12129
|
-
const pathRaw = hit.captures.route_path;
|
|
12130
|
-
if (pathRaw) {
|
|
12131
|
-
const literal = pathRaw.replace(/^["']/, "").replace(/["']$/, "");
|
|
12132
|
-
const base = extractPrefixBase6(literal);
|
|
12133
|
-
if (base && !prefixBases.has(base)) {
|
|
12134
|
-
prefixBases.set(base, { line: hit.line, file: file.path });
|
|
12135
|
-
}
|
|
12136
|
-
}
|
|
12137
|
-
}
|
|
12138
|
-
for (const hit of runQuery2(parser, file.content, HTTP_ATTR_QUERY, "aspnet-http-attr", file.path)) {
|
|
12139
|
-
const attrRaw = hit.captures.attr_name;
|
|
12140
|
-
if (!attrRaw)
|
|
12141
|
-
continue;
|
|
12142
|
-
const verb = attrRaw.replace(/^Http/, "");
|
|
12143
|
-
if (!routeMethods.has(verb)) {
|
|
12144
|
-
routeMethods.set(verb, { line: hit.line, file: file.path });
|
|
12145
|
-
}
|
|
12146
|
-
}
|
|
12147
|
-
for (const hit of runQuery2(parser, file.content, ROUTE_ATTR_QUERY, "aspnet-route-attr", file.path)) {
|
|
12148
|
-
const tplRaw = hit.captures.route_template;
|
|
12149
|
-
if (!tplRaw)
|
|
12150
|
-
continue;
|
|
12151
|
-
const literal = tplRaw.replace(/^["']/, "").replace(/["']$/, "");
|
|
12152
|
-
const base = extractPrefixBase6(literal);
|
|
12153
|
-
if (base && !prefixBases.has(base)) {
|
|
12154
|
-
prefixBases.set(base, { line: hit.line, file: file.path });
|
|
12155
|
-
}
|
|
12156
|
-
}
|
|
12157
|
-
for (const hit of runQuery2(parser, file.content, CONTROLLER_CLASS_QUERY, "aspnet-controller-class", file.path)) {
|
|
12158
|
-
const name = hit.captures.class_name;
|
|
12159
|
-
if (name && !controllerClasses.has(name)) {
|
|
12160
|
-
controllerClasses.set(name, { line: hit.line, file: file.path });
|
|
12161
|
-
}
|
|
12162
|
-
}
|
|
12163
|
-
} catch (e2) {
|
|
12164
|
-
if (e2 instanceof InvalidQueryError2) {
|
|
12165
|
-
throw e2;
|
|
12166
|
-
}
|
|
12167
|
-
continue;
|
|
12168
|
-
}
|
|
12169
|
-
}
|
|
12170
|
-
} finally {
|
|
12171
|
-
try {
|
|
12172
|
-
parser.delete();
|
|
12173
|
-
} catch {
|
|
12174
|
-
}
|
|
12175
|
-
}
|
|
12176
|
-
const conventions = {};
|
|
12177
|
-
const provenance = [];
|
|
12178
|
-
if (routeMethods.size === 1) {
|
|
12179
|
-
const [name, { line, file }] = routeMethods.entries().next().value;
|
|
12180
|
-
conventions.route_method = name;
|
|
12181
|
-
provenance.push({ field: "route_method", sourceFile: file, line, query: "aspnet-map-verb" });
|
|
12182
|
-
} else if (routeMethods.size >= 2) {
|
|
12183
|
-
const [name, { line, file }] = routeMethods.entries().next().value;
|
|
12184
|
-
conventions.route_method = name;
|
|
12185
|
-
provenance.push({ field: "route_method", sourceFile: file, line, query: "aspnet-map-verb" });
|
|
12186
|
-
}
|
|
12187
|
-
if (prefixBases.size >= 1) {
|
|
12188
|
-
const [base, { line, file }] = prefixBases.entries().next().value;
|
|
12189
|
-
conventions.route_prefix_base = base;
|
|
12190
|
-
provenance.push({ field: "route_prefix_base", sourceFile: file, line, query: "aspnet-route-prefix" });
|
|
12191
|
-
}
|
|
12192
|
-
if (controllerClasses.size >= 1) {
|
|
12193
|
-
const [name, { line, file }] = controllerClasses.entries().next().value;
|
|
12194
|
-
conventions.controller_class = name;
|
|
12195
|
-
provenance.push({ field: "controller_class", sourceFile: file, line, query: "aspnet-controller-class" });
|
|
12196
|
-
}
|
|
12197
|
-
let confidence;
|
|
12198
|
-
if (Object.keys(conventions).length === 0) {
|
|
12199
|
-
confidence = "none";
|
|
12200
|
-
} else if (routeMethods.size === 1) {
|
|
12201
|
-
confidence = "high";
|
|
12202
|
-
} else if (routeMethods.size >= 2) {
|
|
12203
|
-
confidence = "low";
|
|
12204
|
-
} else {
|
|
12205
|
-
confidence = "medium";
|
|
12206
|
-
}
|
|
12207
|
-
return { conventions, provenance, confidence };
|
|
12208
|
-
}
|
|
12209
|
-
};
|
|
12210
11183
|
}
|
|
12211
11184
|
});
|
|
12212
11185
|
|
|
12213
11186
|
// src/detect/adapters/aspnet.ts
|
|
11187
|
+
import { aspnetAdapter } from "@massu/adapter-aspnet";
|
|
12214
11188
|
var init_aspnet = __esm({
|
|
12215
11189
|
"src/detect/adapters/aspnet.ts"() {
|
|
12216
11190
|
"use strict";
|
|
12217
|
-
init_dist4();
|
|
12218
|
-
}
|
|
12219
|
-
});
|
|
12220
|
-
|
|
12221
|
-
// ../adapter-spring/dist/index.js
|
|
12222
|
-
import { Parser as Parser12 } from "web-tree-sitter";
|
|
12223
|
-
function extractPrefixBase7(prefix3) {
|
|
12224
|
-
const stripped = prefix3.replace(/^\/+/, "");
|
|
12225
|
-
const firstSeg = stripped.split("/")[0];
|
|
12226
|
-
if (!firstSeg)
|
|
12227
|
-
return null;
|
|
12228
|
-
return "/" + firstSeg;
|
|
12229
|
-
}
|
|
12230
|
-
var HTTP_MAPPING_QUERY, HTTP_MAPPING_NO_ARGS_QUERY, REQUEST_MAPPING_QUERY, CONTROLLER_CLASS_QUERY2, springAdapter;
|
|
12231
|
-
var init_dist5 = __esm({
|
|
12232
|
-
"../adapter-spring/dist/index.js"() {
|
|
12233
|
-
"use strict";
|
|
12234
|
-
init_adapter();
|
|
12235
|
-
HTTP_MAPPING_QUERY = `
|
|
12236
|
-
(annotation
|
|
12237
|
-
name: (identifier) @method (#match? @method "^(Get|Post|Put|Patch|Delete|Head|Options)Mapping$")
|
|
12238
|
-
arguments: (annotation_argument_list
|
|
12239
|
-
(string_literal) @route_path))
|
|
12240
|
-
`;
|
|
12241
|
-
HTTP_MAPPING_NO_ARGS_QUERY = `
|
|
12242
|
-
(marker_annotation
|
|
12243
|
-
name: (identifier) @method (#match? @method "^(Get|Post|Put|Patch|Delete|Head|Options)Mapping$"))
|
|
12244
|
-
`;
|
|
12245
|
-
REQUEST_MAPPING_QUERY = `
|
|
12246
|
-
(annotation
|
|
12247
|
-
name: (identifier) @_name (#eq? @_name "RequestMapping")
|
|
12248
|
-
arguments: (annotation_argument_list
|
|
12249
|
-
(string_literal) @route_template))
|
|
12250
|
-
`;
|
|
12251
|
-
CONTROLLER_CLASS_QUERY2 = `
|
|
12252
|
-
(class_declaration
|
|
12253
|
-
(modifiers
|
|
12254
|
-
(marker_annotation
|
|
12255
|
-
name: (identifier) @_anno (#match? @_anno "^(RestController|Controller)$")))
|
|
12256
|
-
name: (identifier) @class_name)
|
|
12257
|
-
|
|
12258
|
-
(class_declaration
|
|
12259
|
-
(modifiers
|
|
12260
|
-
(annotation
|
|
12261
|
-
name: (identifier) @_anno (#match? @_anno "^(RestController|Controller)$")))
|
|
12262
|
-
name: (identifier) @class_name)
|
|
12263
|
-
`;
|
|
12264
|
-
springAdapter = {
|
|
12265
|
-
id: "spring",
|
|
12266
|
-
languages: ["java"],
|
|
12267
|
-
matches(signals) {
|
|
12268
|
-
if (signals.pomXml && /\bspring-boot-starter[\w-]*\b/.test(signals.pomXml)) {
|
|
12269
|
-
return true;
|
|
12270
|
-
}
|
|
12271
|
-
if (signals.gradleBuild && /\bspring-boot-starter[\w-]*\b/.test(signals.gradleBuild)) {
|
|
12272
|
-
return true;
|
|
12273
|
-
}
|
|
12274
|
-
if (signals.pomXml && /\borg\.springframework\b/.test(signals.pomXml)) {
|
|
12275
|
-
return true;
|
|
12276
|
-
}
|
|
12277
|
-
if (signals.gradleBuild && /\borg\.springframework\b/.test(signals.gradleBuild)) {
|
|
12278
|
-
return true;
|
|
12279
|
-
}
|
|
12280
|
-
return false;
|
|
12281
|
-
},
|
|
12282
|
-
async introspect(files, _rootDir) {
|
|
12283
|
-
if (files.length === 0) {
|
|
12284
|
-
return { conventions: {}, provenance: [], confidence: "none" };
|
|
12285
|
-
}
|
|
12286
|
-
let language;
|
|
12287
|
-
try {
|
|
12288
|
-
language = await loadGrammar2("java");
|
|
12289
|
-
} catch (e2) {
|
|
12290
|
-
return { conventions: {}, provenance: [], confidence: "none" };
|
|
12291
|
-
}
|
|
12292
|
-
const parser = new Parser12();
|
|
12293
|
-
parser.setLanguage(language);
|
|
12294
|
-
const routeMethods = /* @__PURE__ */ new Map();
|
|
12295
|
-
const prefixBases = /* @__PURE__ */ new Map();
|
|
12296
|
-
const controllerClasses = /* @__PURE__ */ new Map();
|
|
12297
|
-
try {
|
|
12298
|
-
for (const file of files) {
|
|
12299
|
-
const skip = isParsableSource2(file.content, file.size);
|
|
12300
|
-
if (skip) {
|
|
12301
|
-
process.stderr.write(`[massu/ast] WARN: spring skipping ${file.path}: ${skip.reason} (${skip.detail}). Cap=${MAX_AST_FILE_BYTES2}. (Phase 3.5 mitigation)
|
|
12302
|
-
`);
|
|
12303
|
-
continue;
|
|
12304
|
-
}
|
|
12305
|
-
try {
|
|
12306
|
-
for (const hit of runQuery2(parser, file.content, HTTP_MAPPING_QUERY, "spring-http-mapping", file.path)) {
|
|
12307
|
-
const methodRaw = hit.captures.method;
|
|
12308
|
-
if (!methodRaw)
|
|
12309
|
-
continue;
|
|
12310
|
-
const verb = methodRaw.replace(/Mapping$/, "");
|
|
12311
|
-
if (!routeMethods.has(verb)) {
|
|
12312
|
-
routeMethods.set(verb, { line: hit.line, file: file.path });
|
|
12313
|
-
}
|
|
12314
|
-
}
|
|
12315
|
-
for (const hit of runQuery2(parser, file.content, HTTP_MAPPING_NO_ARGS_QUERY, "spring-http-mapping-marker", file.path)) {
|
|
12316
|
-
const methodRaw = hit.captures.method;
|
|
12317
|
-
if (!methodRaw)
|
|
12318
|
-
continue;
|
|
12319
|
-
const verb = methodRaw.replace(/Mapping$/, "");
|
|
12320
|
-
if (!routeMethods.has(verb)) {
|
|
12321
|
-
routeMethods.set(verb, { line: hit.line, file: file.path });
|
|
12322
|
-
}
|
|
12323
|
-
}
|
|
12324
|
-
for (const hit of runQuery2(parser, file.content, REQUEST_MAPPING_QUERY, "spring-request-mapping", file.path)) {
|
|
12325
|
-
const tplRaw = hit.captures.route_template;
|
|
12326
|
-
if (!tplRaw)
|
|
12327
|
-
continue;
|
|
12328
|
-
const literal = tplRaw.replace(/^["']/, "").replace(/["']$/, "");
|
|
12329
|
-
const base = extractPrefixBase7(literal);
|
|
12330
|
-
if (base && !prefixBases.has(base)) {
|
|
12331
|
-
prefixBases.set(base, { line: hit.line, file: file.path });
|
|
12332
|
-
}
|
|
12333
|
-
}
|
|
12334
|
-
for (const hit of runQuery2(parser, file.content, CONTROLLER_CLASS_QUERY2, "spring-controller-class", file.path)) {
|
|
12335
|
-
const name = hit.captures.class_name;
|
|
12336
|
-
if (name && !controllerClasses.has(name)) {
|
|
12337
|
-
controllerClasses.set(name, { line: hit.line, file: file.path });
|
|
12338
|
-
}
|
|
12339
|
-
}
|
|
12340
|
-
} catch (e2) {
|
|
12341
|
-
if (e2 instanceof InvalidQueryError2) {
|
|
12342
|
-
throw e2;
|
|
12343
|
-
}
|
|
12344
|
-
continue;
|
|
12345
|
-
}
|
|
12346
|
-
}
|
|
12347
|
-
} finally {
|
|
12348
|
-
try {
|
|
12349
|
-
parser.delete();
|
|
12350
|
-
} catch {
|
|
12351
|
-
}
|
|
12352
|
-
}
|
|
12353
|
-
const conventions = {};
|
|
12354
|
-
const provenance = [];
|
|
12355
|
-
if (routeMethods.size === 1) {
|
|
12356
|
-
const [name, { line, file }] = routeMethods.entries().next().value;
|
|
12357
|
-
conventions.route_method = name;
|
|
12358
|
-
provenance.push({ field: "route_method", sourceFile: file, line, query: "spring-http-mapping" });
|
|
12359
|
-
} else if (routeMethods.size >= 2) {
|
|
12360
|
-
const [name, { line, file }] = routeMethods.entries().next().value;
|
|
12361
|
-
conventions.route_method = name;
|
|
12362
|
-
provenance.push({ field: "route_method", sourceFile: file, line, query: "spring-http-mapping" });
|
|
12363
|
-
}
|
|
12364
|
-
if (prefixBases.size >= 1) {
|
|
12365
|
-
const [base, { line, file }] = prefixBases.entries().next().value;
|
|
12366
|
-
conventions.route_prefix_base = base;
|
|
12367
|
-
provenance.push({ field: "route_prefix_base", sourceFile: file, line, query: "spring-request-mapping" });
|
|
12368
|
-
}
|
|
12369
|
-
if (controllerClasses.size >= 1) {
|
|
12370
|
-
const [name, { line, file }] = controllerClasses.entries().next().value;
|
|
12371
|
-
conventions.controller_class = name;
|
|
12372
|
-
provenance.push({ field: "controller_class", sourceFile: file, line, query: "spring-controller-class" });
|
|
12373
|
-
}
|
|
12374
|
-
let confidence;
|
|
12375
|
-
if (Object.keys(conventions).length === 0) {
|
|
12376
|
-
confidence = "none";
|
|
12377
|
-
} else if (routeMethods.size === 1) {
|
|
12378
|
-
confidence = "high";
|
|
12379
|
-
} else if (routeMethods.size >= 2) {
|
|
12380
|
-
confidence = "low";
|
|
12381
|
-
} else {
|
|
12382
|
-
confidence = "medium";
|
|
12383
|
-
}
|
|
12384
|
-
return { conventions, provenance, confidence };
|
|
12385
|
-
}
|
|
12386
|
-
};
|
|
12387
11191
|
}
|
|
12388
11192
|
});
|
|
12389
11193
|
|
|
12390
11194
|
// src/detect/adapters/spring.ts
|
|
11195
|
+
import { springAdapter } from "@massu/adapter-spring";
|
|
12391
11196
|
var init_spring = __esm({
|
|
12392
11197
|
"src/detect/adapters/spring.ts"() {
|
|
12393
11198
|
"use strict";
|
|
12394
|
-
init_dist5();
|
|
12395
11199
|
}
|
|
12396
11200
|
});
|
|
12397
11201
|
|
|
@@ -12402,8 +11206,8 @@ __export(file_sampler_exports, {
|
|
|
12402
11206
|
SAMPLE_TEST_FILE_PATTERNS: () => SAMPLE_TEST_FILE_PATTERNS,
|
|
12403
11207
|
sampleFilesForAdapter: () => sampleFilesForAdapter
|
|
12404
11208
|
});
|
|
12405
|
-
import { readdirSync as
|
|
12406
|
-
import { join as
|
|
11209
|
+
import { readdirSync as readdirSync9, readFileSync as readFileSync9, lstatSync as lstatSync4 } from "node:fs";
|
|
11210
|
+
import { join as join9, extname } from "node:path";
|
|
12407
11211
|
function sampleFilesForAdapter(adapter, projectRoot, detection, options = {}) {
|
|
12408
11212
|
const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
12409
11213
|
const maxFiles = options.maxFilesPerAdapter ?? DEFAULT_MAX_FILES;
|
|
@@ -12418,7 +11222,7 @@ function sampleFilesForAdapter(adapter, projectRoot, detection, options = {}) {
|
|
|
12418
11222
|
const langDetection = detection.sourceDirs[langKey];
|
|
12419
11223
|
const candidateDirs = [];
|
|
12420
11224
|
if (langDetection?.source_dirs && langDetection.source_dirs.length > 0) {
|
|
12421
|
-
candidateDirs.push(...langDetection.source_dirs.map((d2) =>
|
|
11225
|
+
candidateDirs.push(...langDetection.source_dirs.map((d2) => join9(projectRoot, d2)));
|
|
12422
11226
|
} else {
|
|
12423
11227
|
candidateDirs.push(projectRoot);
|
|
12424
11228
|
}
|
|
@@ -12434,7 +11238,7 @@ function walkDir(dir, exts, testPatterns, lang, maxDepth, curDepth, out, seen, m
|
|
|
12434
11238
|
if (out.length >= maxFiles) return;
|
|
12435
11239
|
let entries;
|
|
12436
11240
|
try {
|
|
12437
|
-
entries =
|
|
11241
|
+
entries = readdirSync9(dir);
|
|
12438
11242
|
} catch {
|
|
12439
11243
|
return;
|
|
12440
11244
|
}
|
|
@@ -12442,10 +11246,10 @@ function walkDir(dir, exts, testPatterns, lang, maxDepth, curDepth, out, seen, m
|
|
|
12442
11246
|
if (out.length >= maxFiles) return;
|
|
12443
11247
|
if (entry.startsWith(".")) continue;
|
|
12444
11248
|
if (IGNORED_DIRS3.has(entry)) continue;
|
|
12445
|
-
const fullPath =
|
|
11249
|
+
const fullPath = join9(dir, entry);
|
|
12446
11250
|
let st;
|
|
12447
11251
|
try {
|
|
12448
|
-
st =
|
|
11252
|
+
st = lstatSync4(fullPath);
|
|
12449
11253
|
} catch {
|
|
12450
11254
|
continue;
|
|
12451
11255
|
}
|
|
@@ -12463,7 +11267,7 @@ function walkDir(dir, exts, testPatterns, lang, maxDepth, curDepth, out, seen, m
|
|
|
12463
11267
|
seen.add(fullPath);
|
|
12464
11268
|
let content;
|
|
12465
11269
|
try {
|
|
12466
|
-
content =
|
|
11270
|
+
content = readFileSync9(fullPath, "utf-8");
|
|
12467
11271
|
} catch {
|
|
12468
11272
|
continue;
|
|
12469
11273
|
}
|
|
@@ -12701,7 +11505,7 @@ var init_detect = __esm({
|
|
|
12701
11505
|
});
|
|
12702
11506
|
|
|
12703
11507
|
// src/detect/drift.ts
|
|
12704
|
-
import { createHash as
|
|
11508
|
+
import { createHash as createHash3 } from "crypto";
|
|
12705
11509
|
function summarizeDetection(det) {
|
|
12706
11510
|
const languages = Array.from(new Set(det.manifests.map((m3) => m3.language))).sort();
|
|
12707
11511
|
const frameworks = {};
|
|
@@ -12732,7 +11536,7 @@ function summarizeDetection(det) {
|
|
|
12732
11536
|
function computeFingerprint(det) {
|
|
12733
11537
|
const data = summarizeDetection(det);
|
|
12734
11538
|
const stable = JSON.stringify(data, Object.keys(data).sort());
|
|
12735
|
-
return
|
|
11539
|
+
return createHash3("sha256").update(stable).digest("hex");
|
|
12736
11540
|
}
|
|
12737
11541
|
function stringOf(v3) {
|
|
12738
11542
|
if (typeof v3 === "string") return v3;
|
|
@@ -13082,7 +11886,7 @@ function cD({ input: t = $, output: u2 = j, overwrite: F = true, hideCursor: e2
|
|
|
13082
11886
|
};
|
|
13083
11887
|
}
|
|
13084
11888
|
var import_sisteransi, import_picocolors, Q, P, X, DD, uD, FD, m, L, N, I, r, tD, eD, iD, v, CD, w, W, rD, R, y, V, z2, ED, _, nD, oD, aD, c, xD, S, AD, pD, h, x, fD, gD, vD, K, dD, bD, mD, Y, wD, yD, _D, Z, kD, SD, $D, q, jD, MD, TD, H, OD, PD;
|
|
13085
|
-
var
|
|
11889
|
+
var init_dist = __esm({
|
|
13086
11890
|
"../../node_modules/@clack/core/dist/index.mjs"() {
|
|
13087
11891
|
import_sisteransi = __toESM(require_src(), 1);
|
|
13088
11892
|
import_picocolors = __toESM(require_picocolors(), 1);
|
|
@@ -13500,10 +12304,10 @@ function X2() {
|
|
|
13500
12304
|
return p.platform !== "win32" ? p.env.TERM !== "linux" : !!p.env.CI || !!p.env.WT_SESSION || !!p.env.TERMINUS_SUBLIME || p.env.ConEmuTask === "{cmd::Cmder}" || p.env.TERM_PROGRAM === "Terminus-Sublime" || p.env.TERM_PROGRAM === "vscode" || p.env.TERM === "xterm-256color" || p.env.TERM === "alacritty" || p.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
13501
12305
|
}
|
|
13502
12306
|
var import_picocolors2, import_sisteransi2, E, u, ee, A2, B, S2, te, a, m2, j2, R2, V2, M2, G2, se, N2, re, ie, ne, ae, oe, ce, le, y2, k2, ue, $e, me, de, he, pe, ge, ye, ve, we, fe, v2, L2, be, xe;
|
|
13503
|
-
var
|
|
12307
|
+
var init_dist2 = __esm({
|
|
13504
12308
|
"../../node_modules/@clack/prompts/dist/index.mjs"() {
|
|
13505
|
-
|
|
13506
|
-
|
|
12309
|
+
init_dist();
|
|
12310
|
+
init_dist();
|
|
13507
12311
|
import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
13508
12312
|
import_sisteransi2 = __toESM(require_src(), 1);
|
|
13509
12313
|
E = X2();
|
|
@@ -13891,10 +12695,10 @@ __export(init_exports, {
|
|
|
13891
12695
|
validateWrittenConfig: () => validateWrittenConfig,
|
|
13892
12696
|
writeConfigAtomic: () => writeConfigAtomic
|
|
13893
12697
|
});
|
|
13894
|
-
import { closeSync as closeSync2, existsSync as existsSync10, fsyncSync as fsyncSync2, openSync as openSync2, readFileSync as
|
|
13895
|
-
import { resolve as resolve6, basename as basename4, dirname as
|
|
12698
|
+
import { closeSync as closeSync2, existsSync as existsSync10, fsyncSync as fsyncSync2, openSync as openSync2, readFileSync as readFileSync10, writeFileSync as writeFileSync2, writeSync as writeSync2, mkdirSync as mkdirSync4, readdirSync as readdirSync10, renameSync as renameSync3, rmSync as rmSync2, statSync as statSync7, chmodSync as chmodSync2 } from "fs";
|
|
12699
|
+
import { resolve as resolve6, basename as basename4, dirname as dirname5 } from "path";
|
|
13896
12700
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
13897
|
-
import { homedir as
|
|
12701
|
+
import { homedir as homedir3 } from "os";
|
|
13898
12702
|
import { stringify as yamlStringify, parse as yamlParse } from "yaml";
|
|
13899
12703
|
function detectFramework(projectRoot) {
|
|
13900
12704
|
const result = {
|
|
@@ -13906,7 +12710,7 @@ function detectFramework(projectRoot) {
|
|
|
13906
12710
|
const pkgPath = resolve6(projectRoot, "package.json");
|
|
13907
12711
|
if (!existsSync10(pkgPath)) return result;
|
|
13908
12712
|
try {
|
|
13909
|
-
const pkg = JSON.parse(
|
|
12713
|
+
const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
|
|
13910
12714
|
const allDeps = {
|
|
13911
12715
|
...pkg.dependencies,
|
|
13912
12716
|
...pkg.devDependencies
|
|
@@ -13953,7 +12757,7 @@ function detectPython(projectRoot) {
|
|
|
13953
12757
|
const filePath = resolve6(projectRoot, file);
|
|
13954
12758
|
if (existsSync10(filePath)) {
|
|
13955
12759
|
try {
|
|
13956
|
-
const content =
|
|
12760
|
+
const content = readFileSync10(filePath, "utf-8").toLowerCase();
|
|
13957
12761
|
if (content.includes("fastapi")) result.hasFastapi = true;
|
|
13958
12762
|
if (content.includes("sqlalchemy")) result.hasSqlalchemy = true;
|
|
13959
12763
|
} catch {
|
|
@@ -13978,7 +12782,7 @@ function detectPython(projectRoot) {
|
|
|
13978
12782
|
}
|
|
13979
12783
|
if (existsSync10(candidatePath)) {
|
|
13980
12784
|
try {
|
|
13981
|
-
const files =
|
|
12785
|
+
const files = readdirSync10(candidatePath);
|
|
13982
12786
|
if (files.some((f2) => f2.endsWith(".py"))) {
|
|
13983
12787
|
result.root = candidate;
|
|
13984
12788
|
break;
|
|
@@ -14043,7 +12847,7 @@ function generateConfig(projectRoot, framework) {
|
|
|
14043
12847
|
# Documentation: https://massu.ai/docs/getting-started/configuration
|
|
14044
12848
|
|
|
14045
12849
|
${yamlStringify(config)}`;
|
|
14046
|
-
|
|
12850
|
+
writeFileSync2(configPath, yamlContent, "utf-8");
|
|
14047
12851
|
return true;
|
|
14048
12852
|
}
|
|
14049
12853
|
function monorepoCommonRoot(packages) {
|
|
@@ -14214,7 +13018,7 @@ function applyVariantTemplate(config, templatesDir) {
|
|
|
14214
13018
|
if (!existsSync10(templatePath)) return config;
|
|
14215
13019
|
let template;
|
|
14216
13020
|
try {
|
|
14217
|
-
template = yamlParse(
|
|
13021
|
+
template = yamlParse(readFileSync10(templatePath, "utf-8"));
|
|
14218
13022
|
} catch {
|
|
14219
13023
|
return config;
|
|
14220
13024
|
}
|
|
@@ -14281,7 +13085,7 @@ function writeConfigAtomic(configPath, content) {
|
|
|
14281
13085
|
}
|
|
14282
13086
|
}
|
|
14283
13087
|
try {
|
|
14284
|
-
|
|
13088
|
+
mkdirSync4(dirname5(configPath), { recursive: true });
|
|
14285
13089
|
const fd = openSync2(tmpPath, "w", 420);
|
|
14286
13090
|
try {
|
|
14287
13091
|
const buf = Buffer.from(content, "utf-8");
|
|
@@ -14294,10 +13098,10 @@ function writeConfigAtomic(configPath, content) {
|
|
|
14294
13098
|
if (parsed === null || typeof parsed !== "object") {
|
|
14295
13099
|
throw new Error("Generated config is not a valid YAML object");
|
|
14296
13100
|
}
|
|
14297
|
-
|
|
13101
|
+
renameSync3(tmpPath, configPath);
|
|
14298
13102
|
if (existingMode !== void 0) {
|
|
14299
13103
|
try {
|
|
14300
|
-
|
|
13104
|
+
chmodSync2(configPath, existingMode);
|
|
14301
13105
|
} catch {
|
|
14302
13106
|
}
|
|
14303
13107
|
}
|
|
@@ -14315,7 +13119,7 @@ function writeConfigAtomic(configPath, content) {
|
|
|
14315
13119
|
function validateWrittenConfig(configPath, projectRoot, checkPaths = true) {
|
|
14316
13120
|
try {
|
|
14317
13121
|
if (!existsSync10(configPath)) return "Config file does not exist after write";
|
|
14318
|
-
const content =
|
|
13122
|
+
const content = readFileSync10(configPath, "utf-8");
|
|
14319
13123
|
const parsed = yamlParse(content);
|
|
14320
13124
|
if (parsed === null || typeof parsed !== "object") {
|
|
14321
13125
|
return "Config is not a valid YAML object";
|
|
@@ -14416,9 +13220,9 @@ function copyTemplateConfig(templateName, targetPath, projectName) {
|
|
|
14416
13220
|
return { success: false, error: `Template '${templateName}' not found at ${srcPath}` };
|
|
14417
13221
|
}
|
|
14418
13222
|
try {
|
|
14419
|
-
let content =
|
|
13223
|
+
let content = readFileSync10(srcPath, "utf-8");
|
|
14420
13224
|
content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
|
|
14421
|
-
|
|
13225
|
+
writeFileSync2(targetPath, content, "utf-8");
|
|
14422
13226
|
return { success: true };
|
|
14423
13227
|
} catch (err) {
|
|
14424
13228
|
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
@@ -14429,7 +13233,7 @@ function registerMcpServer(projectRoot) {
|
|
|
14429
13233
|
let existing = {};
|
|
14430
13234
|
if (existsSync10(mcpPath)) {
|
|
14431
13235
|
try {
|
|
14432
|
-
existing = JSON.parse(
|
|
13236
|
+
existing = JSON.parse(readFileSync10(mcpPath, "utf-8"));
|
|
14433
13237
|
} catch {
|
|
14434
13238
|
existing = {};
|
|
14435
13239
|
}
|
|
@@ -14444,7 +13248,7 @@ function registerMcpServer(projectRoot) {
|
|
|
14444
13248
|
args: ["-y", "@massu/core"]
|
|
14445
13249
|
};
|
|
14446
13250
|
existing.mcpServers = servers;
|
|
14447
|
-
|
|
13251
|
+
writeFileSync2(mcpPath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
|
|
14448
13252
|
return true;
|
|
14449
13253
|
}
|
|
14450
13254
|
function resolveHooksDir() {
|
|
@@ -14549,12 +13353,12 @@ function installHooks(projectRoot) {
|
|
|
14549
13353
|
const claudeDir = resolve6(projectRoot, claudeDirName);
|
|
14550
13354
|
const settingsPath = resolve6(claudeDir, "settings.local.json");
|
|
14551
13355
|
if (!existsSync10(claudeDir)) {
|
|
14552
|
-
|
|
13356
|
+
mkdirSync4(claudeDir, { recursive: true });
|
|
14553
13357
|
}
|
|
14554
13358
|
let settings = {};
|
|
14555
13359
|
if (existsSync10(settingsPath)) {
|
|
14556
13360
|
try {
|
|
14557
|
-
settings = JSON.parse(
|
|
13361
|
+
settings = JSON.parse(readFileSync10(settingsPath, "utf-8"));
|
|
14558
13362
|
} catch {
|
|
14559
13363
|
settings = {};
|
|
14560
13364
|
}
|
|
@@ -14568,15 +13372,15 @@ function installHooks(projectRoot) {
|
|
|
14568
13372
|
}
|
|
14569
13373
|
}
|
|
14570
13374
|
settings.hooks = hooksConfig;
|
|
14571
|
-
|
|
13375
|
+
writeFileSync2(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
14572
13376
|
return { installed: true, count: hookCount };
|
|
14573
13377
|
}
|
|
14574
13378
|
function initMemoryDir(projectRoot) {
|
|
14575
13379
|
const encodedRoot = "-" + projectRoot.replace(/\//g, "-");
|
|
14576
|
-
const memoryDir = resolve6(
|
|
13380
|
+
const memoryDir = resolve6(homedir3(), `.claude/projects/${encodedRoot}/memory`);
|
|
14577
13381
|
let created = false;
|
|
14578
13382
|
if (!existsSync10(memoryDir)) {
|
|
14579
|
-
|
|
13383
|
+
mkdirSync4(memoryDir, { recursive: true });
|
|
14580
13384
|
created = true;
|
|
14581
13385
|
}
|
|
14582
13386
|
const memoryMdPath = resolve6(memoryDir, "MEMORY.md");
|
|
@@ -14597,7 +13401,7 @@ function initMemoryDir(projectRoot) {
|
|
|
14597
13401
|
## File Index
|
|
14598
13402
|
<!-- Significant files and directories -->
|
|
14599
13403
|
`;
|
|
14600
|
-
|
|
13404
|
+
writeFileSync2(memoryMdPath, memoryContent, "utf-8");
|
|
14601
13405
|
memoryMdCreated = true;
|
|
14602
13406
|
}
|
|
14603
13407
|
return { created, memoryMdCreated };
|
|
@@ -14849,8 +13653,8 @@ function installSideEffects(projectRoot, log, skipCommands = false, emptyStack =
|
|
|
14849
13653
|
"\u2014 Massu"
|
|
14850
13654
|
].join("\n");
|
|
14851
13655
|
try {
|
|
14852
|
-
|
|
14853
|
-
|
|
13656
|
+
mkdirSync4(resolve6(cmdResult.claudeDir, "commands"), { recursive: true });
|
|
13657
|
+
writeFileSync2(placeholderPath, placeholderBody, "utf-8");
|
|
14854
13658
|
log(" Wrote _massu-needs-stack.md placeholder (no stack detected yet)");
|
|
14855
13659
|
} catch {
|
|
14856
13660
|
}
|
|
@@ -14869,8 +13673,8 @@ function installSideEffects(projectRoot, log, skipCommands = false, emptyStack =
|
|
|
14869
13673
|
(async () => {
|
|
14870
13674
|
try {
|
|
14871
13675
|
const encodedRoot = projectRoot.replace(/\//g, "-");
|
|
14872
|
-
const memoryDir = resolve6(
|
|
14873
|
-
const memFiles = existsSync10(memoryDir) ?
|
|
13676
|
+
const memoryDir = resolve6(homedir3(), ".claude", "projects", encodedRoot, "memory");
|
|
13677
|
+
const memFiles = existsSync10(memoryDir) ? readdirSync10(memoryDir).filter((f2) => f2.endsWith(".md") && f2 !== "MEMORY.md") : [];
|
|
14874
13678
|
if (memFiles.length > 0) {
|
|
14875
13679
|
const { getMemoryDb: getMemoryDb2 } = await Promise.resolve().then(() => (init_memory_db(), memory_db_exports));
|
|
14876
13680
|
const db = getMemoryDb2();
|
|
@@ -14893,7 +13697,7 @@ function installSideEffects(projectRoot, log, skipCommands = false, emptyStack =
|
|
|
14893
13697
|
}
|
|
14894
13698
|
async function promptOverwrite(configPath) {
|
|
14895
13699
|
try {
|
|
14896
|
-
const { confirm, isCancel } = await Promise.resolve().then(() => (
|
|
13700
|
+
const { confirm, isCancel } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
14897
13701
|
const res = await confirm({
|
|
14898
13702
|
message: `massu.config.yaml already exists at ${configPath}. Overwrite?`,
|
|
14899
13703
|
initialValue: false
|
|
@@ -14906,7 +13710,7 @@ async function promptOverwrite(configPath) {
|
|
|
14906
13710
|
}
|
|
14907
13711
|
async function promptStackConfirm() {
|
|
14908
13712
|
try {
|
|
14909
|
-
const { confirm, isCancel } = await Promise.resolve().then(() => (
|
|
13713
|
+
const { confirm, isCancel } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
14910
13714
|
const res = await confirm({
|
|
14911
13715
|
message: "Generate massu.config.yaml from detected stack?",
|
|
14912
13716
|
initialValue: true
|
|
@@ -14930,7 +13734,7 @@ var init_init = __esm({
|
|
|
14930
13734
|
init_detect();
|
|
14931
13735
|
init_drift();
|
|
14932
13736
|
__filename2 = fileURLToPath2(import.meta.url);
|
|
14933
|
-
__dirname2 =
|
|
13737
|
+
__dirname2 = dirname5(__filename2);
|
|
14934
13738
|
FRAMEWORK_TO_TEMPLATE_ID = {
|
|
14935
13739
|
rails: "rails",
|
|
14936
13740
|
phoenix: "phoenix",
|
|
@@ -14952,7 +13756,7 @@ var init_init = __esm({
|
|
|
14952
13756
|
});
|
|
14953
13757
|
|
|
14954
13758
|
// src/license.ts
|
|
14955
|
-
import { createHash as
|
|
13759
|
+
import { createHash as createHash4 } from "crypto";
|
|
14956
13760
|
function tierLevel(tier) {
|
|
14957
13761
|
return TIER_LEVELS[tier] ?? 0;
|
|
14958
13762
|
}
|
|
@@ -14977,7 +13781,7 @@ function annotateToolDefinitions(defs) {
|
|
|
14977
13781
|
});
|
|
14978
13782
|
}
|
|
14979
13783
|
async function validateLicense(apiKey) {
|
|
14980
|
-
const keyHash =
|
|
13784
|
+
const keyHash = createHash4("sha256").update(apiKey).digest("hex");
|
|
14981
13785
|
const memDb = getMemoryDb();
|
|
14982
13786
|
try {
|
|
14983
13787
|
const cached = memDb.prepare(
|
|
@@ -15038,7 +13842,7 @@ async function validateLicense(apiKey) {
|
|
|
15038
13842
|
}
|
|
15039
13843
|
}
|
|
15040
13844
|
function updateLicenseCache(apiKey, tier, validUntil, features = []) {
|
|
15041
|
-
const keyHash =
|
|
13845
|
+
const keyHash = createHash4("sha256").update(apiKey).digest("hex");
|
|
15042
13846
|
const memDb = getMemoryDb();
|
|
15043
13847
|
try {
|
|
15044
13848
|
memDb.prepare(`
|
|
@@ -15246,8 +14050,8 @@ __export(doctor_exports, {
|
|
|
15246
14050
|
runDoctor: () => runDoctor,
|
|
15247
14051
|
runValidateConfig: () => runValidateConfig
|
|
15248
14052
|
});
|
|
15249
|
-
import { existsSync as existsSync11, readFileSync as
|
|
15250
|
-
import { resolve as resolve7, dirname as
|
|
14053
|
+
import { existsSync as existsSync11, readFileSync as readFileSync11, readdirSync as readdirSync11 } from "fs";
|
|
14054
|
+
import { resolve as resolve7, dirname as dirname6 } from "path";
|
|
15251
14055
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
15252
14056
|
import { parse as parseYaml4 } from "yaml";
|
|
15253
14057
|
function checkConfig(projectRoot) {
|
|
@@ -15256,7 +14060,7 @@ function checkConfig(projectRoot) {
|
|
|
15256
14060
|
return { name: "Configuration", status: "fail", detail: "massu.config.yaml not found. Run: npx massu init" };
|
|
15257
14061
|
}
|
|
15258
14062
|
try {
|
|
15259
|
-
const content =
|
|
14063
|
+
const content = readFileSync11(configPath, "utf-8");
|
|
15260
14064
|
const parsed = parseYaml4(content);
|
|
15261
14065
|
if (!parsed || typeof parsed !== "object") {
|
|
15262
14066
|
return { name: "Configuration", status: "fail", detail: "massu.config.yaml is empty or invalid YAML" };
|
|
@@ -15272,7 +14076,7 @@ function checkMcpServer(projectRoot) {
|
|
|
15272
14076
|
return { name: "MCP Server", status: "fail", detail: ".mcp.json not found. Run: npx massu init" };
|
|
15273
14077
|
}
|
|
15274
14078
|
try {
|
|
15275
|
-
const content = JSON.parse(
|
|
14079
|
+
const content = JSON.parse(readFileSync11(mcpPath, "utf-8"));
|
|
15276
14080
|
const servers = content.mcpServers ?? {};
|
|
15277
14081
|
if (!servers.massu) {
|
|
15278
14082
|
return { name: "MCP Server", status: "fail", detail: "massu not registered in .mcp.json. Run: npx massu init" };
|
|
@@ -15288,7 +14092,7 @@ function checkHooksConfig(projectRoot) {
|
|
|
15288
14092
|
return { name: "Hooks Config", status: "fail", detail: ".claude/settings.local.json not found. Run: npx massu init" };
|
|
15289
14093
|
}
|
|
15290
14094
|
try {
|
|
15291
|
-
const content = JSON.parse(
|
|
14095
|
+
const content = JSON.parse(readFileSync11(settingsPath, "utf-8"));
|
|
15292
14096
|
if (!content.hooks) {
|
|
15293
14097
|
return { name: "Hooks Config", status: "fail", detail: "No hooks configured. Run: npx massu install-hooks" };
|
|
15294
14098
|
}
|
|
@@ -15399,7 +14203,7 @@ function checkShellHooksWired(_projectRoot2) {
|
|
|
15399
14203
|
};
|
|
15400
14204
|
}
|
|
15401
14205
|
try {
|
|
15402
|
-
const content = JSON.parse(
|
|
14206
|
+
const content = JSON.parse(readFileSync11(settingsPath, "utf-8"));
|
|
15403
14207
|
const hooks = content.hooks ?? {};
|
|
15404
14208
|
const hasSessionStart = Array.isArray(hooks.SessionStart) && hooks.SessionStart.length > 0;
|
|
15405
14209
|
const hasPreToolUse = Array.isArray(hooks.PreToolUse) && hooks.PreToolUse.length > 0;
|
|
@@ -15465,7 +14269,7 @@ function checkPythonHealth(projectRoot) {
|
|
|
15465
14269
|
function scanDir(dir, depth) {
|
|
15466
14270
|
if (depth > 5) return;
|
|
15467
14271
|
try {
|
|
15468
|
-
const entries =
|
|
14272
|
+
const entries = readdirSync11(dir, { withFileTypes: true });
|
|
15469
14273
|
for (const entry of entries) {
|
|
15470
14274
|
if (entry.isDirectory()) {
|
|
15471
14275
|
const excludeDirs = config.python?.exclude_dirs || ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"];
|
|
@@ -15473,7 +14277,7 @@ function checkPythonHealth(projectRoot) {
|
|
|
15473
14277
|
const subdir = resolve7(dir, entry.name);
|
|
15474
14278
|
if (depth <= 2 && !existsSync11(resolve7(subdir, "__init__.py"))) {
|
|
15475
14279
|
try {
|
|
15476
|
-
const subEntries =
|
|
14280
|
+
const subEntries = readdirSync11(subdir);
|
|
15477
14281
|
if (subEntries.some((f2) => f2.endsWith(".py") && f2 !== "__init__.py")) {
|
|
15478
14282
|
initPyMissing.push(entry.name);
|
|
15479
14283
|
}
|
|
@@ -15574,7 +14378,7 @@ async function runValidateConfig() {
|
|
|
15574
14378
|
return;
|
|
15575
14379
|
}
|
|
15576
14380
|
try {
|
|
15577
|
-
const content =
|
|
14381
|
+
const content = readFileSync11(configPath, "utf-8");
|
|
15578
14382
|
const parsed = parseYaml4(content);
|
|
15579
14383
|
if (!parsed || typeof parsed !== "object") {
|
|
15580
14384
|
console.error("Error: massu.config.yaml is empty or not a valid YAML object");
|
|
@@ -15613,7 +14417,7 @@ var init_doctor = __esm({
|
|
|
15613
14417
|
init_config();
|
|
15614
14418
|
init_license();
|
|
15615
14419
|
__filename3 = fileURLToPath3(import.meta.url);
|
|
15616
|
-
__dirname3 =
|
|
14420
|
+
__dirname3 = dirname6(__filename3);
|
|
15617
14421
|
EXPECTED_HOOKS = [
|
|
15618
14422
|
"session-start.js",
|
|
15619
14423
|
"session-end.js",
|
|
@@ -15659,7 +14463,7 @@ var show_template_exports = {};
|
|
|
15659
14463
|
__export(show_template_exports, {
|
|
15660
14464
|
runShowTemplate: () => runShowTemplate
|
|
15661
14465
|
});
|
|
15662
|
-
import { existsSync as existsSync12, readFileSync as
|
|
14466
|
+
import { existsSync as existsSync12, readFileSync as readFileSync12 } from "fs";
|
|
15663
14467
|
import { resolve as resolve8 } from "path";
|
|
15664
14468
|
function normalizeBaseName(input) {
|
|
15665
14469
|
return input.endsWith(".md") ? input.slice(0, -".md".length) : input;
|
|
@@ -15695,7 +14499,7 @@ async function runShowTemplate(args2) {
|
|
|
15695
14499
|
process.exit(1);
|
|
15696
14500
|
return;
|
|
15697
14501
|
}
|
|
15698
|
-
process.stdout.write(
|
|
14502
|
+
process.stdout.write(readFileSync12(file, "utf-8"));
|
|
15699
14503
|
}
|
|
15700
14504
|
var init_show_template = __esm({
|
|
15701
14505
|
"src/commands/show-template.ts"() {
|
|
@@ -15748,12 +14552,12 @@ var init_passthrough = __esm({
|
|
|
15748
14552
|
});
|
|
15749
14553
|
|
|
15750
14554
|
// src/lib/fileLock.ts
|
|
15751
|
-
import { mkdirSync as
|
|
15752
|
-
import { dirname as
|
|
14555
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync13, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
14556
|
+
import { dirname as dirname7 } from "path";
|
|
15753
14557
|
import * as lockfile from "proper-lockfile";
|
|
15754
14558
|
function readLockHolderPid(lockPath) {
|
|
15755
14559
|
try {
|
|
15756
|
-
const raw =
|
|
14560
|
+
const raw = readFileSync13(`${lockPath}.pid`, "utf-8").trim();
|
|
15757
14561
|
const pid = Number.parseInt(raw, 10);
|
|
15758
14562
|
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
15759
14563
|
return pid;
|
|
@@ -15772,7 +14576,7 @@ function busyWaitSync(ms) {
|
|
|
15772
14576
|
Atomics.wait(view, 0, 0, ms);
|
|
15773
14577
|
}
|
|
15774
14578
|
function withFileLockSync(lockPath, fn, opts = {}) {
|
|
15775
|
-
|
|
14579
|
+
mkdirSync5(dirname7(lockPath), { recursive: true });
|
|
15776
14580
|
const staleMs = opts.staleMs ?? 3e4;
|
|
15777
14581
|
const blockMs = opts.retries === 0 ? 0 : opts.blockMs ?? 3e4;
|
|
15778
14582
|
const pollIntervalMs = opts.pollIntervalMs ?? 100;
|
|
@@ -15789,7 +14593,7 @@ function withFileLockSync(lockPath, fn, opts = {}) {
|
|
|
15789
14593
|
realpath: false
|
|
15790
14594
|
});
|
|
15791
14595
|
try {
|
|
15792
|
-
|
|
14596
|
+
writeFileSync3(`${lockPath}.pid`, String(process.pid), "utf-8");
|
|
15793
14597
|
} catch {
|
|
15794
14598
|
}
|
|
15795
14599
|
break;
|
|
@@ -15878,7 +14682,7 @@ __export(config_refresh_exports, {
|
|
|
15878
14682
|
mergeRefresh: () => mergeRefresh,
|
|
15879
14683
|
runConfigRefresh: () => runConfigRefresh
|
|
15880
14684
|
});
|
|
15881
|
-
import { existsSync as existsSync13, readFileSync as
|
|
14685
|
+
import { existsSync as existsSync13, readFileSync as readFileSync14, rmSync as rmSync4 } from "fs";
|
|
15882
14686
|
import { resolve as resolve10 } from "path";
|
|
15883
14687
|
import { parse as parseYaml5 } from "yaml";
|
|
15884
14688
|
function flatten(obj, prefix3 = "") {
|
|
@@ -16017,7 +14821,7 @@ async function runConfigRefresh(opts = {}) {
|
|
|
16017
14821
|
}
|
|
16018
14822
|
let existing;
|
|
16019
14823
|
try {
|
|
16020
|
-
const content =
|
|
14824
|
+
const content = readFileSync14(configPath, "utf-8");
|
|
16021
14825
|
const parsed = parseYaml5(content);
|
|
16022
14826
|
if (!parsed || typeof parsed !== "object") {
|
|
16023
14827
|
throw new Error("config is not a YAML object");
|
|
@@ -16062,7 +14866,7 @@ async function runConfigRefresh(opts = {}) {
|
|
|
16062
14866
|
}
|
|
16063
14867
|
log("Config diff:\n");
|
|
16064
14868
|
log(renderDiff(diff));
|
|
16065
|
-
const { confirm } = await Promise.resolve().then(() => (
|
|
14869
|
+
const { confirm } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
16066
14870
|
const apply = await confirm({ message: "Apply these changes to massu.config.yaml?" });
|
|
16067
14871
|
if (apply !== true) {
|
|
16068
14872
|
log("Aborted; no changes written.\n");
|
|
@@ -16415,8 +15219,8 @@ var init_paths = __esm({
|
|
|
16415
15219
|
});
|
|
16416
15220
|
|
|
16417
15221
|
// src/watch/state.ts
|
|
16418
|
-
import { closeSync as closeSync3, existsSync as existsSync15, fsyncSync as fsyncSync3, mkdirSync as
|
|
16419
|
-
import { dirname as
|
|
15222
|
+
import { closeSync as closeSync3, existsSync as existsSync15, fsyncSync as fsyncSync3, mkdirSync as mkdirSync6, openSync as openSync3, readFileSync as readFileSync15, renameSync as renameSync4, rmSync as rmSync5, writeFileSync as writeFileSync4, writeSync as writeSync3 } from "fs";
|
|
15223
|
+
import { dirname as dirname8, resolve as resolve12 } from "path";
|
|
16420
15224
|
function watchStatePath(projectRoot) {
|
|
16421
15225
|
return resolve12(projectRoot, ".massu", "watch-state.json");
|
|
16422
15226
|
}
|
|
@@ -16426,7 +15230,7 @@ function backupStatePath(projectRoot) {
|
|
|
16426
15230
|
function readState(projectRoot) {
|
|
16427
15231
|
const path = watchStatePath(projectRoot);
|
|
16428
15232
|
if (!existsSync15(path)) return { ...DEFAULT_STATE };
|
|
16429
|
-
const content =
|
|
15233
|
+
const content = readFileSync15(path, "utf-8");
|
|
16430
15234
|
let raw;
|
|
16431
15235
|
try {
|
|
16432
15236
|
raw = JSON.parse(content);
|
|
@@ -16468,14 +15272,14 @@ function readState(projectRoot) {
|
|
|
16468
15272
|
}
|
|
16469
15273
|
function archiveCorrupt(projectRoot, content) {
|
|
16470
15274
|
const bak = backupStatePath(projectRoot);
|
|
16471
|
-
|
|
16472
|
-
|
|
15275
|
+
mkdirSync6(dirname8(bak), { recursive: true });
|
|
15276
|
+
writeFileSync4(bak, content, "utf-8");
|
|
16473
15277
|
}
|
|
16474
15278
|
function writeStateAtomic(projectRoot, state) {
|
|
16475
15279
|
const path = watchStatePath(projectRoot);
|
|
16476
15280
|
writeStateAtomicCounter = writeStateAtomicCounter + 1 >>> 0;
|
|
16477
15281
|
const tmp = `${path}.${process.pid}.${writeStateAtomicCounter}.tmp`;
|
|
16478
|
-
|
|
15282
|
+
mkdirSync6(dirname8(path), { recursive: true });
|
|
16479
15283
|
let renamed = false;
|
|
16480
15284
|
try {
|
|
16481
15285
|
const fd = openSync3(tmp, "w");
|
|
@@ -16486,7 +15290,7 @@ function writeStateAtomic(projectRoot, state) {
|
|
|
16486
15290
|
} finally {
|
|
16487
15291
|
closeSync3(fd);
|
|
16488
15292
|
}
|
|
16489
|
-
|
|
15293
|
+
renameSync4(tmp, path);
|
|
16490
15294
|
renamed = true;
|
|
16491
15295
|
} finally {
|
|
16492
15296
|
if (!renamed && existsSync15(tmp)) {
|
|
@@ -16769,8 +15573,8 @@ __export(watch_exports, {
|
|
|
16769
15573
|
runWatch: () => runWatch
|
|
16770
15574
|
});
|
|
16771
15575
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
16772
|
-
import { basename as basename5, dirname as
|
|
16773
|
-
import { appendFileSync, existsSync as existsSync16, mkdirSync as
|
|
15576
|
+
import { basename as basename5, dirname as dirname9, resolve as resolve13 } from "path";
|
|
15577
|
+
import { appendFileSync, existsSync as existsSync16, mkdirSync as mkdirSync7, readFileSync as readFileSync16 } from "fs";
|
|
16774
15578
|
function parseFlags(args2) {
|
|
16775
15579
|
const out = {
|
|
16776
15580
|
foreground: false,
|
|
@@ -17015,7 +15819,7 @@ function refreshLogPath(projectRoot) {
|
|
|
17015
15819
|
function appendRefreshLog(projectRoot, event) {
|
|
17016
15820
|
const path = refreshLogPath(projectRoot);
|
|
17017
15821
|
try {
|
|
17018
|
-
|
|
15822
|
+
mkdirSync7(dirname9(path), { recursive: true });
|
|
17019
15823
|
appendFileSync(path, JSON.stringify(event) + "\n", "utf-8");
|
|
17020
15824
|
} catch {
|
|
17021
15825
|
}
|
|
@@ -17026,7 +15830,7 @@ function readRefreshLog(projectRoot, limit = 10, opts = {}) {
|
|
|
17026
15830
|
const warn = opts.warn ?? ((s) => {
|
|
17027
15831
|
process.stderr.write(s);
|
|
17028
15832
|
});
|
|
17029
|
-
const lines =
|
|
15833
|
+
const lines = readFileSync16(path, "utf-8").split("\n").filter(Boolean);
|
|
17030
15834
|
const tail = lines.slice(-limit);
|
|
17031
15835
|
const out = [];
|
|
17032
15836
|
let corrupt = 0;
|
|
@@ -17097,28 +15901,28 @@ var init_refresh_log = __esm({
|
|
|
17097
15901
|
|
|
17098
15902
|
// src/security/atomic-write.ts
|
|
17099
15903
|
import {
|
|
17100
|
-
chmodSync as
|
|
15904
|
+
chmodSync as chmodSync3,
|
|
17101
15905
|
closeSync as closeSync4,
|
|
17102
15906
|
existsSync as existsSync17,
|
|
17103
15907
|
fsyncSync as fsyncSync4,
|
|
17104
|
-
mkdirSync as
|
|
15908
|
+
mkdirSync as mkdirSync8,
|
|
17105
15909
|
openSync as openSync4,
|
|
17106
|
-
renameSync as
|
|
15910
|
+
renameSync as renameSync5,
|
|
17107
15911
|
rmSync as rmSync6,
|
|
17108
15912
|
statSync as statSync9,
|
|
17109
15913
|
writeSync as writeSync4
|
|
17110
15914
|
} from "node:fs";
|
|
17111
|
-
import { dirname as
|
|
15915
|
+
import { dirname as dirname10 } from "node:path";
|
|
17112
15916
|
function atomicWrite(path, content, opts = {}) {
|
|
17113
15917
|
const tmpPath = `${path}.tmp`;
|
|
17114
|
-
const parentDir =
|
|
15918
|
+
const parentDir = dirname10(path);
|
|
17115
15919
|
try {
|
|
17116
15920
|
if (!existsSync17(parentDir)) {
|
|
17117
15921
|
const mkdirOpts = { recursive: true };
|
|
17118
15922
|
if (opts.ensureParentDirMode !== void 0) {
|
|
17119
15923
|
mkdirOpts.mode = opts.ensureParentDirMode;
|
|
17120
15924
|
}
|
|
17121
|
-
|
|
15925
|
+
mkdirSync8(parentDir, mkdirOpts);
|
|
17122
15926
|
}
|
|
17123
15927
|
const buf = typeof content === "string" ? Buffer.from(content, "utf-8") : content;
|
|
17124
15928
|
const openMode = opts.mode ?? 420;
|
|
@@ -17130,9 +15934,9 @@ function atomicWrite(path, content, opts = {}) {
|
|
|
17130
15934
|
closeSync4(fd);
|
|
17131
15935
|
}
|
|
17132
15936
|
if (opts.mode !== void 0) {
|
|
17133
|
-
|
|
15937
|
+
chmodSync3(tmpPath, opts.mode);
|
|
17134
15938
|
}
|
|
17135
|
-
|
|
15939
|
+
renameSync5(tmpPath, path);
|
|
17136
15940
|
return { written: true };
|
|
17137
15941
|
} catch (err) {
|
|
17138
15942
|
if (existsSync17(tmpPath)) {
|
|
@@ -17215,10 +16019,10 @@ var init_registry_pubkey_generated = __esm({
|
|
|
17215
16019
|
});
|
|
17216
16020
|
|
|
17217
16021
|
// src/security/adapter-verifier.ts
|
|
17218
|
-
import { createHash as
|
|
16022
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
17219
16023
|
import nacl from "tweetnacl";
|
|
17220
16024
|
function sha256Hex(bytes) {
|
|
17221
|
-
return
|
|
16025
|
+
return createHash5("sha256").update(bytes).digest("hex");
|
|
17222
16026
|
}
|
|
17223
16027
|
function reviver(key, value) {
|
|
17224
16028
|
if (key === "__proto__" || key === "constructor" || key === "prototype") {
|
|
@@ -17478,12 +16282,12 @@ var init_fetcher = __esm({
|
|
|
17478
16282
|
});
|
|
17479
16283
|
|
|
17480
16284
|
// src/security/manifest-cache.ts
|
|
17481
|
-
import { existsSync as existsSync18, readFileSync as
|
|
17482
|
-
import { homedir as
|
|
16285
|
+
import { existsSync as existsSync18, readFileSync as readFileSync17, statSync as statSync10 } from "node:fs";
|
|
16286
|
+
import { homedir as homedir4 } from "node:os";
|
|
17483
16287
|
import { resolve as resolve14 } from "node:path";
|
|
17484
16288
|
import { z as z4 } from "zod";
|
|
17485
16289
|
function defaultCachePaths() {
|
|
17486
|
-
const dir = resolve14(
|
|
16290
|
+
const dir = resolve14(homedir4(), ".massu");
|
|
17487
16291
|
return {
|
|
17488
16292
|
cachePath: resolve14(dir, "adapter-manifest.json"),
|
|
17489
16293
|
lockPath: resolve14(dir, ".adapter-manifest.lock")
|
|
@@ -17495,7 +16299,7 @@ function loadCachedManifest(paths = defaultCachePaths()) {
|
|
|
17495
16299
|
}
|
|
17496
16300
|
let raw;
|
|
17497
16301
|
try {
|
|
17498
|
-
const content =
|
|
16302
|
+
const content = readFileSync17(paths.cachePath, "utf-8");
|
|
17499
16303
|
raw = JSON.parse(content);
|
|
17500
16304
|
} catch (err) {
|
|
17501
16305
|
return {
|
|
@@ -17684,10 +16488,10 @@ var init_adapter_origin = __esm({
|
|
|
17684
16488
|
});
|
|
17685
16489
|
|
|
17686
16490
|
// src/security/local-fingerprint.ts
|
|
17687
|
-
import { existsSync as existsSync19, readFileSync as
|
|
17688
|
-
import { homedir as
|
|
16491
|
+
import { existsSync as existsSync19, readFileSync as readFileSync18, lstatSync as lstatSync5 } from "node:fs";
|
|
16492
|
+
import { homedir as homedir5 } from "node:os";
|
|
17689
16493
|
import { resolve as resolve15, isAbsolute } from "node:path";
|
|
17690
|
-
import { createHash as
|
|
16494
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
17691
16495
|
import { z as z5 } from "zod";
|
|
17692
16496
|
function computeLocalFingerprint(localPaths, projectRoot) {
|
|
17693
16497
|
const tuples = [];
|
|
@@ -17695,13 +16499,13 @@ function computeLocalFingerprint(localPaths, projectRoot) {
|
|
|
17695
16499
|
const abs = isAbsolute(p19) ? p19 : resolve15(projectRoot, p19);
|
|
17696
16500
|
let contentTag;
|
|
17697
16501
|
try {
|
|
17698
|
-
const lst =
|
|
16502
|
+
const lst = lstatSync5(abs);
|
|
17699
16503
|
if (lst.isSymbolicLink()) {
|
|
17700
16504
|
contentTag = "<symlink>";
|
|
17701
16505
|
} else if (!lst.isFile()) {
|
|
17702
16506
|
contentTag = "<not-a-file>";
|
|
17703
16507
|
} else {
|
|
17704
|
-
contentTag =
|
|
16508
|
+
contentTag = createHash6("sha256").update(readFileSync18(abs)).digest("hex");
|
|
17705
16509
|
}
|
|
17706
16510
|
} catch {
|
|
17707
16511
|
contentTag = "<missing>";
|
|
@@ -17710,13 +16514,13 @@ function computeLocalFingerprint(localPaths, projectRoot) {
|
|
|
17710
16514
|
}
|
|
17711
16515
|
tuples.sort((a2, b2) => a2.path < b2.path ? -1 : a2.path > b2.path ? 1 : 0);
|
|
17712
16516
|
const canonical = JSON.stringify(tuples);
|
|
17713
|
-
return
|
|
16517
|
+
return createHash6("sha256").update(canonical).digest("hex");
|
|
17714
16518
|
}
|
|
17715
16519
|
function readFingerprintSentinel(path = FINGERPRINT_PATH) {
|
|
17716
16520
|
if (!existsSync19(path)) return null;
|
|
17717
16521
|
let raw;
|
|
17718
16522
|
try {
|
|
17719
|
-
raw = JSON.parse(
|
|
16523
|
+
raw = JSON.parse(readFileSync18(path, "utf-8"));
|
|
17720
16524
|
} catch {
|
|
17721
16525
|
return null;
|
|
17722
16526
|
}
|
|
@@ -17764,7 +16568,7 @@ var init_local_fingerprint = __esm({
|
|
|
17764
16568
|
"use strict";
|
|
17765
16569
|
init_atomic_write();
|
|
17766
16570
|
init_manifest_schema();
|
|
17767
|
-
FINGERPRINT_PATH = resolve15(
|
|
16571
|
+
FINGERPRINT_PATH = resolve15(homedir5(), ".massu", "adapters-local-fingerprint.json");
|
|
17768
16572
|
FingerprintSentinelSchema = z5.object({
|
|
17769
16573
|
fingerprint: z5.string().regex(/^[0-9a-f]{64}$/),
|
|
17770
16574
|
source: z5.enum(["cli", "cli-resync"]),
|
|
@@ -17780,11 +16584,11 @@ var init_local_fingerprint = __esm({
|
|
|
17780
16584
|
});
|
|
17781
16585
|
|
|
17782
16586
|
// src/security/install-tracking.ts
|
|
17783
|
-
import { readFileSync as
|
|
17784
|
-
import { join as
|
|
17785
|
-
import { homedir as
|
|
16587
|
+
import { readFileSync as readFileSync19, readdirSync as readdirSync12, lstatSync as lstatSync6, existsSync as existsSync20 } from "node:fs";
|
|
16588
|
+
import { join as join10, relative as relative5, sep } from "node:path";
|
|
16589
|
+
import { homedir as homedir6 } from "node:os";
|
|
17786
16590
|
import { resolve as resolve16 } from "node:path";
|
|
17787
|
-
import { createHash as
|
|
16591
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
17788
16592
|
import { z as z6 } from "zod";
|
|
17789
16593
|
function containsHiddenDirs(packageDir) {
|
|
17790
16594
|
for (const hidden of EXCLUDED_DIR_NAMES) {
|
|
@@ -17800,15 +16604,15 @@ function sha256OfDir(dir, opts = {}) {
|
|
|
17800
16604
|
function walk(currentDir) {
|
|
17801
16605
|
let entries;
|
|
17802
16606
|
try {
|
|
17803
|
-
entries =
|
|
16607
|
+
entries = readdirSync12(currentDir);
|
|
17804
16608
|
} catch {
|
|
17805
16609
|
return;
|
|
17806
16610
|
}
|
|
17807
16611
|
for (const entry of entries.sort()) {
|
|
17808
|
-
const absPath =
|
|
16612
|
+
const absPath = join10(currentDir, entry);
|
|
17809
16613
|
let lst;
|
|
17810
16614
|
try {
|
|
17811
|
-
lst =
|
|
16615
|
+
lst = lstatSync6(absPath);
|
|
17812
16616
|
} catch {
|
|
17813
16617
|
continue;
|
|
17814
16618
|
}
|
|
@@ -17832,9 +16636,9 @@ function sha256OfDir(dir, opts = {}) {
|
|
|
17832
16636
|
}
|
|
17833
16637
|
walk(dir);
|
|
17834
16638
|
files.sort((a2, b2) => a2.relativePath < b2.relativePath ? -1 : a2.relativePath > b2.relativePath ? 1 : 0);
|
|
17835
|
-
const top =
|
|
16639
|
+
const top = createHash7("sha256");
|
|
17836
16640
|
for (const f2 of files) {
|
|
17837
|
-
const fileHash =
|
|
16641
|
+
const fileHash = createHash7("sha256").update(readFileSync19(f2.absPath)).digest("hex");
|
|
17838
16642
|
top.update(f2.relativePath, "utf-8");
|
|
17839
16643
|
top.update("\0", "utf-8");
|
|
17840
16644
|
top.update(fileHash, "utf-8");
|
|
@@ -17846,7 +16650,7 @@ function readInstalledManifest(path = INSTALLED_MANIFEST_PATH) {
|
|
|
17846
16650
|
if (!existsSync20(path)) return {};
|
|
17847
16651
|
let raw;
|
|
17848
16652
|
try {
|
|
17849
|
-
raw = JSON.parse(
|
|
16653
|
+
raw = JSON.parse(readFileSync19(path, "utf-8"));
|
|
17850
16654
|
} catch {
|
|
17851
16655
|
return {};
|
|
17852
16656
|
}
|
|
@@ -17910,7 +16714,7 @@ var init_install_tracking = __esm({
|
|
|
17910
16714
|
"src/security/install-tracking.ts"() {
|
|
17911
16715
|
"use strict";
|
|
17912
16716
|
init_atomic_write();
|
|
17913
|
-
INSTALLED_MANIFEST_PATH = resolve16(
|
|
16717
|
+
INSTALLED_MANIFEST_PATH = resolve16(homedir6(), ".massu", "adapter-manifest-installed.json");
|
|
17914
16718
|
DEFAULT_MAX_FILE_BYTES = 64 * 1024 * 1024;
|
|
17915
16719
|
EXCLUDED_DIR_NAMES = /* @__PURE__ */ new Set([".git", "node_modules", ".cache", ".tmp"]);
|
|
17916
16720
|
InstallEntrySchema = z6.object({
|
|
@@ -17933,7 +16737,7 @@ var init_install_tracking = __esm({
|
|
|
17933
16737
|
});
|
|
17934
16738
|
|
|
17935
16739
|
// src/detect/adapters/discover.ts
|
|
17936
|
-
import { existsSync as existsSync21, readdirSync as
|
|
16740
|
+
import { existsSync as existsSync21, readdirSync as readdirSync13, readFileSync as readFileSync20, lstatSync as lstatSync7 } from "node:fs";
|
|
17937
16741
|
import { resolve as resolve17, isAbsolute as isAbsolute2 } from "node:path";
|
|
17938
16742
|
import { z as z7 } from "zod";
|
|
17939
16743
|
function walkNodeModules(projectRoot, warnings) {
|
|
@@ -17944,7 +16748,7 @@ function walkNodeModules(projectRoot, warnings) {
|
|
|
17944
16748
|
const candidates = [];
|
|
17945
16749
|
let topLevelEntries;
|
|
17946
16750
|
try {
|
|
17947
|
-
topLevelEntries =
|
|
16751
|
+
topLevelEntries = readdirSync13(nodeModulesDir);
|
|
17948
16752
|
} catch (err) {
|
|
17949
16753
|
warnings.push(`failed to read node_modules: ${err instanceof Error ? err.message : String(err)}`);
|
|
17950
16754
|
return [];
|
|
@@ -17954,7 +16758,7 @@ function walkNodeModules(projectRoot, warnings) {
|
|
|
17954
16758
|
const entryPath = resolve17(nodeModulesDir, entry);
|
|
17955
16759
|
let entryStat;
|
|
17956
16760
|
try {
|
|
17957
|
-
entryStat =
|
|
16761
|
+
entryStat = lstatSync7(entryPath);
|
|
17958
16762
|
} catch {
|
|
17959
16763
|
continue;
|
|
17960
16764
|
}
|
|
@@ -17968,7 +16772,7 @@ function walkNodeModules(projectRoot, warnings) {
|
|
|
17968
16772
|
if (entry.startsWith("@")) {
|
|
17969
16773
|
let scopedEntries;
|
|
17970
16774
|
try {
|
|
17971
|
-
scopedEntries =
|
|
16775
|
+
scopedEntries = readdirSync13(entryPath);
|
|
17972
16776
|
} catch {
|
|
17973
16777
|
continue;
|
|
17974
16778
|
}
|
|
@@ -17976,7 +16780,7 @@ function walkNodeModules(projectRoot, warnings) {
|
|
|
17976
16780
|
const subPath = resolve17(entryPath, sub);
|
|
17977
16781
|
let subStat;
|
|
17978
16782
|
try {
|
|
17979
|
-
subStat =
|
|
16783
|
+
subStat = lstatSync7(subPath);
|
|
17980
16784
|
} catch {
|
|
17981
16785
|
continue;
|
|
17982
16786
|
}
|
|
@@ -17996,7 +16800,7 @@ function tryReadAdapterPackage(packageDir, warnings) {
|
|
|
17996
16800
|
if (!existsSync21(pkgJsonPath)) return null;
|
|
17997
16801
|
let raw;
|
|
17998
16802
|
try {
|
|
17999
|
-
raw = JSON.parse(
|
|
16803
|
+
raw = JSON.parse(readFileSync20(pkgJsonPath, "utf-8"));
|
|
18000
16804
|
} catch (err) {
|
|
18001
16805
|
warnings.push(
|
|
18002
16806
|
`skipping ${packageDir}: package.json parse failed (${err instanceof Error ? err.message : String(err)})`
|
|
@@ -18212,7 +17016,7 @@ __export(adapters_exports, {
|
|
|
18212
17016
|
runAdaptersResyncLocalFingerprint: () => runAdaptersResyncLocalFingerprint,
|
|
18213
17017
|
runAdaptersSearch: () => runAdaptersSearch
|
|
18214
17018
|
});
|
|
18215
|
-
import { existsSync as existsSync22, readFileSync as
|
|
17019
|
+
import { existsSync as existsSync22, readFileSync as readFileSync21 } from "node:fs";
|
|
18216
17020
|
import { resolve as resolve18 } from "node:path";
|
|
18217
17021
|
import { parseDocument } from "yaml";
|
|
18218
17022
|
async function handleAdaptersSubcommand(args2) {
|
|
@@ -18490,7 +17294,7 @@ function mutateLocalArray(mutator, command) {
|
|
|
18490
17294
|
}
|
|
18491
17295
|
let yamlText;
|
|
18492
17296
|
try {
|
|
18493
|
-
yamlText =
|
|
17297
|
+
yamlText = readFileSync21(yamlPath, "utf-8");
|
|
18494
17298
|
} catch (err) {
|
|
18495
17299
|
process.stderr.write(`${command}: failed to read ${yamlPath}: ${err instanceof Error ? err.message : String(err)}
|
|
18496
17300
|
`);
|
|
@@ -18596,7 +17400,7 @@ async function runAdaptersInstall(args2) {
|
|
|
18596
17400
|
}
|
|
18597
17401
|
let pkgJson;
|
|
18598
17402
|
try {
|
|
18599
|
-
pkgJson = JSON.parse(
|
|
17403
|
+
pkgJson = JSON.parse(readFileSync21(pkgJsonPath, "utf-8"));
|
|
18600
17404
|
} catch (err) {
|
|
18601
17405
|
process.stderr.write(`install: ${packageName} has malformed package.json: ${err instanceof Error ? err.message : String(err)}
|
|
18602
17406
|
`);
|
|
@@ -18803,8 +17607,8 @@ var init_adapters2 = __esm({
|
|
|
18803
17607
|
|
|
18804
17608
|
// src/db.ts
|
|
18805
17609
|
import Database2 from "better-sqlite3";
|
|
18806
|
-
import { dirname as
|
|
18807
|
-
import { existsSync as existsSync23, mkdirSync as
|
|
17610
|
+
import { dirname as dirname11, join as join11 } from "path";
|
|
17611
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync9, readdirSync as readdirSync14, statSync as statSync11 } from "fs";
|
|
18808
17612
|
function getCodeGraphDb() {
|
|
18809
17613
|
const dbPath = getResolvedPaths().codegraphDbPath;
|
|
18810
17614
|
if (!existsSync23(dbPath)) {
|
|
@@ -18816,9 +17620,9 @@ function getCodeGraphDb() {
|
|
|
18816
17620
|
}
|
|
18817
17621
|
function getDataDb() {
|
|
18818
17622
|
const dbPath = getResolvedPaths().dataDbPath;
|
|
18819
|
-
const dir =
|
|
17623
|
+
const dir = dirname11(dbPath);
|
|
18820
17624
|
if (!existsSync23(dir)) {
|
|
18821
|
-
|
|
17625
|
+
mkdirSync9(dir, { recursive: true });
|
|
18822
17626
|
}
|
|
18823
17627
|
const db = new Database2(dbPath);
|
|
18824
17628
|
db.pragma("journal_mode = WAL");
|
|
@@ -19088,9 +17892,9 @@ function isPythonDataStale(dataDb2, pythonRoot) {
|
|
|
19088
17892
|
const lastBuildTime = new Date(lastBuild.value).getTime();
|
|
19089
17893
|
function checkDir(dir) {
|
|
19090
17894
|
try {
|
|
19091
|
-
const entries =
|
|
17895
|
+
const entries = readdirSync14(dir, { withFileTypes: true });
|
|
19092
17896
|
for (const entry of entries) {
|
|
19093
|
-
const fullPath =
|
|
17897
|
+
const fullPath = join11(dir, entry.name);
|
|
19094
17898
|
if (entry.isDirectory()) {
|
|
19095
17899
|
if (["__pycache__", ".venv", "venv", "node_modules", ".mypy_cache", ".pytest_cache"].includes(entry.name)) continue;
|
|
19096
17900
|
if (checkDir(fullPath)) return true;
|
|
@@ -19191,8 +17995,8 @@ var init_rules = __esm({
|
|
|
19191
17995
|
});
|
|
19192
17996
|
|
|
19193
17997
|
// src/import-resolver.ts
|
|
19194
|
-
import { readFileSync as
|
|
19195
|
-
import { resolve as resolve20, dirname as
|
|
17998
|
+
import { readFileSync as readFileSync22, existsSync as existsSync24, statSync as statSync12 } from "fs";
|
|
17999
|
+
import { resolve as resolve20, dirname as dirname12, join as join12 } from "path";
|
|
19196
18000
|
function parseImports(source) {
|
|
19197
18001
|
const imports = [];
|
|
19198
18002
|
const lines = source.split("\n");
|
|
@@ -19250,7 +18054,7 @@ function resolveImportPath(specifier, fromFile) {
|
|
|
19250
18054
|
const paths = getResolvedPaths();
|
|
19251
18055
|
basePath = resolve20(paths.pathAlias["@"] ?? paths.srcDir, specifier.slice(2));
|
|
19252
18056
|
} else {
|
|
19253
|
-
basePath = resolve20(
|
|
18057
|
+
basePath = resolve20(dirname12(fromFile), specifier);
|
|
19254
18058
|
}
|
|
19255
18059
|
if (existsSync24(basePath) && !isDirectory(basePath)) {
|
|
19256
18060
|
return toRelative(basePath);
|
|
@@ -19263,7 +18067,7 @@ function resolveImportPath(specifier, fromFile) {
|
|
|
19263
18067
|
}
|
|
19264
18068
|
}
|
|
19265
18069
|
for (const indexFile of resolvedPaths.indexFiles) {
|
|
19266
|
-
const indexPath =
|
|
18070
|
+
const indexPath = join12(basePath, indexFile);
|
|
19267
18071
|
if (existsSync24(indexPath)) {
|
|
19268
18072
|
return toRelative(indexPath);
|
|
19269
18073
|
}
|
|
@@ -19304,7 +18108,7 @@ function buildImportIndex(dataDb2, codegraphDb2) {
|
|
|
19304
18108
|
if (!existsSync24(absPath)) continue;
|
|
19305
18109
|
let source;
|
|
19306
18110
|
try {
|
|
19307
|
-
source =
|
|
18111
|
+
source = readFileSync22(absPath, "utf-8");
|
|
19308
18112
|
} catch {
|
|
19309
18113
|
continue;
|
|
19310
18114
|
}
|
|
@@ -19340,15 +18144,15 @@ var init_import_resolver = __esm({
|
|
|
19340
18144
|
});
|
|
19341
18145
|
|
|
19342
18146
|
// src/trpc-index.ts
|
|
19343
|
-
import { readFileSync as
|
|
19344
|
-
import { resolve as resolve21, join as
|
|
18147
|
+
import { readFileSync as readFileSync23, existsSync as existsSync25, readdirSync as readdirSync15 } from "fs";
|
|
18148
|
+
import { resolve as resolve21, join as join13 } from "path";
|
|
19345
18149
|
function parseRootRouter() {
|
|
19346
18150
|
const paths = getResolvedPaths();
|
|
19347
18151
|
const rootPath = paths.rootRouterPath;
|
|
19348
18152
|
if (!existsSync25(rootPath)) {
|
|
19349
18153
|
throw new Error(`Root router not found at ${rootPath}`);
|
|
19350
18154
|
}
|
|
19351
|
-
const source =
|
|
18155
|
+
const source = readFileSync23(rootPath, "utf-8");
|
|
19352
18156
|
const mappings = [];
|
|
19353
18157
|
const importMap = /* @__PURE__ */ new Map();
|
|
19354
18158
|
const importRegex = /import\s+\{[^}]*?(\w+Router)[^}]*\}\s+from\s+['"]\.\/routers\/([^'"]+)['"]/g;
|
|
@@ -19364,7 +18168,7 @@ function parseRootRouter() {
|
|
|
19364
18168
|
filePath = routersRelPath + "/" + filePath + ext;
|
|
19365
18169
|
break;
|
|
19366
18170
|
}
|
|
19367
|
-
const indexCandidate =
|
|
18171
|
+
const indexCandidate = join13(fullPath, "index.ts");
|
|
19368
18172
|
if (existsSync25(indexCandidate)) {
|
|
19369
18173
|
filePath = routersRelPath + "/" + filePath + "/index.ts";
|
|
19370
18174
|
break;
|
|
@@ -19386,7 +18190,7 @@ function parseRootRouter() {
|
|
|
19386
18190
|
function extractProcedures(routerFilePath) {
|
|
19387
18191
|
const absPath = resolve21(getProjectRoot(), routerFilePath);
|
|
19388
18192
|
if (!existsSync25(absPath)) return [];
|
|
19389
|
-
const source =
|
|
18193
|
+
const source = readFileSync23(absPath, "utf-8");
|
|
19390
18194
|
const procedures = [];
|
|
19391
18195
|
const seen = /* @__PURE__ */ new Set();
|
|
19392
18196
|
const procRegex = /(\w+)\s*:\s*(protected|public)Procedure/g;
|
|
@@ -19421,15 +18225,15 @@ function findUICallSites(routerKey, procedureName) {
|
|
|
19421
18225
|
return callSites;
|
|
19422
18226
|
}
|
|
19423
18227
|
function searchDirectory(dir, pattern, results) {
|
|
19424
|
-
const entries =
|
|
18228
|
+
const entries = readdirSync15(dir, { withFileTypes: true });
|
|
19425
18229
|
for (const entry of entries) {
|
|
19426
|
-
const fullPath =
|
|
18230
|
+
const fullPath = join13(dir, entry.name);
|
|
19427
18231
|
if (entry.isDirectory()) {
|
|
19428
18232
|
if (entry.name === "node_modules" || entry.name === ".next") continue;
|
|
19429
18233
|
searchDirectory(fullPath, pattern, results);
|
|
19430
18234
|
} else if (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx")) {
|
|
19431
18235
|
try {
|
|
19432
|
-
const source =
|
|
18236
|
+
const source = readFileSync23(fullPath, "utf-8");
|
|
19433
18237
|
const lines = source.split("\n");
|
|
19434
18238
|
for (let i = 0; i < lines.length; i++) {
|
|
19435
18239
|
if (lines[i].includes(pattern)) {
|
|
@@ -19492,7 +18296,7 @@ var init_trpc_index = __esm({
|
|
|
19492
18296
|
});
|
|
19493
18297
|
|
|
19494
18298
|
// src/page-deps.ts
|
|
19495
|
-
import { readFileSync as
|
|
18299
|
+
import { readFileSync as readFileSync24, existsSync as existsSync26 } from "fs";
|
|
19496
18300
|
import { resolve as resolve22 } from "path";
|
|
19497
18301
|
function deriveRoute(pageFile) {
|
|
19498
18302
|
let route = pageFile.replace(/^src\/app/, "").replace(/\/page\.tsx?$/, "").replace(/\/page\.jsx?$/, "");
|
|
@@ -19534,7 +18338,7 @@ function findRouterCalls(files) {
|
|
|
19534
18338
|
const absPath = ensureWithinRoot(resolve22(projectRoot, file), projectRoot);
|
|
19535
18339
|
if (!existsSync26(absPath)) continue;
|
|
19536
18340
|
try {
|
|
19537
|
-
const source =
|
|
18341
|
+
const source = readFileSync24(absPath, "utf-8");
|
|
19538
18342
|
const apiCallRegex = /api\.(\w+)\.\w+/g;
|
|
19539
18343
|
let match;
|
|
19540
18344
|
while ((match = apiCallRegex.exec(source)) !== null) {
|
|
@@ -19555,7 +18359,7 @@ function findTablesFromRouters(routerNames, dataDb2) {
|
|
|
19555
18359
|
const absPath = ensureWithinRoot(resolve22(getProjectRoot(), proc.router_file), getProjectRoot());
|
|
19556
18360
|
if (!existsSync26(absPath)) continue;
|
|
19557
18361
|
try {
|
|
19558
|
-
const source =
|
|
18362
|
+
const source = readFileSync24(absPath, "utf-8");
|
|
19559
18363
|
const dbPattern = getConfig().dbAccessPattern ?? "ctx.db.{table}";
|
|
19560
18364
|
const regexStr = dbPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace("\\{table\\}", "(\\w+)");
|
|
19561
18365
|
const tableRegex = new RegExp(regexStr + "\\.", "g");
|
|
@@ -19824,14 +18628,14 @@ var init_domains = __esm({
|
|
|
19824
18628
|
});
|
|
19825
18629
|
|
|
19826
18630
|
// src/schema-mapper.ts
|
|
19827
|
-
import { readFileSync as
|
|
19828
|
-
import { join as
|
|
18631
|
+
import { readFileSync as readFileSync25, existsSync as existsSync27, readdirSync as readdirSync16 } from "fs";
|
|
18632
|
+
import { join as join14 } from "path";
|
|
19829
18633
|
function parsePrismaSchema() {
|
|
19830
18634
|
const schemaPath = getResolvedPaths().prismaSchemaPath;
|
|
19831
18635
|
if (!existsSync27(schemaPath)) {
|
|
19832
18636
|
throw new Error(`Prisma schema not found at ${schemaPath}`);
|
|
19833
18637
|
}
|
|
19834
|
-
const source =
|
|
18638
|
+
const source = readFileSync25(schemaPath, "utf-8");
|
|
19835
18639
|
const models = [];
|
|
19836
18640
|
const sourceLines = source.split("\n");
|
|
19837
18641
|
let i = 0;
|
|
@@ -19894,9 +18698,9 @@ function findColumnUsageInRouters(tableName) {
|
|
|
19894
18698
|
return usage;
|
|
19895
18699
|
}
|
|
19896
18700
|
function scanDirectory(dir, tableName, usage) {
|
|
19897
|
-
const entries =
|
|
18701
|
+
const entries = readdirSync16(dir, { withFileTypes: true });
|
|
19898
18702
|
for (const entry of entries) {
|
|
19899
|
-
const fullPath =
|
|
18703
|
+
const fullPath = join14(dir, entry.name);
|
|
19900
18704
|
if (entry.isDirectory()) {
|
|
19901
18705
|
scanDirectory(fullPath, tableName, usage);
|
|
19902
18706
|
} else if (entry.name.endsWith(".ts")) {
|
|
@@ -19906,7 +18710,7 @@ function scanDirectory(dir, tableName, usage) {
|
|
|
19906
18710
|
}
|
|
19907
18711
|
function scanFile(absPath, tableName, usage) {
|
|
19908
18712
|
try {
|
|
19909
|
-
const source =
|
|
18713
|
+
const source = readFileSync25(absPath, "utf-8");
|
|
19910
18714
|
if (!source.includes(tableName)) return;
|
|
19911
18715
|
const relPath = absPath.slice(getProjectRoot().length + 1);
|
|
19912
18716
|
const lines = source.split("\n");
|
|
@@ -19952,14 +18756,14 @@ function detectMismatches(models) {
|
|
|
19952
18756
|
function findFilesUsingColumn(dir, column, tableName) {
|
|
19953
18757
|
const result = [];
|
|
19954
18758
|
if (!existsSync27(dir)) return result;
|
|
19955
|
-
const entries =
|
|
18759
|
+
const entries = readdirSync16(dir, { withFileTypes: true });
|
|
19956
18760
|
for (const entry of entries) {
|
|
19957
|
-
const fullPath =
|
|
18761
|
+
const fullPath = join14(dir, entry.name);
|
|
19958
18762
|
if (entry.isDirectory()) {
|
|
19959
18763
|
result.push(...findFilesUsingColumn(fullPath, column, tableName));
|
|
19960
18764
|
} else if (entry.name.endsWith(".ts")) {
|
|
19961
18765
|
try {
|
|
19962
|
-
const source =
|
|
18766
|
+
const source = readFileSync25(fullPath, "utf-8");
|
|
19963
18767
|
if (source.includes(tableName) && source.includes(column)) {
|
|
19964
18768
|
result.push(fullPath.slice(getProjectRoot().length + 1));
|
|
19965
18769
|
}
|
|
@@ -20104,32 +18908,32 @@ var init_import_parser = __esm({
|
|
|
20104
18908
|
});
|
|
20105
18909
|
|
|
20106
18910
|
// src/python/import-resolver.ts
|
|
20107
|
-
import { readFileSync as
|
|
20108
|
-
import { resolve as resolve24, join as
|
|
18911
|
+
import { readFileSync as readFileSync26, existsSync as existsSync28, readdirSync as readdirSync17 } from "fs";
|
|
18912
|
+
import { resolve as resolve24, join as join15, relative as relative6, dirname as dirname13 } from "path";
|
|
20109
18913
|
function resolvePythonModulePath(module, fromFile, pythonRoot, level) {
|
|
20110
18914
|
const projectRoot = getProjectRoot();
|
|
20111
18915
|
if (level > 0) {
|
|
20112
|
-
let baseDir =
|
|
18916
|
+
let baseDir = dirname13(resolve24(projectRoot, fromFile));
|
|
20113
18917
|
for (let i = 1; i < level; i++) {
|
|
20114
|
-
baseDir =
|
|
18918
|
+
baseDir = dirname13(baseDir);
|
|
20115
18919
|
}
|
|
20116
18920
|
const modulePart = module.replace(/^\.+/, "");
|
|
20117
18921
|
if (modulePart) {
|
|
20118
18922
|
const parts2 = modulePart.split(".");
|
|
20119
|
-
return tryResolvePythonPath(
|
|
18923
|
+
return tryResolvePythonPath(join15(baseDir, ...parts2), projectRoot);
|
|
20120
18924
|
}
|
|
20121
18925
|
return tryResolvePythonPath(baseDir, projectRoot);
|
|
20122
18926
|
}
|
|
20123
18927
|
const parts = module.split(".");
|
|
20124
|
-
const candidate =
|
|
18928
|
+
const candidate = join15(resolve24(projectRoot, pythonRoot), ...parts);
|
|
20125
18929
|
return tryResolvePythonPath(candidate, projectRoot);
|
|
20126
18930
|
}
|
|
20127
18931
|
function tryResolvePythonPath(basePath, projectRoot) {
|
|
20128
18932
|
if (existsSync28(basePath + ".py")) {
|
|
20129
18933
|
return relative6(projectRoot, basePath + ".py");
|
|
20130
18934
|
}
|
|
20131
|
-
if (existsSync28(
|
|
20132
|
-
return relative6(projectRoot,
|
|
18935
|
+
if (existsSync28(join15(basePath, "__init__.py"))) {
|
|
18936
|
+
return relative6(projectRoot, join15(basePath, "__init__.py"));
|
|
20133
18937
|
}
|
|
20134
18938
|
if (basePath.endsWith(".py") && existsSync28(basePath)) {
|
|
20135
18939
|
return relative6(projectRoot, basePath);
|
|
@@ -20139,13 +18943,13 @@ function tryResolvePythonPath(basePath, projectRoot) {
|
|
|
20139
18943
|
function walkPythonFiles(dir, excludeDirs) {
|
|
20140
18944
|
const files = [];
|
|
20141
18945
|
try {
|
|
20142
|
-
const entries =
|
|
18946
|
+
const entries = readdirSync17(dir, { withFileTypes: true });
|
|
20143
18947
|
for (const entry of entries) {
|
|
20144
18948
|
if (entry.isDirectory()) {
|
|
20145
18949
|
if (excludeDirs.includes(entry.name)) continue;
|
|
20146
|
-
files.push(...walkPythonFiles(
|
|
18950
|
+
files.push(...walkPythonFiles(join15(dir, entry.name), excludeDirs));
|
|
20147
18951
|
} else if (entry.name.endsWith(".py")) {
|
|
20148
|
-
files.push(
|
|
18952
|
+
files.push(join15(dir, entry.name));
|
|
20149
18953
|
}
|
|
20150
18954
|
}
|
|
20151
18955
|
} catch {
|
|
@@ -20171,7 +18975,7 @@ function buildPythonImportIndex(dataDb2, pythonRoot, excludeDirs = ["__pycache__
|
|
|
20171
18975
|
const relFile = relative6(projectRoot, absFile);
|
|
20172
18976
|
let source;
|
|
20173
18977
|
try {
|
|
20174
|
-
source =
|
|
18978
|
+
source = readFileSync26(absFile, "utf-8");
|
|
20175
18979
|
} catch {
|
|
20176
18980
|
continue;
|
|
20177
18981
|
}
|
|
@@ -20437,18 +19241,18 @@ var init_route_parser = __esm({
|
|
|
20437
19241
|
});
|
|
20438
19242
|
|
|
20439
19243
|
// src/python/route-indexer.ts
|
|
20440
|
-
import { readFileSync as
|
|
20441
|
-
import { join as
|
|
19244
|
+
import { readFileSync as readFileSync27, readdirSync as readdirSync18 } from "fs";
|
|
19245
|
+
import { join as join16, relative as relative7 } from "path";
|
|
20442
19246
|
function walkPyFiles(dir, excludeDirs) {
|
|
20443
19247
|
const files = [];
|
|
20444
19248
|
try {
|
|
20445
|
-
const entries =
|
|
19249
|
+
const entries = readdirSync18(dir, { withFileTypes: true });
|
|
20446
19250
|
for (const entry of entries) {
|
|
20447
19251
|
if (entry.isDirectory()) {
|
|
20448
19252
|
if (excludeDirs.includes(entry.name)) continue;
|
|
20449
|
-
files.push(...walkPyFiles(
|
|
19253
|
+
files.push(...walkPyFiles(join16(dir, entry.name), excludeDirs));
|
|
20450
19254
|
} else if (entry.name.endsWith(".py")) {
|
|
20451
|
-
files.push(
|
|
19255
|
+
files.push(join16(dir, entry.name));
|
|
20452
19256
|
}
|
|
20453
19257
|
}
|
|
20454
19258
|
} catch {
|
|
@@ -20457,7 +19261,7 @@ function walkPyFiles(dir, excludeDirs) {
|
|
|
20457
19261
|
}
|
|
20458
19262
|
function buildPythonRouteIndex(dataDb2, pythonRoot, excludeDirs = ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"]) {
|
|
20459
19263
|
const projectRoot = getProjectRoot();
|
|
20460
|
-
const absRoot =
|
|
19264
|
+
const absRoot = join16(projectRoot, pythonRoot);
|
|
20461
19265
|
dataDb2.exec("DELETE FROM massu_py_routes");
|
|
20462
19266
|
dataDb2.exec("DELETE FROM massu_py_route_callers");
|
|
20463
19267
|
const insertStmt = dataDb2.prepare(
|
|
@@ -20470,7 +19274,7 @@ function buildPythonRouteIndex(dataDb2, pythonRoot, excludeDirs = ["__pycache__"
|
|
|
20470
19274
|
const relFile = relative7(projectRoot, absFile);
|
|
20471
19275
|
let source;
|
|
20472
19276
|
try {
|
|
20473
|
-
source =
|
|
19277
|
+
source = readFileSync27(absFile, "utf-8");
|
|
20474
19278
|
} catch {
|
|
20475
19279
|
continue;
|
|
20476
19280
|
}
|
|
@@ -20681,18 +19485,18 @@ var init_model_parser = __esm({
|
|
|
20681
19485
|
});
|
|
20682
19486
|
|
|
20683
19487
|
// src/python/model-indexer.ts
|
|
20684
|
-
import { readFileSync as
|
|
20685
|
-
import { join as
|
|
19488
|
+
import { readFileSync as readFileSync28, readdirSync as readdirSync19 } from "fs";
|
|
19489
|
+
import { join as join17, relative as relative8 } from "path";
|
|
20686
19490
|
function walkPyFiles2(dir, excludeDirs) {
|
|
20687
19491
|
const files = [];
|
|
20688
19492
|
try {
|
|
20689
|
-
const entries =
|
|
19493
|
+
const entries = readdirSync19(dir, { withFileTypes: true });
|
|
20690
19494
|
for (const entry of entries) {
|
|
20691
19495
|
if (entry.isDirectory()) {
|
|
20692
19496
|
if (excludeDirs.includes(entry.name)) continue;
|
|
20693
|
-
files.push(...walkPyFiles2(
|
|
19497
|
+
files.push(...walkPyFiles2(join17(dir, entry.name), excludeDirs));
|
|
20694
19498
|
} else if (entry.name.endsWith(".py")) {
|
|
20695
|
-
files.push(
|
|
19499
|
+
files.push(join17(dir, entry.name));
|
|
20696
19500
|
}
|
|
20697
19501
|
}
|
|
20698
19502
|
} catch {
|
|
@@ -20701,7 +19505,7 @@ function walkPyFiles2(dir, excludeDirs) {
|
|
|
20701
19505
|
}
|
|
20702
19506
|
function buildPythonModelIndex(dataDb2, pythonRoot, excludeDirs = ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"]) {
|
|
20703
19507
|
const projectRoot = getProjectRoot();
|
|
20704
|
-
const absRoot =
|
|
19508
|
+
const absRoot = join17(projectRoot, pythonRoot);
|
|
20705
19509
|
dataDb2.exec("DELETE FROM massu_py_models");
|
|
20706
19510
|
dataDb2.exec("DELETE FROM massu_py_fk_edges");
|
|
20707
19511
|
const insertModel = dataDb2.prepare(
|
|
@@ -20717,7 +19521,7 @@ function buildPythonModelIndex(dataDb2, pythonRoot, excludeDirs = ["__pycache__"
|
|
|
20717
19521
|
const relFile = relative8(projectRoot, absFile);
|
|
20718
19522
|
let source;
|
|
20719
19523
|
try {
|
|
20720
|
-
source =
|
|
19524
|
+
source = readFileSync28(absFile, "utf-8");
|
|
20721
19525
|
} catch {
|
|
20722
19526
|
continue;
|
|
20723
19527
|
}
|
|
@@ -20977,19 +19781,19 @@ var init_migration_parser = __esm({
|
|
|
20977
19781
|
});
|
|
20978
19782
|
|
|
20979
19783
|
// src/python/migration-indexer.ts
|
|
20980
|
-
import { readFileSync as
|
|
20981
|
-
import { join as
|
|
19784
|
+
import { readFileSync as readFileSync29, readdirSync as readdirSync20 } from "fs";
|
|
19785
|
+
import { join as join18, relative as relative9 } from "path";
|
|
20982
19786
|
function buildPythonMigrationIndex(dataDb2, alembicDir) {
|
|
20983
19787
|
const projectRoot = getProjectRoot();
|
|
20984
|
-
const absDir =
|
|
19788
|
+
const absDir = join18(projectRoot, alembicDir);
|
|
20985
19789
|
dataDb2.exec("DELETE FROM massu_py_migrations");
|
|
20986
|
-
const versionsDir =
|
|
19790
|
+
const versionsDir = join18(absDir, "versions");
|
|
20987
19791
|
let files = [];
|
|
20988
19792
|
try {
|
|
20989
|
-
files =
|
|
19793
|
+
files = readdirSync20(versionsDir).filter((f2) => f2.endsWith(".py")).map((f2) => join18(versionsDir, f2));
|
|
20990
19794
|
} catch {
|
|
20991
19795
|
try {
|
|
20992
|
-
files =
|
|
19796
|
+
files = readdirSync20(absDir).filter((f2) => f2.endsWith(".py") && f2 !== "env.py").map((f2) => join18(absDir, f2));
|
|
20993
19797
|
} catch {
|
|
20994
19798
|
}
|
|
20995
19799
|
}
|
|
@@ -21003,7 +19807,7 @@ function buildPythonMigrationIndex(dataDb2, alembicDir) {
|
|
|
21003
19807
|
for (const absFile of files) {
|
|
21004
19808
|
let source;
|
|
21005
19809
|
try {
|
|
21006
|
-
source =
|
|
19810
|
+
source = readFileSync29(absFile, "utf-8");
|
|
21007
19811
|
} catch {
|
|
21008
19812
|
continue;
|
|
21009
19813
|
}
|
|
@@ -21037,12 +19841,12 @@ var init_migration_indexer = __esm({
|
|
|
21037
19841
|
});
|
|
21038
19842
|
|
|
21039
19843
|
// src/python/coupling-detector.ts
|
|
21040
|
-
import { readFileSync as
|
|
21041
|
-
import { join as
|
|
19844
|
+
import { readFileSync as readFileSync30, readdirSync as readdirSync21 } from "fs";
|
|
19845
|
+
import { join as join19, relative as relative10 } from "path";
|
|
21042
19846
|
function buildPythonCouplingIndex(dataDb2) {
|
|
21043
19847
|
const projectRoot = getProjectRoot();
|
|
21044
19848
|
const config = getConfig();
|
|
21045
|
-
const srcDir =
|
|
19849
|
+
const srcDir = join19(projectRoot, config.paths.source);
|
|
21046
19850
|
const routes = dataDb2.prepare("SELECT id, method, path FROM massu_py_routes").all();
|
|
21047
19851
|
if (routes.length === 0) return 0;
|
|
21048
19852
|
dataDb2.exec("DELETE FROM massu_py_route_callers");
|
|
@@ -21074,7 +19878,7 @@ function buildPythonCouplingIndex(dataDb2) {
|
|
|
21074
19878
|
const relFile = relative10(projectRoot, absFile);
|
|
21075
19879
|
let source;
|
|
21076
19880
|
try {
|
|
21077
|
-
source =
|
|
19881
|
+
source = readFileSync30(absFile, "utf-8");
|
|
21078
19882
|
} catch {
|
|
21079
19883
|
continue;
|
|
21080
19884
|
}
|
|
@@ -21102,13 +19906,13 @@ function walkFrontendFiles(dir) {
|
|
|
21102
19906
|
const files = [];
|
|
21103
19907
|
const exclude = ["node_modules", ".next", "dist", ".git", "__pycache__", ".venv", "venv"];
|
|
21104
19908
|
try {
|
|
21105
|
-
const entries =
|
|
19909
|
+
const entries = readdirSync21(dir, { withFileTypes: true });
|
|
21106
19910
|
for (const entry of entries) {
|
|
21107
19911
|
if (entry.isDirectory()) {
|
|
21108
19912
|
if (exclude.includes(entry.name)) continue;
|
|
21109
|
-
files.push(...walkFrontendFiles(
|
|
19913
|
+
files.push(...walkFrontendFiles(join19(dir, entry.name)));
|
|
21110
19914
|
} else if (/\.(tsx?|jsx?)$/.test(entry.name)) {
|
|
21111
|
-
files.push(
|
|
19915
|
+
files.push(join19(dir, entry.name));
|
|
21112
19916
|
}
|
|
21113
19917
|
}
|
|
21114
19918
|
} catch {
|
|
@@ -21479,7 +20283,7 @@ var init_memory_tools = __esm({
|
|
|
21479
20283
|
});
|
|
21480
20284
|
|
|
21481
20285
|
// src/docs-tools.ts
|
|
21482
|
-
import { readFileSync as
|
|
20286
|
+
import { readFileSync as readFileSync31, existsSync as existsSync29 } from "fs";
|
|
21483
20287
|
import { resolve as resolve25, basename as basename6 } from "path";
|
|
21484
20288
|
function p3(baseName) {
|
|
21485
20289
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
@@ -21538,7 +20342,7 @@ function loadDocsMap() {
|
|
|
21538
20342
|
if (!existsSync29(mapPath)) {
|
|
21539
20343
|
throw new Error(`docs-map.json not found at ${mapPath}`);
|
|
21540
20344
|
}
|
|
21541
|
-
return JSON.parse(
|
|
20345
|
+
return JSON.parse(readFileSync31(mapPath, "utf-8"));
|
|
21542
20346
|
}
|
|
21543
20347
|
function matchesPattern(filePath, pattern) {
|
|
21544
20348
|
const regexStr = pattern.replace(/\./g, "\\.").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
@@ -21612,9 +20416,9 @@ function extractProcedureNames(routerPath) {
|
|
|
21612
20416
|
if (!existsSync29(absPath)) {
|
|
21613
20417
|
const altPath = ensureWithinRoot(resolve25(getResolvedPaths().srcDir, "../server/api/routers", basename6(routerPath)), root);
|
|
21614
20418
|
if (!existsSync29(altPath)) return [];
|
|
21615
|
-
return extractProcedureNamesFromContent(
|
|
20419
|
+
return extractProcedureNamesFromContent(readFileSync31(altPath, "utf-8"));
|
|
21616
20420
|
}
|
|
21617
|
-
return extractProcedureNamesFromContent(
|
|
20421
|
+
return extractProcedureNamesFromContent(readFileSync31(absPath, "utf-8"));
|
|
21618
20422
|
}
|
|
21619
20423
|
function extractProcedureNamesFromContent(content) {
|
|
21620
20424
|
const procRegex = /\.(?:query|mutation)\s*\(/g;
|
|
@@ -21667,7 +20471,7 @@ function handleDocsAudit(args2) {
|
|
|
21667
20471
|
});
|
|
21668
20472
|
continue;
|
|
21669
20473
|
}
|
|
21670
|
-
const content =
|
|
20474
|
+
const content = readFileSync31(helpPagePath, "utf-8");
|
|
21671
20475
|
const sections = extractSections(content);
|
|
21672
20476
|
const frontmatter = extractFrontmatter(content);
|
|
21673
20477
|
const staleReasons = [];
|
|
@@ -21709,7 +20513,7 @@ function handleDocsAudit(args2) {
|
|
|
21709
20513
|
if (parentId === mappingId) {
|
|
21710
20514
|
const guidePath = ensureWithinRoot(resolve25(getResolvedPaths().helpSitePath, `pages/user-guides/${guideName}/index.mdx`), getProjectRoot());
|
|
21711
20515
|
if (existsSync29(guidePath)) {
|
|
21712
|
-
const guideContent =
|
|
20516
|
+
const guideContent = readFileSync31(guidePath, "utf-8");
|
|
21713
20517
|
const guideFrontmatter = extractFrontmatter(guideContent);
|
|
21714
20518
|
if (!guideFrontmatter?.lastVerified || status === "STALE") {
|
|
21715
20519
|
results.push({
|
|
@@ -21749,7 +20553,7 @@ function handleDocsCoverage(args2) {
|
|
|
21749
20553
|
let lastVerified = null;
|
|
21750
20554
|
let status = null;
|
|
21751
20555
|
if (exists) {
|
|
21752
|
-
const content =
|
|
20556
|
+
const content = readFileSync31(helpPagePath, "utf-8");
|
|
21753
20557
|
lineCount = content.split("\n").length;
|
|
21754
20558
|
hasContent = lineCount > 10;
|
|
21755
20559
|
const frontmatter = extractFrontmatter(content);
|
|
@@ -22867,8 +21671,8 @@ var init_sentinel_tools = __esm({
|
|
|
22867
21671
|
});
|
|
22868
21672
|
|
|
22869
21673
|
// src/sentinel-scanner.ts
|
|
22870
|
-
import { readFileSync as
|
|
22871
|
-
import { resolve as resolve27, join as
|
|
21674
|
+
import { readFileSync as readFileSync32, existsSync as existsSync31, readdirSync as readdirSync22, statSync as statSync13 } from "fs";
|
|
21675
|
+
import { resolve as resolve27, join as join20, basename as basename7, dirname as dirname14, relative as relative11 } from "path";
|
|
22872
21676
|
function inferDomain(filePath) {
|
|
22873
21677
|
const domains = getConfig().domains;
|
|
22874
21678
|
const path = filePath.toLowerCase();
|
|
@@ -23000,7 +21804,7 @@ function scanComponentExports(dataDb2) {
|
|
|
23000
21804
|
const basePath = resolve27(projectRoot, componentsBase);
|
|
23001
21805
|
if (existsSync31(basePath)) {
|
|
23002
21806
|
try {
|
|
23003
|
-
const entries =
|
|
21807
|
+
const entries = readdirSync22(basePath, { withFileTypes: true });
|
|
23004
21808
|
for (const entry of entries) {
|
|
23005
21809
|
if (entry.isDirectory()) {
|
|
23006
21810
|
componentDirs.push(componentsBase + "/" + entry.name);
|
|
@@ -23015,7 +21819,7 @@ function scanComponentExports(dataDb2) {
|
|
|
23015
21819
|
const files = walkDir2(absDir).filter((f2) => f2.endsWith(".tsx") || f2.endsWith(".ts"));
|
|
23016
21820
|
for (const file of files) {
|
|
23017
21821
|
const relPath = relative11(projectRoot, file);
|
|
23018
|
-
const source =
|
|
21822
|
+
const source = readFileSync32(file, "utf-8");
|
|
23019
21823
|
const annotations = parseFeatureAnnotations(source);
|
|
23020
21824
|
if (annotations.length > 0) {
|
|
23021
21825
|
for (const ann of annotations) {
|
|
@@ -23041,7 +21845,7 @@ function scanComponentExports(dataDb2) {
|
|
|
23041
21845
|
if (hasHandlers && exportMatch) {
|
|
23042
21846
|
const componentName = exportMatch[1];
|
|
23043
21847
|
const domain = inferDomain(relPath);
|
|
23044
|
-
const subdomain = basename7(
|
|
21848
|
+
const subdomain = basename7(dirname14(relPath));
|
|
23045
21849
|
const featureKey = `component.${subdomain}.${componentName.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "")}`;
|
|
23046
21850
|
if (!annotations.some((a2) => a2.featureKey === featureKey)) {
|
|
23047
21851
|
features.push({
|
|
@@ -23064,9 +21868,9 @@ function scanComponentExports(dataDb2) {
|
|
|
23064
21868
|
function walkDir2(dir) {
|
|
23065
21869
|
const results = [];
|
|
23066
21870
|
try {
|
|
23067
|
-
const entries =
|
|
21871
|
+
const entries = readdirSync22(dir);
|
|
23068
21872
|
for (const entry of entries) {
|
|
23069
|
-
const fullPath =
|
|
21873
|
+
const fullPath = join20(dir, entry);
|
|
23070
21874
|
try {
|
|
23071
21875
|
const stat = statSync13(fullPath);
|
|
23072
21876
|
if (stat.isDirectory()) {
|
|
@@ -24054,7 +22858,7 @@ var init_audit_trail = __esm({
|
|
|
24054
22858
|
});
|
|
24055
22859
|
|
|
24056
22860
|
// src/validation-engine.ts
|
|
24057
|
-
import { existsSync as existsSync32, readFileSync as
|
|
22861
|
+
import { existsSync as existsSync32, readFileSync as readFileSync33 } from "fs";
|
|
24058
22862
|
function p10(baseName) {
|
|
24059
22863
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
24060
22864
|
}
|
|
@@ -24094,7 +22898,7 @@ function validateFile(filePath, projectRoot) {
|
|
|
24094
22898
|
});
|
|
24095
22899
|
return checks;
|
|
24096
22900
|
}
|
|
24097
|
-
const source =
|
|
22901
|
+
const source = readFileSync33(absPath, "utf-8");
|
|
24098
22902
|
const lines = source.split("\n");
|
|
24099
22903
|
if (activeChecks.rule_compliance !== false) {
|
|
24100
22904
|
for (const ruleSet of config.rules) {
|
|
@@ -24539,7 +23343,7 @@ var init_adr_generator = __esm({
|
|
|
24539
23343
|
});
|
|
24540
23344
|
|
|
24541
23345
|
// src/security-scorer.ts
|
|
24542
|
-
import { existsSync as existsSync33, readFileSync as
|
|
23346
|
+
import { existsSync as existsSync33, readFileSync as readFileSync34 } from "fs";
|
|
24543
23347
|
function p12(baseName) {
|
|
24544
23348
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
24545
23349
|
}
|
|
@@ -24568,7 +23372,7 @@ function scoreFileSecurity(filePath, projectRoot) {
|
|
|
24568
23372
|
}
|
|
24569
23373
|
let source;
|
|
24570
23374
|
try {
|
|
24571
|
-
source =
|
|
23375
|
+
source = readFileSync34(absPath, "utf-8");
|
|
24572
23376
|
} catch {
|
|
24573
23377
|
return { riskScore: 0, findings: [] };
|
|
24574
23378
|
}
|
|
@@ -24857,7 +23661,7 @@ var init_security_scorer = __esm({
|
|
|
24857
23661
|
});
|
|
24858
23662
|
|
|
24859
23663
|
// src/dependency-scorer.ts
|
|
24860
|
-
import { existsSync as existsSync34, readFileSync as
|
|
23664
|
+
import { existsSync as existsSync34, readFileSync as readFileSync35 } from "fs";
|
|
24861
23665
|
import { resolve as resolve28 } from "path";
|
|
24862
23666
|
function p13(baseName) {
|
|
24863
23667
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
@@ -24893,7 +23697,7 @@ function getInstalledPackages(projectRoot) {
|
|
|
24893
23697
|
const pkgPath = resolve28(projectRoot, "package.json");
|
|
24894
23698
|
if (!existsSync34(pkgPath)) return /* @__PURE__ */ new Map();
|
|
24895
23699
|
try {
|
|
24896
|
-
const pkg = JSON.parse(
|
|
23700
|
+
const pkg = JSON.parse(readFileSync35(pkgPath, "utf-8"));
|
|
24897
23701
|
const packages = /* @__PURE__ */ new Map();
|
|
24898
23702
|
for (const [name, version] of Object.entries(pkg.dependencies ?? {})) {
|
|
24899
23703
|
packages.set(name, version);
|
|
@@ -25495,8 +24299,8 @@ var init_regression_detector = __esm({
|
|
|
25495
24299
|
});
|
|
25496
24300
|
|
|
25497
24301
|
// src/knowledge-indexer.ts
|
|
25498
|
-
import { createHash as
|
|
25499
|
-
import { readFileSync as
|
|
24302
|
+
import { createHash as createHash8 } from "crypto";
|
|
24303
|
+
import { readFileSync as readFileSync36, readdirSync as readdirSync23, statSync as statSync14, existsSync as existsSync35 } from "fs";
|
|
25500
24304
|
import { resolve as resolve29, relative as relative12, basename as basename8, extname as extname2 } from "path";
|
|
25501
24305
|
function getKnowledgePaths() {
|
|
25502
24306
|
const resolved = getResolvedPaths();
|
|
@@ -25523,7 +24327,7 @@ function discoverMarkdownFiles(baseDir) {
|
|
|
25523
24327
|
const files = [];
|
|
25524
24328
|
function walk(dir) {
|
|
25525
24329
|
try {
|
|
25526
|
-
const entries =
|
|
24330
|
+
const entries = readdirSync23(dir, { withFileTypes: true });
|
|
25527
24331
|
for (const entry of entries) {
|
|
25528
24332
|
const fullPath = resolve29(dir, entry.name);
|
|
25529
24333
|
if (entry.isDirectory()) {
|
|
@@ -25583,7 +24387,7 @@ function categorizeFile(filePath) {
|
|
|
25583
24387
|
return "root";
|
|
25584
24388
|
}
|
|
25585
24389
|
function hashContent2(content) {
|
|
25586
|
-
return
|
|
24390
|
+
return createHash8("sha256").update(content).digest("hex");
|
|
25587
24391
|
}
|
|
25588
24392
|
function parseCRTable(content) {
|
|
25589
24393
|
const rules = [];
|
|
@@ -25851,7 +24655,7 @@ function indexAllKnowledge(db) {
|
|
|
25851
24655
|
}
|
|
25852
24656
|
for (const filePath of files) {
|
|
25853
24657
|
if (!existsSync35(filePath)) continue;
|
|
25854
|
-
const content =
|
|
24658
|
+
const content = readFileSync36(filePath, "utf-8");
|
|
25855
24659
|
const hash = hashContent2(content);
|
|
25856
24660
|
const relPath = filePath.startsWith(paths.claudeDir) ? relative12(paths.claudeDir, filePath) : filePath.startsWith(paths.plansDir) ? "plans/" + relative12(paths.plansDir, filePath) : filePath.startsWith(paths.docsDir) ? "docs/" + relative12(paths.docsDir, filePath) : filePath.startsWith(paths.memoryDir) ? `memory/${relative12(paths.memoryDir, filePath)}` : basename8(filePath);
|
|
25857
24661
|
const category = categorizeFile(filePath);
|
|
@@ -26003,7 +24807,7 @@ var init_knowledge_indexer = __esm({
|
|
|
26003
24807
|
});
|
|
26004
24808
|
|
|
26005
24809
|
// src/knowledge-tools.ts
|
|
26006
|
-
import { readFileSync as
|
|
24810
|
+
import { readFileSync as readFileSync37, writeFileSync as writeFileSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync24 } from "fs";
|
|
26007
24811
|
import { resolve as resolve30, basename as basename9 } from "path";
|
|
26008
24812
|
function p16(baseName) {
|
|
26009
24813
|
return `${getConfig().toolPrefix}_${baseName}`;
|
|
@@ -26754,14 +25558,14 @@ ${crRule ? `- **CR**: ${crRule}
|
|
|
26754
25558
|
`;
|
|
26755
25559
|
let existing = "";
|
|
26756
25560
|
try {
|
|
26757
|
-
existing =
|
|
25561
|
+
existing = readFileSync37(correctionsPath, "utf-8");
|
|
26758
25562
|
} catch {
|
|
26759
25563
|
}
|
|
26760
25564
|
const archiveIdx = existing.indexOf("## Archived");
|
|
26761
25565
|
if (archiveIdx > 0) {
|
|
26762
25566
|
const before = existing.slice(0, archiveIdx);
|
|
26763
25567
|
const after = existing.slice(archiveIdx);
|
|
26764
|
-
|
|
25568
|
+
writeFileSync5(correctionsPath, before + entry + after);
|
|
26765
25569
|
} else {
|
|
26766
25570
|
appendFileSync2(correctionsPath, entry);
|
|
26767
25571
|
}
|
|
@@ -26936,7 +25740,7 @@ function handleGaps(db, args2) {
|
|
|
26936
25740
|
} else if (checkType === "routers") {
|
|
26937
25741
|
try {
|
|
26938
25742
|
const routersDir = getResolvedPaths().routersDir;
|
|
26939
|
-
const routerFiles =
|
|
25743
|
+
const routerFiles = readdirSync24(routersDir).filter((f2) => f2.endsWith(".ts") && !f2.startsWith("_"));
|
|
26940
25744
|
lines.push(`| Router | Knowledge Hits | Status |`);
|
|
26941
25745
|
lines.push(`|--------|----------------|--------|`);
|
|
26942
25746
|
for (const file of routerFiles) {
|
|
@@ -27092,13 +25896,13 @@ var init_knowledge_tools = __esm({
|
|
|
27092
25896
|
|
|
27093
25897
|
// src/knowledge-db.ts
|
|
27094
25898
|
import Database3 from "better-sqlite3";
|
|
27095
|
-
import { dirname as
|
|
27096
|
-
import { existsSync as existsSync37, mkdirSync as
|
|
25899
|
+
import { dirname as dirname15 } from "path";
|
|
25900
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync10 } from "fs";
|
|
27097
25901
|
function getKnowledgeDb() {
|
|
27098
25902
|
const dbPath = getResolvedPaths().knowledgeDbPath;
|
|
27099
|
-
const dir =
|
|
25903
|
+
const dir = dirname15(dbPath);
|
|
27100
25904
|
if (!existsSync37(dir)) {
|
|
27101
|
-
|
|
25905
|
+
mkdirSync10(dir, { recursive: true });
|
|
27102
25906
|
}
|
|
27103
25907
|
const db = new Database3(dbPath);
|
|
27104
25908
|
db.pragma("journal_mode = WAL");
|
|
@@ -27831,7 +26635,7 @@ var init_python_tools = __esm({
|
|
|
27831
26635
|
});
|
|
27832
26636
|
|
|
27833
26637
|
// src/tools.ts
|
|
27834
|
-
import { readFileSync as
|
|
26638
|
+
import { readFileSync as readFileSync38, existsSync as existsSync38 } from "fs";
|
|
27835
26639
|
import { resolve as resolve31, basename as basename10 } from "path";
|
|
27836
26640
|
function prefix2() {
|
|
27837
26641
|
return getConfig().toolPrefix;
|
|
@@ -28268,7 +27072,7 @@ function handleContext(file, dataDb2, codegraphDb2) {
|
|
|
28268
27072
|
const root = getProjectRoot();
|
|
28269
27073
|
const absFilePath = ensureWithinRoot(resolve31(resolvedPaths.srcDir, "..", file), root);
|
|
28270
27074
|
if (existsSync38(absFilePath)) {
|
|
28271
|
-
const fileContent =
|
|
27075
|
+
const fileContent = readFileSync38(absFilePath, "utf-8").slice(0, 3e3);
|
|
28272
27076
|
const keywords = [];
|
|
28273
27077
|
if (fileContent.includes("ctx.db")) keywords.push("database", "schema");
|
|
28274
27078
|
if (fileContent.includes("BigInt") || fileContent.includes("Decimal")) keywords.push("BigInt", "serialization");
|
|
@@ -28696,7 +27500,7 @@ function handleSchema(args2) {
|
|
|
28696
27500
|
if (!existsSync38(absPath)) {
|
|
28697
27501
|
return text17(`File not found: ${file}`);
|
|
28698
27502
|
}
|
|
28699
|
-
const source =
|
|
27503
|
+
const source = readFileSync38(absPath, "utf-8");
|
|
28700
27504
|
const config = getConfig();
|
|
28701
27505
|
const dbPattern = config.dbAccessPattern ?? "ctx.db.{table}";
|
|
28702
27506
|
const regexStr = dbPattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace("\\{table\\}", "(\\w+)");
|
|
@@ -28774,8 +27578,8 @@ var init_tools = __esm({
|
|
|
28774
27578
|
|
|
28775
27579
|
// src/server.ts
|
|
28776
27580
|
var server_exports = {};
|
|
28777
|
-
import { readFileSync as
|
|
28778
|
-
import { resolve as resolve32, dirname as
|
|
27581
|
+
import { readFileSync as readFileSync39 } from "fs";
|
|
27582
|
+
import { resolve as resolve32, dirname as dirname16 } from "path";
|
|
28779
27583
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
28780
27584
|
function getDb() {
|
|
28781
27585
|
if (!codegraphDb) codegraphDb = getCodeGraphDb();
|
|
@@ -28867,10 +27671,10 @@ var init_server = __esm({
|
|
|
28867
27671
|
init_tools();
|
|
28868
27672
|
init_memory_db();
|
|
28869
27673
|
init_license();
|
|
28870
|
-
__dirname4 =
|
|
27674
|
+
__dirname4 = dirname16(fileURLToPath4(import.meta.url));
|
|
28871
27675
|
PKG_VERSION = (() => {
|
|
28872
27676
|
try {
|
|
28873
|
-
const pkg = JSON.parse(
|
|
27677
|
+
const pkg = JSON.parse(readFileSync39(resolve32(__dirname4, "..", "package.json"), "utf-8"));
|
|
28874
27678
|
return pkg.version ?? "0.0.0";
|
|
28875
27679
|
} catch {
|
|
28876
27680
|
return "0.0.0";
|
|
@@ -29173,7 +27977,7 @@ var config_upgrade_exports = {};
|
|
|
29173
27977
|
__export(config_upgrade_exports, {
|
|
29174
27978
|
runConfigUpgrade: () => runConfigUpgrade
|
|
29175
27979
|
});
|
|
29176
|
-
import { existsSync as existsSync39, readFileSync as
|
|
27980
|
+
import { existsSync as existsSync39, readFileSync as readFileSync40, writeFileSync as writeFileSync6, copyFileSync, unlinkSync as unlinkSync2 } from "fs";
|
|
29177
27981
|
import { resolve as resolve33 } from "path";
|
|
29178
27982
|
import { parse as parseYaml6 } from "yaml";
|
|
29179
27983
|
async function runConfigUpgrade(opts = {}) {
|
|
@@ -29192,7 +27996,7 @@ async function runConfigUpgrade(opts = {}) {
|
|
|
29192
27996
|
}
|
|
29193
27997
|
try {
|
|
29194
27998
|
copyFileSync(bakPath, configPath);
|
|
29195
|
-
|
|
27999
|
+
unlinkSync2(bakPath);
|
|
29196
28000
|
log("Config restored from backup.\n");
|
|
29197
28001
|
return { exitCode: 0, action: "rolled-back" };
|
|
29198
28002
|
} catch (e2) {
|
|
@@ -29208,7 +28012,7 @@ async function runConfigUpgrade(opts = {}) {
|
|
|
29208
28012
|
}
|
|
29209
28013
|
let existing;
|
|
29210
28014
|
try {
|
|
29211
|
-
const content =
|
|
28015
|
+
const content = readFileSync40(configPath, "utf-8");
|
|
29212
28016
|
const parsed = parseYaml6(content);
|
|
29213
28017
|
if (!parsed || typeof parsed !== "object") {
|
|
29214
28018
|
throw new Error("config is not a YAML object");
|
|
@@ -29231,8 +28035,8 @@ async function runConfigUpgrade(opts = {}) {
|
|
|
29231
28035
|
fingerprint: computeFingerprint(detection)
|
|
29232
28036
|
};
|
|
29233
28037
|
try {
|
|
29234
|
-
const original =
|
|
29235
|
-
|
|
28038
|
+
const original = readFileSync40(configPath, "utf-8");
|
|
28039
|
+
writeFileSync6(bakPath, original, "utf-8");
|
|
29236
28040
|
} catch (e2) {
|
|
29237
28041
|
const message = `Failed to write backup: ${e2 instanceof Error ? e2.message : String(e2)}`;
|
|
29238
28042
|
err(message + "\n");
|
|
@@ -29265,7 +28069,7 @@ var config_check_drift_exports = {};
|
|
|
29265
28069
|
__export(config_check_drift_exports, {
|
|
29266
28070
|
runConfigCheckDrift: () => runConfigCheckDrift
|
|
29267
28071
|
});
|
|
29268
|
-
import { existsSync as existsSync40, readFileSync as
|
|
28072
|
+
import { existsSync as existsSync40, readFileSync as readFileSync41 } from "fs";
|
|
29269
28073
|
import { resolve as resolve34 } from "path";
|
|
29270
28074
|
import { parse as parseYaml7 } from "yaml";
|
|
29271
28075
|
function renderChanges(changes) {
|
|
@@ -29293,7 +28097,7 @@ async function runConfigCheckDrift(opts = {}) {
|
|
|
29293
28097
|
}
|
|
29294
28098
|
let config;
|
|
29295
28099
|
try {
|
|
29296
|
-
const content =
|
|
28100
|
+
const content = readFileSync41(configPath, "utf-8");
|
|
29297
28101
|
const parsed = parseYaml7(content);
|
|
29298
28102
|
if (!parsed || typeof parsed !== "object") {
|
|
29299
28103
|
throw new Error("config is not a YAML object");
|
|
@@ -29360,11 +28164,11 @@ var init_config_check_drift = __esm({
|
|
|
29360
28164
|
});
|
|
29361
28165
|
|
|
29362
28166
|
// src/cli.ts
|
|
29363
|
-
import { readFileSync as
|
|
29364
|
-
import { resolve as resolve35, dirname as
|
|
28167
|
+
import { readFileSync as readFileSync42 } from "fs";
|
|
28168
|
+
import { resolve as resolve35, dirname as dirname17 } from "path";
|
|
29365
28169
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
29366
28170
|
var __filename4 = fileURLToPath5(import.meta.url);
|
|
29367
|
-
var __dirname5 =
|
|
28171
|
+
var __dirname5 = dirname17(__filename4);
|
|
29368
28172
|
var args = process.argv.slice(2);
|
|
29369
28173
|
var subcommand = args[0];
|
|
29370
28174
|
async function main() {
|
|
@@ -29546,7 +28350,7 @@ Examples:
|
|
|
29546
28350
|
}
|
|
29547
28351
|
function printVersion() {
|
|
29548
28352
|
try {
|
|
29549
|
-
const pkg = JSON.parse(
|
|
28353
|
+
const pkg = JSON.parse(readFileSync42(resolve35(__dirname5, "../package.json"), "utf-8"));
|
|
29550
28354
|
console.log(`massu v${pkg.version}`);
|
|
29551
28355
|
} catch {
|
|
29552
28356
|
console.log("massu v0.1.0");
|