@agfpd/iapeer-memory-core 0.1.1

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/src/utils.ts ADDED
@@ -0,0 +1,69 @@
1
+ import crypto from "node:crypto";
2
+ import path from "node:path";
3
+
4
+ // Hash the FULL file content. Was a 4096-char prefix hash — that skipped
5
+ // reindexing whenever an append-only note (План / Фаза / Список — a
6
+ // first-class vault genre that grows downward) changed below the prefix
7
+ // window, leaving vault_search / embeddings on the stale tail. Markdown is
8
+ // cheap; correctness over the micro-optimisation. If profiling ever demands
9
+ // it, gate a full hash behind size+mtime, never trust a prefix as the source
10
+ // of truth.
11
+ export function hashContent(content: string): string {
12
+ return crypto.createHash("sha256").update(content).digest("hex");
13
+ }
14
+
15
+ export function nowIso(): string {
16
+ return new Date().toISOString();
17
+ }
18
+
19
+ export function normalizeRelativePath(input: string): string {
20
+ return input.split(path.sep).join("/").normalize("NFD");
21
+ }
22
+
23
+ /**
24
+ * Normalize a path to NFD for iCloud/macOS compatibility.
25
+ * macOS stores filenames in NFD (decomposed), but user input and code often uses NFC.
26
+ */
27
+ export function normalizePath(input: string): string {
28
+ return input.normalize("NFD");
29
+ }
30
+
31
+ export function noteTitleFromPath(relativePath: string): string {
32
+ const base = path.basename(relativePath, path.extname(relativePath));
33
+ return base.trim();
34
+ }
35
+
36
+ export function toJson(value: unknown): string {
37
+ return JSON.stringify(value ?? null);
38
+ }
39
+
40
+ export function fromJson<T>(value: string | null, fallback: T): T {
41
+ if (!value) return fallback;
42
+ try {
43
+ return JSON.parse(value) as T;
44
+ } catch {
45
+ return fallback;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Split a raw user query into the bare search tokens — same normalisation the
51
+ * FTS path uses (strip control chars + FTS-significant punctuation, split on
52
+ * whitespace), minus the `"tok"*` wrapping. Shared so the FTS query and the
53
+ * query-aware snippet builder tokenise identically: the snippet highlights
54
+ * exactly the words FTS treated as terms, без расхождений.
55
+ */
56
+ export function queryTokens(query: string): string[] {
57
+ return query
58
+ .replace(/[\x00-\x1f]/g, " ")
59
+ .replace(/["(){}[\]:!^~@#$%&|\\<>=+;,./\-]/g, " ")
60
+ .trim()
61
+ .split(/\s+/)
62
+ .filter(Boolean);
63
+ }
64
+
65
+ export function escapeFtsQuery(query: string): string {
66
+ return queryTokens(query)
67
+ .map((token) => `"${token}"*`)
68
+ .join(" ");
69
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "lib": [
4
+ "ESNext"
5
+ ],
6
+ "target": "ESNext",
7
+ "module": "ESNext",
8
+ "moduleResolution": "bundler",
9
+ "types": [
10
+ "bun"
11
+ ],
12
+ "strict": true,
13
+ "noEmit": true,
14
+ "skipLibCheck": true,
15
+ "allowImportingTsExtensions": false,
16
+ "verbatimModuleSyntax": false,
17
+ "forceConsistentCasingInFileNames": true,
18
+ "resolveJsonModule": true
19
+ },
20
+ "include": [
21
+ "src/**/*.ts",
22
+ "tests/**/*.ts"
23
+ ]
24
+ }