@hasna/contacts 0.6.18 → 0.6.20
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 +831 -155
- package/dist/index.js +67 -69
- package/dist/mcp/index.js +70 -79
- package/dist/server/index.js +80 -89
- package/package.json +3 -2
package/dist/mcp/index.js
CHANGED
|
@@ -31,14 +31,14 @@ import { join, relative } from "path";
|
|
|
31
31
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, writeFileSync } from "fs";
|
|
32
32
|
import { homedir as homedir2 } from "os";
|
|
33
33
|
import { join as join2 } from "path";
|
|
34
|
-
import { readdirSync as
|
|
35
|
-
import { join as
|
|
36
|
-
import { homedir as
|
|
34
|
+
import { readdirSync as readdirSync3, existsSync as existsSync6 } from "fs";
|
|
35
|
+
import { join as join6 } from "path";
|
|
36
|
+
import { homedir as homedir5 } from "os";
|
|
37
37
|
import { hostname } from "os";
|
|
38
|
-
import { homedir as
|
|
39
|
-
import { join as
|
|
40
|
-
import { join as
|
|
41
|
-
import { homedir as
|
|
38
|
+
import { homedir as homedir3 } from "os";
|
|
39
|
+
import { join as join3 } from "path";
|
|
40
|
+
import { join as join5, dirname } from "path";
|
|
41
|
+
import { homedir as homedir4, platform } from "os";
|
|
42
42
|
function __accessProp(key) {
|
|
43
43
|
return this[key];
|
|
44
44
|
}
|
|
@@ -966,11 +966,11 @@ function isSyncExcludedTable(table) {
|
|
|
966
966
|
return SYNC_EXCLUDED_TABLE_PATTERNS.some((p) => p.test(table));
|
|
967
967
|
}
|
|
968
968
|
function discoverServices() {
|
|
969
|
-
const dataDir =
|
|
970
|
-
if (!
|
|
969
|
+
const dataDir = join6(homedir5(), ".hasna");
|
|
970
|
+
if (!existsSync6(dataDir))
|
|
971
971
|
return [];
|
|
972
972
|
try {
|
|
973
|
-
const entries =
|
|
973
|
+
const entries = readdirSync3(dataDir, { withFileTypes: true });
|
|
974
974
|
return entries.filter((e) => {
|
|
975
975
|
if (!e.isDirectory())
|
|
976
976
|
return false;
|
|
@@ -982,30 +982,30 @@ function discoverServices() {
|
|
|
982
982
|
return [];
|
|
983
983
|
}
|
|
984
984
|
}
|
|
985
|
-
function
|
|
985
|
+
function discoverSyncableServices2() {
|
|
986
986
|
const local = discoverServices();
|
|
987
987
|
const pgSet = new Set(KNOWN_PG_SERVICES);
|
|
988
988
|
return local.filter((s) => pgSet.has(s));
|
|
989
989
|
}
|
|
990
990
|
function getServiceDbPath(service) {
|
|
991
|
-
const dataDir =
|
|
992
|
-
if (!
|
|
991
|
+
const dataDir = join6(homedir5(), ".hasna", service);
|
|
992
|
+
if (!existsSync6(dataDir))
|
|
993
993
|
return null;
|
|
994
994
|
const candidates = [
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
995
|
+
join6(dataDir, `${service}.db`),
|
|
996
|
+
join6(dataDir, "data.db"),
|
|
997
|
+
join6(dataDir, "database.db")
|
|
998
998
|
];
|
|
999
999
|
try {
|
|
1000
|
-
const files =
|
|
1000
|
+
const files = readdirSync3(dataDir);
|
|
1001
1001
|
for (const f of files) {
|
|
1002
1002
|
if (f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm")) {
|
|
1003
|
-
candidates.push(
|
|
1003
|
+
candidates.push(join6(dataDir, f));
|
|
1004
1004
|
}
|
|
1005
1005
|
}
|
|
1006
1006
|
} catch {}
|
|
1007
1007
|
for (const p of candidates) {
|
|
1008
|
-
if (
|
|
1008
|
+
if (existsSync6(p))
|
|
1009
1009
|
return p;
|
|
1010
1010
|
}
|
|
1011
1011
|
return null;
|
|
@@ -1312,9 +1312,9 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
1312
1312
|
const batch = rows.slice(offset, offset + batchSize);
|
|
1313
1313
|
try {
|
|
1314
1314
|
if (isAsyncAdapter(target)) {
|
|
1315
|
-
await batchUpsertPg(target, table, columns, updateCols, pkColumns, batch
|
|
1315
|
+
await batchUpsertPg(target, table, columns, updateCols, pkColumns, batch);
|
|
1316
1316
|
} else {
|
|
1317
|
-
batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch
|
|
1317
|
+
batchUpsertSqlite(target, table, columns, updateCols, pkColumns, batch);
|
|
1318
1318
|
}
|
|
1319
1319
|
result.rowsWritten += batch.length;
|
|
1320
1320
|
} catch (err) {
|
|
@@ -1361,7 +1361,7 @@ async function syncTransfer(source, target, options, _direction) {
|
|
|
1361
1361
|
}
|
|
1362
1362
|
return results;
|
|
1363
1363
|
}
|
|
1364
|
-
async function batchUpsertPg(target, table, columns, updateCols, primaryKeys, batch
|
|
1364
|
+
async function batchUpsertPg(target, table, columns, updateCols, primaryKeys, batch) {
|
|
1365
1365
|
if (batch.length === 0)
|
|
1366
1366
|
return;
|
|
1367
1367
|
const colList = columns.map((c) => `"${c}"`).join(", ");
|
|
@@ -1371,22 +1371,20 @@ async function batchUpsertPg(target, table, columns, updateCols, primaryKeys, ba
|
|
|
1371
1371
|
}).join(", ");
|
|
1372
1372
|
const pkList = primaryKeys.map((c) => `"${c}"`).join(", ");
|
|
1373
1373
|
const setClause = updateCols.length > 0 ? updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ") : `"${primaryKeys[0]}" = EXCLUDED."${primaryKeys[0]}"`;
|
|
1374
|
-
const whereClause = conflictColumn && updateCols.includes(conflictColumn) ? ` WHERE "${table}"."${conflictColumn}" IS NULL OR EXCLUDED."${conflictColumn}" >= "${table}"."${conflictColumn}"` : "";
|
|
1375
1374
|
const sql = `INSERT INTO "${table}" (${colList}) VALUES ${valuePlaceholders}
|
|
1376
|
-
ON CONFLICT (${pkList}) DO UPDATE SET ${setClause}
|
|
1375
|
+
ON CONFLICT (${pkList}) DO UPDATE SET ${setClause}`;
|
|
1377
1376
|
const params = batch.flatMap((row) => columns.map((c) => row[c] ?? null));
|
|
1378
1377
|
await target.run(sql, ...params);
|
|
1379
1378
|
}
|
|
1380
|
-
function batchUpsertSqlite(target, table, columns, updateCols, primaryKeys, batch
|
|
1379
|
+
function batchUpsertSqlite(target, table, columns, updateCols, primaryKeys, batch) {
|
|
1381
1380
|
if (batch.length === 0)
|
|
1382
1381
|
return;
|
|
1383
1382
|
const colList = columns.map((c) => `"${c}"`).join(", ");
|
|
1384
1383
|
const valuePlaceholders = batch.map(() => `(${columns.map(() => "?").join(", ")})`).join(", ");
|
|
1385
1384
|
const pkList = primaryKeys.map((c) => `"${c}"`).join(", ");
|
|
1386
1385
|
const setClause = updateCols.length > 0 ? updateCols.map((c) => `"${c}" = EXCLUDED."${c}"`).join(", ") : `"${primaryKeys[0]}" = EXCLUDED."${primaryKeys[0]}"`;
|
|
1387
|
-
const whereClause = conflictColumn && updateCols.includes(conflictColumn) ? ` WHERE "${table}"."${conflictColumn}" IS NULL OR EXCLUDED."${conflictColumn}" >= "${table}"."${conflictColumn}"` : "";
|
|
1388
1386
|
const sql = `INSERT INTO "${table}" (${colList}) VALUES ${valuePlaceholders}
|
|
1389
|
-
ON CONFLICT (${pkList}) DO UPDATE SET ${setClause}
|
|
1387
|
+
ON CONFLICT (${pkList}) DO UPDATE SET ${setClause}`;
|
|
1390
1388
|
const params = batch.flatMap((row) => columns.map((c) => coerceForSqlite(row[c])));
|
|
1391
1389
|
target.run(sql, ...params);
|
|
1392
1390
|
}
|
|
@@ -1611,7 +1609,7 @@ class SyncProgressTracker {
|
|
|
1611
1609
|
}
|
|
1612
1610
|
}
|
|
1613
1611
|
}
|
|
1614
|
-
function registerCloudTools(server, serviceName
|
|
1612
|
+
function registerCloudTools(server, serviceName) {
|
|
1615
1613
|
server.tool(`${serviceName}_cloud_status`, "Show cloud configuration and connection health", {}, async () => {
|
|
1616
1614
|
const config = getCloudConfig();
|
|
1617
1615
|
const lines = [
|
|
@@ -1644,13 +1642,8 @@ function registerCloudTools(server, serviceName, opts = {}) {
|
|
|
1644
1642
|
isError: true
|
|
1645
1643
|
};
|
|
1646
1644
|
}
|
|
1647
|
-
const local = new SqliteAdapter(
|
|
1645
|
+
const local = new SqliteAdapter(getDbPath(serviceName));
|
|
1648
1646
|
const cloud = new PgAdapterAsync(getConnectionString(serviceName));
|
|
1649
|
-
if (opts.migrations?.length) {
|
|
1650
|
-
for (const sql of opts.migrations) {
|
|
1651
|
-
await cloud.run(sql);
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
1647
|
const tableList = tablesStr ? tablesStr.split(",").map((t) => t.trim()) : listSqliteTables(local);
|
|
1655
1648
|
const results = await syncPush(local, cloud, { tables: tableList });
|
|
1656
1649
|
local.close();
|
|
@@ -1672,7 +1665,7 @@ function registerCloudTools(server, serviceName, opts = {}) {
|
|
|
1672
1665
|
isError: true
|
|
1673
1666
|
};
|
|
1674
1667
|
}
|
|
1675
|
-
const local = new SqliteAdapter(
|
|
1668
|
+
const local = new SqliteAdapter(getDbPath(serviceName));
|
|
1676
1669
|
const cloud = new PgAdapterAsync(getConnectionString(serviceName));
|
|
1677
1670
|
let tableList;
|
|
1678
1671
|
if (tablesStr) {
|
|
@@ -9977,7 +9970,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
9977
9970
|
__export2(exports_discover, {
|
|
9978
9971
|
isSyncExcludedTable: () => isSyncExcludedTable,
|
|
9979
9972
|
getServiceDbPath: () => getServiceDbPath,
|
|
9980
|
-
discoverSyncableServices: () =>
|
|
9973
|
+
discoverSyncableServices: () => discoverSyncableServices2,
|
|
9981
9974
|
discoverServices: () => discoverServices,
|
|
9982
9975
|
SYNC_EXCLUDED_TABLE_PATTERNS: () => SYNC_EXCLUDED_TABLE_PATTERNS,
|
|
9983
9976
|
KNOWN_PG_SERVICES: () => KNOWN_PG_SERVICES
|
|
@@ -10032,15 +10025,13 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
10032
10025
|
init_config();
|
|
10033
10026
|
init_config();
|
|
10034
10027
|
init_dotfile();
|
|
10035
|
-
init_adapter();
|
|
10036
10028
|
init_config();
|
|
10037
|
-
|
|
10038
|
-
AUTO_SYNC_CONFIG_PATH = join4(homedir4(), ".hasna", "cloud", "config.json");
|
|
10029
|
+
AUTO_SYNC_CONFIG_PATH = join3(homedir3(), ".hasna", "cloud", "config.json");
|
|
10039
10030
|
init_config();
|
|
10040
10031
|
init_adapter();
|
|
10041
10032
|
init_dotfile();
|
|
10042
10033
|
init_config();
|
|
10043
|
-
CONFIG_DIR2 =
|
|
10034
|
+
CONFIG_DIR2 = join5(homedir4(), ".hasna", "cloud");
|
|
10044
10035
|
init_adapter();
|
|
10045
10036
|
init_config();
|
|
10046
10037
|
init_discover();
|
|
@@ -10054,15 +10045,15 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
10054
10045
|
});
|
|
10055
10046
|
|
|
10056
10047
|
// src/db/database.ts
|
|
10057
|
-
import { copyFileSync as copyFileSync2, existsSync as
|
|
10048
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync5, mkdirSync as mkdirSync3, readdirSync as readdirSync2, statSync } from "fs";
|
|
10058
10049
|
import { dirname as dirname2, join as join7, resolve } from "path";
|
|
10059
10050
|
function getDataDir2() {
|
|
10060
10051
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
10061
10052
|
const newDir = join7(home, ".hasna", "contacts");
|
|
10062
10053
|
const oldDir = join7(home, ".contacts");
|
|
10063
|
-
if (
|
|
10054
|
+
if (existsSync5(oldDir) && !existsSync5(newDir)) {
|
|
10064
10055
|
mkdirSync3(newDir, { recursive: true });
|
|
10065
|
-
for (const file of
|
|
10056
|
+
for (const file of readdirSync2(oldDir)) {
|
|
10066
10057
|
const oldPath = join7(oldDir, file);
|
|
10067
10058
|
if (statSync(oldPath).isFile()) {
|
|
10068
10059
|
copyFileSync2(oldPath, join7(newDir, file));
|
|
@@ -10083,7 +10074,7 @@ function ensureDir(filePath) {
|
|
|
10083
10074
|
if (filePath === ":memory:")
|
|
10084
10075
|
return;
|
|
10085
10076
|
const dir = dirname2(resolve(filePath));
|
|
10086
|
-
if (!
|
|
10077
|
+
if (!existsSync5(dir))
|
|
10087
10078
|
mkdirSync3(dir, { recursive: true });
|
|
10088
10079
|
}
|
|
10089
10080
|
function getDatabase(path) {
|
|
@@ -11431,13 +11422,13 @@ var init_events = __esm(() => {
|
|
|
11431
11422
|
// src/mcp/index.ts
|
|
11432
11423
|
init_dist();
|
|
11433
11424
|
import { readFileSync as readFileSync6 } from "fs";
|
|
11434
|
-
import { join as
|
|
11425
|
+
import { join as join11 } from "path";
|
|
11435
11426
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11436
11427
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11437
11428
|
|
|
11438
11429
|
// src/lib/connector.ts
|
|
11439
|
-
import { join as
|
|
11440
|
-
import { existsSync as
|
|
11430
|
+
import { join as join4 } from "path";
|
|
11431
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
11441
11432
|
import { homedir as homedir6 } from "os";
|
|
11442
11433
|
|
|
11443
11434
|
class ConnectorNotInstalledError extends Error {
|
|
@@ -11506,12 +11497,12 @@ async function runConnector(name, args, opts = {}) {
|
|
|
11506
11497
|
}
|
|
11507
11498
|
function getConnectorTokenPath(name, profile = "default") {
|
|
11508
11499
|
const bases = [
|
|
11509
|
-
|
|
11510
|
-
|
|
11511
|
-
|
|
11500
|
+
join4(homedir6(), ".connectors", `connect-${name}`, "profiles", profile, "tokens.json"),
|
|
11501
|
+
join4(homedir6(), ".connect", `connect-${name}`, "profiles", profile, "tokens.json"),
|
|
11502
|
+
join4(homedir6(), ".connect", `connect-${name}`, "tokens.json")
|
|
11512
11503
|
];
|
|
11513
11504
|
for (const p of bases) {
|
|
11514
|
-
if (
|
|
11505
|
+
if (existsSync3(p))
|
|
11515
11506
|
return p;
|
|
11516
11507
|
}
|
|
11517
11508
|
return null;
|
|
@@ -15322,9 +15313,9 @@ function getCoverageGaps(companyId, db) {
|
|
|
15322
15313
|
|
|
15323
15314
|
// src/lib/images.ts
|
|
15324
15315
|
init_database();
|
|
15325
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync5, copyFileSync as copyFileSync3, unlinkSync, readdirSync as
|
|
15326
|
-
import { join as
|
|
15327
|
-
var IMAGES_DIR =
|
|
15316
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, copyFileSync as copyFileSync3, unlinkSync, readdirSync as readdirSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
15317
|
+
import { join as join9, extname, basename } from "path";
|
|
15318
|
+
var IMAGES_DIR = join9(getDataDir2(), "images");
|
|
15328
15319
|
function ensureImagesDir() {
|
|
15329
15320
|
if (!existsSync7(IMAGES_DIR))
|
|
15330
15321
|
mkdirSync5(IMAGES_DIR, { recursive: true });
|
|
@@ -15337,14 +15328,14 @@ function saveImage(entityId, source, options) {
|
|
|
15337
15328
|
const ext2 = base64Match[1] === "jpeg" ? "jpg" : base64Match[1];
|
|
15338
15329
|
const data = Buffer.from(base64Match[2], "base64");
|
|
15339
15330
|
const filename2 = `${entityId}.${ext2}`;
|
|
15340
|
-
writeFileSync2(
|
|
15331
|
+
writeFileSync2(join9(IMAGES_DIR, filename2), data);
|
|
15341
15332
|
return filename2;
|
|
15342
15333
|
}
|
|
15343
15334
|
if (!existsSync7(source) && /^[A-Za-z0-9+/=\n\r]+$/.test(source.trim()) && source.length > 100) {
|
|
15344
15335
|
const ext2 = options?.format || "jpg";
|
|
15345
15336
|
const data = Buffer.from(source.trim(), "base64");
|
|
15346
15337
|
const filename2 = `${entityId}.${ext2}`;
|
|
15347
|
-
writeFileSync2(
|
|
15338
|
+
writeFileSync2(join9(IMAGES_DIR, filename2), data);
|
|
15348
15339
|
return filename2;
|
|
15349
15340
|
}
|
|
15350
15341
|
if (!existsSync7(source)) {
|
|
@@ -15356,14 +15347,14 @@ function saveImage(entityId, source, options) {
|
|
|
15356
15347
|
throw new Error(`Unsupported image format: ${ext}. Supported: ${validExts.join(", ")}`);
|
|
15357
15348
|
}
|
|
15358
15349
|
const filename = `${entityId}.${ext === "jpeg" ? "jpg" : ext}`;
|
|
15359
|
-
copyFileSync3(source,
|
|
15350
|
+
copyFileSync3(source, join9(IMAGES_DIR, filename));
|
|
15360
15351
|
return filename;
|
|
15361
15352
|
}
|
|
15362
15353
|
function getImagePath(entityId) {
|
|
15363
15354
|
ensureImagesDir();
|
|
15364
|
-
const files =
|
|
15355
|
+
const files = readdirSync4(IMAGES_DIR);
|
|
15365
15356
|
const match = files.find((f) => f.startsWith(`${entityId}.`));
|
|
15366
|
-
return match ?
|
|
15357
|
+
return match ? join9(IMAGES_DIR, match) : null;
|
|
15367
15358
|
}
|
|
15368
15359
|
function getImageAsBase64(entityId) {
|
|
15369
15360
|
const path = getImagePath(entityId);
|
|
@@ -15376,11 +15367,11 @@ function getImageAsBase64(entityId) {
|
|
|
15376
15367
|
}
|
|
15377
15368
|
function deleteImage(entityId) {
|
|
15378
15369
|
ensureImagesDir();
|
|
15379
|
-
const files =
|
|
15370
|
+
const files = readdirSync4(IMAGES_DIR);
|
|
15380
15371
|
let deleted = false;
|
|
15381
15372
|
for (const f of files) {
|
|
15382
15373
|
if (f.startsWith(`${entityId}.`)) {
|
|
15383
|
-
unlinkSync(
|
|
15374
|
+
unlinkSync(join9(IMAGES_DIR, f));
|
|
15384
15375
|
deleted = true;
|
|
15385
15376
|
}
|
|
15386
15377
|
}
|
|
@@ -15389,13 +15380,13 @@ function deleteImage(entityId) {
|
|
|
15389
15380
|
|
|
15390
15381
|
// src/lib/vault.ts
|
|
15391
15382
|
init_database();
|
|
15392
|
-
import { existsSync as
|
|
15393
|
-
import { join as
|
|
15383
|
+
import { existsSync as existsSync9, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync6, unlinkSync as unlinkSync2 } from "fs";
|
|
15384
|
+
import { join as join10 } from "path";
|
|
15394
15385
|
import { createCipheriv, createDecipheriv, randomBytes, pbkdf2Sync, createHash } from "crypto";
|
|
15395
15386
|
var VAULT_DIR = getDataDir2();
|
|
15396
|
-
var VAULT_CONFIG =
|
|
15397
|
-
var VAULT_SESSION =
|
|
15398
|
-
var DOCUMENTS_DIR =
|
|
15387
|
+
var VAULT_CONFIG = join10(VAULT_DIR, "vault.json");
|
|
15388
|
+
var VAULT_SESSION = join10(VAULT_DIR, ".vault-session");
|
|
15389
|
+
var DOCUMENTS_DIR = join10(VAULT_DIR, "documents");
|
|
15399
15390
|
var SESSION_TTL_MS = 30 * 60 * 1000;
|
|
15400
15391
|
var _derivedKey = null;
|
|
15401
15392
|
function deriveKey(passphrase, salt) {
|
|
@@ -15409,7 +15400,7 @@ function saveSession(key) {
|
|
|
15409
15400
|
writeFileSync3(VAULT_SESSION, JSON.stringify(session), { mode: 384 });
|
|
15410
15401
|
}
|
|
15411
15402
|
function loadSession() {
|
|
15412
|
-
if (!
|
|
15403
|
+
if (!existsSync9(VAULT_SESSION))
|
|
15413
15404
|
return null;
|
|
15414
15405
|
try {
|
|
15415
15406
|
const session = JSON.parse(readFileSync4(VAULT_SESSION, "utf-8"));
|
|
@@ -15426,14 +15417,14 @@ function loadSession() {
|
|
|
15426
15417
|
}
|
|
15427
15418
|
function clearSession() {
|
|
15428
15419
|
try {
|
|
15429
|
-
if (
|
|
15420
|
+
if (existsSync9(VAULT_SESSION))
|
|
15430
15421
|
unlinkSync2(VAULT_SESSION);
|
|
15431
15422
|
} catch {}
|
|
15432
15423
|
}
|
|
15433
15424
|
function initVault(passphrase) {
|
|
15434
|
-
if (!
|
|
15425
|
+
if (!existsSync9(VAULT_DIR))
|
|
15435
15426
|
mkdirSync6(VAULT_DIR, { recursive: true });
|
|
15436
|
-
if (!
|
|
15427
|
+
if (!existsSync9(DOCUMENTS_DIR))
|
|
15437
15428
|
mkdirSync6(DOCUMENTS_DIR, { recursive: true });
|
|
15438
15429
|
const salt = randomBytes(32);
|
|
15439
15430
|
const key = deriveKey(passphrase, salt);
|
|
@@ -15444,10 +15435,10 @@ function initVault(passphrase) {
|
|
|
15444
15435
|
saveSession(key);
|
|
15445
15436
|
}
|
|
15446
15437
|
function isVaultInitialized() {
|
|
15447
|
-
return
|
|
15438
|
+
return existsSync9(VAULT_CONFIG);
|
|
15448
15439
|
}
|
|
15449
15440
|
function unlockVault(passphrase) {
|
|
15450
|
-
if (!
|
|
15441
|
+
if (!existsSync9(VAULT_CONFIG))
|
|
15451
15442
|
throw new Error("Vault not initialized. Run 'contacts vault init' first.");
|
|
15452
15443
|
const config = JSON.parse(readFileSync4(VAULT_CONFIG, "utf-8"));
|
|
15453
15444
|
const salt = Buffer.from(config.salt, "hex");
|
|
@@ -15504,10 +15495,10 @@ function decrypt(ciphertext, iv) {
|
|
|
15504
15495
|
return decrypted;
|
|
15505
15496
|
}
|
|
15506
15497
|
function storeFile(sourcePath, entityId) {
|
|
15507
|
-
if (!
|
|
15498
|
+
if (!existsSync9(DOCUMENTS_DIR))
|
|
15508
15499
|
mkdirSync6(DOCUMENTS_DIR, { recursive: true });
|
|
15509
15500
|
const ext = sourcePath.split(".").pop() || "bin";
|
|
15510
|
-
const destPath =
|
|
15501
|
+
const destPath = join10(DOCUMENTS_DIR, `${entityId}.${ext}`);
|
|
15511
15502
|
const data = readFileSync4(sourcePath);
|
|
15512
15503
|
writeFileSync3(destPath, data);
|
|
15513
15504
|
return destPath;
|
|
@@ -15515,7 +15506,7 @@ function storeFile(sourcePath, entityId) {
|
|
|
15515
15506
|
|
|
15516
15507
|
// src/db/documents.ts
|
|
15517
15508
|
init_database();
|
|
15518
|
-
import { existsSync as
|
|
15509
|
+
import { existsSync as existsSync10, unlinkSync as unlinkSync3 } from "fs";
|
|
15519
15510
|
var DOCUMENT_TYPES = [
|
|
15520
15511
|
"passport",
|
|
15521
15512
|
"national_id",
|
|
@@ -15572,7 +15563,7 @@ function listDocuments(contactId, db) {
|
|
|
15572
15563
|
function deleteDocument(id, db) {
|
|
15573
15564
|
const _db2 = db || getDatabase();
|
|
15574
15565
|
const row = _db2.query(`SELECT encrypted_file_path FROM contact_documents WHERE id = ?`).get(id);
|
|
15575
|
-
if (row?.encrypted_file_path &&
|
|
15566
|
+
if (row?.encrypted_file_path && existsSync10(row.encrypted_file_path)) {
|
|
15576
15567
|
try {
|
|
15577
15568
|
unlinkSync3(row.encrypted_file_path);
|
|
15578
15569
|
} catch {}
|
|
@@ -15690,7 +15681,7 @@ function deleteHealthData(contactId, db) {
|
|
|
15690
15681
|
}
|
|
15691
15682
|
|
|
15692
15683
|
// src/lib/document-scanner.ts
|
|
15693
|
-
import { readFileSync as readFileSync5, existsSync as
|
|
15684
|
+
import { readFileSync as readFileSync5, existsSync as existsSync11 } from "fs";
|
|
15694
15685
|
import { extname as extname2 } from "path";
|
|
15695
15686
|
async function scanDocument(imageSource, docType) {
|
|
15696
15687
|
const apiKey = process.env["OPENAI_API_KEY"];
|
|
@@ -15700,7 +15691,7 @@ async function scanDocument(imageSource, docType) {
|
|
|
15700
15691
|
let imageData;
|
|
15701
15692
|
if (imageSource.startsWith("data:image/")) {
|
|
15702
15693
|
imageData = imageSource;
|
|
15703
|
-
} else if (
|
|
15694
|
+
} else if (existsSync11(imageSource)) {
|
|
15704
15695
|
const buffer = readFileSync5(imageSource);
|
|
15705
15696
|
const ext = extname2(imageSource).slice(1).toLowerCase();
|
|
15706
15697
|
const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "png" ? "image/png" : ext === "webp" ? "image/webp" : ext === "gif" ? "image/gif" : "image/jpeg";
|
|
@@ -21983,7 +21974,7 @@ function startMcpHttpServer(options) {
|
|
|
21983
21974
|
// src/mcp/index.ts
|
|
21984
21975
|
function getServerVersion() {
|
|
21985
21976
|
try {
|
|
21986
|
-
const packageJsonPath =
|
|
21977
|
+
const packageJsonPath = join11(import.meta.dir, "..", "..", "package.json");
|
|
21987
21978
|
const pkg = JSON.parse(readFileSync6(packageJsonPath, "utf8"));
|
|
21988
21979
|
return pkg.version ?? "0.0.0";
|
|
21989
21980
|
} catch {
|