@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.
- package/README.md +336 -0
- package/dist/config/loader.d.ts +12 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +46 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/merge.d.ts +20 -0
- package/dist/config/merge.d.ts.map +1 -0
- package/dist/config/merge.js +71 -0
- package/dist/config/merge.js.map +1 -0
- package/dist/config/migration-manager.d.ts +46 -0
- package/dist/config/migration-manager.d.ts.map +1 -0
- package/dist/config/migration-manager.js +119 -0
- package/dist/config/migration-manager.js.map +1 -0
- package/dist/config/migration.d.ts +20 -0
- package/dist/config/migration.d.ts.map +1 -0
- package/dist/config/migration.js +155 -0
- package/dist/config/migration.js.map +1 -0
- package/dist/config/schema.d.ts +101 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +58 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/service.d.ts +122 -0
- package/dist/config/service.d.ts.map +1 -0
- package/dist/config/service.js +477 -0
- package/dist/config/service.js.map +1 -0
- package/dist/constants.d.ts +20 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +43 -0
- package/dist/constants.js.map +1 -0
- package/dist/embeddings/cache.d.ts +45 -0
- package/dist/embeddings/cache.d.ts.map +1 -0
- package/dist/embeddings/cache.js +109 -0
- package/dist/embeddings/cache.js.map +1 -0
- package/dist/embeddings/local.d.ts +10 -0
- package/dist/embeddings/local.d.ts.map +1 -0
- package/dist/embeddings/local.js +63 -0
- package/dist/embeddings/local.js.map +1 -0
- package/dist/embeddings/types.d.ts +9 -0
- package/dist/embeddings/types.d.ts.map +1 -0
- package/dist/embeddings/types.js +5 -0
- package/dist/embeddings/types.js.map +1 -0
- package/dist/errors/codes.d.ts +18 -0
- package/dist/errors/codes.d.ts.map +1 -0
- package/dist/errors/codes.js +25 -0
- package/dist/errors/codes.js.map +1 -0
- package/dist/errors/index.d.ts +85 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +134 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/frameworks/detector-service.d.ts +59 -0
- package/dist/frameworks/detector-service.d.ts.map +1 -0
- package/dist/frameworks/detector-service.js +219 -0
- package/dist/frameworks/detector-service.js.map +1 -0
- package/dist/frameworks/laravel/config.d.ts +6 -0
- package/dist/frameworks/laravel/config.d.ts.map +1 -0
- package/dist/frameworks/laravel/config.js +68 -0
- package/dist/frameworks/laravel/config.js.map +1 -0
- package/dist/frameworks/laravel/detector.d.ts +6 -0
- package/dist/frameworks/laravel/detector.d.ts.map +1 -0
- package/dist/frameworks/laravel/detector.js +96 -0
- package/dist/frameworks/laravel/detector.js.map +1 -0
- package/dist/frameworks/nodejs/config.d.ts +6 -0
- package/dist/frameworks/nodejs/config.d.ts.map +1 -0
- package/dist/frameworks/nodejs/config.js +57 -0
- package/dist/frameworks/nodejs/config.js.map +1 -0
- package/dist/frameworks/nodejs/detector.d.ts +6 -0
- package/dist/frameworks/nodejs/detector.d.ts.map +1 -0
- package/dist/frameworks/nodejs/detector.js +77 -0
- package/dist/frameworks/nodejs/detector.js.map +1 -0
- package/dist/frameworks/php/config.d.ts +6 -0
- package/dist/frameworks/php/config.d.ts.map +1 -0
- package/dist/frameworks/php/config.js +53 -0
- package/dist/frameworks/php/config.js.map +1 -0
- package/dist/frameworks/php/detector.d.ts +7 -0
- package/dist/frameworks/php/detector.d.ts.map +1 -0
- package/dist/frameworks/php/detector.js +101 -0
- package/dist/frameworks/php/detector.js.map +1 -0
- package/dist/frameworks/registry.d.ts +20 -0
- package/dist/frameworks/registry.d.ts.map +1 -0
- package/dist/frameworks/registry.js +38 -0
- package/dist/frameworks/registry.js.map +1 -0
- package/dist/frameworks/shopify/config.d.ts +6 -0
- package/dist/frameworks/shopify/config.d.ts.map +1 -0
- package/dist/frameworks/shopify/config.js +50 -0
- package/dist/frameworks/shopify/config.js.map +1 -0
- package/dist/frameworks/shopify/detector.d.ts +6 -0
- package/dist/frameworks/shopify/detector.d.ts.map +1 -0
- package/dist/frameworks/shopify/detector.js +103 -0
- package/dist/frameworks/shopify/detector.js.map +1 -0
- package/dist/frameworks/types.d.ts +51 -0
- package/dist/frameworks/types.d.ts.map +1 -0
- package/dist/frameworks/types.js +21 -0
- package/dist/frameworks/types.js.map +1 -0
- package/dist/git/tracker.d.ts +56 -0
- package/dist/git/tracker.d.ts.map +1 -0
- package/dist/git/tracker.js +189 -0
- package/dist/git/tracker.js.map +1 -0
- package/dist/git/utils.d.ts +60 -0
- package/dist/git/utils.d.ts.map +1 -0
- package/dist/git/utils.js +152 -0
- package/dist/git/utils.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/ast/chunker.d.ts +28 -0
- package/dist/indexer/ast/chunker.d.ts.map +1 -0
- package/dist/indexer/ast/chunker.js +268 -0
- package/dist/indexer/ast/chunker.js.map +1 -0
- package/dist/indexer/ast/complexity/cognitive.d.ts +16 -0
- package/dist/indexer/ast/complexity/cognitive.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/cognitive.js +106 -0
- package/dist/indexer/ast/complexity/cognitive.js.map +1 -0
- package/dist/indexer/ast/complexity/cyclomatic.d.ts +12 -0
- package/dist/indexer/ast/complexity/cyclomatic.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/cyclomatic.js +61 -0
- package/dist/indexer/ast/complexity/cyclomatic.js.map +1 -0
- package/dist/indexer/ast/complexity/halstead.d.ts +55 -0
- package/dist/indexer/ast/complexity/halstead.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/halstead.js +290 -0
- package/dist/indexer/ast/complexity/halstead.js.map +1 -0
- package/dist/indexer/ast/complexity/index.d.ts +13 -0
- package/dist/indexer/ast/complexity/index.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/index.js +12 -0
- package/dist/indexer/ast/complexity/index.js.map +1 -0
- package/dist/indexer/ast/parser.d.ts +27 -0
- package/dist/indexer/ast/parser.d.ts.map +1 -0
- package/dist/indexer/ast/parser.js +103 -0
- package/dist/indexer/ast/parser.js.map +1 -0
- package/dist/indexer/ast/symbols.d.ts +17 -0
- package/dist/indexer/ast/symbols.d.ts.map +1 -0
- package/dist/indexer/ast/symbols.js +265 -0
- package/dist/indexer/ast/symbols.js.map +1 -0
- package/dist/indexer/ast/traversers/index.d.ts +19 -0
- package/dist/indexer/ast/traversers/index.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/index.js +42 -0
- package/dist/indexer/ast/traversers/index.js.map +1 -0
- package/dist/indexer/ast/traversers/php.d.ts +21 -0
- package/dist/indexer/ast/traversers/php.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/php.js +67 -0
- package/dist/indexer/ast/traversers/php.js.map +1 -0
- package/dist/indexer/ast/traversers/python.d.ts +28 -0
- package/dist/indexer/ast/traversers/python.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/python.js +67 -0
- package/dist/indexer/ast/traversers/python.js.map +1 -0
- package/dist/indexer/ast/traversers/types.d.ts +98 -0
- package/dist/indexer/ast/traversers/types.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/types.js +2 -0
- package/dist/indexer/ast/traversers/types.js.map +1 -0
- package/dist/indexer/ast/traversers/typescript.d.ts +29 -0
- package/dist/indexer/ast/traversers/typescript.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/typescript.js +88 -0
- package/dist/indexer/ast/traversers/typescript.js.map +1 -0
- package/dist/indexer/ast/types.d.ts +59 -0
- package/dist/indexer/ast/types.d.ts.map +1 -0
- package/dist/indexer/ast/types.js +2 -0
- package/dist/indexer/ast/types.js.map +1 -0
- package/dist/indexer/change-detector.d.ts +17 -0
- package/dist/indexer/change-detector.d.ts.map +1 -0
- package/dist/indexer/change-detector.js +207 -0
- package/dist/indexer/change-detector.js.map +1 -0
- package/dist/indexer/chunk-batch-processor.d.ts +103 -0
- package/dist/indexer/chunk-batch-processor.d.ts.map +1 -0
- package/dist/indexer/chunk-batch-processor.js +179 -0
- package/dist/indexer/chunk-batch-processor.js.map +1 -0
- package/dist/indexer/chunker.d.ts +10 -0
- package/dist/indexer/chunker.d.ts.map +1 -0
- package/dist/indexer/chunker.js +96 -0
- package/dist/indexer/chunker.js.map +1 -0
- package/dist/indexer/dependency-analyzer.d.ts +60 -0
- package/dist/indexer/dependency-analyzer.d.ts.map +1 -0
- package/dist/indexer/dependency-analyzer.js +261 -0
- package/dist/indexer/dependency-analyzer.js.map +1 -0
- package/dist/indexer/incremental.d.ts +47 -0
- package/dist/indexer/incremental.d.ts.map +1 -0
- package/dist/indexer/incremental.js +284 -0
- package/dist/indexer/incremental.js.map +1 -0
- package/dist/indexer/index.d.ts +80 -0
- package/dist/indexer/index.d.ts.map +1 -0
- package/dist/indexer/index.js +364 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/json-template-chunker.d.ts +9 -0
- package/dist/indexer/json-template-chunker.d.ts.map +1 -0
- package/dist/indexer/json-template-chunker.js +83 -0
- package/dist/indexer/json-template-chunker.js.map +1 -0
- package/dist/indexer/liquid-chunker.d.ts +13 -0
- package/dist/indexer/liquid-chunker.d.ts.map +1 -0
- package/dist/indexer/liquid-chunker.js +272 -0
- package/dist/indexer/liquid-chunker.js.map +1 -0
- package/dist/indexer/manifest.d.ts +122 -0
- package/dist/indexer/manifest.d.ts.map +1 -0
- package/dist/indexer/manifest.js +262 -0
- package/dist/indexer/manifest.js.map +1 -0
- package/dist/indexer/progress-tracker.d.ts +35 -0
- package/dist/indexer/progress-tracker.d.ts.map +1 -0
- package/dist/indexer/progress-tracker.js +33 -0
- package/dist/indexer/progress-tracker.js.map +1 -0
- package/dist/indexer/scanner.d.ts +16 -0
- package/dist/indexer/scanner.d.ts.map +1 -0
- package/dist/indexer/scanner.js +159 -0
- package/dist/indexer/scanner.js.map +1 -0
- package/dist/indexer/symbol-extractor.d.ts +18 -0
- package/dist/indexer/symbol-extractor.d.ts.map +1 -0
- package/dist/indexer/symbol-extractor.js +351 -0
- package/dist/indexer/symbol-extractor.js.map +1 -0
- package/dist/indexer/types.d.ts +34 -0
- package/dist/indexer/types.d.ts.map +1 -0
- package/dist/indexer/types.js +2 -0
- package/dist/indexer/types.js.map +1 -0
- package/dist/insights/complexity-analyzer.d.ts +82 -0
- package/dist/insights/complexity-analyzer.d.ts.map +1 -0
- package/dist/insights/complexity-analyzer.js +356 -0
- package/dist/insights/complexity-analyzer.js.map +1 -0
- package/dist/insights/formatters/index.d.ts +11 -0
- package/dist/insights/formatters/index.d.ts.map +1 -0
- package/dist/insights/formatters/index.js +20 -0
- package/dist/insights/formatters/index.js.map +1 -0
- package/dist/insights/formatters/json.d.ts +7 -0
- package/dist/insights/formatters/json.d.ts.map +1 -0
- package/dist/insights/formatters/json.js +14 -0
- package/dist/insights/formatters/json.js.map +1 -0
- package/dist/insights/formatters/sarif.d.ts +6 -0
- package/dist/insights/formatters/sarif.d.ts.map +1 -0
- package/dist/insights/formatters/sarif.js +113 -0
- package/dist/insights/formatters/sarif.js.map +1 -0
- package/dist/insights/formatters/text.d.ts +6 -0
- package/dist/insights/formatters/text.d.ts.map +1 -0
- package/dist/insights/formatters/text.js +154 -0
- package/dist/insights/formatters/text.js.map +1 -0
- package/dist/insights/types.d.ts +73 -0
- package/dist/insights/types.d.ts.map +1 -0
- package/dist/insights/types.js +9 -0
- package/dist/insights/types.js.map +1 -0
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/path-matching.d.ts +69 -0
- package/dist/utils/path-matching.d.ts.map +1 -0
- package/dist/utils/path-matching.js +123 -0
- package/dist/utils/path-matching.js.map +1 -0
- package/dist/utils/result.d.ts +65 -0
- package/dist/utils/result.d.ts.map +1 -0
- package/dist/utils/result.js +67 -0
- package/dist/utils/result.js.map +1 -0
- package/dist/utils/version.d.ts +22 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +28 -0
- package/dist/utils/version.js.map +1 -0
- package/dist/vectordb/batch-insert.d.ts +14 -0
- package/dist/vectordb/batch-insert.d.ts.map +1 -0
- package/dist/vectordb/batch-insert.js +185 -0
- package/dist/vectordb/batch-insert.js.map +1 -0
- package/dist/vectordb/boosting/composer.d.ts +51 -0
- package/dist/vectordb/boosting/composer.d.ts.map +1 -0
- package/dist/vectordb/boosting/composer.js +65 -0
- package/dist/vectordb/boosting/composer.js.map +1 -0
- package/dist/vectordb/boosting/index.d.ts +22 -0
- package/dist/vectordb/boosting/index.d.ts.map +1 -0
- package/dist/vectordb/boosting/index.js +22 -0
- package/dist/vectordb/boosting/index.js.map +1 -0
- package/dist/vectordb/boosting/strategies.d.ts +40 -0
- package/dist/vectordb/boosting/strategies.d.ts.map +1 -0
- package/dist/vectordb/boosting/strategies.js +174 -0
- package/dist/vectordb/boosting/strategies.js.map +1 -0
- package/dist/vectordb/boosting/types.d.ts +20 -0
- package/dist/vectordb/boosting/types.d.ts.map +1 -0
- package/dist/vectordb/boosting/types.js +2 -0
- package/dist/vectordb/boosting/types.js.map +1 -0
- package/dist/vectordb/intent-classifier.d.ts +99 -0
- package/dist/vectordb/intent-classifier.d.ts.map +1 -0
- package/dist/vectordb/intent-classifier.js +193 -0
- package/dist/vectordb/intent-classifier.js.map +1 -0
- package/dist/vectordb/lancedb.d.ts +45 -0
- package/dist/vectordb/lancedb.d.ts.map +1 -0
- package/dist/vectordb/lancedb.js +203 -0
- package/dist/vectordb/lancedb.js.map +1 -0
- package/dist/vectordb/maintenance.d.ts +18 -0
- package/dist/vectordb/maintenance.d.ts.map +1 -0
- package/dist/vectordb/maintenance.js +87 -0
- package/dist/vectordb/maintenance.js.map +1 -0
- package/dist/vectordb/query.d.ts +34 -0
- package/dist/vectordb/query.d.ts.map +1 -0
- package/dist/vectordb/query.js +303 -0
- package/dist/vectordb/query.js.map +1 -0
- package/dist/vectordb/relevance.d.ts +15 -0
- package/dist/vectordb/relevance.d.ts.map +1 -0
- package/dist/vectordb/relevance.js +19 -0
- package/dist/vectordb/relevance.js.map +1 -0
- package/dist/vectordb/types.d.ts +29 -0
- package/dist/vectordb/types.d.ts.map +1 -0
- package/dist/vectordb/types.js +2 -0
- package/dist/vectordb/types.js.map +1 -0
- package/dist/vectordb/version.d.ts +16 -0
- package/dist/vectordb/version.d.ts.map +1 -0
- package/dist/vectordb/version.js +40 -0
- package/dist/vectordb/version.js.map +1 -0
- 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
|