Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

refactor(config): lazy lookup interface for @elastic/config-resolver

Đang mở
#716 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

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
Lĩnh vực
cli, tooling

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 search still runs every $(cmd:...) / $(pass:...) in the kibana and cloud blocks, even though only elasticsearch is used.
  • Command registration and --help only need elasticsearch.version / kibana.version and the command policy. To avoid resolving secrets there (#706) we added skipContextResolve, a cache exception, and a separate fast path in loader.ts (resolveHelpConfig) that reads raw YAML and skips validation.
  • That fast path reads version unresolved, so version: $(env:ES_VERSION) is silently ignored when filtering help.
  • The preAction hook resolves secrets before --dry-run is 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__ / constructor guard.
  • Errors keep the field path in the message, and the CLI maps them to the existing config_unresolved error.code (the code catalog is frozen).

CLI side:

  • loadConfig keeps 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.
  • ResolvedConfig becomes a thin facade over get.
  • Delete skipContextResolve, resolveHelpConfig and the associated cache exception.

Design decisions to settle

  1. Post-resolution validation. ContextSchema currently validates the resolved context (e.g. URL scheme), so url: $(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 in schema.ts). This is the largest piece of work.
  2. Sync vs async. All seven built-in resolvers are synchronous (execSync / readFileSync), but ResolverFn allows promises. An async get() would make getEsClient, getCloudClient and getKbClient async and ripple into factory.ts. Narrowing ResolverFn to sync would let ResolvedConfig keep its current shape with memoized lazy getters on secret-bearing leaves, so consumers would not change. The package is private at 0.1.2, so that break is cheap, but it drops async custom resolvers. Proposal: start sync.
  3. 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.
  4. Enumeration safety. A lazy config object must not fire every resolver (or leak values) when serialized or spread. Audit status, the config commands, and extension/context.ts (which references ResolvedConfig; changing its shape may be an extension-facing API change).
  5. commands policy. Currently resolved like everything else; becomes a lazy get(['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.ts is 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)

  1. Lazy accessor in config-resolver with tests for memoization, concurrent access, error paths (field path preserved), and the prototype guard.
  2. Leaf validators covering the rules ContextSchema enforces after resolution.
  3. Switch loadConfig and the three clients over; delete skipContextResolve and resolveHelpConfig.
  4. Rewrite tests that pin eager semantics, listing each change with justification.

Acceptance

  • Reading elasticsearch.* never runs resolvers for kibana.* or cloud.*.
  • --help and --dry-run never run a secret resolver.
  • version: $(env:...) is honoured for availability filtering.
  • config_unresolved is still emitted for unresolvable expressions, and no new error.code strings are introduced.
  • npm test and 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

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của elastic/cli

Tất cả issue của elastic/cli

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.