Skip to content

implemented namespaced config#4

Merged
y-aithnini merged 3 commits intodevelopfrom
feature/COMPT-52-namespaced-config
Apr 8, 2026
Merged

implemented namespaced config#4
y-aithnini merged 3 commits intodevelopfrom
feature/COMPT-52-namespaced-config

Conversation

@y-aithnini
Copy link
Copy Markdown

Summary

  • What does this PR change?

Why

  • Why is this change needed?

Checklist

  • Added/updated tests (if behavior changed)
  • npm run lint passes
  • npm run typecheck passes
  • npm test passes
  • npm run build passes
  • Added a changeset (npx changeset) if this affects consumers

Notes

  • Anything reviewers should pay attention to?

Copilot AI review requested due to automatic review settings April 8, 2026 12:09
@y-aithnini y-aithnini requested a review from a team as a code owner April 8, 2026 12:09
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for “namespaced” (per-feature) configuration slices in ConfigKit, including DI tokens, a namespace registry for duplicate detection, and a consumer-facing injection decorator.

Changes:

  • Exported new public API: defineNamespace, NamespacedConfig, InjectConfig, and DuplicateNamespaceError.
  • Introduced namespace DI token generation (getNamespaceToken) and a shared registry token (NAMESPACE_REGISTRY_TOKEN).
  • Updated ConfigModule.register() / registerAsync() to provide + export the namespace registry for duplicate detection.

Reviewed changes

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

Show a summary per file
File Description
src/index.ts Exposes the new namespaced-config APIs from the package entrypoint.
src/define-namespace.ts Implements defineNamespace() / NamespacedConfig.asProvider() and the duplicate-namespace error.
src/decorators/inject-config.decorator.ts Adds @InjectConfig(namespace) as a thin wrapper over token-based injection.
src/constants.ts Adds namespace token generator + registry token constant.
src/config.module.ts Provides/exports the namespace registry so feature providers can detect duplicates.

Comment on lines +15 to +17
* 3. ConfigModule (via forRoot / register) parses ALL namespaced schemas as
* part of the same validation pass, so misconfigured slices also prevent
* the app from booting.
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

The module-level doc says ConfigModule parses “ALL namespaced schemas as part of the same validation pass”, but the current implementation parses each namespace inside NamespacedConfig.asProvider() (via definition.parse(process.env)). Either update the documentation to match the per-provider parsing behavior, or move namespaced-slice validation into ConfigModule so all schemas are validated together as described.

Suggested change
* 3. ConfigModule (via forRoot / register) parses ALL namespaced schemas as
* part of the same validation pass, so misconfigured slices also prevent
* the app from booting.
* 3. Each `NamespacedConfig` validates its own schema when
* `NamespacedConfig.asProvider()` is resolved, so a misconfigured slice
* still prevents the app from booting during startup.

Copilot uses AI. Check for mistakes.
* export class DatabaseModule {}
*
* // database/database.service.ts
* constructor(@InjectConfig('database') private cfg: typeof dbConfig.schema._output) {}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

The example type typeof dbConfig.schema._output is incorrect: NamespacedConfig doesn’t expose a schema property (it’s under dbConfig.definition.schema), and _output isn’t the recommended public type surface. The example should reference the schema via definition.schema and use z.output<...> (or an exported helper type) so consumers can copy/paste it without type errors.

Suggested change
* constructor(@InjectConfig('database') private cfg: typeof dbConfig.schema._output) {}
* constructor(@InjectConfig('database') private cfg: z.output<typeof dbConfig.definition.schema>) {}

Copilot uses AI. Check for mistakes.
Comment on lines +202 to +204
* The namespace name must be unique across the entire application — attempting
* to call `asProvider()` on two configs with the same name will throw
* `DuplicateNamespaceError` at module init.
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

defineNamespace() docs (and DuplicateNamespaceError message) state namespaces must be unique across the entire application, but duplicate detection is implemented via a Set<string> provided by the nearest ConfigModule instance. If an app imports ConfigModule more than once (e.g., multiple register() calls), duplicates across those module graphs won’t be detected. Consider clarifying the scope in docs or making the registry truly app-wide.

Copilot uses AI. Check for mistakes.
Comment on lines +150 to 156
// A fresh Set is created per ConfigModule instance.
const namespaceRegistryProvider: Provider = {
provide: NAMESPACE_REGISTRY_TOKEN,
useValue: new Set<string>(),
};

return {
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

The namespace registry is created as new Set<string>() per ConfigModule.register() / registerAsync() call. That means duplicate namespace detection only works within the scope of a single ConfigModule instance; importing ConfigModule multiple times will create multiple registries and allow duplicate namespaces across module graphs. If app-wide uniqueness is required, consider using a shared singleton registry (or enforce a single ConfigModule import) and document the expected usage.

Copilot uses AI. Check for mistakes.
@y-aithnini y-aithnini merged commit c9df163 into develop Apr 8, 2026
1 of 2 checks passed
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