@@ -79,9 +79,9 @@ async function fetchBulkDownloads(
7979/**
8080 * Fetch all packages for an npm organization.
8181 *
82- * When the user has Algolia search enabled, uses Algolia's `owner.name` filter
83- * for a much faster lookup (single request vs N+1 packument fetches).
84- * Falls back to the npm registry API when using the npm search provider .
82+ * Always uses the npm registry's org endpoint as the source of truth for which
83+ * packages belong to the org. When Algolia is enabled, uses it to quickly fetch
84+ * metadata for those packages (instead of N+1 packument fetches) .
8585 */
8686export function useOrgPackages ( orgName : MaybeRefOrGetter < string > ) {
8787 const { searchProvider } = useSearchProvider ( )
@@ -95,21 +95,9 @@ export function useOrgPackages(orgName: MaybeRefOrGetter<string>) {
9595 return emptySearchResponse
9696 }
9797
98- // --- Algolia fast path ---
99- if ( searchProvider . value === 'algolia' ) {
100- try {
101- const response = await searchByOwner ( org )
102- // If Algolia returns no results, the org may not exist — fall through
103- // to npm registry path which can properly detect a 404
104- if ( response . objects . length > 0 ) {
105- return response
106- }
107- } catch {
108- // Fall through to npm registry path on Algolia failure
109- }
110- }
111-
112- // --- npm registry path ---
98+ // Always get the authoritative package list from the npm registry.
99+ // Algolia's owner.name filter doesn't precisely match npm org membership
100+ // (e.g. it includes @nuxtjs/* packages for the @nuxt org).
113101 let packageNames : string [ ]
114102 try {
115103 const { packages } = await $fetch < { packages : string [ ] ; count : number } > (
@@ -138,9 +126,33 @@ export function useOrgPackages(orgName: MaybeRefOrGetter<string>) {
138126 return emptySearchResponse
139127 }
140128
141- // Fetch packuments and downloads in parallel
129+ // --- Algolia fast path: use Algolia to get metadata for known packages ---
130+ if ( searchProvider . value === 'algolia' ) {
131+ try {
132+ const response = await searchByOwner ( org )
133+ if ( response . objects . length > 0 ) {
134+ // Filter Algolia results to only include packages that are
135+ // actually in the org (per the npm registry's authoritative list)
136+ const orgPackageSet = new Set ( packageNames . map ( n => n . toLowerCase ( ) ) )
137+ const filtered = response . objects . filter ( obj =>
138+ orgPackageSet . has ( obj . package . name . toLowerCase ( ) ) ,
139+ )
140+
141+ if ( filtered . length > 0 ) {
142+ return {
143+ ...response ,
144+ objects : filtered ,
145+ total : filtered . length ,
146+ }
147+ }
148+ }
149+ } catch {
150+ // Fall through to npm registry path
151+ }
152+ }
153+
154+ // --- npm registry path: fetch packuments individually ---
142155 const [ packuments , downloads ] = await Promise . all ( [
143- // Fetch packuments with concurrency limit
144156 ( async ( ) => {
145157 const results = await mapWithConcurrency (
146158 packageNames ,
@@ -157,16 +169,13 @@ export function useOrgPackages(orgName: MaybeRefOrGetter<string>) {
157169 } ,
158170 10 ,
159171 )
160- // Filter out any unpublished packages (missing dist-tags)
161172 return results . filter (
162173 ( pkg ) : pkg is MinimalPackument => pkg !== null && ! ! pkg [ 'dist-tags' ] ,
163174 )
164175 } ) ( ) ,
165- // Fetch downloads in bulk
166176 fetchBulkDownloads ( $npmApi , packageNames , { signal } ) ,
167177 ] )
168178
169- // Convert to search results with download data
170179 const results : NpmSearchResult [ ] = packuments . map ( pkg =>
171180 packumentToSearchResult ( pkg , downloads . get ( pkg . name ) ) ,
172181 )
0 commit comments