@danielsimonjr/memory-mcp 0.47.1 → 9.8.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.
Files changed (207) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +2000 -194
  3. package/dist/__tests__/file-path.test.js +5 -5
  4. package/dist/__tests__/knowledge-graph.test.js +3 -8
  5. package/dist/core/EntityManager.d.ts +266 -0
  6. package/dist/core/EntityManager.d.ts.map +1 -0
  7. package/dist/core/EntityManager.js +85 -133
  8. package/dist/core/GraphEventEmitter.d.ts +202 -0
  9. package/dist/core/GraphEventEmitter.d.ts.map +1 -0
  10. package/dist/core/GraphEventEmitter.js +346 -0
  11. package/dist/core/GraphStorage.d.ts +395 -0
  12. package/dist/core/GraphStorage.d.ts.map +1 -0
  13. package/dist/core/GraphStorage.js +643 -31
  14. package/dist/core/GraphTraversal.d.ts +141 -0
  15. package/dist/core/GraphTraversal.d.ts.map +1 -0
  16. package/dist/core/GraphTraversal.js +573 -0
  17. package/dist/core/HierarchyManager.d.ts +111 -0
  18. package/dist/core/HierarchyManager.d.ts.map +1 -0
  19. package/dist/{features → core}/HierarchyManager.js +14 -9
  20. package/dist/core/ManagerContext.d.ts +72 -0
  21. package/dist/core/ManagerContext.d.ts.map +1 -0
  22. package/dist/core/ManagerContext.js +118 -0
  23. package/dist/core/ObservationManager.d.ts +85 -0
  24. package/dist/core/ObservationManager.d.ts.map +1 -0
  25. package/dist/core/ObservationManager.js +51 -57
  26. package/dist/core/RelationManager.d.ts +131 -0
  27. package/dist/core/RelationManager.d.ts.map +1 -0
  28. package/dist/core/RelationManager.js +31 -7
  29. package/dist/core/SQLiteStorage.d.ts +354 -0
  30. package/dist/core/SQLiteStorage.d.ts.map +1 -0
  31. package/dist/core/SQLiteStorage.js +917 -0
  32. package/dist/core/StorageFactory.d.ts +45 -0
  33. package/dist/core/StorageFactory.d.ts.map +1 -0
  34. package/dist/core/StorageFactory.js +64 -0
  35. package/dist/core/TransactionManager.d.ts +464 -0
  36. package/dist/core/TransactionManager.d.ts.map +1 -0
  37. package/dist/core/TransactionManager.js +490 -13
  38. package/dist/core/index.d.ts +17 -0
  39. package/dist/core/index.d.ts.map +1 -0
  40. package/dist/core/index.js +12 -2
  41. package/dist/features/AnalyticsManager.d.ts +44 -0
  42. package/dist/features/AnalyticsManager.d.ts.map +1 -0
  43. package/dist/features/AnalyticsManager.js +14 -13
  44. package/dist/features/ArchiveManager.d.ts +133 -0
  45. package/dist/features/ArchiveManager.d.ts.map +1 -0
  46. package/dist/features/ArchiveManager.js +221 -14
  47. package/dist/features/CompressionManager.d.ts +117 -0
  48. package/dist/features/CompressionManager.d.ts.map +1 -0
  49. package/dist/features/CompressionManager.js +189 -20
  50. package/dist/features/IOManager.d.ts +225 -0
  51. package/dist/features/IOManager.d.ts.map +1 -0
  52. package/dist/features/IOManager.js +1041 -0
  53. package/dist/features/StreamingExporter.d.ts +123 -0
  54. package/dist/features/StreamingExporter.d.ts.map +1 -0
  55. package/dist/features/StreamingExporter.js +203 -0
  56. package/dist/features/TagManager.d.ts +147 -0
  57. package/dist/features/TagManager.d.ts.map +1 -0
  58. package/dist/features/index.d.ts +12 -0
  59. package/dist/features/index.d.ts.map +1 -0
  60. package/dist/features/index.js +5 -6
  61. package/dist/index.d.ts +9 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +12 -45
  64. package/dist/memory.jsonl +1 -18
  65. package/dist/search/BasicSearch.d.ts +51 -0
  66. package/dist/search/BasicSearch.d.ts.map +1 -0
  67. package/dist/search/BasicSearch.js +9 -3
  68. package/dist/search/BooleanSearch.d.ts +98 -0
  69. package/dist/search/BooleanSearch.d.ts.map +1 -0
  70. package/dist/search/BooleanSearch.js +156 -9
  71. package/dist/search/EmbeddingService.d.ts +178 -0
  72. package/dist/search/EmbeddingService.d.ts.map +1 -0
  73. package/dist/search/EmbeddingService.js +358 -0
  74. package/dist/search/FuzzySearch.d.ts +118 -0
  75. package/dist/search/FuzzySearch.d.ts.map +1 -0
  76. package/dist/search/FuzzySearch.js +241 -25
  77. package/dist/search/QueryCostEstimator.d.ts +111 -0
  78. package/dist/search/QueryCostEstimator.d.ts.map +1 -0
  79. package/dist/search/QueryCostEstimator.js +355 -0
  80. package/dist/search/RankedSearch.d.ts +71 -0
  81. package/dist/search/RankedSearch.d.ts.map +1 -0
  82. package/dist/search/RankedSearch.js +54 -6
  83. package/dist/search/SavedSearchManager.d.ts +79 -0
  84. package/dist/search/SavedSearchManager.d.ts.map +1 -0
  85. package/dist/search/SearchFilterChain.d.ts +120 -0
  86. package/dist/search/SearchFilterChain.d.ts.map +1 -0
  87. package/dist/search/SearchFilterChain.js +2 -4
  88. package/dist/search/SearchManager.d.ts +326 -0
  89. package/dist/search/SearchManager.d.ts.map +1 -0
  90. package/dist/search/SearchManager.js +148 -0
  91. package/dist/search/SearchSuggestions.d.ts +27 -0
  92. package/dist/search/SearchSuggestions.d.ts.map +1 -0
  93. package/dist/search/SearchSuggestions.js +1 -1
  94. package/dist/search/SemanticSearch.d.ts +149 -0
  95. package/dist/search/SemanticSearch.d.ts.map +1 -0
  96. package/dist/search/SemanticSearch.js +323 -0
  97. package/dist/search/TFIDFEventSync.d.ts +85 -0
  98. package/dist/search/TFIDFEventSync.d.ts.map +1 -0
  99. package/dist/search/TFIDFEventSync.js +133 -0
  100. package/dist/search/TFIDFIndexManager.d.ts +151 -0
  101. package/dist/search/TFIDFIndexManager.d.ts.map +1 -0
  102. package/dist/search/TFIDFIndexManager.js +232 -17
  103. package/dist/search/VectorStore.d.ts +235 -0
  104. package/dist/search/VectorStore.d.ts.map +1 -0
  105. package/dist/search/VectorStore.js +311 -0
  106. package/dist/search/index.d.ts +21 -0
  107. package/dist/search/index.d.ts.map +1 -0
  108. package/dist/search/index.js +12 -0
  109. package/dist/server/MCPServer.d.ts +21 -0
  110. package/dist/server/MCPServer.d.ts.map +1 -0
  111. package/dist/server/MCPServer.js +4 -4
  112. package/dist/server/responseCompressor.d.ts +94 -0
  113. package/dist/server/responseCompressor.d.ts.map +1 -0
  114. package/dist/server/responseCompressor.js +127 -0
  115. package/dist/server/toolDefinitions.d.ts +27 -0
  116. package/dist/server/toolDefinitions.d.ts.map +1 -0
  117. package/dist/server/toolDefinitions.js +189 -18
  118. package/dist/server/toolHandlers.d.ts +41 -0
  119. package/dist/server/toolHandlers.d.ts.map +1 -0
  120. package/dist/server/toolHandlers.js +467 -75
  121. package/dist/types/index.d.ts +13 -0
  122. package/dist/types/index.d.ts.map +1 -0
  123. package/dist/types/index.js +1 -1
  124. package/dist/types/types.d.ts +1654 -0
  125. package/dist/types/types.d.ts.map +1 -0
  126. package/dist/types/types.js +9 -0
  127. package/dist/utils/compressedCache.d.ts +192 -0
  128. package/dist/utils/compressedCache.d.ts.map +1 -0
  129. package/dist/utils/compressedCache.js +309 -0
  130. package/dist/utils/compressionUtil.d.ts +214 -0
  131. package/dist/utils/compressionUtil.d.ts.map +1 -0
  132. package/dist/utils/compressionUtil.js +247 -0
  133. package/dist/utils/constants.d.ts +245 -0
  134. package/dist/utils/constants.d.ts.map +1 -0
  135. package/dist/utils/constants.js +124 -0
  136. package/dist/utils/entityUtils.d.ts +321 -0
  137. package/dist/utils/entityUtils.d.ts.map +1 -0
  138. package/dist/utils/entityUtils.js +434 -4
  139. package/dist/utils/errors.d.ts +95 -0
  140. package/dist/utils/errors.d.ts.map +1 -0
  141. package/dist/utils/errors.js +24 -0
  142. package/dist/utils/formatters.d.ts +145 -0
  143. package/dist/utils/formatters.d.ts.map +1 -0
  144. package/dist/utils/{paginationUtils.js → formatters.js} +54 -3
  145. package/dist/utils/index.d.ts +23 -0
  146. package/dist/utils/index.d.ts.map +1 -0
  147. package/dist/utils/index.js +69 -31
  148. package/dist/utils/indexes.d.ts +270 -0
  149. package/dist/utils/indexes.d.ts.map +1 -0
  150. package/dist/utils/indexes.js +526 -0
  151. package/dist/utils/logger.d.ts +24 -0
  152. package/dist/utils/logger.d.ts.map +1 -0
  153. package/dist/utils/operationUtils.d.ts +124 -0
  154. package/dist/utils/operationUtils.d.ts.map +1 -0
  155. package/dist/utils/operationUtils.js +175 -0
  156. package/dist/utils/parallelUtils.d.ts +72 -0
  157. package/dist/utils/parallelUtils.d.ts.map +1 -0
  158. package/dist/utils/parallelUtils.js +169 -0
  159. package/dist/utils/schemas.d.ts +374 -0
  160. package/dist/utils/schemas.d.ts.map +1 -0
  161. package/dist/utils/schemas.js +302 -2
  162. package/dist/utils/searchAlgorithms.d.ts +99 -0
  163. package/dist/utils/searchAlgorithms.d.ts.map +1 -0
  164. package/dist/utils/searchAlgorithms.js +167 -0
  165. package/dist/utils/searchCache.d.ts +108 -0
  166. package/dist/utils/searchCache.d.ts.map +1 -0
  167. package/dist/utils/taskScheduler.d.ts +290 -0
  168. package/dist/utils/taskScheduler.d.ts.map +1 -0
  169. package/dist/utils/taskScheduler.js +466 -0
  170. package/dist/workers/index.d.ts +12 -0
  171. package/dist/workers/index.d.ts.map +1 -0
  172. package/dist/workers/index.js +9 -0
  173. package/dist/workers/levenshteinWorker.d.ts +60 -0
  174. package/dist/workers/levenshteinWorker.d.ts.map +1 -0
  175. package/dist/workers/levenshteinWorker.js +98 -0
  176. package/package.json +17 -4
  177. package/dist/__tests__/edge-cases/edge-cases.test.js +0 -406
  178. package/dist/__tests__/integration/workflows.test.js +0 -449
  179. package/dist/__tests__/performance/benchmarks.test.js +0 -413
  180. package/dist/__tests__/unit/core/EntityManager.test.js +0 -334
  181. package/dist/__tests__/unit/core/GraphStorage.test.js +0 -205
  182. package/dist/__tests__/unit/core/RelationManager.test.js +0 -274
  183. package/dist/__tests__/unit/features/CompressionManager.test.js +0 -350
  184. package/dist/__tests__/unit/search/BasicSearch.test.js +0 -311
  185. package/dist/__tests__/unit/search/BooleanSearch.test.js +0 -432
  186. package/dist/__tests__/unit/search/FuzzySearch.test.js +0 -448
  187. package/dist/__tests__/unit/search/RankedSearch.test.js +0 -379
  188. package/dist/__tests__/unit/utils/levenshtein.test.js +0 -77
  189. package/dist/core/KnowledgeGraphManager.js +0 -423
  190. package/dist/features/BackupManager.js +0 -311
  191. package/dist/features/ExportManager.js +0 -305
  192. package/dist/features/ImportExportManager.js +0 -50
  193. package/dist/features/ImportManager.js +0 -328
  194. package/dist/types/analytics.types.js +0 -6
  195. package/dist/types/entity.types.js +0 -7
  196. package/dist/types/import-export.types.js +0 -7
  197. package/dist/types/search.types.js +0 -7
  198. package/dist/types/tag.types.js +0 -6
  199. package/dist/utils/dateUtils.js +0 -89
  200. package/dist/utils/filterUtils.js +0 -155
  201. package/dist/utils/levenshtein.js +0 -62
  202. package/dist/utils/pathUtils.js +0 -115
  203. package/dist/utils/responseFormatter.js +0 -55
  204. package/dist/utils/tagUtils.js +0 -107
  205. package/dist/utils/tfidf.js +0 -90
  206. package/dist/utils/validationHelper.js +0 -99
  207. package/dist/utils/validationUtils.js +0 -109
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Compression Utility Module
3
+ *
4
+ * Provides brotli compression and decompression utilities using Node.js
5
+ * built-in zlib module. No external dependencies required.
6
+ *
7
+ * Brotli offers 15-20% better compression than gzip, with 60-75%
8
+ * compression typical for JSON data.
9
+ *
10
+ * @module utils/compressionUtil
11
+ */
12
+ /**
13
+ * Options for compression operations.
14
+ */
15
+ export interface CompressionOptions {
16
+ /**
17
+ * Brotli quality level (0-11).
18
+ * Higher values = better compression but slower.
19
+ * @default 6
20
+ */
21
+ quality?: number;
22
+ /**
23
+ * Window size (10-24) for the LZ77 algorithm.
24
+ * Larger windows = better compression for large files.
25
+ * @default 22
26
+ */
27
+ lgwin?: number;
28
+ /**
29
+ * Compression mode hint.
30
+ * - 'text': Optimized for UTF-8 text
31
+ * - 'generic': General-purpose compression
32
+ * @default 'generic'
33
+ */
34
+ mode?: 'text' | 'generic';
35
+ }
36
+ /**
37
+ * Result of a compression operation.
38
+ */
39
+ export interface CompressionResult {
40
+ /** The compressed data as a Buffer */
41
+ compressed: Buffer;
42
+ /** Original size in bytes */
43
+ originalSize: number;
44
+ /** Compressed size in bytes */
45
+ compressedSize: number;
46
+ /** Compression ratio (compressedSize / originalSize). Lower is better. */
47
+ ratio: number;
48
+ }
49
+ /**
50
+ * Metadata about a compressed file for storage alongside the compressed data.
51
+ */
52
+ export interface CompressionMetadata {
53
+ /** Whether the data is compressed */
54
+ compressed: boolean;
55
+ /** Compression format used */
56
+ compressionFormat: 'brotli' | 'none';
57
+ /** Original size before compression in bytes */
58
+ originalSize: number;
59
+ /** Size after compression in bytes */
60
+ compressedSize: number;
61
+ /** Optional checksum of original data for integrity verification */
62
+ originalChecksum?: string;
63
+ /** ISO 8601 timestamp when compression was performed */
64
+ createdAt: string;
65
+ }
66
+ /**
67
+ * Check if a file path indicates brotli compression based on extension.
68
+ *
69
+ * Note: Brotli doesn't have reliable magic bytes for detection.
70
+ * Using file extension (.br) is the recommended detection method.
71
+ *
72
+ * @param filePath - The file path to check
73
+ * @returns True if the path ends with .br extension
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * hasBrotliExtension('backup.jsonl.br') // true
78
+ * hasBrotliExtension('backup.jsonl') // false
79
+ * hasBrotliExtension('data.json') // false
80
+ * ```
81
+ */
82
+ export declare function hasBrotliExtension(filePath: string): boolean;
83
+ /**
84
+ * Compress data using brotli algorithm.
85
+ *
86
+ * @param data - The data to compress (string or Buffer)
87
+ * @param options - Compression options
88
+ * @returns Compression result with compressed data and statistics
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * const jsonData = JSON.stringify({ entities: [...] });
93
+ * const result = await compress(jsonData, { quality: 11 });
94
+ * console.log(`Compressed from ${result.originalSize} to ${result.compressedSize} bytes`);
95
+ * console.log(`Compression ratio: ${(result.ratio * 100).toFixed(1)}%`);
96
+ * ```
97
+ */
98
+ export declare function compress(data: Buffer | string, options?: CompressionOptions): Promise<CompressionResult>;
99
+ /**
100
+ * Decompress brotli-compressed data.
101
+ *
102
+ * @param data - The compressed data as a Buffer
103
+ * @returns The decompressed data as a Buffer
104
+ * @throws Error if decompression fails (corrupt or invalid data)
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * const compressed = await fs.readFile('backup.jsonl.br');
109
+ * const decompressed = await decompress(compressed);
110
+ * const jsonData = decompressed.toString('utf-8');
111
+ * ```
112
+ */
113
+ export declare function decompress(data: Buffer): Promise<Buffer>;
114
+ /**
115
+ * Calculate compression ratio.
116
+ *
117
+ * @param originalSize - Original size in bytes
118
+ * @param compressedSize - Compressed size in bytes
119
+ * @returns Ratio as a decimal (e.g., 0.25 = 75% compression)
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const ratio = getCompressionRatio(1000, 250);
124
+ * console.log(`Compression ratio: ${(1 - ratio) * 100}%`); // "Compression ratio: 75%"
125
+ * ```
126
+ */
127
+ export declare function getCompressionRatio(originalSize: number, compressedSize: number): number;
128
+ /**
129
+ * Compress a file and write the result to disk.
130
+ *
131
+ * @param inputPath - Path to the input file
132
+ * @param outputPath - Path for the compressed output file
133
+ * @param options - Compression options
134
+ * @returns Compression result with statistics
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * const result = await compressFile(
139
+ * 'memory.jsonl',
140
+ * 'memory.jsonl.br',
141
+ * { quality: 11 }
142
+ * );
143
+ * console.log(`Saved ${result.originalSize - result.compressedSize} bytes`);
144
+ * ```
145
+ */
146
+ export declare function compressFile(inputPath: string, outputPath: string, options?: CompressionOptions): Promise<CompressionResult>;
147
+ /**
148
+ * Decompress a file and write the result to disk.
149
+ *
150
+ * @param inputPath - Path to the compressed input file
151
+ * @param outputPath - Path for the decompressed output file
152
+ * @throws Error if file not found or decompression fails
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * await decompressFile('backup.jsonl.br', 'restored.jsonl');
157
+ * ```
158
+ */
159
+ export declare function decompressFile(inputPath: string, outputPath: string): Promise<void>;
160
+ /**
161
+ * Create metadata object for a compression result.
162
+ * This metadata should be stored alongside compressed files for
163
+ * integrity verification and restoration.
164
+ *
165
+ * @param result - The compression result
166
+ * @param checksum - Optional checksum of the original data
167
+ * @returns Compression metadata object
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const result = await compress(data);
172
+ * const metadata = createMetadata(result);
173
+ * await fs.writeFile('backup.meta.json', JSON.stringify(metadata, null, 2));
174
+ * ```
175
+ */
176
+ export declare function createMetadata(result: CompressionResult, checksum?: string): CompressionMetadata;
177
+ /**
178
+ * Create metadata for uncompressed data.
179
+ * Useful for consistent metadata format when compression is disabled.
180
+ *
181
+ * @param size - Size of the data in bytes
182
+ * @returns Compression metadata indicating no compression
183
+ */
184
+ export declare function createUncompressedMetadata(size: number): CompressionMetadata;
185
+ /**
186
+ * Compress a string and return base64-encoded result.
187
+ * Useful for embedding compressed data in JSON responses.
188
+ *
189
+ * @param data - String data to compress
190
+ * @param options - Compression options
191
+ * @returns Base64-encoded compressed data
192
+ *
193
+ * @example
194
+ * ```typescript
195
+ * const encoded = await compressToBase64(jsonString);
196
+ * // Send in response: { compressed: true, data: encoded }
197
+ * ```
198
+ */
199
+ export declare function compressToBase64(data: string, options?: CompressionOptions): Promise<string>;
200
+ /**
201
+ * Decompress base64-encoded compressed data.
202
+ * Counterpart to compressToBase64.
203
+ *
204
+ * @param base64Data - Base64-encoded compressed data
205
+ * @returns Decompressed string
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * const original = await decompressFromBase64(response.data);
210
+ * const parsed = JSON.parse(original);
211
+ * ```
212
+ */
213
+ export declare function decompressFromBase64(base64Data: string): Promise<string>;
214
+ //# sourceMappingURL=compressionUtil.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compressionUtil.d.ts","sourceRoot":"","sources":["../../src/utils/compressionUtil.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,UAAU,EAAE,OAAO,CAAC;IACpB,8BAA8B;IAC9B,iBAAiB,EAAE,QAAQ,GAAG,MAAM,CAAC;IACrC,gDAAgD;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CAoC5B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAe9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,GACrB,MAAM,CAGR;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAK5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,iBAAiB,EACzB,QAAQ,CAAC,EAAE,MAAM,GAChB,mBAAmB,CASrB;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAQ5E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAI9E"}
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Compression Utility Module
3
+ *
4
+ * Provides brotli compression and decompression utilities using Node.js
5
+ * built-in zlib module. No external dependencies required.
6
+ *
7
+ * Brotli offers 15-20% better compression than gzip, with 60-75%
8
+ * compression typical for JSON data.
9
+ *
10
+ * @module utils/compressionUtil
11
+ */
12
+ import { brotliCompress, brotliDecompress, constants } from 'zlib';
13
+ import { promisify } from 'util';
14
+ import { promises as fs } from 'fs';
15
+ import { COMPRESSION_CONFIG } from './constants.js';
16
+ // Promisify Node.js zlib functions for async/await usage
17
+ const compressAsync = promisify(brotliCompress);
18
+ const decompressAsync = promisify(brotliDecompress);
19
+ /**
20
+ * Check if a file path indicates brotli compression based on extension.
21
+ *
22
+ * Note: Brotli doesn't have reliable magic bytes for detection.
23
+ * Using file extension (.br) is the recommended detection method.
24
+ *
25
+ * @param filePath - The file path to check
26
+ * @returns True if the path ends with .br extension
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * hasBrotliExtension('backup.jsonl.br') // true
31
+ * hasBrotliExtension('backup.jsonl') // false
32
+ * hasBrotliExtension('data.json') // false
33
+ * ```
34
+ */
35
+ export function hasBrotliExtension(filePath) {
36
+ return filePath.endsWith(COMPRESSION_CONFIG.BROTLI_EXTENSION);
37
+ }
38
+ /**
39
+ * Compress data using brotli algorithm.
40
+ *
41
+ * @param data - The data to compress (string or Buffer)
42
+ * @param options - Compression options
43
+ * @returns Compression result with compressed data and statistics
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const jsonData = JSON.stringify({ entities: [...] });
48
+ * const result = await compress(jsonData, { quality: 11 });
49
+ * console.log(`Compressed from ${result.originalSize} to ${result.compressedSize} bytes`);
50
+ * console.log(`Compression ratio: ${(result.ratio * 100).toFixed(1)}%`);
51
+ * ```
52
+ */
53
+ export async function compress(data, options = {}) {
54
+ const input = Buffer.isBuffer(data) ? data : Buffer.from(data, 'utf-8');
55
+ const quality = options.quality ?? COMPRESSION_CONFIG.BROTLI_QUALITY_BATCH;
56
+ // Validate quality range
57
+ if (quality < 0 || quality > 11) {
58
+ throw new Error(`Invalid brotli quality level: ${quality}. Must be 0-11.`);
59
+ }
60
+ const zlibOptions = {
61
+ params: {
62
+ [constants.BROTLI_PARAM_QUALITY]: quality,
63
+ [constants.BROTLI_PARAM_MODE]: options.mode === 'text'
64
+ ? constants.BROTLI_MODE_TEXT
65
+ : constants.BROTLI_MODE_GENERIC,
66
+ },
67
+ };
68
+ if (options.lgwin !== undefined) {
69
+ if (options.lgwin < 10 || options.lgwin > 24) {
70
+ throw new Error(`Invalid brotli window size: ${options.lgwin}. Must be 10-24.`);
71
+ }
72
+ zlibOptions.params[constants.BROTLI_PARAM_LGWIN] = options.lgwin;
73
+ }
74
+ const compressed = await compressAsync(input, zlibOptions);
75
+ return {
76
+ compressed,
77
+ originalSize: input.length,
78
+ compressedSize: compressed.length,
79
+ ratio: input.length > 0 ? compressed.length / input.length : 1,
80
+ };
81
+ }
82
+ /**
83
+ * Decompress brotli-compressed data.
84
+ *
85
+ * @param data - The compressed data as a Buffer
86
+ * @returns The decompressed data as a Buffer
87
+ * @throws Error if decompression fails (corrupt or invalid data)
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const compressed = await fs.readFile('backup.jsonl.br');
92
+ * const decompressed = await decompress(compressed);
93
+ * const jsonData = decompressed.toString('utf-8');
94
+ * ```
95
+ */
96
+ export async function decompress(data) {
97
+ if (!Buffer.isBuffer(data)) {
98
+ throw new Error('Input must be a Buffer');
99
+ }
100
+ if (data.length === 0) {
101
+ return Buffer.alloc(0);
102
+ }
103
+ try {
104
+ return await decompressAsync(data);
105
+ }
106
+ catch (error) {
107
+ const message = error instanceof Error ? error.message : 'Unknown error';
108
+ throw new Error(`Brotli decompression failed: ${message}`);
109
+ }
110
+ }
111
+ /**
112
+ * Calculate compression ratio.
113
+ *
114
+ * @param originalSize - Original size in bytes
115
+ * @param compressedSize - Compressed size in bytes
116
+ * @returns Ratio as a decimal (e.g., 0.25 = 75% compression)
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * const ratio = getCompressionRatio(1000, 250);
121
+ * console.log(`Compression ratio: ${(1 - ratio) * 100}%`); // "Compression ratio: 75%"
122
+ * ```
123
+ */
124
+ export function getCompressionRatio(originalSize, compressedSize) {
125
+ if (originalSize <= 0)
126
+ return 1;
127
+ return compressedSize / originalSize;
128
+ }
129
+ /**
130
+ * Compress a file and write the result to disk.
131
+ *
132
+ * @param inputPath - Path to the input file
133
+ * @param outputPath - Path for the compressed output file
134
+ * @param options - Compression options
135
+ * @returns Compression result with statistics
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * const result = await compressFile(
140
+ * 'memory.jsonl',
141
+ * 'memory.jsonl.br',
142
+ * { quality: 11 }
143
+ * );
144
+ * console.log(`Saved ${result.originalSize - result.compressedSize} bytes`);
145
+ * ```
146
+ */
147
+ export async function compressFile(inputPath, outputPath, options) {
148
+ const input = await fs.readFile(inputPath);
149
+ const result = await compress(input, options);
150
+ await fs.writeFile(outputPath, result.compressed);
151
+ return result;
152
+ }
153
+ /**
154
+ * Decompress a file and write the result to disk.
155
+ *
156
+ * @param inputPath - Path to the compressed input file
157
+ * @param outputPath - Path for the decompressed output file
158
+ * @throws Error if file not found or decompression fails
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * await decompressFile('backup.jsonl.br', 'restored.jsonl');
163
+ * ```
164
+ */
165
+ export async function decompressFile(inputPath, outputPath) {
166
+ const input = await fs.readFile(inputPath);
167
+ const decompressed = await decompress(input);
168
+ await fs.writeFile(outputPath, decompressed);
169
+ }
170
+ /**
171
+ * Create metadata object for a compression result.
172
+ * This metadata should be stored alongside compressed files for
173
+ * integrity verification and restoration.
174
+ *
175
+ * @param result - The compression result
176
+ * @param checksum - Optional checksum of the original data
177
+ * @returns Compression metadata object
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * const result = await compress(data);
182
+ * const metadata = createMetadata(result);
183
+ * await fs.writeFile('backup.meta.json', JSON.stringify(metadata, null, 2));
184
+ * ```
185
+ */
186
+ export function createMetadata(result, checksum) {
187
+ return {
188
+ compressed: true,
189
+ compressionFormat: 'brotli',
190
+ originalSize: result.originalSize,
191
+ compressedSize: result.compressedSize,
192
+ originalChecksum: checksum,
193
+ createdAt: new Date().toISOString(),
194
+ };
195
+ }
196
+ /**
197
+ * Create metadata for uncompressed data.
198
+ * Useful for consistent metadata format when compression is disabled.
199
+ *
200
+ * @param size - Size of the data in bytes
201
+ * @returns Compression metadata indicating no compression
202
+ */
203
+ export function createUncompressedMetadata(size) {
204
+ return {
205
+ compressed: false,
206
+ compressionFormat: 'none',
207
+ originalSize: size,
208
+ compressedSize: size,
209
+ createdAt: new Date().toISOString(),
210
+ };
211
+ }
212
+ /**
213
+ * Compress a string and return base64-encoded result.
214
+ * Useful for embedding compressed data in JSON responses.
215
+ *
216
+ * @param data - String data to compress
217
+ * @param options - Compression options
218
+ * @returns Base64-encoded compressed data
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * const encoded = await compressToBase64(jsonString);
223
+ * // Send in response: { compressed: true, data: encoded }
224
+ * ```
225
+ */
226
+ export async function compressToBase64(data, options) {
227
+ const result = await compress(data, options);
228
+ return result.compressed.toString('base64');
229
+ }
230
+ /**
231
+ * Decompress base64-encoded compressed data.
232
+ * Counterpart to compressToBase64.
233
+ *
234
+ * @param base64Data - Base64-encoded compressed data
235
+ * @returns Decompressed string
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * const original = await decompressFromBase64(response.data);
240
+ * const parsed = JSON.parse(original);
241
+ * ```
242
+ */
243
+ export async function decompressFromBase64(base64Data) {
244
+ const buffer = Buffer.from(base64Data, 'base64');
245
+ const decompressed = await decompress(buffer);
246
+ return decompressed.toString('utf-8');
247
+ }