refactor(config): lazy lookup interface for @elastic/config-resolver
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Tái cấu trúc
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- typescript
Hướng nghiên cứu
Start with the suggested TDD order: inspect the @elastic/config-resolver entry point and its tests, then review loader.ts, schema.ts, factory.ts, and extension/context.ts. Run the existing config tests to identify eager-resolution assumptions, including the skipContextResolve and resolveHelpConfig paths. Done means lazy memoized access, preserved validation and error codes, updated clients and tests, and passing npm test and lint.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
Refactor @elastic/config-resolver to expose a lazy, memoized lookup interface, and move the CLI's resolve-then-validate logic (resolveExpressions + post-resolution ContextSchema validation + the skipContextResolve special case) behind it. This is a standalone refactor of that library and the CLI code that consumes it; it is not tied to any feature work.
Motivation
Today loadConfig resolves every expression in the active context up front (resolveExpressions deep-walks the whole context and commands), then validates the resolved result with ContextSchema. That is all-or-nothing, and it has accumulated workarounds:
elastic es searchstill runs every$(cmd:...)/$(pass:...)in thekibanaandcloudblocks, even though onlyelasticsearchis used.- Command registration and
--helponly needelasticsearch.version/kibana.versionand the command policy. To avoid resolving secrets there (#706) we addedskipContextResolve, a cache exception, and a separate fast path inloader.ts(resolveHelpConfig) that reads raw YAML and skips validation. - That fast path reads
versionunresolved, soversion: $(env:ES_VERSION)is silently ignored when filtering help. - The
preActionhook resolves secrets before--dry-runis considered, so a dry run still spawns secret subprocesses.
Lazy per-field lookup removes the need for the special case and fixes the above.
Proposal
Add a lazy accessor to @elastic/config-resolver:
createLazyConfig(raw: object, opts?: {
leafValidators?: Record<string, (value: string) => string | undefined>
}): {
get(path: readonly string[]): string | undefined // resolve + validate leaf + memoize
peek(path: readonly string[]): unknown // raw, unresolved
}
- Array paths, not dotted strings (context names can contain dots).
- Memoized per path; concurrent
gets of the same path share one resolution. - Keep the existing
__proto__/constructorguard. - Errors keep the field path in the message, and the CLI maps them to the existing
config_unresolvederror.code(the code catalog is frozen).
CLI side:
loadConfigkeeps file discovery, YAML parsing, structural validation, context selection, profile precedence and the inline-secret permission warning. Only the resolve + validate steps and the result cache move behind the lazy accessor.ResolvedConfigbecomes a thin facade overget.- Delete
skipContextResolve,resolveHelpConfigand the associated cache exception.
Design decisions to settle
- Post-resolution validation.
ContextSchemacurrently validates the resolved context (e.g. URL scheme), sourl: $(cmd:...)could not pass it unresolved. This needs two layers: a raw-shape check that accepts expression strings, plus per-field leaf validators applied when a value is read (the URL scheme and non-empty rules currently inschema.ts). This is the largest piece of work. - Sync vs async. All seven built-in resolvers are synchronous (
execSync/readFileSync), butResolverFnallows promises. An asyncget()would makegetEsClient,getCloudClientandgetKbClientasync and ripple intofactory.ts. NarrowingResolverFnto sync would letResolvedConfigkeep its current shape with memoized lazy getters on secret-bearing leaves, so consumers would not change. The package isprivateat 0.1.2, so that break is cheap, but it drops async custom resolvers. Proposal: start sync. - Failure timing. A bad expression currently fails the command up front. Lazily it fails when the value is first read, inside the handler. Existing tests pin the old timing (e.g. "still fails when the active context has an unresolvable expression" in
test/config/loader.test.ts) and would need rewriting, each change called out explicitly. - Enumeration safety. A lazy config object must not fire every resolver (or leak values) when serialized or spread. Audit
status, theconfigcommands, andextension/context.ts(which referencesResolvedConfig; changing its shape may be an extension-facing API change). commandspolicy. Currently resolved like everything else; becomes a lazyget(['commands']).
Out of scope
- Moving file discovery, YAML/JSON parsing, structural validation, profile precedence or the permission warning out of the CLI. Only about a third of
loader.tsis affected. - Any startup-performance claim. The help-path ajv/YAML cost is already addressed separately; this refactor simplifies that code but is not expected to make it faster.
Suggested order of work (TDD)
- Lazy accessor in
config-resolverwith tests for memoization, concurrent access, error paths (field path preserved), and the prototype guard. - Leaf validators covering the rules
ContextSchemaenforces after resolution. - Switch
loadConfigand the three clients over; deleteskipContextResolveandresolveHelpConfig. - Rewrite tests that pin eager semantics, listing each change with justification.
Acceptance
- Reading
elasticsearch.*never runs resolvers forkibana.*orcloud.*. --helpand--dry-runnever run a secret resolver.version: $(env:...)is honoured for availability filtering.config_unresolvedis still emitted for unresolvable expressions, and no newerror.codestrings are introduced.npm testand lint pass; startup perf baselines are not regressed.
authored by Pi Coding Agent (Claude Opus 4.8)
- Ngôn ngữ chính
- TypeScript
- Star
- 47
- Fork
- 27
- Merge trung bình
- 2 ngày 6 giờ
- Pull request đã merge (30 ngày)
- 52
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của elastic/cli
-
feat: ship skills/elastic/SKILL.md for agent invocationCó thể đã có người làm @onatozmenn đã nhận 16 ngày trước. Đang mởenhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
elastic/cli#628 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
elastic/cli#617 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 Nửa ngày Mức phù hợp với người mới 62/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 20/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 70/100
Maintainer thường phản hồi trong vòng 1 ngày
Issue tương tự
-
documentation good first issue hacktoberfest help wanted
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
libredb/libredb-studio#1756 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
state:triage-needed
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
Maintainer thường phản hồi trong vòng 1 ngày
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 72/100
lingdojo/kana-dojo#32365 · 1 bình luận · 5 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
friction
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
kentcdodds/kody#3706 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
copperheadhq/copperhead#378 ·
Maintainer thường phản hồi trong vòng 1 ngày