fix(core): proxy provider improvements - optional deps, better error messages, docs caveats#579
Open
Papooch wants to merge 3 commits into
Open
fix(core): proxy provider improvements - optional deps, better error messages, docs caveats#579Papooch wants to merge 3 commits into
Papooch wants to merge 3 commits into
Conversation
01184bc to
1eb80bc
Compare
There was a problem hiding this comment.
Pull request overview
Improves Proxy Provider ergonomics and reliability in nestjs-cls by supporting Nest’s optional factory injection syntax, adding stricter validation of factory return values during proxy resolution, and documenting common lifecycle/scope pitfalls.
Changes:
- Extend Proxy Provider/Plugin factory
injecttyping to acceptOptionalFactoryDependency(e.g.{ token, optional: true }) and add tests for optional injection behavior and ordering. - Validate resolved Proxy Provider factory return values and throw
ProxyProviderInvalidReturnTypeExceptionfornull/undefined/primitives; track “resolved” providers explicitly per CLS context. - Update docs with stricter-mode wording and new caveats around bootstrap timing and REQUEST-scoped providers.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/core/test/proxy-providers/for-feature.spec.ts | Adds tests for @Optional() in class proxies and OptionalFactoryDependency in factory proxy inject arrays (including ordering). |
| packages/core/src/lib/proxy-provider/proxy-provider.interfaces.ts | Widens inject/dependencies types to include OptionalFactoryDependency. |
| packages/core/src/lib/proxy-provider/proxy-provider.exceptions.ts | Introduces ProxyProviderInvalidReturnTypeException with an explanatory message. |
| packages/core/src/lib/proxy-provider/proxy-provider-resolver.ts | Extracts tokens from optional deps for dependency ordering; adds per-context resolved tracking; throws on invalid factory return values. |
| packages/core/src/lib/proxy-provider/proxy-provider-manager.spec.ts | Adds coverage for invalid return type handling and “don’t re-resolve” behavior. |
| packages/core/src/lib/plugin/cls-plugin-base.ts | Updates plugin hook provider inject typing to accept OptionalFactoryDependency. |
| docs/docs/03_features-and-use-cases/06_proxy-providers.md | Updates strict-mode wording and adds new caveats (bootstrap timing, REQUEST-scoped mixing, primitive returns). |
| docs/docs/03_features-and-use-cases/04_usage-outside-of-web-request.md | Adds a warning about background workers and Proxy Provider availability timing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… arrays
Accepts `{ token: T, optional: true }` in the `inject` array of
`ClsModule.forFeatureAsync` factory providers and in `ClsPluginBase.registerHooks`.
The `extractInjectionToken` helper correctly extracts the bare token from an
`OptionalFactoryDependency` when building the proxy-to-proxy dependency graph,
so resolution ordering is preserved even for optional cross-proxy deps.
`@Optional()` on class proxy provider constructor params already worked via
`moduleRef.create()` — integration tests verify both class and factory cases.
Closes #381
…ve returns - Track resolved providers in a Set (CLS_PROXY_PROVIDER_RESOLVED_SET) to distinguish 'not resolved yet' from 'resolved to undefined/null' - Throw ProxyProviderInvalidReturnTypeException when factory returns a primitive (string, number, boolean, null, undefined) - Handle OptionalFactoryDependency entries in the dependencies array - Add tests covering all new error paths and resolution tracking Closes #375 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1eb80bc to
a614f71
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
packages/core/src/lib/proxy-provider/proxy-provider-resolver.ts:163
getAllNeededProviderSymbolsonly adds direct dependencies of the requested providers. When resolving a subset (e.g.cls.proxy.resolve([B])) andB -> A -> C(transitively),Cis never added toresolutionPromisesMap, soAwill not actually wait forC(becausedependencyPromises.get(C)isundefined) and can resolve out of order. This breaks the “resolve dependencies first” guarantee for selective resolution. Consider computing the full transitive closure of proxy-provider dependencies (DFS/BFS) and/or throwing if a dependency symbol is missing fromdependencyPromises.
private getAllNeededProviderSymbols(providerSymbols: symbol[]) {
const resolvedSet = this.getOrCreateCurrentResolvedSet();
return new Set<symbol>(
providerSymbols
.filter((providerSymbol) => !resolvedSet.has(providerSymbol))
.map((providerSymbol) => {
const deps =
this.proxyProviderDependenciesMap.get(providerSymbol) ??
[];
return [providerSymbol, ...deps];
})
.flat(),
);
}
…ped mixing - Warn that proxy providers are unavailable until onApplicationBootstrap (BullMQ and similar workers must not consume in onModuleInit) - Danger block: never inject Scope.REQUEST providers into proxy provider factories; shows before/after with CLS_REQ pattern Closes #404, relates to #375 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
a614f71 to
676c0c9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
Support
OptionalFactoryDependencyininjectarrays (closes #381)Factory proxy providers now accept
{ token: T, optional: true }ininject:@Optional()on class proxy constructor params already worked.Throw on invalid factory return values (closes #375)
Factories returning
null,undefined, or a primitive now throwProxyProviderInvalidReturnTypeExceptioninstead of silently producing a broken proxy.Docs
ProxyProviderNotResolvedExceptionexplicitly (ProxyProviderNotResolvedException thrown even after resolveProxyProviders(...) #375)onApplicationBootstrap— accessing them inonModuleInit(e.g. BullMQ) will fail (closes Regression: Tenant connection mix-up after upgrading from 2.5.1 to 2.6.0 #404)Scope.REQUESTproviders into proxy provider factories — shows the correctCLS_REQpattern