mdcontext 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/README.md +28 -0
- package/.changeset/config.json +11 -0
- package/.claude/settings.local.json +25 -0
- package/.github/workflows/ci.yml +83 -0
- package/.github/workflows/claude-code-review.yml +44 -0
- package/.github/workflows/claude.yml +85 -0
- package/.github/workflows/release.yml +113 -0
- package/.tldrignore +112 -0
- package/BACKLOG.md +338 -0
- package/CONTRIBUTING.md +186 -0
- package/NOTES/NOTES +44 -0
- package/README.md +434 -11
- package/biome.json +36 -0
- package/cspell.config.yaml +14 -0
- package/dist/chunk-23UPXDNL.js +3044 -0
- package/dist/chunk-2W7MO2DL.js +1366 -0
- package/dist/chunk-3NUAZGMA.js +1689 -0
- package/dist/chunk-7TOWB2XB.js +366 -0
- package/dist/chunk-7XOTOADQ.js +3065 -0
- package/dist/chunk-AH2PDM2K.js +3042 -0
- package/dist/chunk-BNXWSZ63.js +3742 -0
- package/dist/chunk-BTL5DJVU.js +3222 -0
- package/dist/chunk-HDHYG7E4.js +104 -0
- package/dist/chunk-HLR4KZBP.js +3234 -0
- package/dist/chunk-IP3FRFEB.js +1045 -0
- package/dist/chunk-KHU56VDO.js +3042 -0
- package/dist/chunk-KRYIFLQR.js +88 -0
- package/dist/chunk-LBSDNLEM.js +287 -0
- package/dist/chunk-MNTQ7HCP.js +2643 -0
- package/dist/chunk-MUJELQQ6.js +1387 -0
- package/dist/chunk-MXJGMSLV.js +2199 -0
- package/dist/chunk-N6QJGC3Z.js +2636 -0
- package/dist/chunk-OBELGBPM.js +1713 -0
- package/dist/chunk-OT7R5XTA.js +3192 -0
- package/dist/chunk-P7X4RA2T.js +106 -0
- package/dist/chunk-PIDUQNC2.js +3185 -0
- package/dist/chunk-POGCDIH4.js +3187 -0
- package/dist/chunk-PSIEOQGZ.js +3043 -0
- package/dist/chunk-PVRT3IHA.js +3238 -0
- package/dist/chunk-QNN4TT23.js +1430 -0
- package/dist/chunk-RE3R45RJ.js +3042 -0
- package/dist/chunk-S7E6TFX6.js +803 -0
- package/dist/chunk-SG6GLU4U.js +1378 -0
- package/dist/chunk-SJCDV2ST.js +274 -0
- package/dist/chunk-SYE5XLF3.js +104 -0
- package/dist/chunk-T5VLYBZD.js +103 -0
- package/dist/chunk-TOQB7VWU.js +3238 -0
- package/dist/chunk-VFNMZ4ZQ.js +3228 -0
- package/dist/chunk-VVTGZNBT.js +1629 -0
- package/dist/chunk-W7Q4RFEV.js +104 -0
- package/dist/chunk-XTYYVRLO.js +3190 -0
- package/dist/chunk-Y6MDYVJD.js +3063 -0
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.js +5458 -0
- package/dist/index.d.ts +653 -0
- package/dist/index.js +79 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +472 -0
- package/dist/schema-BAWSG7KY.js +22 -0
- package/dist/schema-E3QUPL26.js +20 -0
- package/dist/schema-EHL7WUT6.js +20 -0
- package/docs/019-USAGE.md +625 -0
- package/docs/020-current-implementation.md +364 -0
- package/docs/021-DOGFOODING-FINDINGS.md +175 -0
- package/docs/BACKLOG.md +80 -0
- package/docs/CONFIG.md +1123 -0
- package/docs/DESIGN.md +439 -0
- package/docs/ERRORS.md +383 -0
- package/docs/PROJECT.md +88 -0
- package/docs/ROADMAP.md +407 -0
- package/docs/summarization.md +320 -0
- package/docs/test-links.md +9 -0
- package/justfile +40 -0
- package/package.json +74 -9
- package/pnpm-workspace.yaml +5 -0
- package/research/INDEX.md +315 -0
- package/research/code-review/README.md +90 -0
- package/research/code-review/cli-error-handling-review.md +979 -0
- package/research/code-review/code-review-validation-report.md +464 -0
- package/research/code-review/main-ts-review.md +1128 -0
- package/research/config-analysis/01-current-implementation.md +470 -0
- package/research/config-analysis/02-strategy-recommendation.md +428 -0
- package/research/config-analysis/03-task-candidates.md +715 -0
- package/research/config-analysis/033-research-configuration-management.md +828 -0
- package/research/config-analysis/034-research-effect-cli-config.md +1504 -0
- package/research/config-analysis/04-consolidated-task-candidates.md +277 -0
- package/research/config-docs/SUMMARY.md +357 -0
- package/research/config-docs/TEST-RESULTS.md +776 -0
- package/research/config-docs/TODO.md +542 -0
- package/research/config-docs/analysis.md +744 -0
- package/research/config-docs/fix-validation.md +502 -0
- package/research/config-docs/help-audit.md +264 -0
- package/research/config-docs/help-system-analysis.md +890 -0
- package/research/dogfood/consolidated-tool-evaluation.md +373 -0
- package/research/dogfood/strategy-a/a-synthesis.md +184 -0
- package/research/dogfood/strategy-a/a1-docs.md +226 -0
- package/research/dogfood/strategy-a/a2-amorphic.md +156 -0
- package/research/dogfood/strategy-a/a3-llm.md +164 -0
- package/research/dogfood/strategy-b/b-synthesis.md +228 -0
- package/research/dogfood/strategy-b/b1-architecture.md +207 -0
- package/research/dogfood/strategy-b/b2-gaps.md +258 -0
- package/research/dogfood/strategy-b/b3-workflows.md +250 -0
- package/research/dogfood/strategy-c/c-synthesis.md +451 -0
- package/research/dogfood/strategy-c/c1-explorer.md +192 -0
- package/research/dogfood/strategy-c/c2-diver-memory.md +145 -0
- package/research/dogfood/strategy-c/c3-diver-control.md +148 -0
- package/research/dogfood/strategy-c/c4-diver-failure.md +151 -0
- package/research/dogfood/strategy-c/c5-diver-execution.md +221 -0
- package/research/dogfood/strategy-c/c6-diver-org.md +221 -0
- package/research/effect-cli-error-handling.md +845 -0
- package/research/effect-errors-as-values.md +943 -0
- package/research/errors-task-analysis/00-consolidated-tasks.md +207 -0
- package/research/errors-task-analysis/cli-commands-analysis.md +909 -0
- package/research/errors-task-analysis/embeddings-analysis.md +709 -0
- package/research/errors-task-analysis/index-search-analysis.md +812 -0
- package/research/frontmatter/COMMENTS-ARE-SKIPPED.md +149 -0
- package/research/frontmatter/LLM-CODE-NAVIGATION.md +276 -0
- package/research/issue-review.md +603 -0
- package/research/llm-summarization/agent-cli-tools-2026.md +1082 -0
- package/research/llm-summarization/alternative-providers-2026.md +1428 -0
- package/research/llm-summarization/anthropic-2026.md +367 -0
- package/research/llm-summarization/claude-cli-integration.md +1706 -0
- package/research/llm-summarization/cli-integration-patterns.md +3155 -0
- package/research/llm-summarization/openai-2026.md +473 -0
- package/research/llm-summarization/openai-compatible-providers-2026.md +1022 -0
- package/research/llm-summarization/opencode-cli-integration.md +1552 -0
- package/research/llm-summarization/prompt-engineering-2026.md +1426 -0
- package/research/llm-summarization/prototype-results.md +56 -0
- package/research/llm-summarization/provider-switching-patterns-2026.md +2153 -0
- package/research/llm-summarization/typescript-llm-libraries-2026.md +2436 -0
- package/research/mdcontext-error-analysis.md +521 -0
- package/research/mdcontext-pudding/00-EXECUTIVE-SUMMARY.md +282 -0
- package/research/mdcontext-pudding/01-index-embed.md +956 -0
- package/research/mdcontext-pudding/02-search-COMMANDS.md +142 -0
- package/research/mdcontext-pudding/02-search-SUMMARY.md +146 -0
- package/research/mdcontext-pudding/02-search.md +970 -0
- package/research/mdcontext-pudding/03-context.md +779 -0
- package/research/mdcontext-pudding/04-navigation-and-analytics.md +803 -0
- package/research/mdcontext-pudding/04-tree.md +704 -0
- package/research/mdcontext-pudding/05-config.md +1038 -0
- package/research/mdcontext-pudding/06-links-summary.txt +87 -0
- package/research/mdcontext-pudding/06-links.md +679 -0
- package/research/mdcontext-pudding/07-stats.md +693 -0
- package/research/mdcontext-pudding/BUG-FIX-PLAN.md +388 -0
- package/research/mdcontext-pudding/P0-BUG-VALIDATION.md +167 -0
- package/research/mdcontext-pudding/README.md +168 -0
- package/research/mdcontext-pudding/TESTING-SUMMARY.md +128 -0
- package/research/npm_publish/011-npm-workflow-research-agent2.md +792 -0
- package/research/npm_publish/012-npm-workflow-research-agent1.md +530 -0
- package/research/npm_publish/013-npm-workflow-research-agent3.md +722 -0
- package/research/npm_publish/014-npm-workflow-synthesis.md +556 -0
- package/research/npm_publish/031-npm-workflow-task-analysis.md +134 -0
- package/research/research-quality-review.md +834 -0
- package/research/semantic-search/002-research-embedding-models.md +490 -0
- package/research/semantic-search/003-research-rag-alternatives.md +523 -0
- package/research/semantic-search/004-research-vector-search.md +841 -0
- package/research/semantic-search/032-research-semantic-search.md +427 -0
- package/research/semantic-search/embedding-text-analysis.md +156 -0
- package/research/semantic-search/multi-word-failure-reproduction.md +171 -0
- package/research/semantic-search/query-processing-analysis.md +207 -0
- package/research/semantic-search/root-cause-and-solution.md +114 -0
- package/research/semantic-search/threshold-validation-report.md +69 -0
- package/research/semantic-search/vector-search-analysis.md +63 -0
- package/research/task-management-2026/00-synthesis-recommendations.md +295 -0
- package/research/task-management-2026/01-ai-workflow-tools.md +416 -0
- package/research/task-management-2026/02-agent-framework-patterns.md +476 -0
- package/research/task-management-2026/03-lightweight-file-based.md +567 -0
- package/research/task-management-2026/04-established-tools-ai-features.md +541 -0
- package/research/task-management-2026/linear/01-core-features-workflow.md +771 -0
- package/research/task-management-2026/linear/02-api-integrations.md +930 -0
- package/research/task-management-2026/linear/03-ai-features.md +368 -0
- package/research/task-management-2026/linear/04-pricing-setup.md +205 -0
- package/research/task-management-2026/linear/05-usage-patterns-best-practices.md +605 -0
- package/research/test-path-issues.md +276 -0
- package/review/ALP-76/1-error-type-design.md +962 -0
- package/review/ALP-76/2-error-handling-patterns.md +906 -0
- package/review/ALP-76/3-error-presentation.md +624 -0
- package/review/ALP-76/4-test-coverage.md +625 -0
- package/review/ALP-76/5-migration-completeness.md +440 -0
- package/review/ALP-76/6-effect-best-practices.md +755 -0
- package/scripts/apply-branch-protection.sh +47 -0
- package/scripts/branch-protection-templates.json +79 -0
- package/scripts/prototype-summarization.ts +346 -0
- package/scripts/rebuild-hnswlib.js +58 -0
- package/scripts/setup-branch-protection.sh +64 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/active-provider.json +7 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.json +541 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.meta.json +5 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/config.json +8 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/documents.json +60 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/links.json +13 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/sections.json +1197 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/configuration-management.md +99 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/distributed-systems.md +92 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/error-handling.md +78 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/failure-automation.md +55 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/job-context.md +69 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/process-orchestration.md +99 -0
- package/src/cli/argv-preprocessor.test.ts +210 -0
- package/src/cli/argv-preprocessor.ts +202 -0
- package/src/cli/cli.test.ts +627 -0
- package/src/cli/commands/backlinks.ts +54 -0
- package/src/cli/commands/config-cmd.ts +642 -0
- package/src/cli/commands/context.ts +285 -0
- package/src/cli/commands/duplicates.ts +122 -0
- package/src/cli/commands/embeddings.ts +529 -0
- package/src/cli/commands/index-cmd.ts +480 -0
- package/src/cli/commands/index.ts +16 -0
- package/src/cli/commands/links.ts +52 -0
- package/src/cli/commands/search.ts +1281 -0
- package/src/cli/commands/stats.ts +149 -0
- package/src/cli/commands/tree.ts +128 -0
- package/src/cli/config-layer.ts +176 -0
- package/src/cli/error-handler.test.ts +235 -0
- package/src/cli/error-handler.ts +655 -0
- package/src/cli/flag-schemas.ts +341 -0
- package/src/cli/help.ts +588 -0
- package/src/cli/index.ts +9 -0
- package/src/cli/main.ts +435 -0
- package/src/cli/options.ts +41 -0
- package/src/cli/shared-error-handling.ts +199 -0
- package/src/cli/typo-suggester.test.ts +105 -0
- package/src/cli/typo-suggester.ts +130 -0
- package/src/cli/utils.ts +259 -0
- package/src/config/file-provider.test.ts +320 -0
- package/src/config/file-provider.ts +273 -0
- package/src/config/index.ts +72 -0
- package/src/config/integration.test.ts +667 -0
- package/src/config/precedence.test.ts +277 -0
- package/src/config/precedence.ts +451 -0
- package/src/config/schema.test.ts +414 -0
- package/src/config/schema.ts +603 -0
- package/src/config/service.test.ts +320 -0
- package/src/config/service.ts +243 -0
- package/src/config/testing.test.ts +264 -0
- package/src/config/testing.ts +110 -0
- package/src/core/index.ts +1 -0
- package/src/core/types.ts +113 -0
- package/src/duplicates/detector.test.ts +183 -0
- package/src/duplicates/detector.ts +414 -0
- package/src/duplicates/index.ts +18 -0
- package/src/embeddings/embedding-namespace.test.ts +300 -0
- package/src/embeddings/embedding-namespace.ts +947 -0
- package/src/embeddings/heading-boost.test.ts +222 -0
- package/src/embeddings/hnsw-build-options.test.ts +198 -0
- package/src/embeddings/hyde.test.ts +272 -0
- package/src/embeddings/hyde.ts +264 -0
- package/src/embeddings/index.ts +10 -0
- package/src/embeddings/openai-provider.ts +414 -0
- package/src/embeddings/pricing.json +22 -0
- package/src/embeddings/provider-constants.ts +204 -0
- package/src/embeddings/provider-errors.test.ts +967 -0
- package/src/embeddings/provider-errors.ts +565 -0
- package/src/embeddings/provider-factory.test.ts +240 -0
- package/src/embeddings/provider-factory.ts +225 -0
- package/src/embeddings/provider-integration.test.ts +788 -0
- package/src/embeddings/query-preprocessing.test.ts +187 -0
- package/src/embeddings/semantic-search-threshold.test.ts +508 -0
- package/src/embeddings/semantic-search.ts +1270 -0
- package/src/embeddings/types.ts +359 -0
- package/src/embeddings/vector-store.ts +708 -0
- package/src/embeddings/voyage-provider.ts +313 -0
- package/src/errors/errors.test.ts +845 -0
- package/src/errors/index.ts +533 -0
- package/src/index/ignore-patterns.test.ts +354 -0
- package/src/index/ignore-patterns.ts +305 -0
- package/src/index/index.ts +4 -0
- package/src/index/indexer.ts +684 -0
- package/src/index/storage.ts +260 -0
- package/src/index/types.ts +147 -0
- package/src/index/watcher.ts +189 -0
- package/src/index.ts +30 -0
- package/src/integration/search-keyword.test.ts +678 -0
- package/src/mcp/server.ts +612 -0
- package/src/parser/index.ts +1 -0
- package/src/parser/parser.test.ts +291 -0
- package/src/parser/parser.ts +394 -0
- package/src/parser/section-filter.test.ts +277 -0
- package/src/parser/section-filter.ts +392 -0
- package/src/search/__tests__/hybrid-search.test.ts +650 -0
- package/src/search/bm25-store.ts +366 -0
- package/src/search/cross-encoder.test.ts +253 -0
- package/src/search/cross-encoder.ts +406 -0
- package/src/search/fuzzy-search.test.ts +419 -0
- package/src/search/fuzzy-search.ts +273 -0
- package/src/search/hybrid-search.ts +448 -0
- package/src/search/path-matcher.test.ts +276 -0
- package/src/search/path-matcher.ts +33 -0
- package/src/search/query-parser.test.ts +260 -0
- package/src/search/query-parser.ts +319 -0
- package/src/search/searcher.test.ts +280 -0
- package/src/search/searcher.ts +724 -0
- package/src/search/wink-bm25.d.ts +30 -0
- package/src/summarization/cli-providers/claude.ts +202 -0
- package/src/summarization/cli-providers/detection.test.ts +273 -0
- package/src/summarization/cli-providers/detection.ts +118 -0
- package/src/summarization/cli-providers/index.ts +8 -0
- package/src/summarization/cost.test.ts +139 -0
- package/src/summarization/cost.ts +102 -0
- package/src/summarization/error-handler.test.ts +127 -0
- package/src/summarization/error-handler.ts +111 -0
- package/src/summarization/index.ts +102 -0
- package/src/summarization/pipeline.test.ts +498 -0
- package/src/summarization/pipeline.ts +231 -0
- package/src/summarization/prompts.test.ts +269 -0
- package/src/summarization/prompts.ts +133 -0
- package/src/summarization/provider-factory.test.ts +396 -0
- package/src/summarization/provider-factory.ts +178 -0
- package/src/summarization/types.ts +184 -0
- package/src/summarize/budget-bugs.test.ts +620 -0
- package/src/summarize/formatters.ts +419 -0
- package/src/summarize/index.ts +20 -0
- package/src/summarize/summarizer.test.ts +275 -0
- package/src/summarize/summarizer.ts +597 -0
- package/src/summarize/verify-bugs.test.ts +238 -0
- package/src/types/huggingface-transformers.d.ts +66 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/tokens.test.ts +142 -0
- package/src/utils/tokens.ts +186 -0
- package/tests/fixtures/cli/.mdcontext/active-provider.json +7 -0
- package/tests/fixtures/cli/.mdcontext/config.json +8 -0
- package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
- package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
- package/tests/fixtures/cli/.mdcontext/indexes/documents.json +33 -0
- package/tests/fixtures/cli/.mdcontext/indexes/links.json +12 -0
- package/tests/fixtures/cli/.mdcontext/indexes/sections.json +247 -0
- package/tests/fixtures/cli/README.md +9 -0
- package/tests/fixtures/cli/api-reference.md +11 -0
- package/tests/fixtures/cli/getting-started.md +11 -0
- package/tests/integration/embed-index.test.ts +712 -0
- package/tests/integration/search-context.test.ts +469 -0
- package/tests/integration/search-semantic.test.ts +522 -0
- package/tsconfig.json +26 -0
- package/vitest.config.ts +16 -0
- package/vitest.setup.ts +12 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ConfigService Unit Tests
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive tests for the Effect-based ConfigService layer and related
|
|
5
|
+
* utilities. This suite verifies how configuration is loaded, merged, and
|
|
6
|
+
* accessed across different Effect layers.
|
|
7
|
+
*
|
|
8
|
+
* Patterns under test:
|
|
9
|
+
* - Default configuration via `ConfigServiceDefault`
|
|
10
|
+
* - Live configuration via `ConfigServiceLive` combined with `ConfigProvider`
|
|
11
|
+
* - Creating ad-hoc layers with `makeConfigLayer` and `makeConfigLayerPartial`
|
|
12
|
+
* - Merging user-provided values with `defaultConfig` using `mergeWithDefaults`
|
|
13
|
+
* - Reading configuration through the `ConfigService` tag and helpers
|
|
14
|
+
* (`getConfig`, `getConfigSection`, `getConfigValue`)
|
|
15
|
+
*
|
|
16
|
+
* Key scenarios:
|
|
17
|
+
* - Ensuring all top-level sections (index, search, embeddings, output, paths)
|
|
18
|
+
* receive correct default values when no overrides are provided
|
|
19
|
+
* - Overriding selected values via `ConfigProvider.fromMap` while preserving
|
|
20
|
+
* defaults for unspecified keys
|
|
21
|
+
* - Providing fully-specified configs and partially-specified configs and
|
|
22
|
+
* verifying correct fallback/merge behavior
|
|
23
|
+
* - Validating lookup helpers return the expected values and handle missing
|
|
24
|
+
* keys using Effect/Option semantics
|
|
25
|
+
*
|
|
26
|
+
* Test organization and setup:
|
|
27
|
+
* - Uses Vitest (`describe`/`it`) with Effect programs composed via
|
|
28
|
+
* `Effect.gen` and executed through `Effect.runPromise`
|
|
29
|
+
* - Layers and config providers are attached on a per-test basis using
|
|
30
|
+
* `Effect.provide` and `Effect.withConfigProvider`, so tests are isolated
|
|
31
|
+
* and do not share state between runs
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import { ConfigProvider, Effect, Option } from 'effect'
|
|
35
|
+
import { describe, expect, it } from 'vitest'
|
|
36
|
+
import { defaultConfig } from './schema.js'
|
|
37
|
+
import {
|
|
38
|
+
ConfigService,
|
|
39
|
+
ConfigServiceDefault,
|
|
40
|
+
ConfigServiceLive,
|
|
41
|
+
getConfig,
|
|
42
|
+
getConfigSection,
|
|
43
|
+
getConfigValue,
|
|
44
|
+
makeConfigLayer,
|
|
45
|
+
makeConfigLayerPartial,
|
|
46
|
+
mergeWithDefaults,
|
|
47
|
+
} from './service.js'
|
|
48
|
+
|
|
49
|
+
describe('ConfigService', () => {
|
|
50
|
+
describe('ConfigServiceDefault', () => {
|
|
51
|
+
it('should provide default configuration values', async () => {
|
|
52
|
+
const program = Effect.gen(function* () {
|
|
53
|
+
return yield* ConfigService
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const result = await Effect.runPromise(
|
|
57
|
+
program.pipe(Effect.provide(ConfigServiceDefault)),
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
expect(result.index.maxDepth).toBe(10)
|
|
61
|
+
expect(result.search.defaultLimit).toBe(10)
|
|
62
|
+
expect(result.embeddings.provider).toBe('openai')
|
|
63
|
+
expect(result.output.format).toBe('text')
|
|
64
|
+
expect(result.paths.cacheDir).toBe('.mdcontext/cache')
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
describe('ConfigServiceLive', () => {
|
|
69
|
+
it('should load configuration from ConfigProvider', async () => {
|
|
70
|
+
const program = Effect.gen(function* () {
|
|
71
|
+
return yield* ConfigService
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
const provider = ConfigProvider.fromMap(
|
|
75
|
+
new Map([
|
|
76
|
+
['index.maxDepth', '20'],
|
|
77
|
+
['search.defaultLimit', '25'],
|
|
78
|
+
]),
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
const result = await Effect.runPromise(
|
|
82
|
+
program.pipe(
|
|
83
|
+
Effect.provide(ConfigServiceLive),
|
|
84
|
+
Effect.withConfigProvider(provider),
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
expect(result.index.maxDepth).toBe(20)
|
|
89
|
+
expect(result.search.defaultLimit).toBe(25)
|
|
90
|
+
// Other values should use defaults
|
|
91
|
+
expect(result.embeddings.provider).toBe('openai')
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
describe('makeConfigLayer', () => {
|
|
96
|
+
it('should create a layer with the provided config', async () => {
|
|
97
|
+
const customConfig = {
|
|
98
|
+
...defaultConfig,
|
|
99
|
+
index: { ...defaultConfig.index, maxDepth: 5 },
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const program = Effect.gen(function* () {
|
|
103
|
+
return yield* ConfigService
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
const result = await Effect.runPromise(
|
|
107
|
+
program.pipe(Effect.provide(makeConfigLayer(customConfig))),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
expect(result.index.maxDepth).toBe(5)
|
|
111
|
+
expect(result.search.defaultLimit).toBe(10) // unchanged
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
describe('makeConfigLayerPartial', () => {
|
|
116
|
+
it('should merge partial config with defaults', async () => {
|
|
117
|
+
const program = Effect.gen(function* () {
|
|
118
|
+
return yield* ConfigService
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
const result = await Effect.runPromise(
|
|
122
|
+
program.pipe(
|
|
123
|
+
Effect.provide(
|
|
124
|
+
makeConfigLayerPartial({
|
|
125
|
+
index: { maxDepth: 3 },
|
|
126
|
+
output: { verbose: true },
|
|
127
|
+
}),
|
|
128
|
+
),
|
|
129
|
+
),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
expect(result.index.maxDepth).toBe(3)
|
|
133
|
+
expect(result.index.excludePatterns).toEqual([
|
|
134
|
+
'node_modules',
|
|
135
|
+
'.git',
|
|
136
|
+
'dist',
|
|
137
|
+
'build',
|
|
138
|
+
])
|
|
139
|
+
expect(result.output.verbose).toBe(true)
|
|
140
|
+
expect(result.output.format).toBe('text')
|
|
141
|
+
})
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
describe('getConfig', () => {
|
|
145
|
+
it('should return the full configuration', async () => {
|
|
146
|
+
const program = Effect.gen(function* () {
|
|
147
|
+
return yield* getConfig
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
const result = await Effect.runPromise(
|
|
151
|
+
program.pipe(Effect.provide(ConfigServiceDefault)),
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
expect(result).toEqual(defaultConfig)
|
|
155
|
+
})
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
describe('getConfigSection', () => {
|
|
159
|
+
it('should return a specific config section', async () => {
|
|
160
|
+
const program = Effect.gen(function* () {
|
|
161
|
+
return yield* getConfigSection('index')
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
const result = await Effect.runPromise(
|
|
165
|
+
program.pipe(Effect.provide(ConfigServiceDefault)),
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
expect(result.maxDepth).toBe(10)
|
|
169
|
+
expect(result.excludePatterns).toEqual([
|
|
170
|
+
'node_modules',
|
|
171
|
+
'.git',
|
|
172
|
+
'dist',
|
|
173
|
+
'build',
|
|
174
|
+
])
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('should work for all sections', async () => {
|
|
178
|
+
const getAll = Effect.gen(function* () {
|
|
179
|
+
const index = yield* getConfigSection('index')
|
|
180
|
+
const search = yield* getConfigSection('search')
|
|
181
|
+
const embeddings = yield* getConfigSection('embeddings')
|
|
182
|
+
const output = yield* getConfigSection('output')
|
|
183
|
+
const paths = yield* getConfigSection('paths')
|
|
184
|
+
return { index, search, embeddings, output, paths }
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
const result = await Effect.runPromise(
|
|
188
|
+
getAll.pipe(Effect.provide(ConfigServiceDefault)),
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
expect(result.index.maxDepth).toBe(10)
|
|
192
|
+
expect(result.search.defaultLimit).toBe(10)
|
|
193
|
+
expect(result.embeddings.provider).toBe('openai')
|
|
194
|
+
expect(result.output.format).toBe('text')
|
|
195
|
+
expect(result.paths.cacheDir).toBe('.mdcontext/cache')
|
|
196
|
+
})
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
describe('getConfigValue', () => {
|
|
200
|
+
it('should return a specific config value', async () => {
|
|
201
|
+
const program = Effect.gen(function* () {
|
|
202
|
+
return yield* getConfigValue('index', 'maxDepth')
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
const result = await Effect.runPromise(
|
|
206
|
+
program.pipe(Effect.provide(ConfigServiceDefault)),
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
expect(result).toBe(10)
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it('should work with nested values', async () => {
|
|
213
|
+
const program = Effect.gen(function* () {
|
|
214
|
+
const maxDepth = yield* getConfigValue('index', 'maxDepth')
|
|
215
|
+
const format = yield* getConfigValue('output', 'format')
|
|
216
|
+
const provider = yield* getConfigValue('embeddings', 'provider')
|
|
217
|
+
return { maxDepth, format, provider }
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
const result = await Effect.runPromise(
|
|
221
|
+
program.pipe(Effect.provide(ConfigServiceDefault)),
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
expect(result.maxDepth).toBe(10)
|
|
225
|
+
expect(result.format).toBe('text')
|
|
226
|
+
expect(result.provider).toBe('openai')
|
|
227
|
+
})
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
describe('mergeWithDefaults', () => {
|
|
231
|
+
it('should merge empty partial with defaults', () => {
|
|
232
|
+
const result = mergeWithDefaults({})
|
|
233
|
+
expect(result).toEqual(defaultConfig)
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
it('should override specific values', () => {
|
|
237
|
+
const result = mergeWithDefaults({
|
|
238
|
+
index: { maxDepth: 5 },
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
expect(result.index.maxDepth).toBe(5)
|
|
242
|
+
expect(result.index.excludePatterns).toEqual([
|
|
243
|
+
'node_modules',
|
|
244
|
+
'.git',
|
|
245
|
+
'dist',
|
|
246
|
+
'build',
|
|
247
|
+
])
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('should merge multiple sections', () => {
|
|
251
|
+
const result = mergeWithDefaults({
|
|
252
|
+
index: { maxDepth: 5, followSymlinks: true },
|
|
253
|
+
search: { defaultLimit: 20 },
|
|
254
|
+
output: { verbose: true, debug: true },
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
expect(result.index.maxDepth).toBe(5)
|
|
258
|
+
expect(result.index.followSymlinks).toBe(true)
|
|
259
|
+
expect(result.index.excludePatterns).toEqual([
|
|
260
|
+
'node_modules',
|
|
261
|
+
'.git',
|
|
262
|
+
'dist',
|
|
263
|
+
'build',
|
|
264
|
+
])
|
|
265
|
+
expect(result.search.defaultLimit).toBe(20)
|
|
266
|
+
expect(result.search.maxLimit).toBe(100)
|
|
267
|
+
expect(result.output.verbose).toBe(true)
|
|
268
|
+
expect(result.output.debug).toBe(true)
|
|
269
|
+
expect(result.output.format).toBe('text')
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
it('should preserve Option values from defaults', () => {
|
|
273
|
+
const result = mergeWithDefaults({
|
|
274
|
+
paths: { cacheDir: '/custom/cache' },
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
// Verify the merge preserves defaults for unspecified values
|
|
278
|
+
expect(Option.isNone(result.paths.root)).toBe(true)
|
|
279
|
+
expect(Option.isNone(result.paths.configFile)).toBe(true)
|
|
280
|
+
expect(result.paths.cacheDir).toBe('/custom/cache')
|
|
281
|
+
})
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
describe('service composition', () => {
|
|
285
|
+
it('should allow services to depend on ConfigService', async () => {
|
|
286
|
+
// Example of a service that uses config
|
|
287
|
+
const myService = Effect.gen(function* () {
|
|
288
|
+
const config = yield* ConfigService
|
|
289
|
+
return `Max depth is ${config.index.maxDepth}`
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
const result = await Effect.runPromise(
|
|
293
|
+
myService.pipe(Effect.provide(ConfigServiceDefault)),
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
expect(result).toBe('Max depth is 10')
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
it('should allow testing with different configs', async () => {
|
|
300
|
+
const myService = Effect.gen(function* () {
|
|
301
|
+
const config = yield* ConfigService
|
|
302
|
+
return config.index.maxDepth > 5 ? 'deep' : 'shallow'
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
// Test with default (maxDepth = 10)
|
|
306
|
+
const defaultResult = await Effect.runPromise(
|
|
307
|
+
myService.pipe(Effect.provide(ConfigServiceDefault)),
|
|
308
|
+
)
|
|
309
|
+
expect(defaultResult).toBe('deep')
|
|
310
|
+
|
|
311
|
+
// Test with custom config (maxDepth = 3)
|
|
312
|
+
const customResult = await Effect.runPromise(
|
|
313
|
+
myService.pipe(
|
|
314
|
+
Effect.provide(makeConfigLayerPartial({ index: { maxDepth: 3 } })),
|
|
315
|
+
),
|
|
316
|
+
)
|
|
317
|
+
expect(customResult).toBe('shallow')
|
|
318
|
+
})
|
|
319
|
+
})
|
|
320
|
+
})
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ConfigService Layer
|
|
3
|
+
*
|
|
4
|
+
* Wraps configuration in an Effect Context.Tag and Layer, enabling
|
|
5
|
+
* dependency injection throughout the application. Services access
|
|
6
|
+
* config via `yield* ConfigService` rather than direct function parameters.
|
|
7
|
+
*
|
|
8
|
+
* ## Benefits
|
|
9
|
+
*
|
|
10
|
+
* - Test isolation without mocking (just provide different Layer)
|
|
11
|
+
* - Consistent config access across all commands and services
|
|
12
|
+
* - Effect best practices for dependency management
|
|
13
|
+
* - Type-safe configuration access
|
|
14
|
+
*
|
|
15
|
+
* ## Usage
|
|
16
|
+
*
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { ConfigService, ConfigServiceLive } from './config/service.js'
|
|
19
|
+
* import { Effect, Layer } from 'effect'
|
|
20
|
+
*
|
|
21
|
+
* const program = Effect.gen(function* () {
|
|
22
|
+
* const config = yield* ConfigService
|
|
23
|
+
* console.log(`Max depth: ${config.index.maxDepth}`)
|
|
24
|
+
* })
|
|
25
|
+
*
|
|
26
|
+
* // Run with live config
|
|
27
|
+
* Effect.runPromise(program.pipe(Effect.provide(ConfigServiceLive)))
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { type ConfigError, Context, Effect, Layer } from 'effect'
|
|
32
|
+
import type { MdContextConfig } from './schema.js'
|
|
33
|
+
import {
|
|
34
|
+
defaultConfig,
|
|
35
|
+
MdContextConfig as MdContextConfigSchema,
|
|
36
|
+
} from './schema.js'
|
|
37
|
+
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// Service Definition
|
|
40
|
+
// ============================================================================
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* ConfigService provides access to the application configuration.
|
|
44
|
+
*
|
|
45
|
+
* Use this service to access configuration values throughout the application.
|
|
46
|
+
* The service is provided via a Layer, enabling different configurations
|
|
47
|
+
* for production, testing, and development environments.
|
|
48
|
+
*/
|
|
49
|
+
export class ConfigService extends Context.Tag('ConfigService')<
|
|
50
|
+
ConfigService,
|
|
51
|
+
MdContextConfig
|
|
52
|
+
>() {}
|
|
53
|
+
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// Layer Implementations
|
|
56
|
+
// ============================================================================
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Live ConfigService layer that loads configuration from the Effect
|
|
60
|
+
* ConfigProvider (environment variables, config files, etc.)
|
|
61
|
+
*
|
|
62
|
+
* This layer reads from the current ConfigProvider in the Effect context.
|
|
63
|
+
* By default, this is the environment, but it can be customized using
|
|
64
|
+
* Effect.withConfigProvider.
|
|
65
|
+
*
|
|
66
|
+
* Note: This layer may fail with ConfigError if required configuration
|
|
67
|
+
* is missing or invalid. Use ConfigServiceDefault for a guaranteed-success layer.
|
|
68
|
+
*/
|
|
69
|
+
export const ConfigServiceLive: Layer.Layer<
|
|
70
|
+
ConfigService,
|
|
71
|
+
ConfigError.ConfigError
|
|
72
|
+
> = Layer.effect(ConfigService, MdContextConfigSchema)
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Create a ConfigService layer with a custom configuration object.
|
|
76
|
+
*
|
|
77
|
+
* Useful for:
|
|
78
|
+
* - Testing with specific config values
|
|
79
|
+
* - CLI flag overrides
|
|
80
|
+
* - Programmatic configuration
|
|
81
|
+
*
|
|
82
|
+
* @param config - The configuration object to use
|
|
83
|
+
* @returns A Layer that provides the ConfigService with the given config
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const testConfig = {
|
|
88
|
+
* ...defaultConfig,
|
|
89
|
+
* index: { ...defaultConfig.index, maxDepth: 5 }
|
|
90
|
+
* }
|
|
91
|
+
* const TestConfigLayer = makeConfigLayer(testConfig)
|
|
92
|
+
*
|
|
93
|
+
* const program = Effect.gen(function* () {
|
|
94
|
+
* const config = yield* ConfigService
|
|
95
|
+
* console.log(config.index.maxDepth) // 5
|
|
96
|
+
* })
|
|
97
|
+
*
|
|
98
|
+
* Effect.runPromise(program.pipe(Effect.provide(TestConfigLayer)))
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export const makeConfigLayer = (
|
|
102
|
+
config: MdContextConfig,
|
|
103
|
+
): Layer.Layer<ConfigService> => Layer.succeed(ConfigService, config)
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Default ConfigService layer with all default values.
|
|
107
|
+
*
|
|
108
|
+
* Useful for:
|
|
109
|
+
* - Quick testing without external dependencies
|
|
110
|
+
* - Fallback when no config file or environment is available
|
|
111
|
+
*/
|
|
112
|
+
export const ConfigServiceDefault: Layer.Layer<ConfigService> =
|
|
113
|
+
makeConfigLayer(defaultConfig)
|
|
114
|
+
|
|
115
|
+
// ============================================================================
|
|
116
|
+
// Helper Functions
|
|
117
|
+
// ============================================================================
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Access the full configuration object.
|
|
121
|
+
*
|
|
122
|
+
* @returns An Effect that yields the full MdContextConfig
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* const program = Effect.gen(function* () {
|
|
127
|
+
* const config = yield* getConfig
|
|
128
|
+
* console.log(config.index.maxDepth)
|
|
129
|
+
* })
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export const getConfig: Effect.Effect<MdContextConfig, never, ConfigService> =
|
|
133
|
+
ConfigService
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Access a specific section of the configuration.
|
|
137
|
+
*
|
|
138
|
+
* @param section - The section key to access
|
|
139
|
+
* @returns An Effect that yields the specified config section
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* const program = Effect.gen(function* () {
|
|
144
|
+
* const indexConfig = yield* getConfigSection('index')
|
|
145
|
+
* console.log(indexConfig.maxDepth)
|
|
146
|
+
* })
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export const getConfigSection = <K extends keyof MdContextConfig>(
|
|
150
|
+
section: K,
|
|
151
|
+
): Effect.Effect<MdContextConfig[K], never, ConfigService> =>
|
|
152
|
+
Effect.map(ConfigService, (config) => config[section])
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Access a specific value from the configuration.
|
|
156
|
+
*
|
|
157
|
+
* @param section - The section key
|
|
158
|
+
* @param key - The key within the section
|
|
159
|
+
* @returns An Effect that yields the specified config value
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* const program = Effect.gen(function* () {
|
|
164
|
+
* const maxDepth = yield* getConfigValue('index', 'maxDepth')
|
|
165
|
+
* console.log(maxDepth)
|
|
166
|
+
* })
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
export const getConfigValue = <
|
|
170
|
+
K extends keyof MdContextConfig,
|
|
171
|
+
V extends keyof MdContextConfig[K],
|
|
172
|
+
>(
|
|
173
|
+
section: K,
|
|
174
|
+
key: V,
|
|
175
|
+
): Effect.Effect<MdContextConfig[K][V], never, ConfigService> =>
|
|
176
|
+
Effect.map(ConfigService, (config) => config[section][key])
|
|
177
|
+
|
|
178
|
+
// ============================================================================
|
|
179
|
+
// Partial Config Utilities
|
|
180
|
+
// ============================================================================
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Deeply partial type for MdContextConfig
|
|
184
|
+
*/
|
|
185
|
+
export type PartialMdContextConfig = {
|
|
186
|
+
[K in keyof MdContextConfig]?: Partial<MdContextConfig[K]>
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Merge partial configuration with defaults.
|
|
191
|
+
*
|
|
192
|
+
* Creates a complete MdContextConfig by merging user-provided values
|
|
193
|
+
* with the default configuration. Useful for applying config file values
|
|
194
|
+
* or CLI overrides.
|
|
195
|
+
*
|
|
196
|
+
* @param partial - Partial configuration to merge
|
|
197
|
+
* @returns Complete MdContextConfig with defaults filled in
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```typescript
|
|
201
|
+
* const userConfig = {
|
|
202
|
+
* index: { maxDepth: 5 },
|
|
203
|
+
* output: { verbose: true }
|
|
204
|
+
* }
|
|
205
|
+
* const fullConfig = mergeWithDefaults(userConfig)
|
|
206
|
+
* // fullConfig.index.maxDepth === 5
|
|
207
|
+
* // fullConfig.index.excludePatterns === defaultConfig.index.excludePatterns
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
export const mergeWithDefaults = (
|
|
211
|
+
partial: PartialMdContextConfig,
|
|
212
|
+
): MdContextConfig => ({
|
|
213
|
+
index: { ...defaultConfig.index, ...partial.index },
|
|
214
|
+
search: { ...defaultConfig.search, ...partial.search },
|
|
215
|
+
embeddings: { ...defaultConfig.embeddings, ...partial.embeddings },
|
|
216
|
+
summarization: { ...defaultConfig.summarization, ...partial.summarization },
|
|
217
|
+
aiSummarization: {
|
|
218
|
+
...defaultConfig.aiSummarization,
|
|
219
|
+
...partial.aiSummarization,
|
|
220
|
+
},
|
|
221
|
+
output: { ...defaultConfig.output, ...partial.output },
|
|
222
|
+
paths: { ...defaultConfig.paths, ...partial.paths },
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Create a ConfigService layer from partial configuration.
|
|
227
|
+
*
|
|
228
|
+
* Combines makeConfigLayer with mergeWithDefaults for convenience.
|
|
229
|
+
*
|
|
230
|
+
* @param partial - Partial configuration to use
|
|
231
|
+
* @returns A Layer that provides ConfigService with merged config
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```typescript
|
|
235
|
+
* const TestLayer = makeConfigLayerPartial({
|
|
236
|
+
* index: { maxDepth: 5 },
|
|
237
|
+
* output: { debug: true }
|
|
238
|
+
* })
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
export const makeConfigLayerPartial = (
|
|
242
|
+
partial: PartialMdContextConfig,
|
|
243
|
+
): Layer.Layer<ConfigService> => makeConfigLayer(mergeWithDefaults(partial))
|