Skip to content

feat(config): typed ConfigService with dot-path inference - #8

Merged
msalvatti merged 5 commits into
mainfrom
feat/phase-04-typed-accessor
Jul 16, 2026
Merged

feat(config): typed ConfigService with dot-path inference#8
msalvatti merged 5 commits into
mainfrom
feat/phase-04-typed-accessor

Conversation

@msalvatti

Copy link
Copy Markdown
Member

Summary

Phase 4 (typed-accessor) ships ConfigService<T>, the recommended consumption surface over the frozen BYMAX_CONFIG object, with compile-time dot-path inference limited to the two-level namespace.leaf convention. Consumers read validated values with the leaf type inferred from the path and no cast, while invalid paths fail to compile.

What changed

  • Path<T> and PathValue<T, P> type utilities (src/types.ts): template-literal utilities scoped to exactly two levels (namespace and leaf), with no recursive conditional types, so compiler cost stays flat for large schemas. Deeper nesting stays typed through getAll() and is documented as a known limitation.
  • ConfigService<T> (src/config.service.ts): @Injectable() accessor injecting the frozen config via explicit @Inject(BYMAX_CONFIG) (no decorator metadata; the build has no emitDecoratorMetadata). API:
    • get<P extends Path<T>>(path) returns PathValue<T, P>, resolving the single-dot path across the two fixed levels. Never throws for a declared path because validation completed at bootstrap.
    • getAll() returns the same deep-frozen root by reference (the escape hatch for arbitrary-depth typing).
    • has(path) reports declared-path presence, returning false when the resolved value is undefined.
  • Module registration (src/config.module.ts): BymaxConfigModule now provides and exports ConfigService alongside BYMAX_CONFIG, for both forRoot and forRootAsync.
  • Public surface (src/index.ts): exports ConfigService, Path, and PathValue.

Verification

All gates green:

  • pnpm typecheck — clean (both tsconfig.json and tsconfig.build.json), including the compile-time type-test assertions.
  • pnpm lint — clean (zero warnings).
  • pnpm build — emits .mjs / .cjs / .d.ts for both subpaths (. and ./testing).
  • pnpm test:cov:all — 95/95 tests pass, 100% statements / branches / functions / lines on every runtime file, including the new config.service.ts (type-only files carry no runtime code).

Type-inference evidence (pinned by compile-time assertions):

  • get('database.url') types as string; get('server.port') as number; get('server.env') as the declared literal union.
  • PathValue<AppConfig, 'server.port'> resolves to number.
  • Rejected paths fail compilation, asserted with @ts-expect-error inside the type-test specs (a positive compile-time assertion: an unused directive fails the build): namespace-only ('database'), undeclared leaf ('database.missing'), and arbitrary strings ('not.a.path').

Global typed injection is proven end-to-end in the integration suite: a feature provider in a nested module injects ConfigService<AppConfig> without importing BymaxConfigModule and reads typed values, sharing the single frozen root.

Definition of Done (P4)

  • get('database.url') type-checks as string and get('server.port') as number; an invalid path fails compilation. Done.
  • getAll returns the frozen root; has reports declared-path presence. Done.
  • Runtime behavior covered at 100%; type behavior pinned with dedicated type-assertion tests. Done.

Follow-ups

  • Testing subpath helpers (createTestConfig, configTestingModule) land in Phase 5.
  • Deeper-than-two-level dot-path inference remains intentionally out of scope (spec §12.1); getAll() is the typed escape hatch.

Copilot AI review requested due to automatic review settings July 16, 2026 16:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a typed, injectable ConfigService<T> as the primary consumption API for validated configuration, including compile-time namespace.leaf dot-path inference via new Path<T> / PathValue<T, P> utilities, and wires the service into the module’s provider/exports surface.

Changes:

  • Introduces Path<T> / PathValue<T, P> template-literal type utilities (two-level only) with compile-time type tests.
  • Adds ConfigService<T> (get, getAll, has) and registers/exports it from BymaxConfigModule, including global-injection integration coverage.
  • Updates public exports and phase/dashboard documentation to mark Phase 4 complete.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/types.ts Adds Path / PathValue type utilities for two-level dot-path inference.
src/types.spec.ts Adds compile-time and runtime assertions for Path / PathValue.
src/index.ts Exports ConfigService, Path, and PathValue from the public surface.
src/config.service.ts Introduces injectable typed accessor over BYMAX_CONFIG.
src/config.service.spec.ts Unit coverage for ConfigService behavior and type inference.
src/config.module.ts Registers and exports ConfigService alongside BYMAX_CONFIG.
src/config.module.spec.ts Verifies module provides/exports both config surfaces.
src/config.module.integration.spec.ts Proves global injection of ConfigService<AppConfig> from a non-importing module.
docs/tasks/README.md Updates phase progress table for Phase 4 completion.
docs/tasks/phase-04-typed-accessor.md Marks Phase 4 tasks complete and logs completion details.
docs/development_plan.md Updates overall dashboard progress and Phase 4 status.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/config.service.ts Outdated
Comment thread src/config.service.ts
Comment thread src/types.ts
Comment thread src/config.service.ts Outdated
Copilot AI review requested due to automatic review settings July 16, 2026 16:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

@msalvatti
msalvatti merged commit 3e278cd into main Jul 16, 2026
5 checks passed
@msalvatti
msalvatti deleted the feat/phase-04-typed-accessor branch July 16, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants