@neat.is/core 0.3.1 → 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/cli.cjs +76 -27
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +76 -27
- package/dist/cli.js.map +1 -1
- package/dist/neatd.cjs +14 -2
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +14 -2
- package/dist/neatd.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.cjs
CHANGED
|
@@ -381,7 +381,7 @@ __export(cli_exports, {
|
|
|
381
381
|
module.exports = __toCommonJS(cli_exports);
|
|
382
382
|
init_cjs_shims();
|
|
383
383
|
var import_node_path37 = __toESM(require("path"), 1);
|
|
384
|
-
var
|
|
384
|
+
var import_node_fs23 = require("fs");
|
|
385
385
|
|
|
386
386
|
// src/graph.ts
|
|
387
387
|
init_cjs_shims();
|
|
@@ -3901,6 +3901,7 @@ function startPersistLoop(graph, outPath, intervalMs = 6e4) {
|
|
|
3901
3901
|
|
|
3902
3902
|
// src/watch.ts
|
|
3903
3903
|
init_cjs_shims();
|
|
3904
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
3904
3905
|
var import_node_path34 = __toESM(require("path"), 1);
|
|
3905
3906
|
var import_chokidar = __toESM(require("chokidar"), 1);
|
|
3906
3907
|
|
|
@@ -5301,6 +5302,16 @@ async function runExtractPhases(graph, scanPath, phases, project = DEFAULT_PROJE
|
|
|
5301
5302
|
durationMs: Date.now() - started
|
|
5302
5303
|
};
|
|
5303
5304
|
}
|
|
5305
|
+
var IGNORED_WATCH_GLOBS = [
|
|
5306
|
+
"**/node_modules/**",
|
|
5307
|
+
"**/.git/**",
|
|
5308
|
+
"**/dist/**",
|
|
5309
|
+
"**/build/**",
|
|
5310
|
+
"**/.turbo/**",
|
|
5311
|
+
"**/.next/**",
|
|
5312
|
+
"**/neat-out/**",
|
|
5313
|
+
"**/.DS_Store"
|
|
5314
|
+
];
|
|
5304
5315
|
var IGNORED_WATCH_PATHS = [
|
|
5305
5316
|
/(?:^|[\\/])node_modules[\\/]/,
|
|
5306
5317
|
/(?:^|[\\/])\.git[\\/]/,
|
|
@@ -5314,6 +5325,35 @@ var IGNORED_WATCH_PATHS = [
|
|
|
5314
5325
|
function shouldIgnore(absPath) {
|
|
5315
5326
|
return IGNORED_WATCH_PATHS.some((re) => re.test(absPath));
|
|
5316
5327
|
}
|
|
5328
|
+
var DARWIN_POLLING_DIR_THRESHOLD = 400;
|
|
5329
|
+
function countWatchableDirs(scanPath, limit) {
|
|
5330
|
+
let count = 0;
|
|
5331
|
+
const visit = (dir, depth) => {
|
|
5332
|
+
if (count >= limit) return;
|
|
5333
|
+
let entries;
|
|
5334
|
+
try {
|
|
5335
|
+
entries = import_node_fs20.default.readdirSync(dir, { withFileTypes: true });
|
|
5336
|
+
} catch {
|
|
5337
|
+
return;
|
|
5338
|
+
}
|
|
5339
|
+
for (const e of entries) {
|
|
5340
|
+
if (count >= limit) return;
|
|
5341
|
+
if (!e.isDirectory()) continue;
|
|
5342
|
+
if (IGNORED_WATCH_PATHS.some((re) => re.test(import_node_path34.default.join(dir, e.name) + import_node_path34.default.sep))) continue;
|
|
5343
|
+
count++;
|
|
5344
|
+
if (depth < 2) visit(import_node_path34.default.join(dir, e.name), depth + 1);
|
|
5345
|
+
}
|
|
5346
|
+
};
|
|
5347
|
+
visit(scanPath, 0);
|
|
5348
|
+
return count;
|
|
5349
|
+
}
|
|
5350
|
+
function shouldUsePolling(scanPath) {
|
|
5351
|
+
const env = process.env.NEAT_WATCH_POLLING;
|
|
5352
|
+
if (env === "1" || env === "true") return true;
|
|
5353
|
+
if (env === "0" || env === "false") return false;
|
|
5354
|
+
if (process.platform !== "darwin") return false;
|
|
5355
|
+
return countWatchableDirs(scanPath, DARWIN_POLLING_DIR_THRESHOLD) >= DARWIN_POLLING_DIR_THRESHOLD;
|
|
5356
|
+
}
|
|
5317
5357
|
async function startWatch(graph, opts) {
|
|
5318
5358
|
const debounceMs = opts.debounceMs ?? 1e3;
|
|
5319
5359
|
const projectName = opts.project ?? DEFAULT_PROJECT;
|
|
@@ -5483,10 +5523,19 @@ async function startWatch(graph, opts) {
|
|
|
5483
5523
|
}
|
|
5484
5524
|
schedule();
|
|
5485
5525
|
};
|
|
5526
|
+
const usePolling = shouldUsePolling(opts.scanPath);
|
|
5527
|
+
if (usePolling) {
|
|
5528
|
+
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";
|
|
5529
|
+
console.log(`[${projectName}] watch: usePolling=true (${reason})`);
|
|
5530
|
+
}
|
|
5486
5531
|
const watcher = import_chokidar.default.watch(opts.scanPath, {
|
|
5487
5532
|
ignoreInitial: true,
|
|
5488
|
-
|
|
5533
|
+
// Glob array prunes at descent time (#233) so chokidar never opens a
|
|
5534
|
+
// kqueue handle for `node_modules` and friends. The function backstop
|
|
5535
|
+
// catches any path that slipped through and matches the regex set.
|
|
5536
|
+
ignored: [...IGNORED_WATCH_GLOBS, (p) => shouldIgnore(p)],
|
|
5489
5537
|
persistent: true,
|
|
5538
|
+
usePolling,
|
|
5490
5539
|
awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 }
|
|
5491
5540
|
});
|
|
5492
5541
|
watcher.on("add", onPath);
|
|
@@ -5522,7 +5571,7 @@ init_cjs_shims();
|
|
|
5522
5571
|
|
|
5523
5572
|
// src/installers/javascript.ts
|
|
5524
5573
|
init_cjs_shims();
|
|
5525
|
-
var
|
|
5574
|
+
var import_node_fs21 = require("fs");
|
|
5526
5575
|
var import_node_path35 = __toESM(require("path"), 1);
|
|
5527
5576
|
var SDK_PACKAGES = [
|
|
5528
5577
|
{ name: "@opentelemetry/api", version: "^1.9.0" },
|
|
@@ -5539,7 +5588,7 @@ var OTEL_ENV = {
|
|
|
5539
5588
|
};
|
|
5540
5589
|
async function readPackageJson(serviceDir) {
|
|
5541
5590
|
try {
|
|
5542
|
-
const raw = await
|
|
5591
|
+
const raw = await import_node_fs21.promises.readFile(import_node_path35.default.join(serviceDir, "package.json"), "utf8");
|
|
5543
5592
|
return JSON.parse(raw);
|
|
5544
5593
|
} catch {
|
|
5545
5594
|
return null;
|
|
@@ -5605,7 +5654,7 @@ async function apply(installPlan) {
|
|
|
5605
5654
|
const originals = /* @__PURE__ */ new Map();
|
|
5606
5655
|
for (const file of touched) {
|
|
5607
5656
|
try {
|
|
5608
|
-
originals.set(file, await
|
|
5657
|
+
originals.set(file, await import_node_fs21.promises.readFile(file, "utf8"));
|
|
5609
5658
|
} catch {
|
|
5610
5659
|
}
|
|
5611
5660
|
}
|
|
@@ -5631,8 +5680,8 @@ async function apply(installPlan) {
|
|
|
5631
5680
|
}
|
|
5632
5681
|
const newRaw = JSON.stringify(pkg, null, 2) + "\n";
|
|
5633
5682
|
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
5634
|
-
await
|
|
5635
|
-
await
|
|
5683
|
+
await import_node_fs21.promises.writeFile(tmp, newRaw, "utf8");
|
|
5684
|
+
await import_node_fs21.promises.rename(tmp, file);
|
|
5636
5685
|
}
|
|
5637
5686
|
} catch (err) {
|
|
5638
5687
|
await rollback(installPlan, originals);
|
|
@@ -5643,7 +5692,7 @@ async function rollback(installPlan, originals) {
|
|
|
5643
5692
|
const restored = [];
|
|
5644
5693
|
for (const [file, raw] of originals.entries()) {
|
|
5645
5694
|
try {
|
|
5646
|
-
await
|
|
5695
|
+
await import_node_fs21.promises.writeFile(file, raw, "utf8");
|
|
5647
5696
|
restored.push(file);
|
|
5648
5697
|
} catch {
|
|
5649
5698
|
}
|
|
@@ -5658,7 +5707,7 @@ async function rollback(installPlan, originals) {
|
|
|
5658
5707
|
""
|
|
5659
5708
|
];
|
|
5660
5709
|
const rollbackPath = import_node_path35.default.join(installPlan.serviceDir, "neat-rollback.patch");
|
|
5661
|
-
await
|
|
5710
|
+
await import_node_fs21.promises.writeFile(rollbackPath, lines.join("\n"), "utf8");
|
|
5662
5711
|
}
|
|
5663
5712
|
var javascriptInstaller = {
|
|
5664
5713
|
name: "javascript",
|
|
@@ -5669,7 +5718,7 @@ var javascriptInstaller = {
|
|
|
5669
5718
|
|
|
5670
5719
|
// src/installers/python.ts
|
|
5671
5720
|
init_cjs_shims();
|
|
5672
|
-
var
|
|
5721
|
+
var import_node_fs22 = require("fs");
|
|
5673
5722
|
var import_node_path36 = __toESM(require("path"), 1);
|
|
5674
5723
|
var SDK_PACKAGES2 = [
|
|
5675
5724
|
{ name: "opentelemetry-distro", version: ">=0.49b0" },
|
|
@@ -5682,7 +5731,7 @@ var OTEL_ENV2 = {
|
|
|
5682
5731
|
};
|
|
5683
5732
|
async function exists2(p) {
|
|
5684
5733
|
try {
|
|
5685
|
-
await
|
|
5734
|
+
await import_node_fs22.promises.stat(p);
|
|
5686
5735
|
return true;
|
|
5687
5736
|
} catch {
|
|
5688
5737
|
return false;
|
|
@@ -5703,7 +5752,7 @@ function reqPackageName(line) {
|
|
|
5703
5752
|
async function planRequirementsTxtEdits(serviceDir) {
|
|
5704
5753
|
const file = import_node_path36.default.join(serviceDir, "requirements.txt");
|
|
5705
5754
|
if (!await exists2(file)) return null;
|
|
5706
|
-
const raw = await
|
|
5755
|
+
const raw = await import_node_fs22.promises.readFile(file, "utf8");
|
|
5707
5756
|
const presentNames = new Set(
|
|
5708
5757
|
raw.split(/\r?\n/).map(reqPackageName).filter((n) => n.length > 0)
|
|
5709
5758
|
);
|
|
@@ -5713,7 +5762,7 @@ async function planRequirementsTxtEdits(serviceDir) {
|
|
|
5713
5762
|
async function planProcfileEdits(serviceDir) {
|
|
5714
5763
|
const procfile = import_node_path36.default.join(serviceDir, "Procfile");
|
|
5715
5764
|
if (!await exists2(procfile)) return [];
|
|
5716
|
-
const raw = await
|
|
5765
|
+
const raw = await import_node_fs22.promises.readFile(procfile, "utf8");
|
|
5717
5766
|
const edits = [];
|
|
5718
5767
|
for (const line of raw.split(/\r?\n/)) {
|
|
5719
5768
|
if (line.length === 0) continue;
|
|
@@ -5765,8 +5814,8 @@ async function applyRequirementsTxt(manifest, edits, original) {
|
|
|
5765
5814
|
const next = `${original}${trailing}${newlines.join("\n")}
|
|
5766
5815
|
`;
|
|
5767
5816
|
const tmp = `${manifest}.${process.pid}.${Date.now()}.tmp`;
|
|
5768
|
-
await
|
|
5769
|
-
await
|
|
5817
|
+
await import_node_fs22.promises.writeFile(tmp, next, "utf8");
|
|
5818
|
+
await import_node_fs22.promises.rename(tmp, manifest);
|
|
5770
5819
|
}
|
|
5771
5820
|
async function applyProcfile(procfile, edits, original) {
|
|
5772
5821
|
let next = original;
|
|
@@ -5775,8 +5824,8 @@ async function applyProcfile(procfile, edits, original) {
|
|
|
5775
5824
|
next = next.replace(e.before, e.after);
|
|
5776
5825
|
}
|
|
5777
5826
|
const tmp = `${procfile}.${process.pid}.${Date.now()}.tmp`;
|
|
5778
|
-
await
|
|
5779
|
-
await
|
|
5827
|
+
await import_node_fs22.promises.writeFile(tmp, next, "utf8");
|
|
5828
|
+
await import_node_fs22.promises.rename(tmp, procfile);
|
|
5780
5829
|
}
|
|
5781
5830
|
async function apply2(installPlan) {
|
|
5782
5831
|
const touched = /* @__PURE__ */ new Set();
|
|
@@ -5786,7 +5835,7 @@ async function apply2(installPlan) {
|
|
|
5786
5835
|
const originals = /* @__PURE__ */ new Map();
|
|
5787
5836
|
for (const file of touched) {
|
|
5788
5837
|
try {
|
|
5789
|
-
originals.set(file, await
|
|
5838
|
+
originals.set(file, await import_node_fs22.promises.readFile(file, "utf8"));
|
|
5790
5839
|
} catch {
|
|
5791
5840
|
}
|
|
5792
5841
|
}
|
|
@@ -5814,7 +5863,7 @@ async function rollback2(installPlan, originals) {
|
|
|
5814
5863
|
const restored = [];
|
|
5815
5864
|
for (const [file, raw] of originals.entries()) {
|
|
5816
5865
|
try {
|
|
5817
|
-
await
|
|
5866
|
+
await import_node_fs22.promises.writeFile(file, raw, "utf8");
|
|
5818
5867
|
restored.push(file);
|
|
5819
5868
|
} catch {
|
|
5820
5869
|
}
|
|
@@ -5829,7 +5878,7 @@ async function rollback2(installPlan, originals) {
|
|
|
5829
5878
|
""
|
|
5830
5879
|
];
|
|
5831
5880
|
const rollbackPath = import_node_path36.default.join(installPlan.serviceDir, "neat-rollback.patch");
|
|
5832
|
-
await
|
|
5881
|
+
await import_node_fs22.promises.writeFile(rollbackPath, lines.join("\n"), "utf8");
|
|
5833
5882
|
}
|
|
5834
5883
|
var pythonInstaller = {
|
|
5835
5884
|
name: "python",
|
|
@@ -6665,7 +6714,7 @@ async function buildPatchSections(services) {
|
|
|
6665
6714
|
}
|
|
6666
6715
|
async function runInit(opts) {
|
|
6667
6716
|
const written = [];
|
|
6668
|
-
const stat = await
|
|
6717
|
+
const stat = await import_node_fs23.promises.stat(opts.scanPath).catch(() => null);
|
|
6669
6718
|
if (!stat || !stat.isDirectory()) {
|
|
6670
6719
|
console.error(`neat init: ${opts.scanPath} is not a directory`);
|
|
6671
6720
|
return { exitCode: 2, writtenFiles: written };
|
|
@@ -6676,7 +6725,7 @@ async function runInit(opts) {
|
|
|
6676
6725
|
const patch = renderPatch(sections);
|
|
6677
6726
|
const patchPath = import_node_path37.default.join(opts.scanPath, "neat.patch");
|
|
6678
6727
|
if (opts.dryRun) {
|
|
6679
|
-
await
|
|
6728
|
+
await import_node_fs23.promises.writeFile(patchPath, patch, "utf8");
|
|
6680
6729
|
written.push(patchPath);
|
|
6681
6730
|
console.log(`dry-run: patch written to ${patchPath}`);
|
|
6682
6731
|
console.log("rerun without --dry-run to register and snapshot.");
|
|
@@ -6716,7 +6765,7 @@ async function runInit(opts) {
|
|
|
6716
6765
|
console.log("patch applied. Run `npm install` (or your language equivalent) to refresh lockfiles.");
|
|
6717
6766
|
}
|
|
6718
6767
|
} else {
|
|
6719
|
-
await
|
|
6768
|
+
await import_node_fs23.promises.writeFile(patchPath, patch, "utf8");
|
|
6720
6769
|
written.push(patchPath);
|
|
6721
6770
|
}
|
|
6722
6771
|
}
|
|
@@ -6770,7 +6819,7 @@ async function runSkill(opts) {
|
|
|
6770
6819
|
const target = claudeConfigPath();
|
|
6771
6820
|
let existing = {};
|
|
6772
6821
|
try {
|
|
6773
|
-
existing = JSON.parse(await
|
|
6822
|
+
existing = JSON.parse(await import_node_fs23.promises.readFile(target, "utf8"));
|
|
6774
6823
|
} catch (err) {
|
|
6775
6824
|
if (err.code !== "ENOENT") {
|
|
6776
6825
|
console.error(`neat skill: failed to read ${target} \u2014 ${err.message}`);
|
|
@@ -6782,8 +6831,8 @@ async function runSkill(opts) {
|
|
|
6782
6831
|
...existing,
|
|
6783
6832
|
mcpServers: { ...mcp, neat: CLAUDE_SKILL_CONFIG.mcpServers.neat }
|
|
6784
6833
|
};
|
|
6785
|
-
await
|
|
6786
|
-
await
|
|
6834
|
+
await import_node_fs23.promises.mkdir(import_node_path37.default.dirname(target), { recursive: true });
|
|
6835
|
+
await import_node_fs23.promises.writeFile(target, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
6787
6836
|
console.log(`neat skill: wrote mcpServers.neat to ${target}`);
|
|
6788
6837
|
console.log("restart Claude Code to pick up the new MCP server.");
|
|
6789
6838
|
return { exitCode: 0 };
|
|
@@ -6843,7 +6892,7 @@ async function main() {
|
|
|
6843
6892
|
process.exit(2);
|
|
6844
6893
|
}
|
|
6845
6894
|
const scanPath = import_node_path37.default.resolve(target);
|
|
6846
|
-
const stat = await
|
|
6895
|
+
const stat = await import_node_fs23.promises.stat(scanPath).catch(() => null);
|
|
6847
6896
|
if (!stat || !stat.isDirectory()) {
|
|
6848
6897
|
console.error(`neat watch: ${scanPath} is not a directory`);
|
|
6849
6898
|
process.exit(2);
|