@hasna/configs 0.2.0 → 0.2.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/index.js +100 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -2394,6 +2394,12 @@ var init_snapshots = __esm(() => {
|
|
|
2394
2394
|
});
|
|
2395
2395
|
|
|
2396
2396
|
// src/lib/apply.ts
|
|
2397
|
+
var exports_apply = {};
|
|
2398
|
+
__export(exports_apply, {
|
|
2399
|
+
expandPath: () => expandPath,
|
|
2400
|
+
applyConfigs: () => applyConfigs,
|
|
2401
|
+
applyConfig: () => applyConfig
|
|
2402
|
+
});
|
|
2397
2403
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, writeFileSync } from "fs";
|
|
2398
2404
|
import { dirname as dirname2, resolve as resolve2 } from "path";
|
|
2399
2405
|
import { homedir } from "os";
|
|
@@ -3882,5 +3888,99 @@ _configs_completions() {
|
|
|
3882
3888
|
complete -F _configs_completions configs`);
|
|
3883
3889
|
}
|
|
3884
3890
|
});
|
|
3891
|
+
program.command("compare <a> <b>").description("Diff two stored configs against each other").action(async (a, b) => {
|
|
3892
|
+
try {
|
|
3893
|
+
const configA = getConfig(a);
|
|
3894
|
+
const configB = getConfig(b);
|
|
3895
|
+
console.log(chalk.bold(`${configA.slug}`) + chalk.dim(` (${configA.category}/${configA.agent})`));
|
|
3896
|
+
console.log(chalk.bold(`${configB.slug}`) + chalk.dim(` (${configB.category}/${configB.agent})`));
|
|
3897
|
+
console.log();
|
|
3898
|
+
const linesA = configA.content.split(`
|
|
3899
|
+
`);
|
|
3900
|
+
const linesB = configB.content.split(`
|
|
3901
|
+
`);
|
|
3902
|
+
const maxLen = Math.max(linesA.length, linesB.length);
|
|
3903
|
+
const lines = [`--- ${configA.slug}`, `+++ ${configB.slug}`];
|
|
3904
|
+
let diffs = 0;
|
|
3905
|
+
for (let i = 0;i < maxLen; i++) {
|
|
3906
|
+
const la = linesA[i];
|
|
3907
|
+
const lb = linesB[i];
|
|
3908
|
+
if (la === lb) {
|
|
3909
|
+
if (la !== undefined)
|
|
3910
|
+
lines.push(` ${la}`);
|
|
3911
|
+
} else {
|
|
3912
|
+
diffs++;
|
|
3913
|
+
if (la !== undefined)
|
|
3914
|
+
lines.push(chalk.red(`-${la}`));
|
|
3915
|
+
if (lb !== undefined)
|
|
3916
|
+
lines.push(chalk.green(`+${lb}`));
|
|
3917
|
+
}
|
|
3918
|
+
}
|
|
3919
|
+
if (diffs === 0) {
|
|
3920
|
+
console.log(chalk.green("\u2713") + " Identical content");
|
|
3921
|
+
} else {
|
|
3922
|
+
console.log(lines.join(`
|
|
3923
|
+
`));
|
|
3924
|
+
console.log(chalk.dim(`
|
|
3925
|
+
${diffs} difference(s)`));
|
|
3926
|
+
}
|
|
3927
|
+
} catch (e) {
|
|
3928
|
+
console.error(chalk.red(e instanceof Error ? e.message : String(e)));
|
|
3929
|
+
process.exit(1);
|
|
3930
|
+
}
|
|
3931
|
+
});
|
|
3932
|
+
program.command("watch").description("Watch known config files for changes and auto-sync to DB").option("-i, --interval <ms>", "poll interval in milliseconds", "3000").action(async (opts) => {
|
|
3933
|
+
const interval = Number(opts.interval);
|
|
3934
|
+
const { statSync: st } = await import("fs");
|
|
3935
|
+
const { expandPath: expandPath2 } = await Promise.resolve().then(() => (init_apply(), exports_apply));
|
|
3936
|
+
console.log(chalk.bold("@hasna/configs watch") + chalk.dim(` \u2014 polling every ${interval}ms`));
|
|
3937
|
+
console.log(chalk.dim(`Watching known config files for changes\u2026
|
|
3938
|
+
`));
|
|
3939
|
+
const mtimes = new Map;
|
|
3940
|
+
for (const k of KNOWN_CONFIGS) {
|
|
3941
|
+
if (k.rulesDir) {
|
|
3942
|
+
const absDir = expandPath2(k.rulesDir);
|
|
3943
|
+
if (!existsSync7(absDir))
|
|
3944
|
+
continue;
|
|
3945
|
+
const { readdirSync: readdirSync3 } = await import("fs");
|
|
3946
|
+
for (const f of readdirSync3(absDir).filter((f2) => f2.endsWith(".md"))) {
|
|
3947
|
+
const abs = join6(absDir, f);
|
|
3948
|
+
mtimes.set(abs, st(abs).mtimeMs);
|
|
3949
|
+
}
|
|
3950
|
+
} else {
|
|
3951
|
+
const abs = expandPath2(k.path);
|
|
3952
|
+
if (existsSync7(abs))
|
|
3953
|
+
mtimes.set(abs, st(abs).mtimeMs);
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
console.log(chalk.dim(`Tracking ${mtimes.size} files`));
|
|
3957
|
+
const tick = async () => {
|
|
3958
|
+
let changed = 0;
|
|
3959
|
+
for (const [abs, oldMtime] of mtimes) {
|
|
3960
|
+
if (!existsSync7(abs))
|
|
3961
|
+
continue;
|
|
3962
|
+
const newMtime = st(abs).mtimeMs;
|
|
3963
|
+
if (newMtime !== oldMtime) {
|
|
3964
|
+
changed++;
|
|
3965
|
+
mtimes.set(abs, newMtime);
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
if (changed > 0) {
|
|
3969
|
+
const result = await syncKnown({});
|
|
3970
|
+
const ts = new Date().toLocaleTimeString();
|
|
3971
|
+
console.log(`${chalk.dim(ts)} ${chalk.green("\u2713")} ${changed} file(s) changed \u2192 synced +${result.added} updated:${result.updated}`);
|
|
3972
|
+
}
|
|
3973
|
+
};
|
|
3974
|
+
setInterval(tick, interval);
|
|
3975
|
+
await new Promise(() => {});
|
|
3976
|
+
});
|
|
3977
|
+
program.command("pull").description("Alias for sync (read from disk into DB)").option("-a, --agent <agent>", "only sync this agent").option("--dry-run", "preview without writing").action(async (opts) => {
|
|
3978
|
+
const result = await syncKnown({ dryRun: opts.dryRun, agent: opts.agent });
|
|
3979
|
+
console.log(chalk.green("\u2713") + ` Pulled: +${result.added} updated:${result.updated} unchanged:${result.unchanged}`);
|
|
3980
|
+
});
|
|
3981
|
+
program.command("push").description("Alias for sync --to-disk (write DB configs to disk)").option("-a, --agent <agent>", "only push this agent").option("--dry-run", "preview without writing").action(async (opts) => {
|
|
3982
|
+
const result = await syncToDisk({ dryRun: opts.dryRun, agent: opts.agent });
|
|
3983
|
+
console.log(chalk.green("\u2713") + ` Pushed: updated:${result.updated} unchanged:${result.unchanged} skipped:${result.skipped.length}`);
|
|
3984
|
+
});
|
|
3885
3985
|
program.version(pkg.version).name("configs");
|
|
3886
3986
|
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/configs",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "AI coding agent configuration manager — store, version, apply, and share all your AI coding configs. CLI + MCP + REST API + Dashboard.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|