Skip to content

Commit 05e8f19

Browse files
authored
fix: allow did in /profile urls as well as resolve a bug in first npmx profile create (#1806)
1 parent 488564c commit 05e8f19

File tree

5 files changed

+28
-20
lines changed

5 files changed

+28
-20
lines changed

app/components/Header/AuthModal.client.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ watch(user, async newUser => {
7878
<div class="flex flex-col space-y-4">
7979
<LinkBase
8080
variant="button-secondary"
81-
:to="{ name: 'profile-handle', params: { handle: user.handle } }"
81+
:to="{ name: 'profile-identity', params: { identity: user.handle } }"
8282
prefetch-on="interaction"
8383
class="w-full"
8484
@click="authModal.close()"
Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<script setup lang="ts">
22
import { updateProfile as updateProfileUtil } from '~/utils/atproto/profile'
33
4-
const route = useRoute('profile-handle')
5-
const handle = computed(() => route.params.handle)
4+
const route = useRoute('profile-identity')
5+
const identity = computed(() => route.params.identity)
66
77
const { data: profile, error: profileError } = await useFetch<NPMXProfile>(
8-
() => `/api/social/profile/${handle.value}`,
8+
() => `/api/social/profile/${identity.value}`,
99
{
1010
default: () => ({
11-
displayName: handle.value,
11+
displayName: identity.value,
1212
description: '',
1313
website: '',
1414
recordExists: false,
@@ -19,7 +19,7 @@ if (!profile.value || profileError.value?.statusCode === 404) {
1919
throw createError({
2020
statusCode: 404,
2121
statusMessage: $t('profile.not_found'),
22-
message: $t('profile.not_found_message', { handle: handle.value }),
22+
message: $t('profile.not_found_message', { handle: identity.value }),
2323
})
2424
}
2525
@@ -53,11 +53,12 @@ async function updateProfile() {
5353
displayName: displayNameInput.value,
5454
description: descriptionInput.value || undefined,
5555
website: websiteInput.value || undefined,
56+
handle: profile.value.handle,
5657
recordExists: true,
5758
}
5859
5960
try {
60-
const result = await updateProfileUtil(handle.value, {
61+
const result = await updateProfileUtil(identity.value, {
6162
displayName: displayNameInput.value,
6263
description: descriptionInput.value || undefined,
6364
website: websiteInput.value || undefined,
@@ -76,25 +77,25 @@ async function updateProfile() {
7677
}
7778
}
7879
79-
const { data: likes, status } = useProfileLikes(handle)
80+
const { data: likes, status } = useProfileLikes(identity)
8081
8182
const showInviteSection = computed(() => {
8283
return (
8384
profile.value.recordExists === false &&
8485
status.value === 'success' &&
8586
!likes.value?.records?.length &&
86-
user.value?.handle !== handle.value
87+
user.value?.handle !== profile.value.handle
8788
)
8889
})
8990
9091
const inviteUrl = computed(() => {
91-
const text = $t('profile.invite.compose_text', { handle: handle.value })
92+
const text = $t('profile.invite.compose_text', { handle: profile.value.handle })
9293
return `https://bsky.app/intent/compose?text=${encodeURIComponent(text)}`
9394
})
9495
9596
useSeoMeta({
96-
title: () => $t('profile.seo_title', { handle: handle.value }),
97-
description: () => $t('profile.seo_description', { handle: handle.value }),
97+
title: () => $t('profile.seo_title', { handle: identity.value }),
98+
description: () => $t('profile.seo_description', { handle: identity.value }),
9899
})
99100
100101
/**
@@ -143,7 +144,7 @@ defineOgImageComponent('Default', {
143144
/>
144145
</label>
145146
<div class="flex gap-4 items-center font-mono text-sm">
146-
<h2>@{{ handle }}</h2>
147+
<h2>@{{ profile?.handle }}</h2>
147148
<ButtonBase @click="isEditing = false">
148149
{{ $t('common.cancel') }}
149150
</ButtonBase>
@@ -164,13 +165,13 @@ defineOgImageComponent('Default', {
164165
</h1>
165166
<p v-if="profile.description">{{ profile.description }}</p>
166167
<div class="flex gap-4 items-center font-mono text-sm">
167-
<h2>@{{ handle }}</h2>
168+
<h2>@{{ profile.handle ?? identity }}</h2>
168169
<LinkBase v-if="profile.website" :to="profile.website" classicon="i-lucide:link">
169170
{{ profile.website }}
170171
</LinkBase>
171172
<ButtonBase
172173
@click="isEditing = true"
173-
:class="user?.handle === handle ? '' : 'invisible'"
174+
:class="user?.handle === profile?.handle ? '' : 'invisible'"
174175
class="hidden sm:inline-flex"
175176
>
176177
{{ $t('common.edit') }}

server/api/auth/atproto.get.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,7 @@ async function getNpmxProfile(handle: string, authSession: OAuthSession) {
302302
return profileResult.body.value
303303
} else {
304304
const profile = {
305-
website: '',
306305
displayName: handle,
307-
description: '',
308306
}
309307

310308
await client.createRecord(

server/utils/atproto/utils/profile.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,23 @@ export class ProfileUtils {
8282
})
8383

8484
if (response.success) {
85-
const validationResult = dev.npmx.actor.profile.$validate(response.body.value)
86-
profile = { recordExists: true, ...validationResult }
87-
await this.cache.set(profileKey, profile, CACHE_MAX_AGE)
85+
try {
86+
const validationResult = dev.npmx.actor.profile.$validate(response.body.value)
87+
profile = { recordExists: true, handle: miniDoc.handle, ...validationResult }
88+
await this.cache.set(profileKey, profile, CACHE_MAX_AGE)
89+
} catch (error) {
90+
//Most new profiles will error because of a bug of setting the website to a non uri string
91+
console.error('[profile-get]', error)
92+
profile = { recordExists: true, handle: miniDoc.handle, displayName: miniDoc.handle }
93+
}
8894
} else {
8995
if (response.error === 'RecordNotFound') {
9096
return {
9197
recordExists: false,
9298
displayName: miniDoc.handle,
9399
description: '',
94100
website: '',
101+
handle: miniDoc.handle,
95102
}
96103
}
97104
throw new Error(`Failed to fetch profile: ${response.error}`)
@@ -104,6 +111,7 @@ export class ProfileUtils {
104111
async updateProfileCache(handle: string, profile: NPMXProfile): Promise<NPMXProfile | undefined> {
105112
const miniDoc = await this.slingshotMiniDoc(handle)
106113
const profileKey = CACHE_PROFILE_KEY(miniDoc.did)
114+
profile.handle = miniDoc.handle
107115
await this.cache.set(profileKey, profile, CACHE_MAX_AGE)
108116
return profile
109117
}

shared/types/social.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ export type NPMXProfile = {
2929
description?: string
3030
// If the atproto record exists for the profile
3131
recordExists: boolean
32+
handle?: string
3233
}

0 commit comments

Comments
 (0)