@hasna/configs 0.2.15 → 0.2.17

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=database.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.test.d.ts","sourceRoot":"","sources":["../../src/db/database.test.ts"],"names":[],"mappings":""}
package/dist/index.d.ts CHANGED
@@ -6,9 +6,9 @@ export { registerMachine, updateMachineApplied, listMachines, currentHostname, c
6
6
  export { getDatabase, resetDatabase, uuid, now, slugify } from "./db/database.js";
7
7
  export { applyConfig, applyConfigs, expandPath } from "./lib/apply.js";
8
8
  export type { ApplyOptions } from "./lib/apply.js";
9
- export { syncKnown, syncToDisk, diffConfig, detectCategory, detectAgent, detectFormat, KNOWN_CONFIGS } from "./lib/sync.js";
9
+ export { syncKnown, syncToDisk, syncProject, diffConfig, detectCategory, detectAgent, detectFormat, KNOWN_CONFIGS, PROJECT_CONFIG_FILES } from "./lib/sync.js";
10
10
  export { syncFromDir, syncToDir } from "./lib/sync-dir.js";
11
- export type { SyncKnownOptions, SyncToDiskOptions } from "./lib/sync.js";
11
+ export type { SyncKnownOptions, SyncToDiskOptions, SyncProjectOptions, KnownConfig } from "./lib/sync.js";
12
12
  export type { SyncFromDirOptions } from "./lib/sync-dir.js";
13
13
  export { exportConfigs } from "./lib/export.js";
14
14
  export { importConfigs } from "./lib/import.js";
@@ -16,4 +16,6 @@ export type { ExportOptions } from "./lib/export.js";
16
16
  export type { ImportOptions, ImportResult } from "./lib/import.js";
17
17
  export { parseTemplateVars, extractTemplateVars, renderTemplate, isTemplate } from "./lib/template.js";
18
18
  export type { TemplateVar } from "./lib/template.js";
19
+ export { redactContent, scanSecrets, hasSecrets } from "./lib/redact.js";
20
+ export type { RedactResult, RedactedVar, RedactFormat } from "./lib/redact.js";
19
21
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGlI,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGrH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGzK,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGnH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAGlF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACvE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC5H,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACzE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGnE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACvG,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGlI,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGrH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGzK,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGnH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAGlF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACvE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC/J,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC1G,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGnE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACvG,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACzE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -700,6 +700,13 @@ function redactContent(content, format) {
700
700
  return redactGeneric(content);
701
701
  }
702
702
  }
703
+ function scanSecrets(content, format) {
704
+ const r = redactContent(content, format);
705
+ return r.redacted;
706
+ }
707
+ function hasSecrets(content, format) {
708
+ return scanSecrets(content, format).length > 0;
709
+ }
703
710
 
704
711
  // src/lib/sync-dir.ts
705
712
  import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync2, statSync } from "fs";
@@ -801,6 +808,77 @@ var KNOWN_CONFIGS = [
801
808
  { path: "~/.npmrc", name: "npmrc", category: "tools", agent: "npm", format: "ini" },
802
809
  { path: "~/.bunfig.toml", name: "bunfig", category: "tools", agent: "global", format: "toml", optional: true }
803
810
  ];
811
+ var PROJECT_CONFIG_FILES = [
812
+ { file: "CLAUDE.md", category: "rules", agent: "claude", format: "markdown" },
813
+ { file: ".claude/settings.json", category: "agent", agent: "claude", format: "json" },
814
+ { file: ".claude/settings.local.json", category: "agent", agent: "claude", format: "json" },
815
+ { file: ".mcp.json", category: "mcp", agent: "claude", format: "json" },
816
+ { file: "AGENTS.md", category: "rules", agent: "codex", format: "markdown" },
817
+ { file: ".codex/AGENTS.md", category: "rules", agent: "codex", format: "markdown" },
818
+ { file: "GEMINI.md", category: "rules", agent: "gemini", format: "markdown" }
819
+ ];
820
+ async function syncProject(opts) {
821
+ const d = opts.db || getDatabase();
822
+ const absDir = expandPath(opts.projectDir);
823
+ const projectName = absDir.split("/").pop() || "project";
824
+ const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
825
+ const allConfigs = listConfigs(undefined, d);
826
+ for (const pf of PROJECT_CONFIG_FILES) {
827
+ const abs = join3(absDir, pf.file);
828
+ if (!existsSync4(abs))
829
+ continue;
830
+ try {
831
+ const rawContent = readFileSync3(abs, "utf-8");
832
+ if (rawContent.length > 500000) {
833
+ result.skipped.push(pf.file);
834
+ continue;
835
+ }
836
+ const { content, isTemplate } = redactContent(rawContent, pf.format);
837
+ const name = `${projectName}/${pf.file}`;
838
+ const targetPath = abs.replace(homedir3(), "~");
839
+ const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
840
+ const existing = allConfigs.find((c) => c.target_path === targetPath || c.slug === slug);
841
+ if (!existing) {
842
+ if (!opts.dryRun)
843
+ createConfig({ name, category: pf.category, agent: pf.agent, format: pf.format, content, target_path: targetPath, is_template: isTemplate }, d);
844
+ result.added++;
845
+ } else if (existing.content !== content) {
846
+ if (!opts.dryRun)
847
+ updateConfig(existing.id, { content, is_template: isTemplate }, d);
848
+ result.updated++;
849
+ } else {
850
+ result.unchanged++;
851
+ }
852
+ } catch {
853
+ result.skipped.push(pf.file);
854
+ }
855
+ }
856
+ const rulesDir = join3(absDir, ".claude", "rules");
857
+ if (existsSync4(rulesDir)) {
858
+ const mdFiles = readdirSync2(rulesDir).filter((f) => f.endsWith(".md"));
859
+ for (const f of mdFiles) {
860
+ const abs = join3(rulesDir, f);
861
+ const raw = readFileSync3(abs, "utf-8");
862
+ const { content, isTemplate } = redactContent(raw, "markdown");
863
+ const name = `${projectName}/rules/${f}`;
864
+ const targetPath = abs.replace(homedir3(), "~");
865
+ const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
866
+ const existing = allConfigs.find((c) => c.target_path === targetPath || c.slug === slug);
867
+ if (!existing) {
868
+ if (!opts.dryRun)
869
+ createConfig({ name, category: "rules", agent: "claude", format: "markdown", content, target_path: targetPath, is_template: isTemplate }, d);
870
+ result.added++;
871
+ } else if (existing.content !== content) {
872
+ if (!opts.dryRun)
873
+ updateConfig(existing.id, { content, is_template: isTemplate }, d);
874
+ result.updated++;
875
+ } else {
876
+ result.unchanged++;
877
+ }
878
+ }
879
+ }
880
+ return result;
881
+ }
804
882
  async function syncKnown(opts = {}) {
805
883
  const d = opts.db || getDatabase();
806
884
  const result = { added: 0, updated: 0, unchanged: 0, skipped: [] };
@@ -1134,13 +1212,16 @@ export {
1134
1212
  updateConfig,
1135
1213
  syncToDisk,
1136
1214
  syncToDir,
1215
+ syncProject,
1137
1216
  syncKnown,
1138
1217
  syncFromDir,
1139
1218
  slugify,
1219
+ scanSecrets,
1140
1220
  resetDatabase,
1141
1221
  renderTemplate,
1142
1222
  removeConfigFromProfile,
1143
1223
  registerMachine,
1224
+ redactContent,
1144
1225
  pruneSnapshots,
1145
1226
  parseTemplateVars,
1146
1227
  now,
@@ -1150,6 +1231,7 @@ export {
1150
1231
  listConfigs,
1151
1232
  isTemplate,
1152
1233
  importConfigs,
1234
+ hasSecrets,
1153
1235
  getSnapshotByVersion,
1154
1236
  getSnapshot,
1155
1237
  getProfileConfigs,
@@ -1177,6 +1259,7 @@ export {
1177
1259
  addConfigToProfile,
1178
1260
  TemplateRenderError,
1179
1261
  ProfileNotFoundError,
1262
+ PROJECT_CONFIG_FILES,
1180
1263
  KNOWN_CONFIGS,
1181
1264
  ConfigNotFoundError,
1182
1265
  ConfigApplyError,
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=export-import.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-import.test.d.ts","sourceRoot":"","sources":["../../src/lib/export-import.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sync-known.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-known.test.d.ts","sourceRoot":"","sources":["../../src/lib/sync-known.test.ts"],"names":[],"mappings":""}
package/dist/mcp/index.js CHANGED
@@ -1,6 +1,21 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
+ var __create = Object.create;
4
+ var __getProtoOf = Object.getPrototypeOf;
3
5
  var __defProp = Object.defineProperty;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __toESM = (mod, isNodeMode, target) => {
9
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
10
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
+ for (let key of __getOwnPropNames(mod))
12
+ if (!__hasOwnProp.call(to, key))
13
+ __defProp(to, key, {
14
+ get: () => mod[key],
15
+ enumerable: true
16
+ });
17
+ return to;
18
+ };
4
19
  var __export = (target, all) => {
5
20
  for (var name in all)
6
21
  __defProp(target, name, {
@@ -11,6 +26,7 @@ var __export = (target, all) => {
11
26
  });
12
27
  };
13
28
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
29
+ var __require = import.meta.require;
14
30
 
15
31
  // src/types/index.ts
16
32
  var ConfigNotFoundError, ProfileNotFoundError, ConfigApplyError, TemplateRenderError;
@@ -346,6 +362,12 @@ var init_snapshots = __esm(() => {
346
362
  });
347
363
 
348
364
  // src/lib/apply.ts
365
+ var exports_apply = {};
366
+ __export(exports_apply, {
367
+ expandPath: () => expandPath,
368
+ applyConfigs: () => applyConfigs,
369
+ applyConfig: () => applyConfig
370
+ });
349
371
  import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, writeFileSync } from "fs";
350
372
  import { dirname as dirname2, resolve as resolve2 } from "path";
351
373
  import { homedir } from "os";
@@ -1189,15 +1211,35 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
1189
1211
  case "get_status": {
1190
1212
  const stats = getConfigStats();
1191
1213
  const allConfigs = listConfigs({ kind: "file" });
1192
- let drifted = 0, secrets = 0, templates = 0;
1214
+ const { existsSync: ex, readFileSync: rf } = await import("fs");
1215
+ const { expandPath: expandPath2 } = await Promise.resolve().then(() => (init_apply(), exports_apply));
1216
+ const { redactContent: redactContent2 } = await Promise.resolve().then(() => (init_redact(), exports_redact));
1217
+ let drifted = 0, missing = 0, templates = 0;
1218
+ const driftedSlugs = [];
1193
1219
  for (const c of allConfigs) {
1194
1220
  if (c.is_template)
1195
1221
  templates++;
1222
+ if (!c.target_path)
1223
+ continue;
1224
+ const abs = expandPath2(c.target_path);
1225
+ if (!ex(abs)) {
1226
+ missing++;
1227
+ continue;
1228
+ }
1229
+ const disk = rf(abs, "utf-8");
1230
+ const { content: redactedDisk } = redactContent2(disk, c.format);
1231
+ if (redactedDisk !== c.content) {
1232
+ drifted++;
1233
+ driftedSlugs.push(c.slug);
1234
+ }
1196
1235
  }
1197
1236
  return ok({
1198
1237
  total: stats["total"] || 0,
1199
1238
  by_category: Object.fromEntries(Object.entries(stats).filter(([k]) => k !== "total")),
1200
1239
  templates,
1240
+ drifted,
1241
+ drifted_configs: driftedSlugs.slice(0, 5),
1242
+ missing,
1201
1243
  db_path: process.env["CONFIGS_DB_PATH"] || "~/.configs/configs.db"
1202
1244
  });
1203
1245
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/configs",
3
- "version": "0.2.15",
3
+ "version": "0.2.17",
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",
@@ -30,7 +30,8 @@
30
30
  "dev:cli": "bun run src/cli/index.tsx",
31
31
  "dev:mcp": "bun run src/mcp/index.ts",
32
32
  "dev:serve": "bun run src/server/index.ts",
33
- "seed": "bun run scripts/seed.ts"
33
+ "seed": "bun run scripts/seed.ts",
34
+ "prepublishOnly": "bun run build"
34
35
  },
35
36
  "keywords": [
36
37
  "configs",