context-vault 3.1.7 → 3.2.0
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/bin/cli.js +11 -11
- package/dist/archive.d.ts +23 -0
- package/dist/archive.d.ts.map +1 -0
- package/dist/archive.js +197 -0
- package/dist/archive.js.map +1 -0
- package/dist/consolidation.d.ts +14 -0
- package/dist/consolidation.d.ts.map +1 -0
- package/dist/consolidation.js +59 -0
- package/dist/consolidation.js.map +1 -0
- package/dist/error-log.d.ts +4 -0
- package/dist/error-log.d.ts.map +1 -0
- package/dist/error-log.js +33 -0
- package/dist/error-log.js.map +1 -0
- package/dist/helpers.d.ts +10 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +42 -0
- package/dist/helpers.js.map +1 -0
- package/dist/linking.d.ts +13 -0
- package/dist/linking.d.ts.map +1 -0
- package/dist/linking.js +86 -0
- package/dist/linking.js.map +1 -0
- package/dist/migrate-dirs.d.ts +16 -0
- package/dist/migrate-dirs.d.ts.map +1 -0
- package/dist/migrate-dirs.js +127 -0
- package/dist/migrate-dirs.js.map +1 -0
- package/dist/register-tools.d.ts +3 -0
- package/dist/register-tools.d.ts.map +1 -0
- package/dist/register-tools.js +161 -0
- package/dist/register-tools.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +241 -0
- package/dist/server.js.map +1 -0
- package/dist/status.d.ts +18 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +265 -0
- package/dist/status.js.map +1 -0
- package/dist/telemetry.d.ts +6 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +74 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/temporal.d.ts +9 -0
- package/dist/temporal.d.ts.map +1 -0
- package/dist/temporal.js +76 -0
- package/dist/temporal.js.map +1 -0
- package/dist/tools/clear-context.d.ts +11 -0
- package/dist/tools/clear-context.d.ts.map +1 -0
- package/dist/tools/clear-context.js +28 -0
- package/dist/tools/clear-context.js.map +1 -0
- package/dist/tools/context-status.d.ts +6 -0
- package/dist/tools/context-status.d.ts.map +1 -0
- package/dist/tools/context-status.js +160 -0
- package/dist/tools/context-status.js.map +1 -0
- package/dist/tools/create-snapshot.d.ts +13 -0
- package/dist/tools/create-snapshot.d.ts.map +1 -0
- package/dist/tools/create-snapshot.js +161 -0
- package/dist/tools/create-snapshot.js.map +1 -0
- package/dist/tools/delete-context.d.ts +9 -0
- package/dist/tools/delete-context.d.ts.map +1 -0
- package/dist/tools/delete-context.js +45 -0
- package/dist/tools/delete-context.js.map +1 -0
- package/dist/tools/get-context.d.ts +83 -0
- package/dist/tools/get-context.d.ts.map +1 -0
- package/dist/tools/get-context.js +598 -0
- package/dist/tools/get-context.js.map +1 -0
- package/dist/tools/ingest-project.d.ts +11 -0
- package/dist/tools/ingest-project.d.ts.map +1 -0
- package/dist/tools/ingest-project.js +226 -0
- package/dist/tools/ingest-project.js.map +1 -0
- package/dist/tools/ingest-url.d.ts +11 -0
- package/dist/tools/ingest-url.d.ts.map +1 -0
- package/dist/tools/ingest-url.js +62 -0
- package/dist/tools/ingest-url.js.map +1 -0
- package/dist/tools/list-buckets.d.ts +9 -0
- package/dist/tools/list-buckets.d.ts.map +1 -0
- package/dist/tools/list-buckets.js +76 -0
- package/dist/tools/list-buckets.js.map +1 -0
- package/dist/tools/list-context.d.ts +19 -0
- package/dist/tools/list-context.d.ts.map +1 -0
- package/dist/tools/list-context.js +110 -0
- package/dist/tools/list-context.js.map +1 -0
- package/dist/tools/save-context.d.ts +36 -0
- package/dist/tools/save-context.d.ts.map +1 -0
- package/dist/tools/save-context.js +466 -0
- package/dist/tools/save-context.js.map +1 -0
- package/dist/tools/session-start.d.ts +11 -0
- package/dist/tools/session-start.d.ts.map +1 -0
- package/dist/tools/session-start.js +224 -0
- package/dist/tools/session-start.js.map +1 -0
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/node_modules/@context-vault/core/dist/constants.d.ts +1 -1
- package/node_modules/@context-vault/core/dist/constants.d.ts.map +1 -1
- package/node_modules/@context-vault/core/dist/constants.js +1 -1
- package/node_modules/@context-vault/core/dist/constants.js.map +1 -1
- package/node_modules/@context-vault/core/dist/search.d.ts +2 -1
- package/node_modules/@context-vault/core/dist/search.d.ts.map +1 -1
- package/node_modules/@context-vault/core/dist/search.js +6 -2
- package/node_modules/@context-vault/core/dist/search.js.map +1 -1
- package/node_modules/@context-vault/core/dist/types.d.ts +1 -0
- package/node_modules/@context-vault/core/dist/types.d.ts.map +1 -1
- package/node_modules/@context-vault/core/package.json +1 -1
- package/node_modules/@context-vault/core/src/constants.ts +1 -1
- package/node_modules/@context-vault/core/src/search.ts +7 -0
- package/node_modules/@context-vault/core/src/types.ts +1 -0
- package/package.json +10 -4
- package/src/{archive.js → archive.ts} +63 -30
- package/src/consolidation.ts +78 -0
- package/src/{error-log.js → error-log.ts} +3 -3
- package/src/{helpers.js → helpers.ts} +11 -5
- package/src/{linking.js → linking.ts} +14 -9
- package/src/{migrate-dirs.js → migrate-dirs.ts} +21 -8
- package/src/{register-tools.js → register-tools.ts} +21 -11
- package/src/{server.js → server.ts} +26 -20
- package/src/{status.js → status.ts} +60 -38
- package/src/{telemetry.js → telemetry.ts} +8 -4
- package/src/{temporal.js → temporal.ts} +10 -3
- package/src/tools/{clear-context.js → clear-context.ts} +2 -5
- package/src/tools/{context-status.js → context-status.ts} +6 -9
- package/src/tools/{create-snapshot.js → create-snapshot.ts} +11 -10
- package/src/tools/{delete-context.js → delete-context.ts} +9 -9
- package/src/tools/{get-context.js → get-context.ts} +72 -62
- package/src/tools/{ingest-project.js → ingest-project.ts} +19 -11
- package/src/tools/{ingest-url.js → ingest-url.ts} +11 -8
- package/src/tools/{list-buckets.js → list-buckets.ts} +11 -15
- package/src/tools/{list-context.js → list-context.ts} +13 -15
- package/src/tools/{save-context.js → save-context.ts} +54 -42
- package/src/tools/{session-start.js → session-start.ts} +29 -20
- package/src/types.ts +29 -0
package/bin/cli.js
CHANGED
|
@@ -34,7 +34,7 @@ const HOME = homedir();
|
|
|
34
34
|
|
|
35
35
|
const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
|
|
36
36
|
const VERSION = pkg.version;
|
|
37
|
-
const SERVER_PATH = resolve(ROOT, '
|
|
37
|
+
const SERVER_PATH = resolve(ROOT, 'dist', 'server.js');
|
|
38
38
|
|
|
39
39
|
/** Detect if running as an npm-installed package (global or local) vs local dev clone */
|
|
40
40
|
function isInstalledPackage() {
|
|
@@ -1707,7 +1707,7 @@ async function runMigrateDirs() {
|
|
|
1707
1707
|
process.exit(1);
|
|
1708
1708
|
}
|
|
1709
1709
|
|
|
1710
|
-
const { planMigration, executeMigration } = await import('../
|
|
1710
|
+
const { planMigration, executeMigration } = await import('../dist/migrate-dirs.js');
|
|
1711
1711
|
|
|
1712
1712
|
const ops = planMigration(vaultDir);
|
|
1713
1713
|
|
|
@@ -1822,7 +1822,7 @@ async function runArchive() {
|
|
|
1822
1822
|
const { resolveConfig } = await import('@context-vault/core/config');
|
|
1823
1823
|
const { initDatabase, prepareStatements, insertVec, deleteVec } =
|
|
1824
1824
|
await import('@context-vault/core/db');
|
|
1825
|
-
const { findArchiveCandidates, archiveEntries } = await import('../
|
|
1825
|
+
const { findArchiveCandidates, archiveEntries } = await import('../dist/archive.js');
|
|
1826
1826
|
|
|
1827
1827
|
const config = resolveConfig();
|
|
1828
1828
|
if (!config.vaultDirExists) {
|
|
@@ -1899,7 +1899,7 @@ async function runRestore() {
|
|
|
1899
1899
|
|
|
1900
1900
|
if (!entryId || entryId.startsWith('--')) {
|
|
1901
1901
|
const { resolveConfig } = await import('@context-vault/core/config');
|
|
1902
|
-
const { listArchivedEntries } = await import('../
|
|
1902
|
+
const { listArchivedEntries } = await import('../dist/archive.js');
|
|
1903
1903
|
|
|
1904
1904
|
const config = resolveConfig();
|
|
1905
1905
|
|
|
@@ -1929,7 +1929,7 @@ async function runRestore() {
|
|
|
1929
1929
|
const { initDatabase, prepareStatements, insertVec, deleteVec } =
|
|
1930
1930
|
await import('@context-vault/core/db');
|
|
1931
1931
|
const { embed } = await import('@context-vault/core/embed');
|
|
1932
|
-
const { restoreEntry } = await import('../
|
|
1932
|
+
const { restoreEntry } = await import('../dist/archive.js');
|
|
1933
1933
|
|
|
1934
1934
|
const config = resolveConfig();
|
|
1935
1935
|
if (!config.vaultDirExists) {
|
|
@@ -1964,8 +1964,8 @@ async function runRestore() {
|
|
|
1964
1964
|
async function runStatus() {
|
|
1965
1965
|
const { resolveConfig } = await import('@context-vault/core/config');
|
|
1966
1966
|
const { initDatabase } = await import('@context-vault/core/db');
|
|
1967
|
-
const { gatherVaultStatus } = await import('../
|
|
1968
|
-
const { errorLogPath, errorLogCount } = await import('../
|
|
1967
|
+
const { gatherVaultStatus } = await import('../dist/status.js');
|
|
1968
|
+
const { errorLogPath, errorLogCount } = await import('../dist/error-log.js');
|
|
1969
1969
|
|
|
1970
1970
|
const config = resolveConfig();
|
|
1971
1971
|
|
|
@@ -4357,7 +4357,7 @@ ${bold('Commands:')}
|
|
|
4357
4357
|
|
|
4358
4358
|
async function runDoctor() {
|
|
4359
4359
|
const { resolveConfig } = await import('@context-vault/core/config');
|
|
4360
|
-
const { errorLogPath, errorLogCount } = await import('../
|
|
4360
|
+
const { errorLogPath, errorLogCount } = await import('../dist/error-log.js');
|
|
4361
4361
|
|
|
4362
4362
|
console.log();
|
|
4363
4363
|
console.log(` ${bold('◇ context-vault doctor')} ${dim(`v${VERSION}`)}`);
|
|
@@ -4966,7 +4966,7 @@ async function runConsolidate() {
|
|
|
4966
4966
|
|
|
4967
4967
|
const { resolveConfig } = await import('@context-vault/core/config');
|
|
4968
4968
|
const { initDatabase } = await import('@context-vault/core/db');
|
|
4969
|
-
const { findHotTags, findColdEntries } = await import('
|
|
4969
|
+
const { findHotTags, findColdEntries } = await import('../dist/consolidation.js');
|
|
4970
4970
|
|
|
4971
4971
|
const config = resolveConfig();
|
|
4972
4972
|
|
|
@@ -5070,7 +5070,7 @@ async function runConsolidate() {
|
|
|
5070
5070
|
|
|
5071
5071
|
async function runDebug() {
|
|
5072
5072
|
const { resolveConfig } = await import('@context-vault/core/config');
|
|
5073
|
-
const { errorLogPath, errorLogCount } = await import('../
|
|
5073
|
+
const { errorLogPath, errorLogCount } = await import('../dist/error-log.js');
|
|
5074
5074
|
|
|
5075
5075
|
let config;
|
|
5076
5076
|
try {
|
|
@@ -5146,7 +5146,7 @@ async function runDebug() {
|
|
|
5146
5146
|
}
|
|
5147
5147
|
|
|
5148
5148
|
async function runServe() {
|
|
5149
|
-
await import('../
|
|
5149
|
+
await import('../dist/server.js');
|
|
5150
5150
|
}
|
|
5151
5151
|
|
|
5152
5152
|
async function main() {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { LocalCtx } from './types.js';
|
|
2
|
+
export declare function findArchiveCandidates(ctx: LocalCtx): unknown[];
|
|
3
|
+
export declare function archiveEntries(ctx: LocalCtx): Promise<{
|
|
4
|
+
archived: unknown[];
|
|
5
|
+
count: number;
|
|
6
|
+
}>;
|
|
7
|
+
export declare function restoreEntry(ctx: LocalCtx, entryId: string): Promise<{
|
|
8
|
+
restored: boolean;
|
|
9
|
+
reason?: string;
|
|
10
|
+
filePath?: string;
|
|
11
|
+
kind?: string;
|
|
12
|
+
id?: string;
|
|
13
|
+
}>;
|
|
14
|
+
export declare function countArchivedEntries(vaultDir: string): number;
|
|
15
|
+
export declare function listArchivedEntries(vaultDir: string): Array<{
|
|
16
|
+
id: string | null;
|
|
17
|
+
kind: string;
|
|
18
|
+
title: string;
|
|
19
|
+
tags: unknown[];
|
|
20
|
+
created: string | null;
|
|
21
|
+
filePath: string;
|
|
22
|
+
}>;
|
|
23
|
+
//# sourceMappingURL=archive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAc3C,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,EAAE,CAmC9D;AAYD,wBAAsB,cAAc,CAClC,GAAG,EAAE,QAAQ,GACZ,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA0CjD;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,QAAQ,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA2EhG;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ7D;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC;IAC3D,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAgCD"}
|
package/dist/archive.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, renameSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join, dirname, relative } from 'node:path';
|
|
3
|
+
import { categoryFor, defaultTierFor } from '@context-vault/core/categories';
|
|
4
|
+
import { parseFrontmatter, parseEntryFromMarkdown } from '@context-vault/core/frontmatter';
|
|
5
|
+
import { DEFAULT_LIFECYCLE } from '@context-vault/core/constants';
|
|
6
|
+
import { walkDir } from '@context-vault/core/files';
|
|
7
|
+
import { indexEntry } from '@context-vault/core/index';
|
|
8
|
+
const VALID_TIERS = new Set(['ephemeral', 'working', 'durable']);
|
|
9
|
+
const VALID_CATEGORIES = new Set(['knowledge', 'entity', 'event']);
|
|
10
|
+
function resolveLifecycle(config) {
|
|
11
|
+
return config?.lifecycle ?? structuredClone(DEFAULT_LIFECYCLE);
|
|
12
|
+
}
|
|
13
|
+
function archiveDir(vaultDir) {
|
|
14
|
+
return join(vaultDir, '_archive');
|
|
15
|
+
}
|
|
16
|
+
export function findArchiveCandidates(ctx) {
|
|
17
|
+
const lifecycle = resolveLifecycle(ctx.config);
|
|
18
|
+
const now = new Date();
|
|
19
|
+
const candidates = [];
|
|
20
|
+
const seen = new Set();
|
|
21
|
+
for (const [key, rules] of Object.entries(lifecycle)) {
|
|
22
|
+
if (!rules?.archiveAfterDays)
|
|
23
|
+
continue;
|
|
24
|
+
const cutoff = new Date(now.getTime() - rules.archiveAfterDays * 86400000).toISOString();
|
|
25
|
+
const isTier = VALID_TIERS.has(key);
|
|
26
|
+
const isCategory = VALID_CATEGORIES.has(key);
|
|
27
|
+
if (!isTier && !isCategory)
|
|
28
|
+
continue;
|
|
29
|
+
const column = isTier ? 'tier' : 'category';
|
|
30
|
+
const rows = ctx.db
|
|
31
|
+
.prepare(`SELECT id, kind, category, title, tier, file_path, created_at, updated_at
|
|
32
|
+
FROM vault
|
|
33
|
+
WHERE ${column} = ? AND COALESCE(updated_at, created_at) <= ?
|
|
34
|
+
ORDER BY COALESCE(updated_at, created_at) ASC`)
|
|
35
|
+
.all(key, cutoff);
|
|
36
|
+
for (const row of rows) {
|
|
37
|
+
if (seen.has(row.id))
|
|
38
|
+
continue;
|
|
39
|
+
seen.add(row.id);
|
|
40
|
+
candidates.push({
|
|
41
|
+
...row,
|
|
42
|
+
reason: `${column}=${key}, archiveAfterDays=${rules.archiveAfterDays}`,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return candidates;
|
|
47
|
+
}
|
|
48
|
+
function removeFromIndex(ctx, id) {
|
|
49
|
+
const rowidRow = ctx.stmts.getRowid.get(id);
|
|
50
|
+
if (rowidRow?.rowid) {
|
|
51
|
+
try {
|
|
52
|
+
ctx.deleteVec(Number(rowidRow.rowid));
|
|
53
|
+
}
|
|
54
|
+
catch { }
|
|
55
|
+
}
|
|
56
|
+
ctx.stmts.deleteEntry.run(id);
|
|
57
|
+
}
|
|
58
|
+
export async function archiveEntries(ctx) {
|
|
59
|
+
const candidates = findArchiveCandidates(ctx);
|
|
60
|
+
if (candidates.length === 0)
|
|
61
|
+
return { archived: candidates, count: 0 };
|
|
62
|
+
const vaultDir = ctx.config.vaultDir;
|
|
63
|
+
const archRoot = archiveDir(vaultDir);
|
|
64
|
+
let count = 0;
|
|
65
|
+
for (const entry of candidates) {
|
|
66
|
+
const filePath = entry.file_path;
|
|
67
|
+
if (!filePath) {
|
|
68
|
+
removeFromIndex(ctx, entry.id);
|
|
69
|
+
count++;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const rel = relative(vaultDir, filePath);
|
|
73
|
+
if (rel.startsWith('..') || rel.startsWith('_archive'))
|
|
74
|
+
continue;
|
|
75
|
+
const destPath = join(archRoot, rel);
|
|
76
|
+
const destDir = dirname(destPath);
|
|
77
|
+
try {
|
|
78
|
+
mkdirSync(destDir, { recursive: true });
|
|
79
|
+
renameSync(filePath, destPath);
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
if (e.code === 'ENOENT' && !existsSync(filePath)) {
|
|
83
|
+
// File already gone — just remove from index
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
throw e;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
removeFromIndex(ctx, entry.id);
|
|
90
|
+
count++;
|
|
91
|
+
}
|
|
92
|
+
return { archived: candidates, count };
|
|
93
|
+
}
|
|
94
|
+
export async function restoreEntry(ctx, entryId) {
|
|
95
|
+
const vaultDir = ctx.config.vaultDir;
|
|
96
|
+
const archRoot = archiveDir(vaultDir);
|
|
97
|
+
if (!existsSync(archRoot)) {
|
|
98
|
+
return { restored: false, reason: 'no _archive directory' };
|
|
99
|
+
}
|
|
100
|
+
const mdFiles = walkDir(archRoot);
|
|
101
|
+
let targetFile = null;
|
|
102
|
+
for (const { filePath } of mdFiles) {
|
|
103
|
+
try {
|
|
104
|
+
const raw = readFileSync(filePath, 'utf-8');
|
|
105
|
+
const { meta } = parseFrontmatter(raw);
|
|
106
|
+
if (meta.id === entryId) {
|
|
107
|
+
targetFile = filePath;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (!targetFile) {
|
|
116
|
+
return { restored: false, reason: `entry ${entryId} not found in _archive` };
|
|
117
|
+
}
|
|
118
|
+
const rel = relative(archRoot, targetFile);
|
|
119
|
+
const destPath = join(vaultDir, rel);
|
|
120
|
+
const destDir = dirname(destPath);
|
|
121
|
+
if (existsSync(destPath)) {
|
|
122
|
+
return { restored: false, reason: `destination already exists: ${destPath}` };
|
|
123
|
+
}
|
|
124
|
+
mkdirSync(destDir, { recursive: true });
|
|
125
|
+
renameSync(targetFile, destPath);
|
|
126
|
+
const raw = readFileSync(destPath, 'utf-8');
|
|
127
|
+
const { meta, body: rawBody } = parseFrontmatter(raw);
|
|
128
|
+
const relFromVault = relative(vaultDir, destPath);
|
|
129
|
+
const kindDir = relFromVault.split('/').filter(Boolean);
|
|
130
|
+
let kind = meta.kind ||
|
|
131
|
+
(kindDir.length >= 2 ? kindDir[kindDir.length - 2] : kindDir[0]) ||
|
|
132
|
+
'note';
|
|
133
|
+
const parsed = parseEntryFromMarkdown(kind, rawBody, meta);
|
|
134
|
+
const category = categoryFor(kind);
|
|
135
|
+
await indexEntry(ctx, {
|
|
136
|
+
id: meta.id || entryId,
|
|
137
|
+
kind,
|
|
138
|
+
category,
|
|
139
|
+
title: parsed.title,
|
|
140
|
+
body: parsed.body,
|
|
141
|
+
meta: parsed.meta ?? undefined,
|
|
142
|
+
tags: Array.isArray(meta.tags) ? meta.tags : null,
|
|
143
|
+
source: meta.source || 'archive-restore',
|
|
144
|
+
filePath: destPath,
|
|
145
|
+
createdAt: meta.created || new Date().toISOString(),
|
|
146
|
+
identity_key: meta.identity_key || null,
|
|
147
|
+
expires_at: meta.expires_at || null,
|
|
148
|
+
tier: meta.tier || defaultTierFor(kind),
|
|
149
|
+
source_files: null,
|
|
150
|
+
});
|
|
151
|
+
return {
|
|
152
|
+
restored: true,
|
|
153
|
+
filePath: destPath,
|
|
154
|
+
kind,
|
|
155
|
+
id: meta.id || entryId,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
export function countArchivedEntries(vaultDir) {
|
|
159
|
+
const archRoot = archiveDir(vaultDir);
|
|
160
|
+
if (!existsSync(archRoot))
|
|
161
|
+
return 0;
|
|
162
|
+
try {
|
|
163
|
+
return walkDir(archRoot).length;
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
export function listArchivedEntries(vaultDir) {
|
|
170
|
+
const archRoot = archiveDir(vaultDir);
|
|
171
|
+
if (!existsSync(archRoot))
|
|
172
|
+
return [];
|
|
173
|
+
const entries = [];
|
|
174
|
+
try {
|
|
175
|
+
const mdFiles = walkDir(archRoot);
|
|
176
|
+
for (const { filePath, relDir } of mdFiles) {
|
|
177
|
+
try {
|
|
178
|
+
const raw = readFileSync(filePath, 'utf-8');
|
|
179
|
+
const { meta, body } = parseFrontmatter(raw);
|
|
180
|
+
entries.push({
|
|
181
|
+
id: meta.id || null,
|
|
182
|
+
kind: relDir?.split('/').pop() || 'unknown',
|
|
183
|
+
title: meta.title || body.slice(0, 80),
|
|
184
|
+
tags: Array.isArray(meta.tags) ? meta.tags : [],
|
|
185
|
+
created: meta.created || null,
|
|
186
|
+
filePath,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch { }
|
|
195
|
+
return entries;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../src/archive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
export declare function findHotTags(db: DatabaseSync, opts?: {
|
|
3
|
+
tagThreshold?: number;
|
|
4
|
+
maxSnapshotAgeDays?: number;
|
|
5
|
+
}): Array<{
|
|
6
|
+
tag: string;
|
|
7
|
+
entryCount: number;
|
|
8
|
+
lastSnapshotAge: number | null;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function findColdEntries(db: DatabaseSync, opts?: {
|
|
11
|
+
maxAgeDays?: number;
|
|
12
|
+
maxHitCount?: number;
|
|
13
|
+
}): string[];
|
|
14
|
+
//# sourceMappingURL=consolidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consolidation.d.ts","sourceRoot":"","sources":["../src/consolidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wBAAgB,WAAW,CACzB,EAAE,EAAE,YAAY,EAChB,IAAI,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAAO,GAChE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAmD5E;AAED,wBAAgB,eAAe,CAC7B,EAAE,EAAE,YAAY,EAChB,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACvD,MAAM,EAAE,CAgBV"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export function findHotTags(db, opts = {}) {
|
|
2
|
+
const tagThreshold = opts.tagThreshold ?? 10;
|
|
3
|
+
const maxSnapshotAgeDays = opts.maxSnapshotAgeDays ?? 7;
|
|
4
|
+
const cutoff = new Date(Date.now() - maxSnapshotAgeDays * 86400000).toISOString();
|
|
5
|
+
const rows = db
|
|
6
|
+
.prepare(`SELECT tags FROM vault
|
|
7
|
+
WHERE kind != 'brief'
|
|
8
|
+
AND superseded_by IS NULL
|
|
9
|
+
AND (expires_at IS NULL OR expires_at > datetime('now'))`)
|
|
10
|
+
.all();
|
|
11
|
+
const tagCounts = new Map();
|
|
12
|
+
for (const row of rows) {
|
|
13
|
+
if (!row.tags)
|
|
14
|
+
continue;
|
|
15
|
+
try {
|
|
16
|
+
const tags = JSON.parse(row.tags);
|
|
17
|
+
for (const tag of tags) {
|
|
18
|
+
tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const results = [];
|
|
26
|
+
for (const [tag, count] of tagCounts) {
|
|
27
|
+
if (count < tagThreshold)
|
|
28
|
+
continue;
|
|
29
|
+
const recentBrief = db
|
|
30
|
+
.prepare(`SELECT created_at FROM vault
|
|
31
|
+
WHERE kind = 'brief'
|
|
32
|
+
AND tags LIKE ?
|
|
33
|
+
ORDER BY created_at DESC LIMIT 1`)
|
|
34
|
+
.get(`%"${tag}"%`);
|
|
35
|
+
let lastSnapshotAge = null;
|
|
36
|
+
if (recentBrief) {
|
|
37
|
+
const brief = recentBrief;
|
|
38
|
+
lastSnapshotAge = Math.round((Date.now() - new Date(brief.created_at).getTime()) / 86400000);
|
|
39
|
+
if (brief.created_at >= cutoff)
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
results.push({ tag, entryCount: count, lastSnapshotAge });
|
|
43
|
+
}
|
|
44
|
+
return results.sort((a, b) => b.entryCount - a.entryCount);
|
|
45
|
+
}
|
|
46
|
+
export function findColdEntries(db, opts = {}) {
|
|
47
|
+
const maxAgeDays = opts.maxAgeDays ?? 90;
|
|
48
|
+
const maxHitCount = opts.maxHitCount ?? 0;
|
|
49
|
+
const cutoff = new Date(Date.now() - maxAgeDays * 86400000).toISOString();
|
|
50
|
+
const rows = db
|
|
51
|
+
.prepare(`SELECT id FROM vault
|
|
52
|
+
WHERE created_at < ?
|
|
53
|
+
AND superseded_by IS NULL
|
|
54
|
+
AND COALESCE(hit_count, 0) <= ?
|
|
55
|
+
AND (expires_at IS NULL OR expires_at > datetime('now'))`)
|
|
56
|
+
.all(cutoff, maxHitCount);
|
|
57
|
+
return rows.map((r) => r.id);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=consolidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consolidation.js","sourceRoot":"","sources":["../src/consolidation.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,WAAW,CACzB,EAAgB,EAChB,OAA+D,EAAE;IAEjE,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC;IAC7C,MAAM,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,IAAI,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,kBAAkB,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAElF,MAAM,IAAI,GAAG,EAAE;SACZ,OAAO,CACN;;;kEAG4D,CAC7D;SACA,GAAG,EAAE,CAAC;IAET,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC5C,KAAK,MAAM,GAAG,IAAI,IAAsC,EAAE,CAAC;QACzD,IAAI,CAAC,GAAG,CAAC,IAAI;YAAE,SAAS;QACxB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC;IACnB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;QACrC,IAAI,KAAK,GAAG,YAAY;YAAE,SAAS;QAEnC,MAAM,WAAW,GAAG,EAAE;aACnB,OAAO,CACN;;;0CAGkC,CACnC;aACA,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;QAErB,IAAI,eAAe,GAAkB,IAAI,CAAC;QAC1C,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,WAAqC,CAAC;YACpD,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC;YAC7F,IAAI,KAAK,CAAC,UAAU,IAAI,MAAM;gBAAE,SAAS;QAC3C,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,EAAgB,EAChB,OAAsD,EAAE;IAExD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;IACzC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAE1E,MAAM,IAAI,GAAG,EAAE;SACZ,OAAO,CACN;;;;kEAI4D,CAC7D;SACA,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAE5B,OAAQ,IAA8B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-log.d.ts","sourceRoot":"","sources":["../src/error-log.ts"],"names":[],"mappings":"AAYA,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAWpF;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUrD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync, } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const MAX_LOG_SIZE = 1024 * 1024;
|
|
4
|
+
export function errorLogPath(dataDir) {
|
|
5
|
+
return join(dataDir, 'error.log');
|
|
6
|
+
}
|
|
7
|
+
export function appendErrorLog(dataDir, entry) {
|
|
8
|
+
try {
|
|
9
|
+
mkdirSync(dataDir, { recursive: true });
|
|
10
|
+
const logPath = errorLogPath(dataDir);
|
|
11
|
+
if (existsSync(logPath) && statSync(logPath).size >= MAX_LOG_SIZE) {
|
|
12
|
+
writeFileSync(logPath, '');
|
|
13
|
+
}
|
|
14
|
+
appendFileSync(logPath, JSON.stringify(entry) + '\n');
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// intentionally swallowed
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function errorLogCount(dataDir) {
|
|
21
|
+
try {
|
|
22
|
+
const logPath = errorLogPath(dataDir);
|
|
23
|
+
if (!existsSync(logPath))
|
|
24
|
+
return 0;
|
|
25
|
+
return readFileSync(logPath, 'utf-8')
|
|
26
|
+
.split('\n')
|
|
27
|
+
.filter((l) => l.trim()).length;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=error-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-log.js","sourceRoot":"","sources":["../src/error-log.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,UAAU,EACV,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,CAAC;AAEjC,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,OAAO,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,KAA8B;IAC5E,IAAI,CAAC;QACH,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,IAAI,YAAY,EAAE,CAAC;YAClE,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC7B,CAAC;QACD,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,CAAC,CAAC;QACnC,OAAO,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC;aAClC,KAAK,CAAC,IAAI,CAAC;aACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { VaultConfig } from '@context-vault/core/types';
|
|
2
|
+
import type { ToolResult } from './types.js';
|
|
3
|
+
declare const pkg: any;
|
|
4
|
+
export declare function ok(text: string): ToolResult;
|
|
5
|
+
export declare function err(text: string, code?: string, meta?: Record<string, unknown>): ToolResult;
|
|
6
|
+
export declare function errWithHint(text: string, code: string, hint?: string): ToolResult;
|
|
7
|
+
export declare function ensureVaultExists(config: VaultConfig): ToolResult | null;
|
|
8
|
+
export declare function ensureValidKind(kind: string): ToolResult | null;
|
|
9
|
+
export { pkg };
|
|
10
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,QAAA,MAAM,GAAG,KAA2E,CAAC;AAErF,wBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAE3C;AAED,wBAAgB,GAAG,CACjB,IAAI,EAAE,MAAM,EACZ,IAAI,SAAY,EAChB,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACjC,UAAU,CAaZ;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAKjF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,UAAU,GAAG,IAAI,CASxE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAQ/D;AAED,OAAO,EAAE,GAAG,EAAE,CAAC"}
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
6
|
+
export function ok(text) {
|
|
7
|
+
return { content: [{ type: 'text', text }] };
|
|
8
|
+
}
|
|
9
|
+
export function err(text, code = 'UNKNOWN', meta = {}) {
|
|
10
|
+
return {
|
|
11
|
+
content: [{ type: 'text', text }],
|
|
12
|
+
isError: true,
|
|
13
|
+
code,
|
|
14
|
+
_meta: {
|
|
15
|
+
cv_version: pkg.version,
|
|
16
|
+
node_version: process.version,
|
|
17
|
+
platform: process.platform,
|
|
18
|
+
arch: process.arch,
|
|
19
|
+
...meta,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export function errWithHint(text, code, hint) {
|
|
24
|
+
const prompt = hint
|
|
25
|
+
? `\n\n**Debug with AI:** Paste this into Claude Code or your AI assistant:\n> "${hint}"`
|
|
26
|
+
: '';
|
|
27
|
+
return err(text + prompt, code);
|
|
28
|
+
}
|
|
29
|
+
export function ensureVaultExists(config) {
|
|
30
|
+
if (!config.vaultDirExists) {
|
|
31
|
+
return errWithHint(`Vault directory not found: ${config.vaultDir}. Run context-status for diagnostics.`, 'VAULT_NOT_FOUND', "My context-vault can't find the vault directory. Run `context-vault doctor` and help me fix it.");
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
export function ensureValidKind(kind) {
|
|
36
|
+
if (!/^[a-z][a-z0-9_-]*$/.test(kind)) {
|
|
37
|
+
return err("Required: kind (lowercase alphanumeric, e.g. 'insight', 'reference')", 'INVALID_KIND');
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
export { pkg };
|
|
42
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAErF,MAAM,UAAU,EAAE,CAAC,IAAY;IAC7B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,GAAG,CACjB,IAAY,EACZ,IAAI,GAAG,SAAS,EAChB,OAAgC,EAAE;IAElC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACjC,OAAO,EAAE,IAAI;QACb,IAAI;QACJ,KAAK,EAAE;YACL,UAAU,EAAE,GAAG,CAAC,OAAO;YACvB,YAAY,EAAE,OAAO,CAAC,OAAO;YAC7B,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,GAAG,IAAI;SACR;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,IAAY,EAAE,IAAa;IACnE,MAAM,MAAM,GAAG,IAAI;QACjB,CAAC,CAAC,gFAAgF,IAAI,GAAG;QACzF,CAAC,CAAC,EAAE,CAAC;IACP,OAAO,GAAG,CAAC,IAAI,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAmB;IACnD,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC3B,OAAO,WAAW,CAChB,8BAA8B,MAAM,CAAC,QAAQ,uCAAuC,EACpF,iBAAiB,EACjB,iGAAiG,CAClG,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,OAAO,GAAG,CACR,sEAAsE,EACtE,cAAc,CACf,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,OAAO,EAAE,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
export declare function parseRelatedTo(raw: unknown): string[];
|
|
3
|
+
export declare function resolveLinks(db: DatabaseSync, ids: string[]): any[];
|
|
4
|
+
export declare function resolveBacklinks(db: DatabaseSync, entryId: string): any[];
|
|
5
|
+
export declare function collectLinkedEntries(db: DatabaseSync, primaryEntries: Array<{
|
|
6
|
+
id: string;
|
|
7
|
+
related_to?: string | null;
|
|
8
|
+
}>): {
|
|
9
|
+
forward: any[];
|
|
10
|
+
backward: any[];
|
|
11
|
+
};
|
|
12
|
+
export declare function validateRelatedTo(relatedTo: unknown): string | null;
|
|
13
|
+
//# sourceMappingURL=linking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linking.d.ts","sourceRoot":"","sources":["../src/linking.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,EAAE,CASrD;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,EAAE,CAgBnE;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,GAAG,EAAE,CAezE;AAED,wBAAgB,oBAAoB,CAClC,EAAE,EAAE,YAAY,EAChB,cAAc,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,GAChE;IAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IAAC,QAAQ,EAAE,GAAG,EAAE,CAAA;CAAE,CAyBrC;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAYnE"}
|
package/dist/linking.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export function parseRelatedTo(raw) {
|
|
2
|
+
if (!raw)
|
|
3
|
+
return [];
|
|
4
|
+
try {
|
|
5
|
+
const parsed = JSON.parse(raw);
|
|
6
|
+
if (!Array.isArray(parsed))
|
|
7
|
+
return [];
|
|
8
|
+
return parsed.filter((id) => typeof id === 'string' && id.trim());
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function resolveLinks(db, ids) {
|
|
15
|
+
if (!ids.length)
|
|
16
|
+
return [];
|
|
17
|
+
const unique = [...new Set(ids)];
|
|
18
|
+
const placeholders = unique.map(() => '?').join(',');
|
|
19
|
+
try {
|
|
20
|
+
return db
|
|
21
|
+
.prepare(`SELECT * FROM vault
|
|
22
|
+
WHERE id IN (${placeholders})
|
|
23
|
+
AND (expires_at IS NULL OR expires_at > datetime('now'))
|
|
24
|
+
AND superseded_by IS NULL`)
|
|
25
|
+
.all(...unique);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function resolveBacklinks(db, entryId) {
|
|
32
|
+
if (!entryId)
|
|
33
|
+
return [];
|
|
34
|
+
const likePattern = `%"${entryId}"%`;
|
|
35
|
+
try {
|
|
36
|
+
return db
|
|
37
|
+
.prepare(`SELECT * FROM vault
|
|
38
|
+
WHERE related_to LIKE ?
|
|
39
|
+
AND (expires_at IS NULL OR expires_at > datetime('now'))
|
|
40
|
+
AND superseded_by IS NULL`)
|
|
41
|
+
.all(likePattern);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function collectLinkedEntries(db, primaryEntries) {
|
|
48
|
+
const primaryIds = new Set(primaryEntries.map((e) => e.id));
|
|
49
|
+
const forwardIds = [];
|
|
50
|
+
for (const entry of primaryEntries) {
|
|
51
|
+
const ids = parseRelatedTo(entry.related_to);
|
|
52
|
+
for (const id of ids) {
|
|
53
|
+
if (!primaryIds.has(id))
|
|
54
|
+
forwardIds.push(id);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const forwardEntries = resolveLinks(db, forwardIds).filter((e) => !primaryIds.has(e.id));
|
|
58
|
+
const backwardSeen = new Set();
|
|
59
|
+
const backwardEntries = [];
|
|
60
|
+
for (const entry of primaryEntries) {
|
|
61
|
+
const backlinks = resolveBacklinks(db, entry.id);
|
|
62
|
+
for (const bl of backlinks) {
|
|
63
|
+
if (!primaryIds.has(bl.id) && !backwardSeen.has(bl.id)) {
|
|
64
|
+
backwardSeen.add(bl.id);
|
|
65
|
+
backwardEntries.push(bl);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return { forward: forwardEntries, backward: backwardEntries };
|
|
70
|
+
}
|
|
71
|
+
export function validateRelatedTo(relatedTo) {
|
|
72
|
+
if (relatedTo === undefined || relatedTo === null)
|
|
73
|
+
return null;
|
|
74
|
+
if (!Array.isArray(relatedTo))
|
|
75
|
+
return 'related_to must be an array of entry IDs';
|
|
76
|
+
for (const id of relatedTo) {
|
|
77
|
+
if (typeof id !== 'string' || !id.trim()) {
|
|
78
|
+
return 'each related_to entry must be a non-empty string ID';
|
|
79
|
+
}
|
|
80
|
+
if (id.length > 32) {
|
|
81
|
+
return `related_to ID too long (max 32 chars): "${id.slice(0, 32)}..."`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=linking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linking.js","sourceRoot":"","sources":["../src/linking.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const PLURAL_TO_SINGULAR: Record<string, string>;
|
|
2
|
+
export interface MigrationOp {
|
|
3
|
+
action: 'rename' | 'merge';
|
|
4
|
+
pluralDir: string;
|
|
5
|
+
singularDir: string;
|
|
6
|
+
pluralName: string;
|
|
7
|
+
singularName: string;
|
|
8
|
+
fileCount: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function planMigration(vaultDir: string): MigrationOp[];
|
|
11
|
+
export declare function executeMigration(ops: MigrationOp[]): {
|
|
12
|
+
renamed: number;
|
|
13
|
+
merged: number;
|
|
14
|
+
errors: string[];
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=migrate-dirs.d.ts.map
|