@hasna/configs 0.2.33 → 0.2.35
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 +781 -98
- package/dist/index.js +60 -62
- package/dist/mcp/index.js +58 -66
- package/dist/server/index.js +225 -132
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -70,13 +70,13 @@ import { join, relative } from "path";
|
|
|
70
70
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, writeFileSync } from "fs";
|
|
71
71
|
import { homedir as homedir2 } from "os";
|
|
72
72
|
import { join as join2 } from "path";
|
|
73
|
-
import { readdirSync as
|
|
74
|
-
import { join as
|
|
73
|
+
import { readdirSync as readdirSync3, existsSync as existsSync6 } from "fs";
|
|
74
|
+
import { join as join6 } from "path";
|
|
75
|
+
import { homedir as homedir5 } from "os";
|
|
75
76
|
import { homedir as homedir3 } from "os";
|
|
76
|
-
import {
|
|
77
|
-
import { join as
|
|
78
|
-
import {
|
|
79
|
-
import { homedir as homedir5, platform } from "os";
|
|
77
|
+
import { join as join3 } from "path";
|
|
78
|
+
import { join as join5, dirname } from "path";
|
|
79
|
+
import { homedir as homedir4, platform } from "os";
|
|
80
80
|
var __create = Object.create;
|
|
81
81
|
var __getProtoOf = Object.getPrototypeOf;
|
|
82
82
|
var __defProp = Object.defineProperty;
|
|
@@ -9362,7 +9362,7 @@ var exports_discover = {};
|
|
|
9362
9362
|
__export(exports_discover, {
|
|
9363
9363
|
isSyncExcludedTable: () => isSyncExcludedTable,
|
|
9364
9364
|
getServiceDbPath: () => getServiceDbPath,
|
|
9365
|
-
discoverSyncableServices: () =>
|
|
9365
|
+
discoverSyncableServices: () => discoverSyncableServices2,
|
|
9366
9366
|
discoverServices: () => discoverServices,
|
|
9367
9367
|
SYNC_EXCLUDED_TABLE_PATTERNS: () => SYNC_EXCLUDED_TABLE_PATTERNS,
|
|
9368
9368
|
KNOWN_PG_SERVICES: () => KNOWN_PG_SERVICES
|
|
@@ -9371,11 +9371,11 @@ function isSyncExcludedTable(table) {
|
|
|
9371
9371
|
return SYNC_EXCLUDED_TABLE_PATTERNS.some((p) => p.test(table));
|
|
9372
9372
|
}
|
|
9373
9373
|
function discoverServices() {
|
|
9374
|
-
const dataDir =
|
|
9375
|
-
if (!
|
|
9374
|
+
const dataDir = join6(homedir5(), ".hasna");
|
|
9375
|
+
if (!existsSync6(dataDir))
|
|
9376
9376
|
return [];
|
|
9377
9377
|
try {
|
|
9378
|
-
const entries =
|
|
9378
|
+
const entries = readdirSync3(dataDir, { withFileTypes: true });
|
|
9379
9379
|
return entries.filter((e) => {
|
|
9380
9380
|
if (!e.isDirectory())
|
|
9381
9381
|
return false;
|
|
@@ -9387,30 +9387,30 @@ function discoverServices() {
|
|
|
9387
9387
|
return [];
|
|
9388
9388
|
}
|
|
9389
9389
|
}
|
|
9390
|
-
function
|
|
9390
|
+
function discoverSyncableServices2() {
|
|
9391
9391
|
const local = discoverServices();
|
|
9392
9392
|
const pgSet = new Set(KNOWN_PG_SERVICES);
|
|
9393
9393
|
return local.filter((s) => pgSet.has(s));
|
|
9394
9394
|
}
|
|
9395
9395
|
function getServiceDbPath(service) {
|
|
9396
|
-
const dataDir =
|
|
9397
|
-
if (!
|
|
9396
|
+
const dataDir = join6(homedir5(), ".hasna", service);
|
|
9397
|
+
if (!existsSync6(dataDir))
|
|
9398
9398
|
return null;
|
|
9399
9399
|
const candidates = [
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9400
|
+
join6(dataDir, `${service}.db`),
|
|
9401
|
+
join6(dataDir, "data.db"),
|
|
9402
|
+
join6(dataDir, "database.db")
|
|
9403
9403
|
];
|
|
9404
9404
|
try {
|
|
9405
|
-
const files =
|
|
9405
|
+
const files = readdirSync3(dataDir);
|
|
9406
9406
|
for (const f of files) {
|
|
9407
9407
|
if (f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm")) {
|
|
9408
|
-
candidates.push(
|
|
9408
|
+
candidates.push(join6(dataDir, f));
|
|
9409
9409
|
}
|
|
9410
9410
|
}
|
|
9411
9411
|
} catch {}
|
|
9412
9412
|
for (const p of candidates) {
|
|
9413
|
-
if (
|
|
9413
|
+
if (existsSync6(p))
|
|
9414
9414
|
return p;
|
|
9415
9415
|
}
|
|
9416
9416
|
return null;
|
|
@@ -9600,15 +9600,13 @@ class SyncProgressTracker {
|
|
|
9600
9600
|
}
|
|
9601
9601
|
}
|
|
9602
9602
|
}
|
|
9603
|
-
init_adapter();
|
|
9604
9603
|
init_config();
|
|
9605
|
-
|
|
9606
|
-
var AUTO_SYNC_CONFIG_PATH = join4(homedir4(), ".hasna", "cloud", "config.json");
|
|
9604
|
+
var AUTO_SYNC_CONFIG_PATH = join3(homedir3(), ".hasna", "cloud", "config.json");
|
|
9607
9605
|
init_config();
|
|
9608
9606
|
init_adapter();
|
|
9609
9607
|
init_dotfile();
|
|
9610
9608
|
init_config();
|
|
9611
|
-
var CONFIG_DIR2 =
|
|
9609
|
+
var CONFIG_DIR2 = join5(homedir4(), ".hasna", "cloud");
|
|
9612
9610
|
init_adapter();
|
|
9613
9611
|
init_config();
|
|
9614
9612
|
init_discover();
|
|
@@ -9622,7 +9620,7 @@ init_adapter();
|
|
|
9622
9620
|
|
|
9623
9621
|
// src/db/database.ts
|
|
9624
9622
|
import { mkdirSync as mkdirSync3 } from "fs";
|
|
9625
|
-
import { join as
|
|
9623
|
+
import { join as join4 } from "path";
|
|
9626
9624
|
import { randomUUID } from "crypto";
|
|
9627
9625
|
function getDbPath2() {
|
|
9628
9626
|
if (process.env["HASNA_CONFIGS_DB_PATH"]) {
|
|
@@ -9633,9 +9631,9 @@ function getDbPath2() {
|
|
|
9633
9631
|
}
|
|
9634
9632
|
migrateDotfile("configs");
|
|
9635
9633
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
9636
|
-
const dir =
|
|
9634
|
+
const dir = join4(home, ".hasna", "configs");
|
|
9637
9635
|
mkdirSync3(dir, { recursive: true });
|
|
9638
|
-
return
|
|
9636
|
+
return join4(dir, "configs.db");
|
|
9639
9637
|
}
|
|
9640
9638
|
function uuid() {
|
|
9641
9639
|
return randomUUID();
|
|
@@ -9937,7 +9935,7 @@ function pruneSnapshots(configId, keep = 10, db) {
|
|
|
9937
9935
|
}
|
|
9938
9936
|
// src/lib/machine.ts
|
|
9939
9937
|
import { arch as currentArch, homedir as homedir6, hostname as currentHostname, type as currentOsType } from "os";
|
|
9940
|
-
import { existsSync as
|
|
9938
|
+
import { existsSync as existsSync5 } from "fs";
|
|
9941
9939
|
import { join as join7 } from "path";
|
|
9942
9940
|
|
|
9943
9941
|
// src/lib/template.ts
|
|
@@ -10001,7 +9999,7 @@ function detectMachineContext(overrides = {}) {
|
|
|
10001
9999
|
const os = overrides.os ?? currentOsType();
|
|
10002
10000
|
const osFamily = normalizeOsFamily(os);
|
|
10003
10001
|
const bunBinDir = overrides.bun_bin_dir ?? join7(homeDir, ".bun", "bin");
|
|
10004
|
-
const defaultBunPath = osFamily === "macos" &&
|
|
10002
|
+
const defaultBunPath = osFamily === "macos" && existsSync5(BREW_BUN_PATH) ? BREW_BUN_PATH : join7(bunBinDir, "bun");
|
|
10005
10003
|
return {
|
|
10006
10004
|
id: "current-machine",
|
|
10007
10005
|
hostname: overrides.hostname ?? currentHostname(),
|
|
@@ -10396,8 +10394,8 @@ function ensurePlatformProfiles(db) {
|
|
|
10396
10394
|
return ensured;
|
|
10397
10395
|
}
|
|
10398
10396
|
// src/lib/sync.ts
|
|
10399
|
-
import { existsSync as
|
|
10400
|
-
import { extname, join as
|
|
10397
|
+
import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync4 } from "fs";
|
|
10398
|
+
import { extname, join as join10 } from "path";
|
|
10401
10399
|
import { homedir as homedir10 } from "os";
|
|
10402
10400
|
|
|
10403
10401
|
// src/lib/redact.ts
|
|
@@ -10581,8 +10579,8 @@ function hasSecrets(content, format) {
|
|
|
10581
10579
|
}
|
|
10582
10580
|
|
|
10583
10581
|
// src/lib/sync-dir.ts
|
|
10584
|
-
import { existsSync as
|
|
10585
|
-
import { join as
|
|
10582
|
+
import { existsSync as existsSync9, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync } from "fs";
|
|
10583
|
+
import { join as join9, relative as relative2 } from "path";
|
|
10586
10584
|
import { homedir as homedir9 } from "os";
|
|
10587
10585
|
var SKIP = [".db", ".db-shm", ".db-wal", ".log", ".lock", ".DS_Store", "node_modules", ".git"];
|
|
10588
10586
|
function shouldSkip(p) {
|
|
@@ -10591,9 +10589,9 @@ function shouldSkip(p) {
|
|
|
10591
10589
|
async function syncFromDir(dir, opts = {}) {
|
|
10592
10590
|
const d = opts.db || getDatabase();
|
|
10593
10591
|
const absDir = expandPath(dir);
|
|
10594
|
-
if (!
|
|
10592
|
+
if (!existsSync9(absDir))
|
|
10595
10593
|
return { added: 0, updated: 0, unchanged: 0, skipped: [`Not found: ${absDir}`] };
|
|
10596
|
-
const files = opts.recursive !== false ? walkDir(absDir) :
|
|
10594
|
+
const files = opts.recursive !== false ? walkDir(absDir) : readdirSync2(absDir).map((f) => join9(absDir, f)).filter((f) => statSync(f).isFile());
|
|
10597
10595
|
const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
|
|
10598
10596
|
const home = homedir9();
|
|
10599
10597
|
const allConfigs = listConfigs(undefined, d);
|
|
@@ -10647,8 +10645,8 @@ async function syncToDir(dir, opts = {}) {
|
|
|
10647
10645
|
return result;
|
|
10648
10646
|
}
|
|
10649
10647
|
function walkDir(dir, files = []) {
|
|
10650
|
-
for (const entry of
|
|
10651
|
-
const full =
|
|
10648
|
+
for (const entry of readdirSync2(dir, { withFileTypes: true })) {
|
|
10649
|
+
const full = join9(dir, entry.name);
|
|
10652
10650
|
if (shouldSkip(full))
|
|
10653
10651
|
continue;
|
|
10654
10652
|
if (entry.isDirectory())
|
|
@@ -10697,8 +10695,8 @@ async function syncProject(opts) {
|
|
|
10697
10695
|
const allConfigs = listConfigs(undefined, d);
|
|
10698
10696
|
const machine = detectMachineContext();
|
|
10699
10697
|
for (const pf of PROJECT_CONFIG_FILES) {
|
|
10700
|
-
const abs =
|
|
10701
|
-
if (!
|
|
10698
|
+
const abs = join10(absDir, pf.file);
|
|
10699
|
+
if (!existsSync10(abs))
|
|
10702
10700
|
continue;
|
|
10703
10701
|
try {
|
|
10704
10702
|
const rawContent = readFileSync4(abs, "utf-8");
|
|
@@ -10729,11 +10727,11 @@ async function syncProject(opts) {
|
|
|
10729
10727
|
result.skipped.push(pf.file);
|
|
10730
10728
|
}
|
|
10731
10729
|
}
|
|
10732
|
-
const rulesDir =
|
|
10733
|
-
if (
|
|
10734
|
-
const mdFiles =
|
|
10730
|
+
const rulesDir = join10(absDir, ".claude", "rules");
|
|
10731
|
+
if (existsSync10(rulesDir)) {
|
|
10732
|
+
const mdFiles = readdirSync4(rulesDir).filter((f) => f.endsWith(".md"));
|
|
10735
10733
|
for (const f of mdFiles) {
|
|
10736
|
-
const abs =
|
|
10734
|
+
const abs = join10(rulesDir, f);
|
|
10737
10735
|
const raw = readFileSync4(abs, "utf-8");
|
|
10738
10736
|
const redacted = redactContent(raw, "markdown");
|
|
10739
10737
|
const machineAware = templateizeMachineContent(redacted.content, machine);
|
|
@@ -10772,13 +10770,13 @@ async function syncKnown(opts = {}) {
|
|
|
10772
10770
|
for (const known of targets) {
|
|
10773
10771
|
if (known.rulesDir) {
|
|
10774
10772
|
const absDir = expandPath(known.rulesDir);
|
|
10775
|
-
if (!
|
|
10773
|
+
if (!existsSync10(absDir)) {
|
|
10776
10774
|
result.skipped.push(known.rulesDir);
|
|
10777
10775
|
continue;
|
|
10778
10776
|
}
|
|
10779
|
-
const mdFiles =
|
|
10777
|
+
const mdFiles = readdirSync4(absDir).filter((f) => f.endsWith(".md"));
|
|
10780
10778
|
for (const f of mdFiles) {
|
|
10781
|
-
const abs2 =
|
|
10779
|
+
const abs2 = join10(absDir, f);
|
|
10782
10780
|
const targetPath = abs2.replace(home, "~");
|
|
10783
10781
|
const raw = readFileSync4(abs2, "utf-8");
|
|
10784
10782
|
const redacted = redactContent(raw, "markdown");
|
|
@@ -10803,7 +10801,7 @@ async function syncKnown(opts = {}) {
|
|
|
10803
10801
|
continue;
|
|
10804
10802
|
}
|
|
10805
10803
|
const abs = expandPath(known.path);
|
|
10806
|
-
if (!
|
|
10804
|
+
if (!existsSync10(abs)) {
|
|
10807
10805
|
result.skipped.push(known.path);
|
|
10808
10806
|
continue;
|
|
10809
10807
|
}
|
|
@@ -10868,7 +10866,7 @@ function diffConfig(config) {
|
|
|
10868
10866
|
if (!config.target_path)
|
|
10869
10867
|
return "(reference \u2014 no target path)";
|
|
10870
10868
|
const path = expandPath(config.target_path);
|
|
10871
|
-
if (!
|
|
10869
|
+
if (!existsSync10(path))
|
|
10872
10870
|
return `(file not found on disk: ${path})`;
|
|
10873
10871
|
const diskContent = readFileSync4(path, "utf-8");
|
|
10874
10872
|
if (diskContent === config.content)
|
|
@@ -10944,15 +10942,15 @@ function detectFormat(filePath) {
|
|
|
10944
10942
|
return "text";
|
|
10945
10943
|
}
|
|
10946
10944
|
// src/lib/export.ts
|
|
10947
|
-
import { existsSync as
|
|
10948
|
-
import { join as
|
|
10945
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync6, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
10946
|
+
import { join as join11, resolve as resolve2 } from "path";
|
|
10949
10947
|
import { tmpdir } from "os";
|
|
10950
10948
|
async function exportConfigs(outputPath, opts = {}) {
|
|
10951
10949
|
const d = opts.db || getDatabase();
|
|
10952
10950
|
const configs = listConfigs(opts.filter, d);
|
|
10953
10951
|
const absOutput = resolve2(outputPath);
|
|
10954
|
-
const tmpDir =
|
|
10955
|
-
const contentsDir =
|
|
10952
|
+
const tmpDir = join11(tmpdir(), `configs-export-${Date.now()}`);
|
|
10953
|
+
const contentsDir = join11(tmpDir, "contents");
|
|
10956
10954
|
try {
|
|
10957
10955
|
mkdirSync6(contentsDir, { recursive: true });
|
|
10958
10956
|
const manifest = {
|
|
@@ -10960,10 +10958,10 @@ async function exportConfigs(outputPath, opts = {}) {
|
|
|
10960
10958
|
exported_at: now(),
|
|
10961
10959
|
configs: configs.map(({ content: _content, ...meta }) => meta)
|
|
10962
10960
|
};
|
|
10963
|
-
writeFileSync3(
|
|
10961
|
+
writeFileSync3(join11(tmpDir, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
|
|
10964
10962
|
for (const config of configs) {
|
|
10965
10963
|
const fileName = `${config.slug}.${config.format === "text" ? "txt" : config.format}`;
|
|
10966
|
-
writeFileSync3(
|
|
10964
|
+
writeFileSync3(join11(contentsDir, fileName), config.content, "utf-8");
|
|
10967
10965
|
}
|
|
10968
10966
|
const proc = Bun.spawn(["tar", "czf", absOutput, "-C", tmpDir, "."], {
|
|
10969
10967
|
stdout: "pipe",
|
|
@@ -10976,20 +10974,20 @@ async function exportConfigs(outputPath, opts = {}) {
|
|
|
10976
10974
|
}
|
|
10977
10975
|
return { path: absOutput, count: configs.length };
|
|
10978
10976
|
} finally {
|
|
10979
|
-
if (
|
|
10977
|
+
if (existsSync11(tmpDir)) {
|
|
10980
10978
|
rmSync(tmpDir, { recursive: true, force: true });
|
|
10981
10979
|
}
|
|
10982
10980
|
}
|
|
10983
10981
|
}
|
|
10984
10982
|
// src/lib/import.ts
|
|
10985
|
-
import { existsSync as
|
|
10986
|
-
import { join as
|
|
10983
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync5, rmSync as rmSync2 } from "fs";
|
|
10984
|
+
import { join as join12, resolve as resolve3 } from "path";
|
|
10987
10985
|
import { tmpdir as tmpdir2 } from "os";
|
|
10988
10986
|
async function importConfigs(bundlePath, opts = {}) {
|
|
10989
10987
|
const d = opts.db || getDatabase();
|
|
10990
10988
|
const conflict = opts.conflict ?? "skip";
|
|
10991
10989
|
const absPath = resolve3(bundlePath);
|
|
10992
|
-
const tmpDir =
|
|
10990
|
+
const tmpDir = join12(tmpdir2(), `configs-import-${Date.now()}`);
|
|
10993
10991
|
const result = { created: 0, updated: 0, skipped: 0, errors: [] };
|
|
10994
10992
|
try {
|
|
10995
10993
|
mkdirSync7(tmpDir, { recursive: true });
|
|
@@ -11002,15 +11000,15 @@ async function importConfigs(bundlePath, opts = {}) {
|
|
|
11002
11000
|
const stderr = await new Response(proc.stderr).text();
|
|
11003
11001
|
throw new Error(`tar extraction failed: ${stderr}`);
|
|
11004
11002
|
}
|
|
11005
|
-
const manifestPath =
|
|
11006
|
-
if (!
|
|
11003
|
+
const manifestPath = join12(tmpDir, "manifest.json");
|
|
11004
|
+
if (!existsSync12(manifestPath))
|
|
11007
11005
|
throw new Error("Invalid bundle: missing manifest.json");
|
|
11008
11006
|
const manifest = JSON.parse(readFileSync5(manifestPath, "utf-8"));
|
|
11009
11007
|
for (const meta of manifest.configs) {
|
|
11010
11008
|
try {
|
|
11011
11009
|
const ext = meta.format === "text" ? "txt" : meta.format;
|
|
11012
|
-
const contentFile =
|
|
11013
|
-
const content =
|
|
11010
|
+
const contentFile = join12(tmpDir, "contents", `${meta.slug}.${ext}`);
|
|
11011
|
+
const content = existsSync12(contentFile) ? readFileSync5(contentFile, "utf-8") : "";
|
|
11014
11012
|
let existing = null;
|
|
11015
11013
|
try {
|
|
11016
11014
|
existing = getConfig(meta.slug, d);
|
|
@@ -11043,7 +11041,7 @@ async function importConfigs(bundlePath, opts = {}) {
|
|
|
11043
11041
|
}
|
|
11044
11042
|
return result;
|
|
11045
11043
|
} finally {
|
|
11046
|
-
if (
|
|
11044
|
+
if (existsSync12(tmpDir)) {
|
|
11047
11045
|
rmSync2(tmpDir, { recursive: true, force: true });
|
|
11048
11046
|
}
|
|
11049
11047
|
}
|