diff --git a/web/app/components/plugins/marketplace/creator-profile/__tests__/data.server.spec.ts b/web/app/components/plugins/marketplace/creator-profile/__tests__/data.server.spec.ts index 66dd5702b91..64cade33cee 100644 --- a/web/app/components/plugins/marketplace/creator-profile/__tests__/data.server.spec.ts +++ b/web/app/components/plugins/marketplace/creator-profile/__tests__/data.server.spec.ts @@ -175,9 +175,39 @@ describe('loadCreatorProfile', () => { expect(loaded?.viewModel.creations.map(({ kind }) => kind)).toEqual(['template']) }) - it('returns null when the primary creator does not exist', async () => { + it('loads a profile from published work when the creator record is missing', async () => { mocks.creatorDetail.mockResolvedValue({ data: {} }) + const loaded = await loadCreatorProfile({ + uniqueHandle: 'template-author', + locale: 'en-US', + }) + + expect(loaded?.viewModel.profile).toMatchObject({ + kind: 'individual', + handle: 'template-author', + displayName: 'template-author', + }) + expect(loaded?.viewModel.creations.map(({ kind }) => kind)).toEqual(['plugin', 'template']) + }) + + it('loads a profile from published work when the creator request fails', async () => { + mocks.creatorDetail.mockRejectedValue(new Error('creator not found or deleted')) + + const loaded = await loadCreatorProfile({ + uniqueHandle: 'template-author', + locale: 'en-US', + }) + + expect(loaded?.viewModel.profile.handle).toBe('template-author') + expect(loaded?.viewModel.creations).toHaveLength(2) + }) + + it('returns null when the creator record and published work are both missing', async () => { + mocks.creatorDetail.mockResolvedValue({ data: {} }) + mocks.publisherPlugins.mockResolvedValue({ data: { plugins: [] } }) + mocks.publisherTemplates.mockResolvedValue({ data: { templates: [] } }) + await expect( loadCreatorProfile({ uniqueHandle: 'missing-creator', locale: 'en-US' }), ).resolves.toBeNull() diff --git a/web/app/components/plugins/marketplace/creator-profile/data.server.ts b/web/app/components/plugins/marketplace/creator-profile/data.server.ts index d569f4dc3ba..7c368e2ac80 100644 --- a/web/app/components/plugins/marketplace/creator-profile/data.server.ts +++ b/web/app/components/plugins/marketplace/creator-profile/data.server.ts @@ -104,13 +104,22 @@ const loadCreatorProfileCached = cache( getPublisherTemplates(uniqueHandle, sortField, sortOrder), ]) - const creator = creatorResult.status === 'fulfilled' ? creatorResult.value : undefined - if (!creator) return null - const plugins: MarketplacePlugin[] = pluginsResult.status === 'fulfilled' ? pluginsResult.value : [] const templates: MarketplaceTemplate[] = templatesResult.status === 'fulfilled' ? templatesResult.value : [] + let creator = creatorResult.status === 'fulfilled' ? creatorResult.value : undefined + // Templates/plugins are keyed by publisher handle. A missing synced creator + // row must not 404 a publisher who already has public work. + if (!creator && (plugins.length > 0 || templates.length > 0)) { + creator = { + unique_handle: uniqueHandle, + display_name: uniqueHandle, + name: uniqueHandle, + social_links: [], + } + } + if (!creator) return null const kind = publisherType === 'organization' ? 'organization' : 'individual' const resource = kind === 'organization' ? 'organizations' : 'creators' const encodedHandle = encodeURIComponent(uniqueHandle)