feat(core): add support for array of global prefixes - #17713
Open
micalevisk wants to merge 2 commits into
Open
micalevisk wants to merge 2 commits into
micalevisk wants to merge 2 commits into
Conversation
Closes nestjs#16095 Ported from nestjs#16102 onto the current master. Conflicts in `registerRouter()` were resolved by keeping the route conflict detection and specificity ordering, passing every global prefix to both `resolve()` calls. The new assertions use vitest's `toEqual`. (cherry picked from commit d5726a4) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
7 tasks
10 tasks
`getGlobalPrefix()` intentionally keeps returning only the first prefix as a `string` so that existing consumers (e.g. `@nestjs/swagger`) do not break. Document that, point to `getGlobalPrefixes()`, and mark the legacy method as deprecated for removal in v13. Co-Authored-By: Claude Code <noreply@anthropic.com> (claude-fable-5-1)
|
Thanks for the thorough writeup on the I'd like to take the swagger-side follow-up once this lands, if that's still open. I went through swagger's current source to scope it out ahead of time, and it looks like three spots need updating, not just the helper:
Happy to align on the intended UI-mounting behavior before implementing. Let me know if you'd already started on this — otherwise I'll open a PR once #17713 (or its follow-up issue) lands. |
Member
Author
|
@alireza-aminzadeh go ahead. Thanks! |
12 tasks
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.
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: #16095
setGlobalPrefix()only accepts a single string. Before v11, the same routes could be served under several base paths with a regex-style prefix such as(prefixOne|prefixTwo), but path-to-regexp v8 no longer supports that.What is the new behavior?
setGlobalPrefix()also accepts an array, and every route is registered under each prefix:ApplicationConfig#getGlobalPrefixes()returns all prefixes.ApplicationConfig#getGlobalPrefix()is now marked@deprecatedand will be removed in NestJS v13. Its JSDoc explains that it deliberately keeps returning only the first prefix (as astring) for backward compatibility, and points togetGlobalPrefixes()as the replacement.RoutePathFactorybuilds one path per prefix. Routes listed inexcludestay unprefixed, as before.RouteInfoPathExtractorbuilds middleware paths for every prefix, including versioned and wildcard routes.NestApplication#registerRouter()passes all prefixes toRoutesResolver#resolve(), both with and without route conflict detection.Does this PR introduce a breaking change?
getGlobalPrefix()still returns a string (the first prefix, or''), so packages that read it, like@nestjs/swagger, keep working. When several prefixes are set, those packages only see the first one until they switch togetGlobalPrefixes(). ThatglobalPrefixes[0]return is intentional and documented in the method's JSDoc; the method is marked@deprecatedso consumers get an editor/compiler hint to migrate togetGlobalPrefixes()before it is removed in v13.Other information
This supersedes #16102 by @malkovitc, which stalled waiting for a rebase. I cherry-picked their commit onto the current
masterand kept them as the author. The conflicts inregisterRouter()were resolved by keeping the route conflict detection and specificity ordering, with every prefix passed to bothresolve()calls.A deprecation note was left on
ApplicationConfig#getGlobalPrefix()stating that returning only the first prefix is intentional to avoid a breaking change, that callers should migrate togetGlobalPrefixes(), and that the legacy method is scheduled for removal in NestJS v13. Core still callsgetGlobalPrefix()inregisterParserMiddleware(),registerNotFoundHandler()andregisterExceptionHandler(), since those adapter hooks accept a single prefix; they are left as-is in this PR.Impact on
@nestjs/swaggerI ran the current
@nestjs/swaggermaster(v12.0.1) against the build from this branch (node_modules/@nestjs/{core,common}symlinked to this branch's packages). Its type-check (tsc -p tsconfig.build.json), unit suite (518 tests) and e2e suite (133 tests) all pass, so this PR does not break it.However, swagger only ever sees the first prefix, because it reads
app.config.getGlobalPrefix()through an untypedanycast (lib/utils/get-global-prefix.ts). Withapp.setGlobalPrefix(['api', 'v1']):SwaggerModule.createDocument()lists/api/catsbut not/v1/cats, even though core serves both.SwaggerModule.setup(..., { useGlobalPrefix: true })mounts the UI and the JSON/YAML documents under/api/...only;/v1/docs-jsonreturns 404.ignoreGlobalPrefix: trueandexcluded routes keep working as before.Since swagger reaches the method via
any, the@deprecatedtag will not show up in its editor/compiler; the migration hint only reaches them through the JSDoc/changelog. The fix on their side is small:RoutePathFactory#create()already fans out when givengetGlobalPrefixes()(verified: it returns['/api/cats', '/v1/cats']), and swagger already iterates multiple paths per route for versioning, so mostly the helper needs to returnstring[](with a fallback togetGlobalPrefix()for older core versions) andsetup()needs to loop over the prefixes. I'll open a follow-up issue on nestjs/swagger once this is merged.