grepmind-core 0.1.0-alpha
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/LICENSE +190 -0
- package/dist/config/types.d.ts +174 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +137 -0
- package/dist/config/types.js.map +1 -0
- package/dist/git.d.ts +98 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +298 -0
- package/dist/git.js.map +1 -0
- package/dist/git.test.d.ts +7 -0
- package/dist/git.test.d.ts.map +1 -0
- package/dist/git.test.js +242 -0
- package/dist/git.test.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/branch.d.ts +121 -0
- package/dist/indexer/branch.d.ts.map +1 -0
- package/dist/indexer/branch.js +451 -0
- package/dist/indexer/branch.js.map +1 -0
- package/dist/indexer/chunker.d.ts +9 -0
- package/dist/indexer/chunker.d.ts.map +1 -0
- package/dist/indexer/chunker.js +70 -0
- package/dist/indexer/chunker.js.map +1 -0
- package/dist/indexer/chunker.test.d.ts +2 -0
- package/dist/indexer/chunker.test.d.ts.map +1 -0
- package/dist/indexer/chunker.test.js +180 -0
- package/dist/indexer/chunker.test.js.map +1 -0
- package/dist/indexer/code/branch.d.ts +155 -0
- package/dist/indexer/code/branch.d.ts.map +1 -0
- package/dist/indexer/code/branch.js +550 -0
- package/dist/indexer/code/branch.js.map +1 -0
- package/dist/indexer/code/branch.test.d.ts +7 -0
- package/dist/indexer/code/branch.test.d.ts.map +1 -0
- package/dist/indexer/code/branch.test.js +241 -0
- package/dist/indexer/code/branch.test.js.map +1 -0
- package/dist/indexer/code/chunker.d.ts +61 -0
- package/dist/indexer/code/chunker.d.ts.map +1 -0
- package/dist/indexer/code/chunker.js +311 -0
- package/dist/indexer/code/chunker.js.map +1 -0
- package/dist/indexer/code/chunker.test.d.ts +2 -0
- package/dist/indexer/code/chunker.test.d.ts.map +1 -0
- package/dist/indexer/code/chunker.test.js +552 -0
- package/dist/indexer/code/chunker.test.js.map +1 -0
- package/dist/indexer/code/fts.test.d.ts +2 -0
- package/dist/indexer/code/fts.test.d.ts.map +1 -0
- package/dist/indexer/code/fts.test.js +14 -0
- package/dist/indexer/code/fts.test.js.map +1 -0
- package/dist/indexer/code/graph/embedded.d.ts +11 -0
- package/dist/indexer/code/graph/embedded.d.ts.map +1 -0
- package/dist/indexer/code/graph/embedded.js +152 -0
- package/dist/indexer/code/graph/embedded.js.map +1 -0
- package/dist/indexer/code/graph/embedded.test.d.ts +2 -0
- package/dist/indexer/code/graph/embedded.test.d.ts.map +1 -0
- package/dist/indexer/code/graph/embedded.test.js +105 -0
- package/dist/indexer/code/graph/embedded.test.js.map +1 -0
- package/dist/indexer/code/graph/facts.d.ts +11 -0
- package/dist/indexer/code/graph/facts.d.ts.map +1 -0
- package/dist/indexer/code/graph/facts.js +456 -0
- package/dist/indexer/code/graph/facts.js.map +1 -0
- package/dist/indexer/code/graph/facts.test.d.ts +2 -0
- package/dist/indexer/code/graph/facts.test.d.ts.map +1 -0
- package/dist/indexer/code/graph/facts.test.js +181 -0
- package/dist/indexer/code/graph/facts.test.js.map +1 -0
- package/dist/indexer/code/graph/id.d.ts +14 -0
- package/dist/indexer/code/graph/id.d.ts.map +1 -0
- package/dist/indexer/code/graph/id.js +40 -0
- package/dist/indexer/code/graph/id.js.map +1 -0
- package/dist/indexer/code/graph/id.test.d.ts +2 -0
- package/dist/indexer/code/graph/id.test.d.ts.map +1 -0
- package/dist/indexer/code/graph/id.test.js +86 -0
- package/dist/indexer/code/graph/id.test.js.map +1 -0
- package/dist/indexer/code/graph/index.d.ts +133 -0
- package/dist/indexer/code/graph/index.d.ts.map +1 -0
- package/dist/indexer/code/graph/index.js +1876 -0
- package/dist/indexer/code/graph/index.js.map +1 -0
- package/dist/indexer/code/graph/index.test.d.ts +2 -0
- package/dist/indexer/code/graph/index.test.d.ts.map +1 -0
- package/dist/indexer/code/graph/index.test.js +210 -0
- package/dist/indexer/code/graph/index.test.js.map +1 -0
- package/dist/indexer/code/graph/queries.d.ts +22 -0
- package/dist/indexer/code/graph/queries.d.ts.map +1 -0
- package/dist/indexer/code/graph/queries.js +79 -0
- package/dist/indexer/code/graph/queries.js.map +1 -0
- package/dist/indexer/code/graph/queries.test.d.ts +2 -0
- package/dist/indexer/code/graph/queries.test.d.ts.map +1 -0
- package/dist/indexer/code/graph/queries.test.js +108 -0
- package/dist/indexer/code/graph/queries.test.js.map +1 -0
- package/dist/indexer/code/graph/resolver.d.ts +136 -0
- package/dist/indexer/code/graph/resolver.d.ts.map +1 -0
- package/dist/indexer/code/graph/resolver.js +839 -0
- package/dist/indexer/code/graph/resolver.js.map +1 -0
- package/dist/indexer/code/graph/resolver.test.d.ts +2 -0
- package/dist/indexer/code/graph/resolver.test.d.ts.map +1 -0
- package/dist/indexer/code/graph/resolver.test.js +482 -0
- package/dist/indexer/code/graph/resolver.test.js.map +1 -0
- package/dist/indexer/code/graph/semantic.d.ts +33 -0
- package/dist/indexer/code/graph/semantic.d.ts.map +1 -0
- package/dist/indexer/code/graph/semantic.js +279 -0
- package/dist/indexer/code/graph/semantic.js.map +1 -0
- package/dist/indexer/code/graph/semantic.test.d.ts +2 -0
- package/dist/indexer/code/graph/semantic.test.d.ts.map +1 -0
- package/dist/indexer/code/graph/semantic.test.js +127 -0
- package/dist/indexer/code/graph/semantic.test.js.map +1 -0
- package/dist/indexer/code/index.d.ts +404 -0
- package/dist/indexer/code/index.d.ts.map +1 -0
- package/dist/indexer/code/index.js +2070 -0
- package/dist/indexer/code/index.js.map +1 -0
- package/dist/indexer/code/languages/bash.d.ts +14 -0
- package/dist/indexer/code/languages/bash.d.ts.map +1 -0
- package/dist/indexer/code/languages/bash.js +125 -0
- package/dist/indexer/code/languages/bash.js.map +1 -0
- package/dist/indexer/code/languages/css.d.ts +16 -0
- package/dist/indexer/code/languages/css.d.ts.map +1 -0
- package/dist/indexer/code/languages/css.js +204 -0
- package/dist/indexer/code/languages/css.js.map +1 -0
- package/dist/indexer/code/languages/generic.d.ts +61 -0
- package/dist/indexer/code/languages/generic.d.ts.map +1 -0
- package/dist/indexer/code/languages/generic.js +150 -0
- package/dist/indexer/code/languages/generic.js.map +1 -0
- package/dist/indexer/code/languages/graphql.d.ts +13 -0
- package/dist/indexer/code/languages/graphql.d.ts.map +1 -0
- package/dist/indexer/code/languages/graphql.js +180 -0
- package/dist/indexer/code/languages/graphql.js.map +1 -0
- package/dist/indexer/code/languages/html.d.ts +16 -0
- package/dist/indexer/code/languages/html.d.ts.map +1 -0
- package/dist/indexer/code/languages/html.js +138 -0
- package/dist/indexer/code/languages/html.js.map +1 -0
- package/dist/indexer/code/languages/index.d.ts +9 -0
- package/dist/indexer/code/languages/index.d.ts.map +1 -0
- package/dist/indexer/code/languages/index.js +12 -0
- package/dist/indexer/code/languages/index.js.map +1 -0
- package/dist/indexer/code/languages/json.d.ts +12 -0
- package/dist/indexer/code/languages/json.d.ts.map +1 -0
- package/dist/indexer/code/languages/json.js +66 -0
- package/dist/indexer/code/languages/json.js.map +1 -0
- package/dist/indexer/code/languages/registry.d.ts +78 -0
- package/dist/indexer/code/languages/registry.d.ts.map +1 -0
- package/dist/indexer/code/languages/registry.js +72 -0
- package/dist/indexer/code/languages/registry.js.map +1 -0
- package/dist/indexer/code/languages/typescript.d.ts +39 -0
- package/dist/indexer/code/languages/typescript.d.ts.map +1 -0
- package/dist/indexer/code/languages/typescript.js +300 -0
- package/dist/indexer/code/languages/typescript.js.map +1 -0
- package/dist/indexer/code/languages/yaml.d.ts +13 -0
- package/dist/indexer/code/languages/yaml.d.ts.map +1 -0
- package/dist/indexer/code/languages/yaml.js +90 -0
- package/dist/indexer/code/languages/yaml.js.map +1 -0
- package/dist/indexer/code/parser.d.ts +26 -0
- package/dist/indexer/code/parser.d.ts.map +1 -0
- package/dist/indexer/code/parser.js +332 -0
- package/dist/indexer/code/parser.js.map +1 -0
- package/dist/indexer/code/retry.d.ts +58 -0
- package/dist/indexer/code/retry.d.ts.map +1 -0
- package/dist/indexer/code/retry.js +192 -0
- package/dist/indexer/code/retry.js.map +1 -0
- package/dist/indexer/code/tree/builder.d.ts +30 -0
- package/dist/indexer/code/tree/builder.d.ts.map +1 -0
- package/dist/indexer/code/tree/builder.js +132 -0
- package/dist/indexer/code/tree/builder.js.map +1 -0
- package/dist/indexer/code/tree/builder.test.d.ts +2 -0
- package/dist/indexer/code/tree/builder.test.d.ts.map +1 -0
- package/dist/indexer/code/tree/builder.test.js +31 -0
- package/dist/indexer/code/tree/builder.test.js.map +1 -0
- package/dist/indexer/code/tree/cache.d.ts +22 -0
- package/dist/indexer/code/tree/cache.d.ts.map +1 -0
- package/dist/indexer/code/tree/cache.js +85 -0
- package/dist/indexer/code/tree/cache.js.map +1 -0
- package/dist/indexer/code/tree/context.d.ts +32 -0
- package/dist/indexer/code/tree/context.d.ts.map +1 -0
- package/dist/indexer/code/tree/context.js +78 -0
- package/dist/indexer/code/tree/context.js.map +1 -0
- package/dist/indexer/code/tree/embedding.d.ts +9 -0
- package/dist/indexer/code/tree/embedding.d.ts.map +1 -0
- package/dist/indexer/code/tree/embedding.js +53 -0
- package/dist/indexer/code/tree/embedding.js.map +1 -0
- package/dist/indexer/code/tree/embedding.test.d.ts +2 -0
- package/dist/indexer/code/tree/embedding.test.d.ts.map +1 -0
- package/dist/indexer/code/tree/embedding.test.js +57 -0
- package/dist/indexer/code/tree/embedding.test.js.map +1 -0
- package/dist/indexer/code/tree/id.d.ts +3 -0
- package/dist/indexer/code/tree/id.d.ts.map +1 -0
- package/dist/indexer/code/tree/id.js +8 -0
- package/dist/indexer/code/tree/id.js.map +1 -0
- package/dist/indexer/code/tree/index.d.ts +113 -0
- package/dist/indexer/code/tree/index.d.ts.map +1 -0
- package/dist/indexer/code/tree/index.js +1146 -0
- package/dist/indexer/code/tree/index.js.map +1 -0
- package/dist/indexer/code/tree/rename.d.ts +13 -0
- package/dist/indexer/code/tree/rename.d.ts.map +1 -0
- package/dist/indexer/code/tree/rename.js +46 -0
- package/dist/indexer/code/tree/rename.js.map +1 -0
- package/dist/indexer/code/tree/repomap.d.ts +29 -0
- package/dist/indexer/code/tree/repomap.d.ts.map +1 -0
- package/dist/indexer/code/tree/repomap.js +95 -0
- package/dist/indexer/code/tree/repomap.js.map +1 -0
- package/dist/indexer/code/tree/repomap.test.d.ts +2 -0
- package/dist/indexer/code/tree/repomap.test.d.ts.map +1 -0
- package/dist/indexer/code/tree/repomap.test.js +93 -0
- package/dist/indexer/code/tree/repomap.test.js.map +1 -0
- package/dist/indexer/code/tree/stats.d.ts +26 -0
- package/dist/indexer/code/tree/stats.d.ts.map +1 -0
- package/dist/indexer/code/tree/stats.js +49 -0
- package/dist/indexer/code/tree/stats.js.map +1 -0
- package/dist/indexer/code/tree/types.d.ts +186 -0
- package/dist/indexer/code/tree/types.d.ts.map +1 -0
- package/dist/indexer/code/tree/types.js +10 -0
- package/dist/indexer/code/tree/types.js.map +1 -0
- package/dist/indexer/code/wal.d.ts +144 -0
- package/dist/indexer/code/wal.d.ts.map +1 -0
- package/dist/indexer/code/wal.js +283 -0
- package/dist/indexer/code/wal.js.map +1 -0
- package/dist/indexer/embeddings.d.ts +113 -0
- package/dist/indexer/embeddings.d.ts.map +1 -0
- package/dist/indexer/embeddings.js +477 -0
- package/dist/indexer/embeddings.js.map +1 -0
- package/dist/indexer/git-sync.d.ts +117 -0
- package/dist/indexer/git-sync.d.ts.map +1 -0
- package/dist/indexer/git-sync.js +398 -0
- package/dist/indexer/git-sync.js.map +1 -0
- package/dist/indexer/index.d.ts +175 -0
- package/dist/indexer/index.d.ts.map +1 -0
- package/dist/indexer/index.js +1096 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/mocks/mock-reranker.d.ts +12 -0
- package/dist/indexer/mocks/mock-reranker.d.ts.map +1 -0
- package/dist/indexer/mocks/mock-reranker.js +26 -0
- package/dist/indexer/mocks/mock-reranker.js.map +1 -0
- package/dist/indexer/parser.d.ts +8 -0
- package/dist/indexer/parser.d.ts.map +1 -0
- package/dist/indexer/parser.js +44 -0
- package/dist/indexer/parser.js.map +1 -0
- package/dist/indexer/parser.test.d.ts +2 -0
- package/dist/indexer/parser.test.d.ts.map +1 -0
- package/dist/indexer/parser.test.js +197 -0
- package/dist/indexer/parser.test.js.map +1 -0
- package/dist/indexer/reranking.d.ts +71 -0
- package/dist/indexer/reranking.d.ts.map +1 -0
- package/dist/indexer/reranking.integration.test.d.ts +2 -0
- package/dist/indexer/reranking.integration.test.d.ts.map +1 -0
- package/dist/indexer/reranking.integration.test.js +104 -0
- package/dist/indexer/reranking.integration.test.js.map +1 -0
- package/dist/indexer/reranking.js +256 -0
- package/dist/indexer/reranking.js.map +1 -0
- package/dist/indexer/reranking.test.d.ts +2 -0
- package/dist/indexer/reranking.test.d.ts.map +1 -0
- package/dist/indexer/reranking.test.js +130 -0
- package/dist/indexer/reranking.test.js.map +1 -0
- package/dist/indexer/wal/file-storage.d.ts +60 -0
- package/dist/indexer/wal/file-storage.d.ts.map +1 -0
- package/dist/indexer/wal/file-storage.js +277 -0
- package/dist/indexer/wal/file-storage.js.map +1 -0
- package/dist/indexer/wal/file-storage.test.d.ts +8 -0
- package/dist/indexer/wal/file-storage.test.d.ts.map +1 -0
- package/dist/indexer/wal/file-storage.test.js +444 -0
- package/dist/indexer/wal/file-storage.test.js.map +1 -0
- package/dist/indexer/wal/index.d.ts +41 -0
- package/dist/indexer/wal/index.d.ts.map +1 -0
- package/dist/indexer/wal/index.js +61 -0
- package/dist/indexer/wal/index.js.map +1 -0
- package/dist/indexer/wal/integration.test.d.ts +11 -0
- package/dist/indexer/wal/integration.test.d.ts.map +1 -0
- package/dist/indexer/wal/integration.test.js +378 -0
- package/dist/indexer/wal/integration.test.js.map +1 -0
- package/dist/indexer/wal/lancedb-storage.d.ts +72 -0
- package/dist/indexer/wal/lancedb-storage.d.ts.map +1 -0
- package/dist/indexer/wal/lancedb-storage.js +462 -0
- package/dist/indexer/wal/lancedb-storage.js.map +1 -0
- package/dist/indexer/wal/lancedb-storage.test.d.ts +8 -0
- package/dist/indexer/wal/lancedb-storage.test.d.ts.map +1 -0
- package/dist/indexer/wal/lancedb-storage.test.js +415 -0
- package/dist/indexer/wal/lancedb-storage.test.js.map +1 -0
- package/dist/indexer/wal/sync-wal.d.ts +144 -0
- package/dist/indexer/wal/sync-wal.d.ts.map +1 -0
- package/dist/indexer/wal/sync-wal.js +863 -0
- package/dist/indexer/wal/sync-wal.js.map +1 -0
- package/dist/indexer/wal/sync-wal.test.d.ts +8 -0
- package/dist/indexer/wal/sync-wal.test.d.ts.map +1 -0
- package/dist/indexer/wal/sync-wal.test.js +752 -0
- package/dist/indexer/wal/sync-wal.test.js.map +1 -0
- package/dist/indexer/wal/types.d.ts +167 -0
- package/dist/indexer/wal/types.d.ts.map +1 -0
- package/dist/indexer/wal/types.js +12 -0
- package/dist/indexer/wal/types.js.map +1 -0
- package/dist/indexer/watcher.d.ts +36 -0
- package/dist/indexer/watcher.d.ts.map +1 -0
- package/dist/indexer/watcher.js +110 -0
- package/dist/indexer/watcher.js.map +1 -0
- package/dist/search/explore.d.ts +62 -0
- package/dist/search/explore.d.ts.map +1 -0
- package/dist/search/explore.js +111 -0
- package/dist/search/explore.js.map +1 -0
- package/dist/search/fts.d.ts +23 -0
- package/dist/search/fts.d.ts.map +1 -0
- package/dist/search/fts.js +64 -0
- package/dist/search/fts.js.map +1 -0
- package/dist/search/fts.test.d.ts +2 -0
- package/dist/search/fts.test.d.ts.map +1 -0
- package/dist/search/fts.test.js +27 -0
- package/dist/search/fts.test.js.map +1 -0
- package/dist/search/grep.d.ts +75 -0
- package/dist/search/grep.d.ts.map +1 -0
- package/dist/search/grep.js +96 -0
- package/dist/search/grep.js.map +1 -0
- package/dist/search/grep.test.d.ts +2 -0
- package/dist/search/grep.test.d.ts.map +1 -0
- package/dist/search/grep.test.js +178 -0
- package/dist/search/grep.test.js.map +1 -0
- package/dist/search/hybrid-grep.d.ts +43 -0
- package/dist/search/hybrid-grep.d.ts.map +1 -0
- package/dist/search/hybrid-grep.js +130 -0
- package/dist/search/hybrid-grep.js.map +1 -0
- package/dist/search/hybrid-grep.test.d.ts +2 -0
- package/dist/search/hybrid-grep.test.d.ts.map +1 -0
- package/dist/search/hybrid-grep.test.js +133 -0
- package/dist/search/hybrid-grep.test.js.map +1 -0
- package/dist/search/rg-executor.d.ts +63 -0
- package/dist/search/rg-executor.d.ts.map +1 -0
- package/dist/search/rg-executor.js +146 -0
- package/dist/search/rg-executor.js.map +1 -0
- package/dist/search/rg-executor.test.d.ts +2 -0
- package/dist/search/rg-executor.test.d.ts.map +1 -0
- package/dist/search/rg-executor.test.js +104 -0
- package/dist/search/rg-executor.test.js.map +1 -0
- package/dist/search/rg-parser/extractor.d.ts +14 -0
- package/dist/search/rg-parser/extractor.d.ts.map +1 -0
- package/dist/search/rg-parser/extractor.js +82 -0
- package/dist/search/rg-parser/extractor.js.map +1 -0
- package/dist/search/rg-parser/extractor.test.d.ts +2 -0
- package/dist/search/rg-parser/extractor.test.d.ts.map +1 -0
- package/dist/search/rg-parser/extractor.test.js +35 -0
- package/dist/search/rg-parser/extractor.test.js.map +1 -0
- package/dist/search/rg-parser/fts-builder.d.ts +7 -0
- package/dist/search/rg-parser/fts-builder.d.ts.map +1 -0
- package/dist/search/rg-parser/fts-builder.js +18 -0
- package/dist/search/rg-parser/fts-builder.js.map +1 -0
- package/dist/search/rg-parser/fts-builder.test.d.ts +2 -0
- package/dist/search/rg-parser/fts-builder.test.d.ts.map +1 -0
- package/dist/search/rg-parser/fts-builder.test.js +26 -0
- package/dist/search/rg-parser/fts-builder.test.js.map +1 -0
- package/dist/search/rg-parser/index.d.ts +36 -0
- package/dist/search/rg-parser/index.d.ts.map +1 -0
- package/dist/search/rg-parser/index.js +83 -0
- package/dist/search/rg-parser/index.js.map +1 -0
- package/dist/search/rg-parser/index.test.d.ts +2 -0
- package/dist/search/rg-parser/index.test.d.ts.map +1 -0
- package/dist/search/rg-parser/index.test.js +34 -0
- package/dist/search/rg-parser/index.test.js.map +1 -0
- package/dist/search/rg-parser/strategy.d.ts +14 -0
- package/dist/search/rg-parser/strategy.d.ts.map +1 -0
- package/dist/search/rg-parser/strategy.js +31 -0
- package/dist/search/rg-parser/strategy.js.map +1 -0
- package/dist/search/rg-parser/strategy.test.d.ts +2 -0
- package/dist/search/rg-parser/strategy.test.d.ts.map +1 -0
- package/dist/search/rg-parser/strategy.test.js +29 -0
- package/dist/search/rg-parser/strategy.test.js.map +1 -0
- package/dist/types.d.ts +345 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/vault.d.ts +84 -0
- package/dist/utils/vault.d.ts.map +1 -0
- package/dist/utils/vault.js +138 -0
- package/dist/utils/vault.js.map +1 -0
- package/dist/utils/vault.test.d.ts +2 -0
- package/dist/utils/vault.test.d.ts.map +1 -0
- package/dist/utils/vault.test.js +153 -0
- package/dist/utils/vault.test.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Tests for Sync WAL
|
|
3
|
+
*
|
|
4
|
+
* Tests that verify complete workflows and edge cases:
|
|
5
|
+
* - Full sync cycle
|
|
6
|
+
* - Recovery scenarios
|
|
7
|
+
* - Multiple sync sessions
|
|
8
|
+
* - Stress testing
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
11
|
+
import * as fs from 'node:fs/promises';
|
|
12
|
+
import * as path from 'node:path';
|
|
13
|
+
import * as os from 'node:os';
|
|
14
|
+
import * as crypto from 'node:crypto';
|
|
15
|
+
import { SyncWal } from './sync-wal.js';
|
|
16
|
+
import { FileWalStorage } from './file-storage.js';
|
|
17
|
+
import { LanceDbWalStorage } from './lancedb-storage.js';
|
|
18
|
+
import { createWalStorage } from './index.js';
|
|
19
|
+
describe('WAL Integration Tests', () => {
|
|
20
|
+
let tempDir;
|
|
21
|
+
let storage;
|
|
22
|
+
let syncWal;
|
|
23
|
+
beforeEach(async () => {
|
|
24
|
+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'wal-integration-'));
|
|
25
|
+
storage = new FileWalStorage(tempDir);
|
|
26
|
+
syncWal = new SyncWal(storage, { checkpointInterval: 10 });
|
|
27
|
+
});
|
|
28
|
+
afterEach(async () => {
|
|
29
|
+
syncWal.stopHeartbeat();
|
|
30
|
+
await fs.rm(tempDir, { recursive: true, force: true });
|
|
31
|
+
});
|
|
32
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
33
|
+
// FULL SYNC CYCLE
|
|
34
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
35
|
+
describe('Full Sync Cycle', () => {
|
|
36
|
+
it('should complete a full notes sync with multiple checkpoints', async () => {
|
|
37
|
+
const files = Array.from({ length: 35 }, (_, i) => `/note-${i}.md`);
|
|
38
|
+
const manifestHash = crypto.createHash('sha256').update(files.join('\n')).digest('hex');
|
|
39
|
+
const taskId = await syncWal.startTask('notes', files.length, manifestHash);
|
|
40
|
+
// Simulate indexing each file
|
|
41
|
+
for (let i = 0; i < files.length; i++) {
|
|
42
|
+
const action = i % 3 === 0 ? 'added' : 'updated';
|
|
43
|
+
await syncWal.fileProcessed(taskId, files[i], Math.floor(Math.random() * 5) + 1, action);
|
|
44
|
+
}
|
|
45
|
+
// Verify progress before completion
|
|
46
|
+
const progress = syncWal.getProgress();
|
|
47
|
+
expect(progress?.processedFiles).toBe(35);
|
|
48
|
+
expect(progress?.added).toBe(12); // Every 3rd file (0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33)
|
|
49
|
+
expect(progress?.updated).toBe(23);
|
|
50
|
+
await syncWal.completeTask(taskId);
|
|
51
|
+
// Verify final state
|
|
52
|
+
const manifest = await storage.getManifest();
|
|
53
|
+
expect(manifest?.current).toBeNull();
|
|
54
|
+
expect(manifest?.lastCompleted?.status).toBe('completed');
|
|
55
|
+
expect(manifest?.lastCompleted?.totalFiles).toBe(35);
|
|
56
|
+
});
|
|
57
|
+
it('should complete a full code sync with failed files', async () => {
|
|
58
|
+
const files = Array.from({ length: 20 }, (_, i) => `/src/file-${i}.ts`);
|
|
59
|
+
const manifestHash = crypto.createHash('sha256').update(files.join('\n')).digest('hex');
|
|
60
|
+
const taskId = await syncWal.startTask('code', files.length, manifestHash);
|
|
61
|
+
// Simulate indexing with some failures
|
|
62
|
+
for (let i = 0; i < files.length; i++) {
|
|
63
|
+
if (i === 5 || i === 15) {
|
|
64
|
+
await syncWal.fileFailed(taskId, files[i], `Syntax error in file ${i}`, 3);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
await syncWal.fileProcessed(taskId, files[i], 2);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
await syncWal.completeTask(taskId);
|
|
71
|
+
const manifest = await storage.getManifest();
|
|
72
|
+
expect(manifest?.lastCompleted?.failedCount).toBe(2);
|
|
73
|
+
expect(manifest?.lastCompleted?.stats.updated).toBe(18);
|
|
74
|
+
});
|
|
75
|
+
it('should handle sync with delete phase', async () => {
|
|
76
|
+
const taskId = await syncWal.startTask('notes', 15);
|
|
77
|
+
// Indexing phase
|
|
78
|
+
syncWal.setPhase('indexing');
|
|
79
|
+
for (let i = 0; i < 10; i++) {
|
|
80
|
+
await syncWal.fileProcessed(taskId, `/file-${i}.md`, 1);
|
|
81
|
+
}
|
|
82
|
+
// Delete phase
|
|
83
|
+
syncWal.setPhase('deleting');
|
|
84
|
+
for (let i = 0; i < 5; i++) {
|
|
85
|
+
await syncWal.fileDeleted(taskId, `/old-file-${i}.md`);
|
|
86
|
+
}
|
|
87
|
+
await syncWal.completeTask(taskId);
|
|
88
|
+
const manifest = await storage.getManifest();
|
|
89
|
+
expect(manifest?.lastCompleted?.stats.updated).toBe(10);
|
|
90
|
+
expect(manifest?.lastCompleted?.stats.deleted).toBe(5);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
94
|
+
// RECOVERY SCENARIOS
|
|
95
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
96
|
+
describe('Recovery Scenarios', () => {
|
|
97
|
+
it('should recover and resume interrupted sync', async () => {
|
|
98
|
+
const files = Array.from({ length: 50 }, (_, i) => `/file-${i}.md`);
|
|
99
|
+
const manifestHash = crypto.createHash('sha256').update(files.join('\n')).digest('hex');
|
|
100
|
+
// Start first sync and process some files
|
|
101
|
+
const taskId1 = await syncWal.startTask('notes', files.length, manifestHash);
|
|
102
|
+
for (let i = 0; i < 25; i++) {
|
|
103
|
+
await syncWal.fileProcessed(taskId1, files[i], 1);
|
|
104
|
+
}
|
|
105
|
+
// Simulate crash by directly stopping without cleanup
|
|
106
|
+
syncWal.stopHeartbeat();
|
|
107
|
+
// Create new SyncWal instance (simulates server restart)
|
|
108
|
+
const newStorage = new FileWalStorage(tempDir);
|
|
109
|
+
const newSyncWal = new SyncWal(newStorage, { checkpointInterval: 10 });
|
|
110
|
+
// Initialize and check for recovery
|
|
111
|
+
const plan = await newSyncWal.initialize();
|
|
112
|
+
expect(plan).not.toBeNull();
|
|
113
|
+
expect(plan?.taskId).toBe(taskId1);
|
|
114
|
+
expect(plan?.skipCount).toBe(25);
|
|
115
|
+
expect(plan?.manifestHash).toBe(manifestHash);
|
|
116
|
+
// Resume and complete
|
|
117
|
+
await newSyncWal.resumeTask(plan);
|
|
118
|
+
// Process remaining files
|
|
119
|
+
for (let i = 25; i < files.length; i++) {
|
|
120
|
+
await newSyncWal.fileProcessed(taskId1, files[i], 1);
|
|
121
|
+
}
|
|
122
|
+
await newSyncWal.completeTask(taskId1);
|
|
123
|
+
// Verify completion
|
|
124
|
+
const manifest = await newStorage.getManifest();
|
|
125
|
+
expect(manifest?.lastCompleted?.status).toBe('completed');
|
|
126
|
+
expect(manifest?.lastCompleted?.totalFiles).toBe(50);
|
|
127
|
+
newSyncWal.stopHeartbeat();
|
|
128
|
+
});
|
|
129
|
+
it('should detect manifest hash mismatch on recovery', async () => {
|
|
130
|
+
const files1 = ['/a.md', '/b.md', '/c.md'];
|
|
131
|
+
const hash1 = crypto.createHash('sha256').update(files1.join('\n')).digest('hex');
|
|
132
|
+
// Start sync and checkpoint
|
|
133
|
+
const taskId = await syncWal.startTask('notes', 3, hash1);
|
|
134
|
+
await syncWal.fileProcessed(taskId, files1[0], 1);
|
|
135
|
+
await syncWal.checkpoint(); // Force checkpoint
|
|
136
|
+
syncWal.stopHeartbeat();
|
|
137
|
+
// Simulate restart with different file list
|
|
138
|
+
const newStorage = new FileWalStorage(tempDir);
|
|
139
|
+
const newSyncWal = new SyncWal(newStorage, { checkpointInterval: 10 });
|
|
140
|
+
const plan = await newSyncWal.initialize();
|
|
141
|
+
expect(plan).not.toBeNull();
|
|
142
|
+
// In real code, you'd compare manifestHash with current files
|
|
143
|
+
// If they differ, you'd start fresh instead of resuming
|
|
144
|
+
const files2 = ['/a.md', '/b.md', '/d.md']; // /c.md changed to /d.md
|
|
145
|
+
const hash2 = crypto.createHash('sha256').update(files2.join('\n')).digest('hex');
|
|
146
|
+
expect(plan?.manifestHash).toBe(hash1);
|
|
147
|
+
expect(hash1).not.toBe(hash2); // Hashes should differ
|
|
148
|
+
newSyncWal.stopHeartbeat();
|
|
149
|
+
// Clear lock for cleanup
|
|
150
|
+
await newStorage.forceClearLock();
|
|
151
|
+
});
|
|
152
|
+
it('should recover from crash before first checkpoint', async () => {
|
|
153
|
+
const taskId = await syncWal.startTask('notes', 100);
|
|
154
|
+
// Process few files, not enough for checkpoint (interval=10)
|
|
155
|
+
for (let i = 0; i < 3; i++) {
|
|
156
|
+
await syncWal.fileProcessed(taskId, `/file-${i}.md`, 1);
|
|
157
|
+
}
|
|
158
|
+
// No checkpoint written yet, simulate crash
|
|
159
|
+
syncWal.stopHeartbeat();
|
|
160
|
+
// New instance
|
|
161
|
+
const newStorage = new FileWalStorage(tempDir);
|
|
162
|
+
const newSyncWal = new SyncWal(newStorage, { checkpointInterval: 10 });
|
|
163
|
+
const plan = await newSyncWal.initialize();
|
|
164
|
+
// Without checkpoint, recovery relies on WAL entries
|
|
165
|
+
// After clear-lock recovery, we should see state from WAL
|
|
166
|
+
expect(plan).toBeNull(); // No checkpoint means no recovery plan
|
|
167
|
+
newSyncWal.stopHeartbeat();
|
|
168
|
+
await newStorage.forceClearLock();
|
|
169
|
+
});
|
|
170
|
+
it('should recover stats from checkpoint', async () => {
|
|
171
|
+
const taskId = await syncWal.startTask('notes', 50);
|
|
172
|
+
// Add varied operations
|
|
173
|
+
for (let i = 0; i < 5; i++) {
|
|
174
|
+
await syncWal.fileProcessed(taskId, `/new-${i}.md`, 1, 'added');
|
|
175
|
+
}
|
|
176
|
+
for (let i = 0; i < 3; i++) {
|
|
177
|
+
await syncWal.fileProcessed(taskId, `/update-${i}.md`, 1, 'updated');
|
|
178
|
+
}
|
|
179
|
+
for (let i = 0; i < 2; i++) {
|
|
180
|
+
await syncWal.fileFailed(taskId, `/fail-${i}.md`, 'error', 0);
|
|
181
|
+
}
|
|
182
|
+
// Force checkpoint at 10 files
|
|
183
|
+
syncWal.stopHeartbeat();
|
|
184
|
+
// Recover
|
|
185
|
+
const newStorage = new FileWalStorage(tempDir);
|
|
186
|
+
const newSyncWal = new SyncWal(newStorage, { checkpointInterval: 10 });
|
|
187
|
+
const plan = await newSyncWal.initialize();
|
|
188
|
+
expect(plan).not.toBeNull();
|
|
189
|
+
expect(plan?.stats.added).toBe(5);
|
|
190
|
+
expect(plan?.stats.updated).toBe(3);
|
|
191
|
+
expect(plan?.stats.failed).toHaveLength(2);
|
|
192
|
+
expect(plan?.skipCount).toBe(10);
|
|
193
|
+
newSyncWal.stopHeartbeat();
|
|
194
|
+
await newStorage.forceClearLock();
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
198
|
+
// MULTIPLE SYNC SESSIONS
|
|
199
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
200
|
+
describe('Multiple Sync Sessions', () => {
|
|
201
|
+
it('should preserve lastCompleted across sessions', async () => {
|
|
202
|
+
// First sync
|
|
203
|
+
const taskId1 = await syncWal.startTask('notes', 10);
|
|
204
|
+
for (let i = 0; i < 10; i++) {
|
|
205
|
+
await syncWal.fileProcessed(taskId1, `/n-${i}.md`, 1);
|
|
206
|
+
}
|
|
207
|
+
await syncWal.completeTask(taskId1);
|
|
208
|
+
// Second sync
|
|
209
|
+
const taskId2 = await syncWal.startTask('code', 5);
|
|
210
|
+
for (let i = 0; i < 5; i++) {
|
|
211
|
+
await syncWal.fileProcessed(taskId2, `/c-${i}.ts`, 1);
|
|
212
|
+
}
|
|
213
|
+
await syncWal.completeTask(taskId2);
|
|
214
|
+
// lastCompleted should be the second sync
|
|
215
|
+
const manifest = await storage.getManifest();
|
|
216
|
+
expect(manifest?.lastCompleted?.id).toBe(taskId2);
|
|
217
|
+
expect(manifest?.lastCompleted?.type).toBe('code');
|
|
218
|
+
// Start third sync and verify we can still access lastCompleted
|
|
219
|
+
const taskId3 = await syncWal.startTask('notes', 3);
|
|
220
|
+
const manifestDuring = await syncWal.getManifest();
|
|
221
|
+
expect(manifestDuring?.lastCompleted?.id).toBe(taskId2);
|
|
222
|
+
await syncWal.completeTask(taskId3);
|
|
223
|
+
});
|
|
224
|
+
it('should handle alternating notes and code syncs', async () => {
|
|
225
|
+
for (let round = 0; round < 3; round++) {
|
|
226
|
+
const type = round % 2 === 0 ? 'notes' : 'code';
|
|
227
|
+
const taskId = await syncWal.startTask(type, 5);
|
|
228
|
+
for (let i = 0; i < 5; i++) {
|
|
229
|
+
await syncWal.fileProcessed(taskId, `/r${round}-f${i}.${type === 'notes' ? 'md' : 'ts'}`, 1);
|
|
230
|
+
}
|
|
231
|
+
await syncWal.completeTask(taskId);
|
|
232
|
+
const manifest = await storage.getManifest();
|
|
233
|
+
expect(manifest?.lastCompleted?.type).toBe(type);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
238
|
+
// FACTORY FUNCTION
|
|
239
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
240
|
+
describe('Factory Function', () => {
|
|
241
|
+
it('should create FileWalStorage via factory', () => {
|
|
242
|
+
const storage = createWalStorage({ type: 'file', dir: tempDir });
|
|
243
|
+
expect(storage).toBeInstanceOf(FileWalStorage);
|
|
244
|
+
});
|
|
245
|
+
it('should create LanceDbWalStorage via factory', () => {
|
|
246
|
+
const storage = createWalStorage({ type: 'lancedb', dbPath: tempDir });
|
|
247
|
+
expect(storage).toBeInstanceOf(LanceDbWalStorage);
|
|
248
|
+
});
|
|
249
|
+
it('should throw for postgres storage (not implemented)', () => {
|
|
250
|
+
expect(() => createWalStorage({ type: 'postgres' })).toThrow(/Postgres storage not implemented/);
|
|
251
|
+
});
|
|
252
|
+
it('should throw when dir not provided for file storage', () => {
|
|
253
|
+
expect(() => createWalStorage({ type: 'file' })).toThrow(/dir is required/);
|
|
254
|
+
});
|
|
255
|
+
it('should throw when dbPath not provided for lancedb storage', () => {
|
|
256
|
+
expect(() => createWalStorage({ type: 'lancedb' })).toThrow(/dbPath is required/);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
260
|
+
// WAL SIZE BOUNDS
|
|
261
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
262
|
+
describe('WAL Size Bounds', () => {
|
|
263
|
+
it('should keep WAL size bounded after checkpoints', async () => {
|
|
264
|
+
const taskId = await syncWal.startTask('notes', 100);
|
|
265
|
+
// Process many files (should trigger multiple checkpoints)
|
|
266
|
+
for (let i = 0; i < 35; i++) {
|
|
267
|
+
await syncWal.fileProcessed(taskId, `/file-${i}.md`, 1);
|
|
268
|
+
}
|
|
269
|
+
// Check WAL size - should be bounded to entries since last checkpoint
|
|
270
|
+
const entries = await storage.getAllEntries();
|
|
271
|
+
// With checkpoint interval of 10, WAL should have at most ~15 entries
|
|
272
|
+
// (checkpoint + entries after it)
|
|
273
|
+
expect(entries.length).toBeLessThanOrEqual(15);
|
|
274
|
+
await syncWal.completeTask(taskId);
|
|
275
|
+
});
|
|
276
|
+
it('should have small checkpoint file size', async () => {
|
|
277
|
+
const taskId = await syncWal.startTask('notes', 100);
|
|
278
|
+
// Process files to create checkpoint
|
|
279
|
+
for (let i = 0; i < 15; i++) {
|
|
280
|
+
if (i === 5) {
|
|
281
|
+
await syncWal.fileFailed(taskId, `/fail-${i}.md`, 'Error message here', 3);
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
await syncWal.fileProcessed(taskId, `/file-${i}.md`, 1);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const paths = storage.getPaths();
|
|
288
|
+
const stats = await fs.stat(paths.checkpoint);
|
|
289
|
+
// Checkpoint should be small (< 5KB even with failed files)
|
|
290
|
+
expect(stats.size).toBeLessThan(5000);
|
|
291
|
+
await syncWal.completeTask(taskId);
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
295
|
+
// PROGRESS TRACKING
|
|
296
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
297
|
+
describe('Progress Tracking', () => {
|
|
298
|
+
it('should track progress accurately through full sync', async () => {
|
|
299
|
+
const progressHistory = [];
|
|
300
|
+
syncWal.onProgress((p) => {
|
|
301
|
+
progressHistory.push({
|
|
302
|
+
processed: p.processedFiles,
|
|
303
|
+
added: p.added,
|
|
304
|
+
updated: p.updated,
|
|
305
|
+
deleted: p.deleted,
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
const taskId = await syncWal.startTask('notes', 20);
|
|
309
|
+
for (let i = 0; i < 10; i++) {
|
|
310
|
+
await syncWal.fileProcessed(taskId, `/a-${i}.md`, 1, 'added');
|
|
311
|
+
}
|
|
312
|
+
for (let i = 0; i < 5; i++) {
|
|
313
|
+
await syncWal.fileProcessed(taskId, `/u-${i}.md`, 1, 'updated');
|
|
314
|
+
}
|
|
315
|
+
syncWal.setPhase('deleting');
|
|
316
|
+
for (let i = 0; i < 5; i++) {
|
|
317
|
+
await syncWal.fileDeleted(taskId, `/d-${i}.md`);
|
|
318
|
+
}
|
|
319
|
+
await syncWal.completeTask(taskId);
|
|
320
|
+
// Verify progress was tracked
|
|
321
|
+
expect(progressHistory.length).toBeGreaterThan(0);
|
|
322
|
+
// Last progress should have full counts
|
|
323
|
+
const lastProgress = progressHistory[progressHistory.length - 1];
|
|
324
|
+
expect(lastProgress.added).toBe(10);
|
|
325
|
+
expect(lastProgress.updated).toBe(5);
|
|
326
|
+
expect(lastProgress.deleted).toBe(5);
|
|
327
|
+
expect(lastProgress.processed).toBe(20);
|
|
328
|
+
});
|
|
329
|
+
it('should estimate remaining time based on progress', async () => {
|
|
330
|
+
const taskId = await syncWal.startTask('notes', 100);
|
|
331
|
+
// Process some files with delays to build timing data
|
|
332
|
+
for (let i = 0; i < 10; i++) {
|
|
333
|
+
await syncWal.fileProcessed(taskId, `/f-${i}.md`, 1);
|
|
334
|
+
await new Promise((r) => setTimeout(r, 5));
|
|
335
|
+
}
|
|
336
|
+
const progress = syncWal.getProgress();
|
|
337
|
+
expect(progress?.estimatedRemainingMs).toBeDefined();
|
|
338
|
+
expect(progress?.estimatedRemainingMs).toBeGreaterThan(0);
|
|
339
|
+
// 90 files remaining, ~5ms each = ~450ms expected.
|
|
340
|
+
// Keep a wide upper bound because CI/VM timer jitter can be high.
|
|
341
|
+
expect(progress?.estimatedRemainingMs).toBeLessThan(10000);
|
|
342
|
+
await syncWal.completeTask(taskId);
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
346
|
+
// STRESS TESTING
|
|
347
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
348
|
+
describe('Stress Testing', () => {
|
|
349
|
+
it('should handle large number of files', async () => {
|
|
350
|
+
const fileCount = 500;
|
|
351
|
+
const wal = new SyncWal(storage, { checkpointInterval: 100 });
|
|
352
|
+
const taskId = await wal.startTask('notes', fileCount);
|
|
353
|
+
for (let i = 0; i < fileCount; i++) {
|
|
354
|
+
await wal.fileProcessed(taskId, `/stress/file-${i}.md`, 1);
|
|
355
|
+
}
|
|
356
|
+
await wal.completeTask(taskId);
|
|
357
|
+
const manifest = await storage.getManifest();
|
|
358
|
+
expect(manifest?.lastCompleted?.totalFiles).toBe(fileCount);
|
|
359
|
+
expect(manifest?.lastCompleted?.status).toBe('completed');
|
|
360
|
+
// WAL should still be bounded
|
|
361
|
+
const entries = await storage.getAllEntries();
|
|
362
|
+
expect(entries.length).toBeLessThan(200); // Way less than 500
|
|
363
|
+
wal.stopHeartbeat();
|
|
364
|
+
}, 30000); // Allow 30 seconds for this test
|
|
365
|
+
it('should handle rapid checkpoint creation', async () => {
|
|
366
|
+
const wal = new SyncWal(storage, { checkpointInterval: 1 }); // Checkpoint every file
|
|
367
|
+
const taskId = await wal.startTask('notes', 50);
|
|
368
|
+
for (let i = 0; i < 50; i++) {
|
|
369
|
+
await wal.fileProcessed(taskId, `/rapid-${i}.md`, 1);
|
|
370
|
+
}
|
|
371
|
+
await wal.completeTask(taskId);
|
|
372
|
+
const manifest = await storage.getManifest();
|
|
373
|
+
expect(manifest?.lastCompleted?.status).toBe('completed');
|
|
374
|
+
wal.stopHeartbeat();
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
//# sourceMappingURL=integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../../../src/indexer/wal/integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,IAAI,OAAe,CAAC;IACpB,IAAI,OAAuB,CAAC;IAC5B,IAAI,OAAgB,CAAC;IAErB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;QACvE,OAAO,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;QACtC,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,OAAO,CAAC,aAAa,EAAE,CAAC;QACxB,MAAM,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;YAC3E,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACpE,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAExF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAE5E,8BAA8B;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;gBACjD,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;YAC3F,CAAC;YAED,oCAAoC;YACpC,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;YACvC,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC1C,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,8DAA8D;YAChG,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnC,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAEnC,qBAAqB;YACrB,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC1D,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YACxE,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAExF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAE3E,uCAAuC;YACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;oBACxB,MAAM,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,wBAAwB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC7E,CAAC;qBAAM,CAAC;oBACN,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC;YAED,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAEnC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;YACpD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAEpD,iBAAiB;YACjB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC1D,CAAC;YAED,eAAe;YACf,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;YACzD,CAAC;YAED,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAEnC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACxD,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,qBAAqB;IACrB,8EAA8E;IAE9E,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;YAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACpE,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAExF,0CAA0C;YAC1C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAE7E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,MAAM,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACpD,CAAC;YAED,sDAAsD;YACtD,OAAO,CAAC,aAAa,EAAE,CAAC;YAExB,yDAAyD;YACzD,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;YAC/C,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,UAAU,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,CAAC,CAAC;YAEvE,oCAAoC;YACpC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;YAE3C,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YAC5B,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACnC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAE9C,sBAAsB;YACtB,MAAM,UAAU,CAAC,UAAU,CAAC,IAAK,CAAC,CAAC;YAEnC,0BAA0B;YAC1B,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACvC,MAAM,UAAU,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACvD,CAAC;YAED,MAAM,UAAU,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAEvC,oBAAoB;YACpB,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,WAAW,EAAE,CAAC;YAChD,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC1D,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAErD,UAAU,CAAC,aAAa,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAElF,4BAA4B;YAC5B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;YAC1D,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAClD,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,mBAAmB;YAC/C,OAAO,CAAC,aAAa,EAAE,CAAC;YAExB,4CAA4C;YAC5C,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;YAC/C,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,UAAU,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,CAAC,CAAC;YAEvE,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;YAE3C,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YAE5B,8DAA8D;YAC9D,wDAAwD;YACxD,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB;YACrE,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAElF,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,uBAAuB;YAEtD,UAAU,CAAC,aAAa,EAAE,CAAC;YAC3B,yBAAyB;YACzB,MAAM,UAAU,CAAC,cAAc,EAAE,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAErD,6DAA6D;YAC7D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC1D,CAAC;YAED,4CAA4C;YAC5C,OAAO,CAAC,aAAa,EAAE,CAAC;YAExB,eAAe;YACf,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;YAC/C,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,UAAU,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,CAAC,CAAC;YAEvE,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;YAE3C,qDAAqD;YACrD,0DAA0D;YAC1D,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,uCAAuC;YAEhE,UAAU,CAAC,aAAa,EAAE,CAAC;YAC3B,MAAM,UAAU,CAAC,cAAc,EAAE,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;YACpD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAEpD,wBAAwB;YACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;YAClE,CAAC;YACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;YACvE,CAAC;YACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;YAChE,CAAC;YAED,+BAA+B;YAC/B,OAAO,CAAC,aAAa,EAAE,CAAC;YAExB,UAAU;YACV,MAAM,UAAU,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC;YAC/C,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,UAAU,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,CAAC,CAAC;YAEvE,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;YAE3C,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YAC5B,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACpC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEjC,UAAU,CAAC,aAAa,EAAE,CAAC;YAC3B,MAAM,UAAU,CAAC,cAAc,EAAE,CAAC;QACpC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,yBAAyB;IACzB,8EAA8E;IAE9E,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,aAAa;YACb,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,MAAM,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACxD,CAAC;YACD,MAAM,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAEpC,cAAc;YACd,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACxD,CAAC;YACD,MAAM,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAEpC,0CAA0C;YAC1C,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAClD,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAEnD,gEAAgE;YAChE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACpD,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;YACnD,MAAM,CAAC,cAAc,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAExD,MAAM,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;gBACvC,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;gBAChD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,IAAwB,EAAE,CAAC,CAAC,CAAC;gBAEpE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC3B,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,KAAK,KAAK,KAAK,CAAC,IAAI,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC/F,CAAC;gBAED,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;gBAEnC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;gBAC7C,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnD,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,mBAAmB;IACnB,8EAA8E;IAE9E,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,OAAO,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;YACjE,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,OAAO,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YACvE,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAC1D,kCAAkC,CACnC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CACtD,iBAAiB,CAClB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CACzD,oBAAoB,CACrB,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAErD,2DAA2D;YAC3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC1D,CAAC;YAED,sEAAsE;YACtE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC;YAC9C,sEAAsE;YACtE,kCAAkC;YAClC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;YAE/C,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAErD,qCAAqC;YACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBACZ,MAAM,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC;gBAC7E,CAAC;qBAAM,CAAC;oBACN,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;gBAC1D,CAAC;YACH,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAE9C,4DAA4D;YAC5D,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAEtC,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,oBAAoB;IACpB,8EAA8E;IAE9E,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,eAAe,GAKhB,EAAE,CAAC;YAER,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE;gBACvB,eAAe,CAAC,IAAI,CAAC;oBACnB,SAAS,EAAE,CAAC,CAAC,cAAc;oBAC3B,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,OAAO,EAAE,CAAC,CAAC,OAAO;iBACnB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAEpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;YAChE,CAAC;YACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;YAClE,CAAC;YACD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YAClD,CAAC;YAED,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAEnC,8BAA8B;YAC9B,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAElD,wCAAwC;YACxC,MAAM,YAAY,GAAG,eAAe,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACjE,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAErD,sDAAsD;YACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,MAAM,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;gBACrD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7C,CAAC;YAED,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;YACvC,MAAM,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC,WAAW,EAAE,CAAC;YACrD,MAAM,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAE1D,mDAAmD;YACnD,kEAAkE;YAClE,MAAM,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YAE3D,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAC9E,iBAAiB;IACjB,8EAA8E;IAE9E,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,MAAM,SAAS,GAAG,GAAG,CAAC;YACtB,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;YAE9D,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAEvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;gBACnC,MAAM,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAC7D,CAAC;YAED,MAAM,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAE/B,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC5D,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAE1D,8BAA8B;YAC9B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC;YAC9C,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,oBAAoB;YAE9D,GAAG,CAAC,aAAa,EAAE,CAAC;QACtB,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,iCAAiC;QAE5C,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,kBAAkB,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,wBAAwB;YACrF,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAEhD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,MAAM,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACvD,CAAC;YAED,MAAM,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAE/B,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;YAC7C,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAE1D,GAAG,CAAC,aAAa,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LanceDbWalStorage - LanceDB-based implementation of WalStorage interface
|
|
3
|
+
*
|
|
4
|
+
* Tables:
|
|
5
|
+
* - sync_lock - Global lock with row versioning for CAS
|
|
6
|
+
* - sync_wal - Append-only WAL entries
|
|
7
|
+
* - sync_checkpoint - Checkpoint data (singleton)
|
|
8
|
+
* - sync_manifest - Manifest data (singleton)
|
|
9
|
+
*
|
|
10
|
+
* Lock Strategy:
|
|
11
|
+
* Uses row versioning with Compare-and-Swap (CAS) pattern:
|
|
12
|
+
* 1. Read current lock
|
|
13
|
+
* 2. If stale (heartbeat timeout), clear it with CAS
|
|
14
|
+
* 3. Try to add new lock (fails if another process already acquired)
|
|
15
|
+
*/
|
|
16
|
+
import type { WalStorage, LockData, WalEntry, CheckpointData, ManifestData } from './types.js';
|
|
17
|
+
export declare class LanceDbWalStorage implements WalStorage {
|
|
18
|
+
private dbPath;
|
|
19
|
+
private storageOptions?;
|
|
20
|
+
private db;
|
|
21
|
+
private lockTable;
|
|
22
|
+
private walTable;
|
|
23
|
+
private checkpointTable;
|
|
24
|
+
private manifestTable;
|
|
25
|
+
private initialized;
|
|
26
|
+
constructor(dbPath: string, storageOptions?: Record<string, string> | undefined);
|
|
27
|
+
initialize(): Promise<void>;
|
|
28
|
+
private ensureLockTable;
|
|
29
|
+
private ensureWalTable;
|
|
30
|
+
private ensureCheckpointTable;
|
|
31
|
+
private ensureManifestTable;
|
|
32
|
+
acquireLock(lock: LockData): Promise<boolean>;
|
|
33
|
+
releaseLock(lockId: string): Promise<void>;
|
|
34
|
+
getLock(): Promise<LockData | null>;
|
|
35
|
+
updateHeartbeat(lockId: string): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Force clear the lock.
|
|
38
|
+
* Use with caution - only for stale lock recovery.
|
|
39
|
+
*/
|
|
40
|
+
forceClearLock(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Atomically clear lock only if it matches expected state.
|
|
43
|
+
* Uses row versioning (CAS) to prevent race conditions.
|
|
44
|
+
*/
|
|
45
|
+
compareAndClearLock(expectedLock: LockData): Promise<boolean>;
|
|
46
|
+
appendEntry(entry: WalEntry): Promise<void>;
|
|
47
|
+
getEntriesFromLsn(lsn: number): Promise<WalEntry[]>;
|
|
48
|
+
getAllEntries(): Promise<WalEntry[]>;
|
|
49
|
+
truncateBeforeLsn(lsn: number): Promise<void>;
|
|
50
|
+
clearWal(): Promise<void>;
|
|
51
|
+
writeCheckpoint(data: CheckpointData): Promise<void>;
|
|
52
|
+
getCheckpoint(): Promise<CheckpointData | null>;
|
|
53
|
+
clearCheckpoint(): Promise<void>;
|
|
54
|
+
writeManifest(data: ManifestData): Promise<void>;
|
|
55
|
+
getManifest(): Promise<ManifestData | null>;
|
|
56
|
+
clearManifest(): Promise<void>;
|
|
57
|
+
clear(): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Check if PID is still running (for stale lock detection)
|
|
60
|
+
*/
|
|
61
|
+
static isPidRunning(pid: number): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Get table names for debugging/testing
|
|
64
|
+
*/
|
|
65
|
+
getTableNames(): {
|
|
66
|
+
lock: string;
|
|
67
|
+
wal: string;
|
|
68
|
+
checkpoint: string;
|
|
69
|
+
manifest: string;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=lancedb-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lancedb-storage.d.ts","sourceRoot":"","sources":["../../../src/indexer/wal/lancedb-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EACV,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,cAAc,EACd,YAAY,EACb,MAAM,YAAY,CAAC;AA4CpB,qBAAa,iBAAkB,YAAW,UAAU;IAShD,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,cAAc,CAAC;IATzB,OAAO,CAAC,EAAE,CAAmC;IAC7C,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,WAAW,CAAS;gBAGlB,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,YAAA;IAO3C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YA8BnB,eAAe;YAwBf,cAAc;YAsBd,qBAAqB;YAoBrB,mBAAmB;IAwB3B,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAuC7C,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1C,OAAO,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IA0BnC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BpD;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAWrC;;;OAGG;IACG,mBAAmB,CAAC,YAAY,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IA0C7D,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAc3C,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAyBnD,aAAa,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAIpC,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW7C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAezB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBpD,aAAa,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAoB/C,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAehC,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBhD,WAAW,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAoB3C,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAe9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IASzC;;OAEG;IACH,aAAa,IAAI;QACf,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;KAClB;CAQF"}
|