@liendev/core 0.19.5

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 (298) hide show
  1. package/README.md +336 -0
  2. package/dist/config/loader.d.ts +12 -0
  3. package/dist/config/loader.d.ts.map +1 -0
  4. package/dist/config/loader.js +46 -0
  5. package/dist/config/loader.js.map +1 -0
  6. package/dist/config/merge.d.ts +20 -0
  7. package/dist/config/merge.d.ts.map +1 -0
  8. package/dist/config/merge.js +71 -0
  9. package/dist/config/merge.js.map +1 -0
  10. package/dist/config/migration-manager.d.ts +46 -0
  11. package/dist/config/migration-manager.d.ts.map +1 -0
  12. package/dist/config/migration-manager.js +119 -0
  13. package/dist/config/migration-manager.js.map +1 -0
  14. package/dist/config/migration.d.ts +20 -0
  15. package/dist/config/migration.d.ts.map +1 -0
  16. package/dist/config/migration.js +155 -0
  17. package/dist/config/migration.js.map +1 -0
  18. package/dist/config/schema.d.ts +101 -0
  19. package/dist/config/schema.d.ts.map +1 -0
  20. package/dist/config/schema.js +58 -0
  21. package/dist/config/schema.js.map +1 -0
  22. package/dist/config/service.d.ts +122 -0
  23. package/dist/config/service.d.ts.map +1 -0
  24. package/dist/config/service.js +477 -0
  25. package/dist/config/service.js.map +1 -0
  26. package/dist/constants.d.ts +20 -0
  27. package/dist/constants.d.ts.map +1 -0
  28. package/dist/constants.js +43 -0
  29. package/dist/constants.js.map +1 -0
  30. package/dist/embeddings/cache.d.ts +45 -0
  31. package/dist/embeddings/cache.d.ts.map +1 -0
  32. package/dist/embeddings/cache.js +109 -0
  33. package/dist/embeddings/cache.js.map +1 -0
  34. package/dist/embeddings/local.d.ts +10 -0
  35. package/dist/embeddings/local.d.ts.map +1 -0
  36. package/dist/embeddings/local.js +63 -0
  37. package/dist/embeddings/local.js.map +1 -0
  38. package/dist/embeddings/types.d.ts +9 -0
  39. package/dist/embeddings/types.d.ts.map +1 -0
  40. package/dist/embeddings/types.js +5 -0
  41. package/dist/embeddings/types.js.map +1 -0
  42. package/dist/errors/codes.d.ts +18 -0
  43. package/dist/errors/codes.d.ts.map +1 -0
  44. package/dist/errors/codes.js +25 -0
  45. package/dist/errors/codes.js.map +1 -0
  46. package/dist/errors/index.d.ts +85 -0
  47. package/dist/errors/index.d.ts.map +1 -0
  48. package/dist/errors/index.js +134 -0
  49. package/dist/errors/index.js.map +1 -0
  50. package/dist/frameworks/detector-service.d.ts +59 -0
  51. package/dist/frameworks/detector-service.d.ts.map +1 -0
  52. package/dist/frameworks/detector-service.js +219 -0
  53. package/dist/frameworks/detector-service.js.map +1 -0
  54. package/dist/frameworks/laravel/config.d.ts +6 -0
  55. package/dist/frameworks/laravel/config.d.ts.map +1 -0
  56. package/dist/frameworks/laravel/config.js +68 -0
  57. package/dist/frameworks/laravel/config.js.map +1 -0
  58. package/dist/frameworks/laravel/detector.d.ts +6 -0
  59. package/dist/frameworks/laravel/detector.d.ts.map +1 -0
  60. package/dist/frameworks/laravel/detector.js +96 -0
  61. package/dist/frameworks/laravel/detector.js.map +1 -0
  62. package/dist/frameworks/nodejs/config.d.ts +6 -0
  63. package/dist/frameworks/nodejs/config.d.ts.map +1 -0
  64. package/dist/frameworks/nodejs/config.js +57 -0
  65. package/dist/frameworks/nodejs/config.js.map +1 -0
  66. package/dist/frameworks/nodejs/detector.d.ts +6 -0
  67. package/dist/frameworks/nodejs/detector.d.ts.map +1 -0
  68. package/dist/frameworks/nodejs/detector.js +77 -0
  69. package/dist/frameworks/nodejs/detector.js.map +1 -0
  70. package/dist/frameworks/php/config.d.ts +6 -0
  71. package/dist/frameworks/php/config.d.ts.map +1 -0
  72. package/dist/frameworks/php/config.js +53 -0
  73. package/dist/frameworks/php/config.js.map +1 -0
  74. package/dist/frameworks/php/detector.d.ts +7 -0
  75. package/dist/frameworks/php/detector.d.ts.map +1 -0
  76. package/dist/frameworks/php/detector.js +101 -0
  77. package/dist/frameworks/php/detector.js.map +1 -0
  78. package/dist/frameworks/registry.d.ts +20 -0
  79. package/dist/frameworks/registry.d.ts.map +1 -0
  80. package/dist/frameworks/registry.js +38 -0
  81. package/dist/frameworks/registry.js.map +1 -0
  82. package/dist/frameworks/shopify/config.d.ts +6 -0
  83. package/dist/frameworks/shopify/config.d.ts.map +1 -0
  84. package/dist/frameworks/shopify/config.js +50 -0
  85. package/dist/frameworks/shopify/config.js.map +1 -0
  86. package/dist/frameworks/shopify/detector.d.ts +6 -0
  87. package/dist/frameworks/shopify/detector.d.ts.map +1 -0
  88. package/dist/frameworks/shopify/detector.js +103 -0
  89. package/dist/frameworks/shopify/detector.js.map +1 -0
  90. package/dist/frameworks/types.d.ts +51 -0
  91. package/dist/frameworks/types.d.ts.map +1 -0
  92. package/dist/frameworks/types.js +21 -0
  93. package/dist/frameworks/types.js.map +1 -0
  94. package/dist/git/tracker.d.ts +56 -0
  95. package/dist/git/tracker.d.ts.map +1 -0
  96. package/dist/git/tracker.js +189 -0
  97. package/dist/git/tracker.js.map +1 -0
  98. package/dist/git/utils.d.ts +60 -0
  99. package/dist/git/utils.d.ts.map +1 -0
  100. package/dist/git/utils.js +152 -0
  101. package/dist/git/utils.js.map +1 -0
  102. package/dist/index.d.ts +77 -0
  103. package/dist/index.d.ts.map +1 -0
  104. package/dist/index.js +95 -0
  105. package/dist/index.js.map +1 -0
  106. package/dist/indexer/ast/chunker.d.ts +28 -0
  107. package/dist/indexer/ast/chunker.d.ts.map +1 -0
  108. package/dist/indexer/ast/chunker.js +268 -0
  109. package/dist/indexer/ast/chunker.js.map +1 -0
  110. package/dist/indexer/ast/complexity/cognitive.d.ts +16 -0
  111. package/dist/indexer/ast/complexity/cognitive.d.ts.map +1 -0
  112. package/dist/indexer/ast/complexity/cognitive.js +106 -0
  113. package/dist/indexer/ast/complexity/cognitive.js.map +1 -0
  114. package/dist/indexer/ast/complexity/cyclomatic.d.ts +12 -0
  115. package/dist/indexer/ast/complexity/cyclomatic.d.ts.map +1 -0
  116. package/dist/indexer/ast/complexity/cyclomatic.js +61 -0
  117. package/dist/indexer/ast/complexity/cyclomatic.js.map +1 -0
  118. package/dist/indexer/ast/complexity/halstead.d.ts +55 -0
  119. package/dist/indexer/ast/complexity/halstead.d.ts.map +1 -0
  120. package/dist/indexer/ast/complexity/halstead.js +290 -0
  121. package/dist/indexer/ast/complexity/halstead.js.map +1 -0
  122. package/dist/indexer/ast/complexity/index.d.ts +13 -0
  123. package/dist/indexer/ast/complexity/index.d.ts.map +1 -0
  124. package/dist/indexer/ast/complexity/index.js +12 -0
  125. package/dist/indexer/ast/complexity/index.js.map +1 -0
  126. package/dist/indexer/ast/parser.d.ts +27 -0
  127. package/dist/indexer/ast/parser.d.ts.map +1 -0
  128. package/dist/indexer/ast/parser.js +103 -0
  129. package/dist/indexer/ast/parser.js.map +1 -0
  130. package/dist/indexer/ast/symbols.d.ts +17 -0
  131. package/dist/indexer/ast/symbols.d.ts.map +1 -0
  132. package/dist/indexer/ast/symbols.js +265 -0
  133. package/dist/indexer/ast/symbols.js.map +1 -0
  134. package/dist/indexer/ast/traversers/index.d.ts +19 -0
  135. package/dist/indexer/ast/traversers/index.d.ts.map +1 -0
  136. package/dist/indexer/ast/traversers/index.js +42 -0
  137. package/dist/indexer/ast/traversers/index.js.map +1 -0
  138. package/dist/indexer/ast/traversers/php.d.ts +21 -0
  139. package/dist/indexer/ast/traversers/php.d.ts.map +1 -0
  140. package/dist/indexer/ast/traversers/php.js +67 -0
  141. package/dist/indexer/ast/traversers/php.js.map +1 -0
  142. package/dist/indexer/ast/traversers/python.d.ts +28 -0
  143. package/dist/indexer/ast/traversers/python.d.ts.map +1 -0
  144. package/dist/indexer/ast/traversers/python.js +67 -0
  145. package/dist/indexer/ast/traversers/python.js.map +1 -0
  146. package/dist/indexer/ast/traversers/types.d.ts +98 -0
  147. package/dist/indexer/ast/traversers/types.d.ts.map +1 -0
  148. package/dist/indexer/ast/traversers/types.js +2 -0
  149. package/dist/indexer/ast/traversers/types.js.map +1 -0
  150. package/dist/indexer/ast/traversers/typescript.d.ts +29 -0
  151. package/dist/indexer/ast/traversers/typescript.d.ts.map +1 -0
  152. package/dist/indexer/ast/traversers/typescript.js +88 -0
  153. package/dist/indexer/ast/traversers/typescript.js.map +1 -0
  154. package/dist/indexer/ast/types.d.ts +59 -0
  155. package/dist/indexer/ast/types.d.ts.map +1 -0
  156. package/dist/indexer/ast/types.js +2 -0
  157. package/dist/indexer/ast/types.js.map +1 -0
  158. package/dist/indexer/change-detector.d.ts +17 -0
  159. package/dist/indexer/change-detector.d.ts.map +1 -0
  160. package/dist/indexer/change-detector.js +207 -0
  161. package/dist/indexer/change-detector.js.map +1 -0
  162. package/dist/indexer/chunk-batch-processor.d.ts +103 -0
  163. package/dist/indexer/chunk-batch-processor.d.ts.map +1 -0
  164. package/dist/indexer/chunk-batch-processor.js +179 -0
  165. package/dist/indexer/chunk-batch-processor.js.map +1 -0
  166. package/dist/indexer/chunker.d.ts +10 -0
  167. package/dist/indexer/chunker.d.ts.map +1 -0
  168. package/dist/indexer/chunker.js +96 -0
  169. package/dist/indexer/chunker.js.map +1 -0
  170. package/dist/indexer/dependency-analyzer.d.ts +60 -0
  171. package/dist/indexer/dependency-analyzer.d.ts.map +1 -0
  172. package/dist/indexer/dependency-analyzer.js +261 -0
  173. package/dist/indexer/dependency-analyzer.js.map +1 -0
  174. package/dist/indexer/incremental.d.ts +47 -0
  175. package/dist/indexer/incremental.d.ts.map +1 -0
  176. package/dist/indexer/incremental.js +284 -0
  177. package/dist/indexer/incremental.js.map +1 -0
  178. package/dist/indexer/index.d.ts +80 -0
  179. package/dist/indexer/index.d.ts.map +1 -0
  180. package/dist/indexer/index.js +364 -0
  181. package/dist/indexer/index.js.map +1 -0
  182. package/dist/indexer/json-template-chunker.d.ts +9 -0
  183. package/dist/indexer/json-template-chunker.d.ts.map +1 -0
  184. package/dist/indexer/json-template-chunker.js +83 -0
  185. package/dist/indexer/json-template-chunker.js.map +1 -0
  186. package/dist/indexer/liquid-chunker.d.ts +13 -0
  187. package/dist/indexer/liquid-chunker.d.ts.map +1 -0
  188. package/dist/indexer/liquid-chunker.js +272 -0
  189. package/dist/indexer/liquid-chunker.js.map +1 -0
  190. package/dist/indexer/manifest.d.ts +122 -0
  191. package/dist/indexer/manifest.d.ts.map +1 -0
  192. package/dist/indexer/manifest.js +262 -0
  193. package/dist/indexer/manifest.js.map +1 -0
  194. package/dist/indexer/progress-tracker.d.ts +35 -0
  195. package/dist/indexer/progress-tracker.d.ts.map +1 -0
  196. package/dist/indexer/progress-tracker.js +33 -0
  197. package/dist/indexer/progress-tracker.js.map +1 -0
  198. package/dist/indexer/scanner.d.ts +16 -0
  199. package/dist/indexer/scanner.d.ts.map +1 -0
  200. package/dist/indexer/scanner.js +159 -0
  201. package/dist/indexer/scanner.js.map +1 -0
  202. package/dist/indexer/symbol-extractor.d.ts +18 -0
  203. package/dist/indexer/symbol-extractor.d.ts.map +1 -0
  204. package/dist/indexer/symbol-extractor.js +351 -0
  205. package/dist/indexer/symbol-extractor.js.map +1 -0
  206. package/dist/indexer/types.d.ts +34 -0
  207. package/dist/indexer/types.d.ts.map +1 -0
  208. package/dist/indexer/types.js +2 -0
  209. package/dist/indexer/types.js.map +1 -0
  210. package/dist/insights/complexity-analyzer.d.ts +82 -0
  211. package/dist/insights/complexity-analyzer.d.ts.map +1 -0
  212. package/dist/insights/complexity-analyzer.js +356 -0
  213. package/dist/insights/complexity-analyzer.js.map +1 -0
  214. package/dist/insights/formatters/index.d.ts +11 -0
  215. package/dist/insights/formatters/index.d.ts.map +1 -0
  216. package/dist/insights/formatters/index.js +20 -0
  217. package/dist/insights/formatters/index.js.map +1 -0
  218. package/dist/insights/formatters/json.d.ts +7 -0
  219. package/dist/insights/formatters/json.d.ts.map +1 -0
  220. package/dist/insights/formatters/json.js +14 -0
  221. package/dist/insights/formatters/json.js.map +1 -0
  222. package/dist/insights/formatters/sarif.d.ts +6 -0
  223. package/dist/insights/formatters/sarif.d.ts.map +1 -0
  224. package/dist/insights/formatters/sarif.js +113 -0
  225. package/dist/insights/formatters/sarif.js.map +1 -0
  226. package/dist/insights/formatters/text.d.ts +6 -0
  227. package/dist/insights/formatters/text.d.ts.map +1 -0
  228. package/dist/insights/formatters/text.js +154 -0
  229. package/dist/insights/formatters/text.js.map +1 -0
  230. package/dist/insights/types.d.ts +73 -0
  231. package/dist/insights/types.d.ts.map +1 -0
  232. package/dist/insights/types.js +9 -0
  233. package/dist/insights/types.js.map +1 -0
  234. package/dist/types/index.d.ts +14 -0
  235. package/dist/types/index.d.ts.map +1 -0
  236. package/dist/types/index.js +8 -0
  237. package/dist/types/index.js.map +1 -0
  238. package/dist/utils/path-matching.d.ts +69 -0
  239. package/dist/utils/path-matching.d.ts.map +1 -0
  240. package/dist/utils/path-matching.js +123 -0
  241. package/dist/utils/path-matching.js.map +1 -0
  242. package/dist/utils/result.d.ts +65 -0
  243. package/dist/utils/result.d.ts.map +1 -0
  244. package/dist/utils/result.js +67 -0
  245. package/dist/utils/result.js.map +1 -0
  246. package/dist/utils/version.d.ts +22 -0
  247. package/dist/utils/version.d.ts.map +1 -0
  248. package/dist/utils/version.js +28 -0
  249. package/dist/utils/version.js.map +1 -0
  250. package/dist/vectordb/batch-insert.d.ts +14 -0
  251. package/dist/vectordb/batch-insert.d.ts.map +1 -0
  252. package/dist/vectordb/batch-insert.js +185 -0
  253. package/dist/vectordb/batch-insert.js.map +1 -0
  254. package/dist/vectordb/boosting/composer.d.ts +51 -0
  255. package/dist/vectordb/boosting/composer.d.ts.map +1 -0
  256. package/dist/vectordb/boosting/composer.js +65 -0
  257. package/dist/vectordb/boosting/composer.js.map +1 -0
  258. package/dist/vectordb/boosting/index.d.ts +22 -0
  259. package/dist/vectordb/boosting/index.d.ts.map +1 -0
  260. package/dist/vectordb/boosting/index.js +22 -0
  261. package/dist/vectordb/boosting/index.js.map +1 -0
  262. package/dist/vectordb/boosting/strategies.d.ts +40 -0
  263. package/dist/vectordb/boosting/strategies.d.ts.map +1 -0
  264. package/dist/vectordb/boosting/strategies.js +174 -0
  265. package/dist/vectordb/boosting/strategies.js.map +1 -0
  266. package/dist/vectordb/boosting/types.d.ts +20 -0
  267. package/dist/vectordb/boosting/types.d.ts.map +1 -0
  268. package/dist/vectordb/boosting/types.js +2 -0
  269. package/dist/vectordb/boosting/types.js.map +1 -0
  270. package/dist/vectordb/intent-classifier.d.ts +99 -0
  271. package/dist/vectordb/intent-classifier.d.ts.map +1 -0
  272. package/dist/vectordb/intent-classifier.js +193 -0
  273. package/dist/vectordb/intent-classifier.js.map +1 -0
  274. package/dist/vectordb/lancedb.d.ts +45 -0
  275. package/dist/vectordb/lancedb.d.ts.map +1 -0
  276. package/dist/vectordb/lancedb.js +203 -0
  277. package/dist/vectordb/lancedb.js.map +1 -0
  278. package/dist/vectordb/maintenance.d.ts +18 -0
  279. package/dist/vectordb/maintenance.d.ts.map +1 -0
  280. package/dist/vectordb/maintenance.js +87 -0
  281. package/dist/vectordb/maintenance.js.map +1 -0
  282. package/dist/vectordb/query.d.ts +34 -0
  283. package/dist/vectordb/query.d.ts.map +1 -0
  284. package/dist/vectordb/query.js +303 -0
  285. package/dist/vectordb/query.js.map +1 -0
  286. package/dist/vectordb/relevance.d.ts +15 -0
  287. package/dist/vectordb/relevance.d.ts.map +1 -0
  288. package/dist/vectordb/relevance.js +19 -0
  289. package/dist/vectordb/relevance.js.map +1 -0
  290. package/dist/vectordb/types.d.ts +29 -0
  291. package/dist/vectordb/types.d.ts.map +1 -0
  292. package/dist/vectordb/types.js +2 -0
  293. package/dist/vectordb/types.js.map +1 -0
  294. package/dist/vectordb/version.d.ts +16 -0
  295. package/dist/vectordb/version.d.ts.map +1 -0
  296. package/dist/vectordb/version.js +40 -0
  297. package/dist/vectordb/version.js.map +1 -0
  298. package/package.json +66 -0
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Extract schema name from JSON content
3
+ *
4
+ * Extracts the "name" field from Shopify schema JSON.
5
+ * Uses JSON.parse to properly handle escaped quotes and other JSON edge cases.
6
+ *
7
+ * Example:
8
+ * {% schema %}
9
+ * {
10
+ * "name": "My \"Special\" Section",
11
+ * "settings": []
12
+ * }
13
+ * {% endschema %}
14
+ *
15
+ * Returns: 'My "Special" Section' (with literal quotes, unescaped)
16
+ */
17
+ function extractSchemaName(schemaContent) {
18
+ try {
19
+ // Remove Liquid tags to isolate JSON content
20
+ // Replace {% schema %} and {% endschema %} (with optional whitespace control)
21
+ let jsonContent = schemaContent
22
+ .replace(/\{%-?\s*schema\s*-?%\}/g, '')
23
+ .replace(/\{%-?\s*endschema\s*-?%\}/g, '')
24
+ .trim();
25
+ // Parse the JSON
26
+ const schema = JSON.parse(jsonContent);
27
+ // Ensure name is a string before returning
28
+ return typeof schema.name === 'string' ? schema.name : undefined;
29
+ }
30
+ catch (error) {
31
+ // Invalid JSON - return undefined
32
+ // This is acceptable: schema blocks with invalid JSON won't have names extracted
33
+ }
34
+ return undefined;
35
+ }
36
+ /**
37
+ * Remove Liquid comment blocks from content to avoid extracting tags from comments
38
+ *
39
+ * Example:
40
+ * {% comment %}Don't use {% render 'old-snippet' %}{% endcomment %}
41
+ * → (removed)
42
+ */
43
+ function removeComments(content) {
44
+ // Remove {% comment %}...{% endcomment %} blocks (with optional whitespace control)
45
+ return content.replace(/\{%-?\s*comment\s*-?%\}[\s\S]*?\{%-?\s*endcomment\s*-?%\}/g, '');
46
+ }
47
+ /**
48
+ * Extract dependencies from {% render %}, {% include %}, and {% section %} tags
49
+ *
50
+ * Examples:
51
+ * - {% render 'product-card' %} → 'product-card'
52
+ * - {% render "cart-item", product: product %} → 'cart-item'
53
+ * - {% include 'snippets/header' %} → 'snippets/header'
54
+ * - {% section 'announcement-bar' %} → 'announcement-bar'
55
+ *
56
+ * Limitations:
57
+ * - Does not handle escaped quotes in snippet names (e.g., {% render 'name\'s' %})
58
+ * - This is acceptable because Shopify snippet names map to filenames, and
59
+ * filesystem restrictions prevent quotes in filenames (snippets/name's.liquid is invalid)
60
+ * - In practice, Shopify snippet names use only alphanumeric, dash, and underscore
61
+ *
62
+ * Note: Expects content with comments already removed for performance
63
+ *
64
+ * @param contentWithoutComments - Content with Liquid comments already removed
65
+ */
66
+ function extractRenderTags(contentWithoutComments) {
67
+ const dependencies = new Set();
68
+ // Match {% render 'snippet-name' %} or {% render "snippet-name" %}
69
+ // Note: Does not handle escaped quotes - see function docs for rationale
70
+ const renderPattern = /\{%-?\s*render\s+['"]([^'"]+)['"]/g;
71
+ let match;
72
+ while ((match = renderPattern.exec(contentWithoutComments)) !== null) {
73
+ dependencies.add(match[1]);
74
+ }
75
+ // Match {% include 'snippet-name' %} or {% include "snippet-name" %}
76
+ const includePattern = /\{%-?\s*include\s+['"]([^'"]+)['"]/g;
77
+ while ((match = includePattern.exec(contentWithoutComments)) !== null) {
78
+ dependencies.add(match[1]);
79
+ }
80
+ // Match {% section 'section-name' %} or {% section "section-name" %}
81
+ const sectionPattern = /\{%-?\s*section\s+['"]([^'"]+)['"]/g;
82
+ while ((match = sectionPattern.exec(contentWithoutComments)) !== null) {
83
+ dependencies.add(match[1]);
84
+ }
85
+ return Array.from(dependencies);
86
+ }
87
+ /**
88
+ * Find all special Liquid blocks in the template
89
+ *
90
+ * Limitation: Does not support nested blocks of the same type.
91
+ * - Matches first start tag with first end tag
92
+ * - This is acceptable because Shopify Liquid does not allow nested blocks
93
+ * - Example invalid: {% schema %}...{% schema %}...{% endschema %} (Shopify rejects this)
94
+ * - If malformed input contains nested blocks, only outermost block is extracted
95
+ */
96
+ function findLiquidBlocks(content) {
97
+ const lines = content.split('\n');
98
+ const blocks = [];
99
+ // Regex patterns for Liquid blocks
100
+ // Note: Matches first start → first end (no nesting support, which is correct for Shopify)
101
+ const blockPatterns = [
102
+ { type: 'schema', start: /\{%-?\s*schema\s*-?%\}/, end: /\{%-?\s*endschema\s*-?%\}/ },
103
+ { type: 'style', start: /\{%-?\s*style\s*-?%\}/, end: /\{%-?\s*endstyle\s*-?%\}/ },
104
+ { type: 'javascript', start: /\{%-?\s*javascript\s*-?%\}/, end: /\{%-?\s*endjavascript\s*-?%\}/ },
105
+ ];
106
+ for (const pattern of blockPatterns) {
107
+ let searchStart = 0;
108
+ while (searchStart < lines.length) {
109
+ // Find start tag
110
+ const startIdx = lines.findIndex((line, idx) => idx >= searchStart && pattern.start.test(line));
111
+ if (startIdx === -1)
112
+ break;
113
+ // Find end tag (allow same line for single-line blocks)
114
+ const endIdx = lines.findIndex((line, idx) => idx >= startIdx && pattern.end.test(line));
115
+ if (endIdx === -1) {
116
+ // No end tag found, treat rest as template
117
+ break;
118
+ }
119
+ // Extract block content
120
+ const blockContent = lines.slice(startIdx, endIdx + 1).join('\n');
121
+ blocks.push({
122
+ type: pattern.type,
123
+ startLine: startIdx,
124
+ endLine: endIdx,
125
+ content: blockContent,
126
+ });
127
+ searchStart = endIdx + 1;
128
+ }
129
+ }
130
+ return blocks.sort((a, b) => a.startLine - b.startLine);
131
+ }
132
+ /**
133
+ * Create a CodeChunk with consistent structure
134
+ */
135
+ function createCodeChunk(content, startLine, endLine, filepath, type, options = {}) {
136
+ return {
137
+ content,
138
+ metadata: {
139
+ file: filepath,
140
+ startLine,
141
+ endLine,
142
+ language: 'liquid',
143
+ type,
144
+ symbolName: options.symbolName,
145
+ symbolType: options.symbolType,
146
+ imports: options.imports?.length ? options.imports : undefined,
147
+ },
148
+ };
149
+ }
150
+ /**
151
+ * Split a large block into multiple chunks with overlap
152
+ */
153
+ function splitLargeBlock(block, ctx, symbolName, imports) {
154
+ const chunks = [];
155
+ const blockLines = block.content.split('\n');
156
+ const { chunkSize, chunkOverlap, filepath } = ctx.params;
157
+ for (let offset = 0; offset < blockLines.length; offset += chunkSize - chunkOverlap) {
158
+ const endOffset = Math.min(offset + chunkSize, blockLines.length);
159
+ const chunkContent = blockLines.slice(offset, endOffset).join('\n');
160
+ if (chunkContent.trim().length > 0) {
161
+ chunks.push(createCodeChunk(chunkContent, block.startLine + offset + 1, block.startLine + endOffset, filepath, 'block', { symbolName, symbolType: block.type, imports }));
162
+ }
163
+ if (endOffset >= blockLines.length)
164
+ break;
165
+ }
166
+ return chunks;
167
+ }
168
+ /**
169
+ * Create chunks from a special Liquid block (schema, style, javascript)
170
+ * Returns the chunks and marks covered lines
171
+ */
172
+ function processSpecialBlock(block, ctx, coveredLines) {
173
+ // Mark lines as covered
174
+ for (let i = block.startLine; i <= block.endLine; i++) {
175
+ coveredLines.add(i);
176
+ }
177
+ // Extract metadata
178
+ const symbolName = block.type === 'schema' ? extractSchemaName(block.content) : undefined;
179
+ // Extract imports from cleaned content
180
+ const blockContentWithoutComments = ctx.linesWithoutComments
181
+ .slice(block.startLine, block.endLine + 1)
182
+ .join('\n');
183
+ const imports = extractRenderTags(blockContentWithoutComments);
184
+ const blockLineCount = block.endLine - block.startLine + 1;
185
+ const maxBlockSize = ctx.params.chunkSize * 3;
186
+ // Keep small blocks as single chunk, split large ones
187
+ if (blockLineCount <= maxBlockSize) {
188
+ return [createCodeChunk(block.content, block.startLine + 1, block.endLine + 1, ctx.params.filepath, 'block', { symbolName, symbolType: block.type, imports })];
189
+ }
190
+ return splitLargeBlock(block, ctx, symbolName, imports);
191
+ }
192
+ /**
193
+ * Create a template chunk from accumulated lines
194
+ */
195
+ function flushTemplateChunk(currentChunk, chunkStartLine, endLine, ctx) {
196
+ if (currentChunk.length === 0)
197
+ return null;
198
+ const chunkContent = currentChunk.join('\n');
199
+ if (chunkContent.trim().length === 0)
200
+ return null;
201
+ const cleanedChunk = ctx.linesWithoutComments.slice(chunkStartLine, endLine).join('\n');
202
+ const imports = extractRenderTags(cleanedChunk);
203
+ return createCodeChunk(chunkContent, chunkStartLine + 1, endLine, ctx.params.filepath, 'template', { imports });
204
+ }
205
+ /**
206
+ * Process uncovered template content into chunks
207
+ */
208
+ function processTemplateContent(ctx, coveredLines) {
209
+ const chunks = [];
210
+ const { lines, params } = ctx;
211
+ const { chunkSize, chunkOverlap } = params;
212
+ let currentChunk = [];
213
+ let chunkStartLine = 0;
214
+ for (let i = 0; i < lines.length; i++) {
215
+ // Skip lines covered by special blocks
216
+ if (coveredLines.has(i)) {
217
+ const chunk = flushTemplateChunk(currentChunk, chunkStartLine, i, ctx);
218
+ if (chunk)
219
+ chunks.push(chunk);
220
+ currentChunk = [];
221
+ continue;
222
+ }
223
+ // Start new chunk if needed
224
+ if (currentChunk.length === 0) {
225
+ chunkStartLine = i;
226
+ }
227
+ currentChunk.push(lines[i]);
228
+ // Flush if chunk is full
229
+ if (currentChunk.length >= chunkSize) {
230
+ const chunk = flushTemplateChunk(currentChunk, chunkStartLine, i + 1, ctx);
231
+ if (chunk)
232
+ chunks.push(chunk);
233
+ // Add overlap for next chunk
234
+ currentChunk = currentChunk.slice(-chunkOverlap);
235
+ chunkStartLine = Math.max(0, i + 1 - chunkOverlap);
236
+ }
237
+ }
238
+ // Flush remaining chunk
239
+ const finalChunk = flushTemplateChunk(currentChunk, chunkStartLine, lines.length, ctx);
240
+ if (finalChunk)
241
+ chunks.push(finalChunk);
242
+ return chunks;
243
+ }
244
+ /**
245
+ * Chunk a Liquid template file
246
+ *
247
+ * Special handling for:
248
+ * - {% schema %} blocks (kept together, extract section name)
249
+ * - {% style %} blocks (kept together)
250
+ * - {% javascript %} blocks (kept together)
251
+ * - {% render %}, {% include %}, and {% section %} tags (tracked as imports)
252
+ * - Regular template content (chunked by lines)
253
+ */
254
+ export function chunkLiquidFile(filepath, content, chunkSize = 75, chunkOverlap = 10) {
255
+ // Build context once for reuse across helpers
256
+ const contentWithoutComments = removeComments(content);
257
+ const ctx = {
258
+ lines: content.split('\n'),
259
+ linesWithoutComments: contentWithoutComments.split('\n'),
260
+ params: { filepath, chunkSize, chunkOverlap },
261
+ };
262
+ // Find special blocks and track covered lines
263
+ const blocks = findLiquidBlocks(content);
264
+ const coveredLines = new Set();
265
+ // Process special blocks
266
+ const blockChunks = blocks.flatMap(block => processSpecialBlock(block, ctx, coveredLines));
267
+ // Process uncovered template content
268
+ const templateChunks = processTemplateContent(ctx, coveredLines);
269
+ // Combine and sort by line number
270
+ return [...blockChunks, ...templateChunks].sort((a, b) => a.metadata.startLine - b.metadata.startLine);
271
+ }
272
+ //# sourceMappingURL=liquid-chunker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"liquid-chunker.js","sourceRoot":"","sources":["../../src/indexer/liquid-chunker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ import { GitState } from '../git/tracker.js';
2
+ /**
3
+ * Represents a single file in the index manifest
4
+ */
5
+ export interface FileEntry {
6
+ filepath: string;
7
+ lastModified: number;
8
+ chunkCount: number;
9
+ }
10
+ /**
11
+ * Index manifest tracking all indexed files and version information
12
+ */
13
+ export interface IndexManifest {
14
+ formatVersion: number;
15
+ lienVersion: string;
16
+ lastIndexed: number;
17
+ gitState?: GitState;
18
+ files: Record<string, FileEntry>;
19
+ }
20
+ /**
21
+ * Manages the index manifest file, tracking which files are indexed
22
+ * and their metadata for incremental indexing support.
23
+ *
24
+ * The manifest includes version checking to invalidate indices when
25
+ * Lien's indexing format changes (e.g., new chunking algorithm,
26
+ * different embedding model, schema changes).
27
+ */
28
+ export declare class ManifestManager {
29
+ private manifestPath;
30
+ private indexPath;
31
+ /**
32
+ * Promise-based lock to prevent race conditions during concurrent updates.
33
+ * Ensures read-modify-write operations are atomic.
34
+ */
35
+ private updateLock;
36
+ /**
37
+ * Creates a new ManifestManager
38
+ * @param indexPath - Path to the index directory (same as VectorDB path)
39
+ */
40
+ constructor(indexPath: string);
41
+ /**
42
+ * Loads the manifest from disk.
43
+ * Returns null if:
44
+ * - Manifest doesn't exist (first run)
45
+ * - Manifest is corrupt
46
+ * - Format version is incompatible (triggers full reindex)
47
+ *
48
+ * @returns Loaded manifest or null
49
+ */
50
+ load(): Promise<IndexManifest | null>;
51
+ /**
52
+ * Saves the manifest to disk.
53
+ * Always saves with current format and package versions.
54
+ *
55
+ * @param manifest - Manifest to save
56
+ */
57
+ save(manifest: IndexManifest): Promise<void>;
58
+ /**
59
+ * Adds or updates a file entry in the manifest.
60
+ * Protected by lock to prevent race conditions during concurrent updates.
61
+ *
62
+ * @param filepath - Path to the file
63
+ * @param entry - File entry metadata
64
+ */
65
+ updateFile(filepath: string, entry: FileEntry): Promise<void>;
66
+ /**
67
+ * Removes a file entry from the manifest.
68
+ * Protected by lock to prevent race conditions during concurrent updates.
69
+ *
70
+ * Note: If the manifest doesn't exist, this is a no-op (not an error).
71
+ * This can happen legitimately after clearing the index or on fresh installs.
72
+ *
73
+ * @param filepath - Path to the file to remove
74
+ */
75
+ removeFile(filepath: string): Promise<void>;
76
+ /**
77
+ * Updates multiple files at once (more efficient than individual updates).
78
+ * Protected by lock to prevent race conditions during concurrent updates.
79
+ *
80
+ * @param entries - Array of file entries to update
81
+ */
82
+ updateFiles(entries: FileEntry[]): Promise<void>;
83
+ /**
84
+ * Updates the git state in the manifest.
85
+ * Protected by lock to prevent race conditions during concurrent updates.
86
+ *
87
+ * @param gitState - Current git state
88
+ */
89
+ updateGitState(gitState: GitState): Promise<void>;
90
+ /**
91
+ * Gets the list of files currently in the manifest
92
+ *
93
+ * @returns Array of filepaths
94
+ */
95
+ getIndexedFiles(): Promise<string[]>;
96
+ /**
97
+ * Detects which files have changed based on mtime comparison
98
+ *
99
+ * @param currentFiles - Map of current files with their mtimes
100
+ * @returns Array of filepaths that have changed
101
+ */
102
+ getChangedFiles(currentFiles: Map<string, number>): Promise<string[]>;
103
+ /**
104
+ * Gets files that are in the manifest but not in the current file list
105
+ * (i.e., deleted files)
106
+ *
107
+ * @param currentFiles - Set of current file paths
108
+ * @returns Array of deleted file paths
109
+ */
110
+ getDeletedFiles(currentFiles: Set<string>): Promise<string[]>;
111
+ /**
112
+ * Clears the manifest file
113
+ */
114
+ clear(): Promise<void>;
115
+ /**
116
+ * Creates an empty manifest with current version information
117
+ *
118
+ * @returns Empty manifest
119
+ */
120
+ private createEmpty;
121
+ }
122
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/indexer/manifest.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAK7C;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAS;IAE1B;;;OAGG;IACH,OAAO,CAAC,UAAU,CAAqB;IAEvC;;;OAGG;gBACS,SAAS,EAAE,MAAM;IAK7B;;;;;;;;OAQG;IACG,IAAI,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IA8B3C;;;;;OAKG;IACG,IAAI,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBlD;;;;;;OAMG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBnE;;;;;;;;OAQG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBjD;;;;;OAKG;IACG,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBtD;;;;;OAKG;IACG,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBvD;;;;OAIG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAO1C;;;;;OAKG;IACG,eAAe,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAwB3E;;;;;;OAMG;IACG,eAAe,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAenE;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B;;;;OAIG;IACH,OAAO,CAAC,WAAW;CAQpB"}
@@ -0,0 +1,262 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import { INDEX_FORMAT_VERSION } from '../constants.js';
4
+ import { getPackageVersion } from '../utils/version.js';
5
+ const MANIFEST_FILE = 'manifest.json';
6
+ /**
7
+ * Manages the index manifest file, tracking which files are indexed
8
+ * and their metadata for incremental indexing support.
9
+ *
10
+ * The manifest includes version checking to invalidate indices when
11
+ * Lien's indexing format changes (e.g., new chunking algorithm,
12
+ * different embedding model, schema changes).
13
+ */
14
+ export class ManifestManager {
15
+ manifestPath;
16
+ indexPath;
17
+ /**
18
+ * Promise-based lock to prevent race conditions during concurrent updates.
19
+ * Ensures read-modify-write operations are atomic.
20
+ */
21
+ updateLock = Promise.resolve();
22
+ /**
23
+ * Creates a new ManifestManager
24
+ * @param indexPath - Path to the index directory (same as VectorDB path)
25
+ */
26
+ constructor(indexPath) {
27
+ this.indexPath = indexPath;
28
+ this.manifestPath = path.join(indexPath, MANIFEST_FILE);
29
+ }
30
+ /**
31
+ * Loads the manifest from disk.
32
+ * Returns null if:
33
+ * - Manifest doesn't exist (first run)
34
+ * - Manifest is corrupt
35
+ * - Format version is incompatible (triggers full reindex)
36
+ *
37
+ * @returns Loaded manifest or null
38
+ */
39
+ async load() {
40
+ try {
41
+ const content = await fs.readFile(this.manifestPath, 'utf-8');
42
+ const manifest = JSON.parse(content);
43
+ // VERSION CHECK: Invalidate if format version doesn't match
44
+ if (manifest.formatVersion !== INDEX_FORMAT_VERSION) {
45
+ console.error(`[Lien] Index format v${manifest.formatVersion} is incompatible with current v${INDEX_FORMAT_VERSION}`);
46
+ console.error(`[Lien] Full reindex required after Lien upgrade`);
47
+ // Clear old manifest and return null (triggers full reindex)
48
+ await this.clear();
49
+ return null;
50
+ }
51
+ return manifest;
52
+ }
53
+ catch (error) {
54
+ // File doesn't exist or is invalid - return null for first run
55
+ if (error.code === 'ENOENT') {
56
+ return null;
57
+ }
58
+ // Corrupt manifest - log warning and return null
59
+ console.error(`[Lien] Warning: Failed to load manifest: ${error}`);
60
+ return null;
61
+ }
62
+ }
63
+ /**
64
+ * Saves the manifest to disk.
65
+ * Always saves with current format and package versions.
66
+ *
67
+ * @param manifest - Manifest to save
68
+ */
69
+ async save(manifest) {
70
+ try {
71
+ // Ensure index directory exists
72
+ await fs.mkdir(this.indexPath, { recursive: true });
73
+ // Always save with current versions
74
+ const manifestToSave = {
75
+ ...manifest,
76
+ formatVersion: INDEX_FORMAT_VERSION,
77
+ lienVersion: getPackageVersion(),
78
+ lastIndexed: Date.now(),
79
+ };
80
+ const content = JSON.stringify(manifestToSave, null, 2);
81
+ await fs.writeFile(this.manifestPath, content, 'utf-8');
82
+ }
83
+ catch (error) {
84
+ // Don't throw - manifest is best-effort
85
+ console.error(`[Lien] Warning: Failed to save manifest: ${error}`);
86
+ }
87
+ }
88
+ /**
89
+ * Adds or updates a file entry in the manifest.
90
+ * Protected by lock to prevent race conditions during concurrent updates.
91
+ *
92
+ * @param filepath - Path to the file
93
+ * @param entry - File entry metadata
94
+ */
95
+ async updateFile(filepath, entry) {
96
+ // Chain this operation to the lock to ensure atomicity
97
+ this.updateLock = this.updateLock.then(async () => {
98
+ const manifest = await this.load() || this.createEmpty();
99
+ manifest.files[filepath] = entry;
100
+ await this.save(manifest);
101
+ }).catch(error => {
102
+ console.error(`[Lien] Failed to update manifest for ${filepath}: ${error}`);
103
+ // Return to reset lock - don't let errors block future operations
104
+ return undefined;
105
+ });
106
+ // Wait for this operation to complete
107
+ await this.updateLock;
108
+ }
109
+ /**
110
+ * Removes a file entry from the manifest.
111
+ * Protected by lock to prevent race conditions during concurrent updates.
112
+ *
113
+ * Note: If the manifest doesn't exist, this is a no-op (not an error).
114
+ * This can happen legitimately after clearing the index or on fresh installs.
115
+ *
116
+ * @param filepath - Path to the file to remove
117
+ */
118
+ async removeFile(filepath) {
119
+ // Chain this operation to the lock to ensure atomicity
120
+ this.updateLock = this.updateLock.then(async () => {
121
+ const manifest = await this.load();
122
+ if (!manifest) {
123
+ // No manifest exists - nothing to remove from (expected in some scenarios)
124
+ return;
125
+ }
126
+ delete manifest.files[filepath];
127
+ await this.save(manifest);
128
+ }).catch(error => {
129
+ console.error(`[Lien] Failed to remove manifest entry for ${filepath}: ${error}`);
130
+ // Return to reset lock - don't let errors block future operations
131
+ return undefined;
132
+ });
133
+ // Wait for this operation to complete
134
+ await this.updateLock;
135
+ }
136
+ /**
137
+ * Updates multiple files at once (more efficient than individual updates).
138
+ * Protected by lock to prevent race conditions during concurrent updates.
139
+ *
140
+ * @param entries - Array of file entries to update
141
+ */
142
+ async updateFiles(entries) {
143
+ // Chain this operation to the lock to ensure atomicity
144
+ this.updateLock = this.updateLock.then(async () => {
145
+ const manifest = await this.load() || this.createEmpty();
146
+ for (const entry of entries) {
147
+ manifest.files[entry.filepath] = entry;
148
+ }
149
+ await this.save(manifest);
150
+ }).catch(error => {
151
+ console.error(`[Lien] Failed to update manifest for ${entries.length} files: ${error}`);
152
+ // Return to reset lock - don't let errors block future operations
153
+ return undefined;
154
+ });
155
+ // Wait for this operation to complete
156
+ await this.updateLock;
157
+ }
158
+ /**
159
+ * Updates the git state in the manifest.
160
+ * Protected by lock to prevent race conditions during concurrent updates.
161
+ *
162
+ * @param gitState - Current git state
163
+ */
164
+ async updateGitState(gitState) {
165
+ // Chain this operation to the lock to ensure atomicity
166
+ this.updateLock = this.updateLock.then(async () => {
167
+ const manifest = await this.load() || this.createEmpty();
168
+ manifest.gitState = gitState;
169
+ await this.save(manifest);
170
+ }).catch(error => {
171
+ console.error(`[Lien] Failed to update git state in manifest: ${error}`);
172
+ // Return to reset lock - don't let errors block future operations
173
+ return undefined;
174
+ });
175
+ // Wait for this operation to complete
176
+ await this.updateLock;
177
+ }
178
+ /**
179
+ * Gets the list of files currently in the manifest
180
+ *
181
+ * @returns Array of filepaths
182
+ */
183
+ async getIndexedFiles() {
184
+ const manifest = await this.load();
185
+ if (!manifest)
186
+ return [];
187
+ return Object.keys(manifest.files);
188
+ }
189
+ /**
190
+ * Detects which files have changed based on mtime comparison
191
+ *
192
+ * @param currentFiles - Map of current files with their mtimes
193
+ * @returns Array of filepaths that have changed
194
+ */
195
+ async getChangedFiles(currentFiles) {
196
+ const manifest = await this.load();
197
+ if (!manifest) {
198
+ // No manifest = all files are "changed" (need full index)
199
+ return Array.from(currentFiles.keys());
200
+ }
201
+ const changedFiles = [];
202
+ for (const [filepath, mtime] of currentFiles) {
203
+ const entry = manifest.files[filepath];
204
+ if (!entry) {
205
+ // New file
206
+ changedFiles.push(filepath);
207
+ }
208
+ else if (entry.lastModified < mtime) {
209
+ // File modified since last index
210
+ changedFiles.push(filepath);
211
+ }
212
+ }
213
+ return changedFiles;
214
+ }
215
+ /**
216
+ * Gets files that are in the manifest but not in the current file list
217
+ * (i.e., deleted files)
218
+ *
219
+ * @param currentFiles - Set of current file paths
220
+ * @returns Array of deleted file paths
221
+ */
222
+ async getDeletedFiles(currentFiles) {
223
+ const manifest = await this.load();
224
+ if (!manifest)
225
+ return [];
226
+ const deletedFiles = [];
227
+ for (const filepath of Object.keys(manifest.files)) {
228
+ if (!currentFiles.has(filepath)) {
229
+ deletedFiles.push(filepath);
230
+ }
231
+ }
232
+ return deletedFiles;
233
+ }
234
+ /**
235
+ * Clears the manifest file
236
+ */
237
+ async clear() {
238
+ try {
239
+ await fs.unlink(this.manifestPath);
240
+ }
241
+ catch (error) {
242
+ // Ignore error if file doesn't exist
243
+ if (error.code !== 'ENOENT') {
244
+ console.error(`[Lien] Warning: Failed to clear manifest: ${error}`);
245
+ }
246
+ }
247
+ }
248
+ /**
249
+ * Creates an empty manifest with current version information
250
+ *
251
+ * @returns Empty manifest
252
+ */
253
+ createEmpty() {
254
+ return {
255
+ formatVersion: INDEX_FORMAT_VERSION,
256
+ lienVersion: getPackageVersion(),
257
+ lastIndexed: Date.now(),
258
+ files: {},
259
+ };
260
+ }
261
+ }
262
+ //# sourceMappingURL=manifest.js.map