@neat.is/core 0.3.0 → 0.3.2
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/{chunk-QYUB3FQL.js → chunk-4ASCXBZF.js} +12 -124
- package/dist/chunk-4ASCXBZF.js.map +1 -0
- package/dist/{chunk-I5KODOJV.js → chunk-66Z5IEFY.js} +126 -7
- package/dist/chunk-66Z5IEFY.js.map +1 -0
- package/dist/{chunk-B7UUGIXB.js → chunk-FIXKIYNF.js} +818 -18
- package/dist/chunk-FIXKIYNF.js.map +1 -0
- package/dist/chunk-G3PDTGOW.js +125 -0
- package/dist/chunk-G3PDTGOW.js.map +1 -0
- package/dist/cli.cjs +76 -27
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +82 -34
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +141 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +10 -11
- package/dist/neatd.cjs +1900 -36
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +19 -5
- package/dist/neatd.js.map +1 -1
- package/dist/{otel-grpc-USFL3OI3.js → otel-grpc-J4O2SIBZ.js} +3 -3
- package/dist/server.js +6 -7
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-B7UUGIXB.js.map +0 -1
- package/dist/chunk-DGUM43GV.js +0 -11
- package/dist/chunk-I5KODOJV.js.map +0 -1
- package/dist/chunk-NVCEZXL7.js +0 -836
- package/dist/chunk-NVCEZXL7.js.map +0 -1
- package/dist/chunk-QYUB3FQL.js.map +0 -1
- package/dist/otel-grpc-USFL3OI3.js.map +0 -1
- /package/dist/{chunk-DGUM43GV.js.map → otel-grpc-J4O2SIBZ.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
import {
|
|
3
3
|
buildSearchIndex
|
|
4
4
|
} from "./chunk-XOOCA5T7.js";
|
|
5
|
-
import {
|
|
6
|
-
buildApi
|
|
7
|
-
} from "./chunk-NVCEZXL7.js";
|
|
8
5
|
import {
|
|
9
6
|
DEFAULT_PROJECT,
|
|
10
7
|
PolicyViolationsLog,
|
|
@@ -18,6 +15,7 @@ import {
|
|
|
18
15
|
addServiceAliases,
|
|
19
16
|
addServiceNodes,
|
|
20
17
|
attachGraphToEventBus,
|
|
18
|
+
buildApi,
|
|
21
19
|
discoverServices,
|
|
22
20
|
emitNeatEvent,
|
|
23
21
|
ensureCompatLoaded,
|
|
@@ -37,18 +35,20 @@ import {
|
|
|
37
35
|
setStatus,
|
|
38
36
|
startPersistLoop,
|
|
39
37
|
startStalenessLoop
|
|
40
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-FIXKIYNF.js";
|
|
41
39
|
import {
|
|
42
|
-
buildOtelReceiver,
|
|
43
40
|
startOtelGrpcReceiver
|
|
44
|
-
} from "./chunk-
|
|
45
|
-
import
|
|
41
|
+
} from "./chunk-G3PDTGOW.js";
|
|
42
|
+
import {
|
|
43
|
+
buildOtelReceiver
|
|
44
|
+
} from "./chunk-4ASCXBZF.js";
|
|
46
45
|
|
|
47
46
|
// src/cli.ts
|
|
48
47
|
import path4 from "path";
|
|
49
|
-
import { promises as
|
|
48
|
+
import { promises as fs4 } from "fs";
|
|
50
49
|
|
|
51
50
|
// src/watch.ts
|
|
51
|
+
import fs from "fs";
|
|
52
52
|
import path from "path";
|
|
53
53
|
import chokidar from "chokidar";
|
|
54
54
|
|
|
@@ -144,6 +144,16 @@ async function runExtractPhases(graph, scanPath, phases, project = DEFAULT_PROJE
|
|
|
144
144
|
durationMs: Date.now() - started
|
|
145
145
|
};
|
|
146
146
|
}
|
|
147
|
+
var IGNORED_WATCH_GLOBS = [
|
|
148
|
+
"**/node_modules/**",
|
|
149
|
+
"**/.git/**",
|
|
150
|
+
"**/dist/**",
|
|
151
|
+
"**/build/**",
|
|
152
|
+
"**/.turbo/**",
|
|
153
|
+
"**/.next/**",
|
|
154
|
+
"**/neat-out/**",
|
|
155
|
+
"**/.DS_Store"
|
|
156
|
+
];
|
|
147
157
|
var IGNORED_WATCH_PATHS = [
|
|
148
158
|
/(?:^|[\\/])node_modules[\\/]/,
|
|
149
159
|
/(?:^|[\\/])\.git[\\/]/,
|
|
@@ -157,6 +167,35 @@ var IGNORED_WATCH_PATHS = [
|
|
|
157
167
|
function shouldIgnore(absPath) {
|
|
158
168
|
return IGNORED_WATCH_PATHS.some((re) => re.test(absPath));
|
|
159
169
|
}
|
|
170
|
+
var DARWIN_POLLING_DIR_THRESHOLD = 400;
|
|
171
|
+
function countWatchableDirs(scanPath, limit) {
|
|
172
|
+
let count = 0;
|
|
173
|
+
const visit = (dir, depth) => {
|
|
174
|
+
if (count >= limit) return;
|
|
175
|
+
let entries;
|
|
176
|
+
try {
|
|
177
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
178
|
+
} catch {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
for (const e of entries) {
|
|
182
|
+
if (count >= limit) return;
|
|
183
|
+
if (!e.isDirectory()) continue;
|
|
184
|
+
if (IGNORED_WATCH_PATHS.some((re) => re.test(path.join(dir, e.name) + path.sep))) continue;
|
|
185
|
+
count++;
|
|
186
|
+
if (depth < 2) visit(path.join(dir, e.name), depth + 1);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
visit(scanPath, 0);
|
|
190
|
+
return count;
|
|
191
|
+
}
|
|
192
|
+
function shouldUsePolling(scanPath) {
|
|
193
|
+
const env = process.env.NEAT_WATCH_POLLING;
|
|
194
|
+
if (env === "1" || env === "true") return true;
|
|
195
|
+
if (env === "0" || env === "false") return false;
|
|
196
|
+
if (process.platform !== "darwin") return false;
|
|
197
|
+
return countWatchableDirs(scanPath, DARWIN_POLLING_DIR_THRESHOLD) >= DARWIN_POLLING_DIR_THRESHOLD;
|
|
198
|
+
}
|
|
160
199
|
async function startWatch(graph, opts) {
|
|
161
200
|
const debounceMs = opts.debounceMs ?? 1e3;
|
|
162
201
|
const projectName = opts.project ?? DEFAULT_PROJECT;
|
|
@@ -326,10 +365,19 @@ async function startWatch(graph, opts) {
|
|
|
326
365
|
}
|
|
327
366
|
schedule();
|
|
328
367
|
};
|
|
368
|
+
const usePolling = shouldUsePolling(opts.scanPath);
|
|
369
|
+
if (usePolling) {
|
|
370
|
+
const reason = process.env.NEAT_WATCH_POLLING === "1" || process.env.NEAT_WATCH_POLLING === "true" ? "NEAT_WATCH_POLLING env override" : "darwin heuristic \u2014 large scan root, kqueue cap risk";
|
|
371
|
+
console.log(`[${projectName}] watch: usePolling=true (${reason})`);
|
|
372
|
+
}
|
|
329
373
|
const watcher = chokidar.watch(opts.scanPath, {
|
|
330
374
|
ignoreInitial: true,
|
|
331
|
-
|
|
375
|
+
// Glob array prunes at descent time (#233) so chokidar never opens a
|
|
376
|
+
// kqueue handle for `node_modules` and friends. The function backstop
|
|
377
|
+
// catches any path that slipped through and matches the regex set.
|
|
378
|
+
ignored: [...IGNORED_WATCH_GLOBS, (p) => shouldIgnore(p)],
|
|
332
379
|
persistent: true,
|
|
380
|
+
usePolling,
|
|
333
381
|
awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 }
|
|
334
382
|
});
|
|
335
383
|
watcher.on("add", onPath);
|
|
@@ -361,7 +409,7 @@ async function startWatch(graph, opts) {
|
|
|
361
409
|
}
|
|
362
410
|
|
|
363
411
|
// src/installers/javascript.ts
|
|
364
|
-
import { promises as
|
|
412
|
+
import { promises as fs2 } from "fs";
|
|
365
413
|
import path2 from "path";
|
|
366
414
|
var SDK_PACKAGES = [
|
|
367
415
|
{ name: "@opentelemetry/api", version: "^1.9.0" },
|
|
@@ -378,7 +426,7 @@ var OTEL_ENV = {
|
|
|
378
426
|
};
|
|
379
427
|
async function readPackageJson(serviceDir) {
|
|
380
428
|
try {
|
|
381
|
-
const raw = await
|
|
429
|
+
const raw = await fs2.readFile(path2.join(serviceDir, "package.json"), "utf8");
|
|
382
430
|
return JSON.parse(raw);
|
|
383
431
|
} catch {
|
|
384
432
|
return null;
|
|
@@ -444,7 +492,7 @@ async function apply(installPlan) {
|
|
|
444
492
|
const originals = /* @__PURE__ */ new Map();
|
|
445
493
|
for (const file of touched) {
|
|
446
494
|
try {
|
|
447
|
-
originals.set(file, await
|
|
495
|
+
originals.set(file, await fs2.readFile(file, "utf8"));
|
|
448
496
|
} catch {
|
|
449
497
|
}
|
|
450
498
|
}
|
|
@@ -470,8 +518,8 @@ async function apply(installPlan) {
|
|
|
470
518
|
}
|
|
471
519
|
const newRaw = JSON.stringify(pkg, null, 2) + "\n";
|
|
472
520
|
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
473
|
-
await
|
|
474
|
-
await
|
|
521
|
+
await fs2.writeFile(tmp, newRaw, "utf8");
|
|
522
|
+
await fs2.rename(tmp, file);
|
|
475
523
|
}
|
|
476
524
|
} catch (err) {
|
|
477
525
|
await rollback(installPlan, originals);
|
|
@@ -482,7 +530,7 @@ async function rollback(installPlan, originals) {
|
|
|
482
530
|
const restored = [];
|
|
483
531
|
for (const [file, raw] of originals.entries()) {
|
|
484
532
|
try {
|
|
485
|
-
await
|
|
533
|
+
await fs2.writeFile(file, raw, "utf8");
|
|
486
534
|
restored.push(file);
|
|
487
535
|
} catch {
|
|
488
536
|
}
|
|
@@ -497,7 +545,7 @@ async function rollback(installPlan, originals) {
|
|
|
497
545
|
""
|
|
498
546
|
];
|
|
499
547
|
const rollbackPath = path2.join(installPlan.serviceDir, "neat-rollback.patch");
|
|
500
|
-
await
|
|
548
|
+
await fs2.writeFile(rollbackPath, lines.join("\n"), "utf8");
|
|
501
549
|
}
|
|
502
550
|
var javascriptInstaller = {
|
|
503
551
|
name: "javascript",
|
|
@@ -507,7 +555,7 @@ var javascriptInstaller = {
|
|
|
507
555
|
};
|
|
508
556
|
|
|
509
557
|
// src/installers/python.ts
|
|
510
|
-
import { promises as
|
|
558
|
+
import { promises as fs3 } from "fs";
|
|
511
559
|
import path3 from "path";
|
|
512
560
|
var SDK_PACKAGES2 = [
|
|
513
561
|
{ name: "opentelemetry-distro", version: ">=0.49b0" },
|
|
@@ -520,7 +568,7 @@ var OTEL_ENV2 = {
|
|
|
520
568
|
};
|
|
521
569
|
async function exists(p) {
|
|
522
570
|
try {
|
|
523
|
-
await
|
|
571
|
+
await fs3.stat(p);
|
|
524
572
|
return true;
|
|
525
573
|
} catch {
|
|
526
574
|
return false;
|
|
@@ -541,7 +589,7 @@ function reqPackageName(line) {
|
|
|
541
589
|
async function planRequirementsTxtEdits(serviceDir) {
|
|
542
590
|
const file = path3.join(serviceDir, "requirements.txt");
|
|
543
591
|
if (!await exists(file)) return null;
|
|
544
|
-
const raw = await
|
|
592
|
+
const raw = await fs3.readFile(file, "utf8");
|
|
545
593
|
const presentNames = new Set(
|
|
546
594
|
raw.split(/\r?\n/).map(reqPackageName).filter((n) => n.length > 0)
|
|
547
595
|
);
|
|
@@ -551,7 +599,7 @@ async function planRequirementsTxtEdits(serviceDir) {
|
|
|
551
599
|
async function planProcfileEdits(serviceDir) {
|
|
552
600
|
const procfile = path3.join(serviceDir, "Procfile");
|
|
553
601
|
if (!await exists(procfile)) return [];
|
|
554
|
-
const raw = await
|
|
602
|
+
const raw = await fs3.readFile(procfile, "utf8");
|
|
555
603
|
const edits = [];
|
|
556
604
|
for (const line of raw.split(/\r?\n/)) {
|
|
557
605
|
if (line.length === 0) continue;
|
|
@@ -603,8 +651,8 @@ async function applyRequirementsTxt(manifest, edits, original) {
|
|
|
603
651
|
const next = `${original}${trailing}${newlines.join("\n")}
|
|
604
652
|
`;
|
|
605
653
|
const tmp = `${manifest}.${process.pid}.${Date.now()}.tmp`;
|
|
606
|
-
await
|
|
607
|
-
await
|
|
654
|
+
await fs3.writeFile(tmp, next, "utf8");
|
|
655
|
+
await fs3.rename(tmp, manifest);
|
|
608
656
|
}
|
|
609
657
|
async function applyProcfile(procfile, edits, original) {
|
|
610
658
|
let next = original;
|
|
@@ -613,8 +661,8 @@ async function applyProcfile(procfile, edits, original) {
|
|
|
613
661
|
next = next.replace(e.before, e.after);
|
|
614
662
|
}
|
|
615
663
|
const tmp = `${procfile}.${process.pid}.${Date.now()}.tmp`;
|
|
616
|
-
await
|
|
617
|
-
await
|
|
664
|
+
await fs3.writeFile(tmp, next, "utf8");
|
|
665
|
+
await fs3.rename(tmp, procfile);
|
|
618
666
|
}
|
|
619
667
|
async function apply2(installPlan) {
|
|
620
668
|
const touched = /* @__PURE__ */ new Set();
|
|
@@ -624,7 +672,7 @@ async function apply2(installPlan) {
|
|
|
624
672
|
const originals = /* @__PURE__ */ new Map();
|
|
625
673
|
for (const file of touched) {
|
|
626
674
|
try {
|
|
627
|
-
originals.set(file, await
|
|
675
|
+
originals.set(file, await fs3.readFile(file, "utf8"));
|
|
628
676
|
} catch {
|
|
629
677
|
}
|
|
630
678
|
}
|
|
@@ -652,7 +700,7 @@ async function rollback2(installPlan, originals) {
|
|
|
652
700
|
const restored = [];
|
|
653
701
|
for (const [file, raw] of originals.entries()) {
|
|
654
702
|
try {
|
|
655
|
-
await
|
|
703
|
+
await fs3.writeFile(file, raw, "utf8");
|
|
656
704
|
restored.push(file);
|
|
657
705
|
} catch {
|
|
658
706
|
}
|
|
@@ -667,7 +715,7 @@ async function rollback2(installPlan, originals) {
|
|
|
667
715
|
""
|
|
668
716
|
];
|
|
669
717
|
const rollbackPath = path3.join(installPlan.serviceDir, "neat-rollback.patch");
|
|
670
|
-
await
|
|
718
|
+
await fs3.writeFile(rollbackPath, lines.join("\n"), "utf8");
|
|
671
719
|
}
|
|
672
720
|
var pythonInstaller = {
|
|
673
721
|
name: "python",
|
|
@@ -1501,7 +1549,7 @@ async function buildPatchSections(services) {
|
|
|
1501
1549
|
}
|
|
1502
1550
|
async function runInit(opts) {
|
|
1503
1551
|
const written = [];
|
|
1504
|
-
const stat = await
|
|
1552
|
+
const stat = await fs4.stat(opts.scanPath).catch(() => null);
|
|
1505
1553
|
if (!stat || !stat.isDirectory()) {
|
|
1506
1554
|
console.error(`neat init: ${opts.scanPath} is not a directory`);
|
|
1507
1555
|
return { exitCode: 2, writtenFiles: written };
|
|
@@ -1512,7 +1560,7 @@ async function runInit(opts) {
|
|
|
1512
1560
|
const patch = renderPatch(sections);
|
|
1513
1561
|
const patchPath = path4.join(opts.scanPath, "neat.patch");
|
|
1514
1562
|
if (opts.dryRun) {
|
|
1515
|
-
await
|
|
1563
|
+
await fs4.writeFile(patchPath, patch, "utf8");
|
|
1516
1564
|
written.push(patchPath);
|
|
1517
1565
|
console.log(`dry-run: patch written to ${patchPath}`);
|
|
1518
1566
|
console.log("rerun without --dry-run to register and snapshot.");
|
|
@@ -1552,7 +1600,7 @@ async function runInit(opts) {
|
|
|
1552
1600
|
console.log("patch applied. Run `npm install` (or your language equivalent) to refresh lockfiles.");
|
|
1553
1601
|
}
|
|
1554
1602
|
} else {
|
|
1555
|
-
await
|
|
1603
|
+
await fs4.writeFile(patchPath, patch, "utf8");
|
|
1556
1604
|
written.push(patchPath);
|
|
1557
1605
|
}
|
|
1558
1606
|
}
|
|
@@ -1606,7 +1654,7 @@ async function runSkill(opts) {
|
|
|
1606
1654
|
const target = claudeConfigPath();
|
|
1607
1655
|
let existing = {};
|
|
1608
1656
|
try {
|
|
1609
|
-
existing = JSON.parse(await
|
|
1657
|
+
existing = JSON.parse(await fs4.readFile(target, "utf8"));
|
|
1610
1658
|
} catch (err) {
|
|
1611
1659
|
if (err.code !== "ENOENT") {
|
|
1612
1660
|
console.error(`neat skill: failed to read ${target} \u2014 ${err.message}`);
|
|
@@ -1618,8 +1666,8 @@ async function runSkill(opts) {
|
|
|
1618
1666
|
...existing,
|
|
1619
1667
|
mcpServers: { ...mcp, neat: CLAUDE_SKILL_CONFIG.mcpServers.neat }
|
|
1620
1668
|
};
|
|
1621
|
-
await
|
|
1622
|
-
await
|
|
1669
|
+
await fs4.mkdir(path4.dirname(target), { recursive: true });
|
|
1670
|
+
await fs4.writeFile(target, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
1623
1671
|
console.log(`neat skill: wrote mcpServers.neat to ${target}`);
|
|
1624
1672
|
console.log("restart Claude Code to pick up the new MCP server.");
|
|
1625
1673
|
return { exitCode: 0 };
|
|
@@ -1679,7 +1727,7 @@ async function main() {
|
|
|
1679
1727
|
process.exit(2);
|
|
1680
1728
|
}
|
|
1681
1729
|
const scanPath = path4.resolve(target);
|
|
1682
|
-
const stat = await
|
|
1730
|
+
const stat = await fs4.stat(scanPath).catch(() => null);
|
|
1683
1731
|
if (!stat || !stat.isDirectory()) {
|
|
1684
1732
|
console.error(`neat watch: ${scanPath} is not a directory`);
|
|
1685
1733
|
process.exit(2);
|