Skip to content

Commit 6bbe538

Browse files
committed
feat: add anonymous sign-ins
1 parent 5c710b4 commit 6bbe538

File tree

13 files changed

+266
-100
lines changed

13 files changed

+266
-100
lines changed

components.d.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,10 @@ export {}
77

88
declare module '@vue/runtime-core' {
99
export interface GlobalComponents {
10-
'Carbon:cafe': typeof import('~icons/carbon/cafe')['default']
11-
'Carbon:logoTwitter': typeof import('~icons/carbon/logo-twitter')['default']
1210
Footer: typeof import('./src/components/Footer.vue')['default']
1311
Hero: typeof import('./src/components/Hero.vue')['default']
1412
IconMenu: typeof import('./src/components/IconMenu.vue')['default']
1513
IconPalette: typeof import('./src/components/IconPalette.vue')['default']
16-
'Logos:nuxtIcon': typeof import('~icons/logos/nuxt-icon')['default']
17-
'Logos:vue': typeof import('~icons/logos/vue')['default']
18-
'Mdi:heart': typeof import('~icons/mdi/heart')['default']
19-
'Ri:githubFill': typeof import('~icons/ri/github-fill')['default']
20-
'Ri:moonLine': typeof import('~icons/ri/moon-line')['default']
21-
'Ri:sunLine': typeof import('~icons/ri/sun-line')['default']
22-
'Ri:translate2': typeof import('~icons/ri/translate2')['default']
2314
ToggleButton: typeof import('./src/components/ToggleButton.vue')['default']
2415
}
2516
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nuxtbase/auth-ui-vue",
3-
"version": "0.3.6",
3+
"version": "0.3.7",
44
"type": "module",
55
"author": "xiaoluoboding <[email protected]>",
66
"scripts": {

packages/auth/AnonymousAuth.vue

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<template>
2+
<form
3+
:id="`auth-${authView}`"
4+
@submit.prevent="handleSubmit"
5+
autoComplete="on"
6+
:style="{
7+
width: '100%'
8+
}"
9+
>
10+
<Container direction="vertical" gap="large" :appearance="appearance">
11+
<Button
12+
type="submit"
13+
color="primary"
14+
:loading="isLoading"
15+
:appearance="appearance"
16+
>
17+
{{ isLoading ? labels?.loading_button_label : labels?.button_label }}
18+
</Button>
19+
</Container>
20+
21+
<Message v-if="message" :appearance="appearance">{{ message }}</Message>
22+
23+
<Message v-if="error" color="danger" :appearance="appearance">
24+
{{ error }}
25+
</Message>
26+
</form>
27+
</template>
28+
29+
<script lang="ts" setup>
30+
import { ref, computed } from 'vue'
31+
import {
32+
SignInAnonymouslyCredentials,
33+
SupabaseClient
34+
} from '@supabase/supabase-js'
35+
import { RedirectTo } from '@supabase/auth-ui-shared'
36+
37+
import {
38+
AuthViewKey,
39+
type Appearance,
40+
type AuthViewInjection,
41+
type AuthI18nVariables
42+
} from '../types'
43+
import { Button, Container, Message } from '../ui/index'
44+
import { injectStrict } from '../utils'
45+
import { useSupabaseUser } from './UserContextProvider'
46+
47+
export interface AnonymousSignInProps {
48+
appearance?: Appearance
49+
supabaseClient: SupabaseClient
50+
redirectTo?: RedirectTo
51+
i18n?: AuthI18nVariables
52+
anonymouslyCredentials?: SignInAnonymouslyCredentials
53+
}
54+
55+
const props = withDefaults(defineProps<AnonymousSignInProps>(), {})
56+
57+
const { supabaseUser } = useSupabaseUser(props.supabaseClient)
58+
59+
const error = ref('')
60+
const message = ref('')
61+
const isLoading = ref(false)
62+
63+
const { authView, setAuthView } = injectStrict<AuthViewInjection>(AuthViewKey)
64+
65+
const labels = computed(
66+
() => props.i18n?.[authView.value] as AuthI18nVariables['anonymous_sign_in']
67+
)
68+
69+
const handleSubmit = async (e: Event) => {
70+
// console.log(props)
71+
error.value = ''
72+
message.value = ''
73+
isLoading.value = true
74+
let signInError: Error | null = null
75+
76+
const { data, error: err } =
77+
await props.supabaseClient.auth.signInAnonymously(
78+
props.anonymouslyCredentials
79+
)
80+
81+
signInError = err
82+
83+
if (signInError) {
84+
error.value = signInError.message
85+
}
86+
isLoading.value = false
87+
}
88+
</script>

packages/auth/Auth.vue

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,23 +61,31 @@
6161
:otpType="otpType"
6262
:i18n="i18n"
6363
/>
64+
<AnonymousAuth
65+
v-if="authView === 'anonymous_sign_in'"
66+
:supabaseClient="supabaseClient"
67+
:appearance="appearance"
68+
:i18n="i18n"
69+
:anonymouslyCredentials="anonymouslyCredentials"
70+
/>
6471
</template>
6572
</template>
6673

6774
<script lang="ts" setup>
6875
import { provide, ref, watch, computed } from 'vue'
69-
import { I18nVariables, ViewType, en, merge } from '@supabase/auth-ui-shared'
76+
import { I18nVariables, en, merge } from '@supabase/auth-ui-shared'
7077
import { createStitches } from '@stitches/core'
7178
import cloneDeep from 'lodash.clonedeep'
7279
73-
import { AuthProps, AuthViewKey } from '../types'
80+
import { AuthProps, AuthViewKey, AuthViewType } from '../types'
7481
import SocialAuthContainer from './SocialAuthContainer.vue'
7582
import EmailAuth from './EmailAuth.vue'
7683
import SocialAuth from './SocialAuth.vue'
7784
import MagicLink from './MagicLink.vue'
7885
import ForgottenPassword from './ForgottenPassword.vue'
7986
import UpdatePassword from './UpdatePassword.vue'
8087
import VerifyOtp from './VerifyOtp.vue'
88+
import AnonymousAuth from './AnonymousAuth.vue'
8189
8290
const props = withDefaults(defineProps<AuthProps>(), {
8391
view: 'sign_in',
@@ -87,13 +95,14 @@ const props = withDefaults(defineProps<AuthProps>(), {
8795
showLinks: true,
8896
dark: false,
8997
theme: 'default',
90-
otpType: 'email'
98+
otpType: 'email',
99+
anonymouslyCredentials: undefined
91100
})
92101
93102
const emit = defineEmits(['update:view'])
94103
95-
const authView = ref<ViewType>(props.view)
96-
const setAuthView = (newView: ViewType) => {
104+
const authView = ref<AuthViewType>(props.view)
105+
const setAuthView = (newView: AuthViewType) => {
97106
emit('update:view', newView)
98107
authView.value = newView
99108
}

packages/auth/EmailAuth.vue

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,14 @@
103103
<script lang="ts" setup>
104104
import { ref, computed, watch } from 'vue'
105105
import { SupabaseClient } from '@supabase/supabase-js'
106-
import { I18nVariables, RedirectTo, VIEWS } from '@supabase/auth-ui-shared'
106+
import { RedirectTo, VIEWS } from '@supabase/auth-ui-shared'
107107
108-
import { AuthViewKey, type Appearance, type AuthViewInjection } from '../types'
108+
import {
109+
AuthViewKey,
110+
type Appearance,
111+
type AuthViewInjection,
112+
type AuthI18nVariables
113+
} from '../types'
109114
import { Anchor, Button, Container, Input, Label, Message } from '../ui/index'
110115
import { injectStrict } from '../utils'
111116
@@ -117,7 +122,7 @@ export interface EmailAuthProps {
117122
redirectTo?: RedirectTo
118123
magicLink?: boolean
119124
showLinks?: boolean
120-
i18n?: I18nVariables
125+
i18n?: AuthI18nVariables
121126
additionalData?: { [key: string]: any }
122127
}
123128
@@ -132,7 +137,7 @@ const isLoading = ref(false)
132137
const { authView, setAuthView } = injectStrict<AuthViewInjection>(AuthViewKey)
133138
134139
const labels = computed(
135-
() => props.i18n?.[authView.value] as I18nVariables['sign_in' | 'sign_up']
140+
() => props.i18n?.[authView.value] as AuthI18nVariables['sign_in' | 'sign_up']
136141
)
137142
const handleSubmit = async (e: Event) => {
138143
// console.log(props)

packages/auth/ForgottenPassword.vue

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,14 @@
5555
<script lang="ts" setup>
5656
import { ref, computed } from 'vue'
5757
import { SupabaseClient } from '@supabase/supabase-js'
58-
import { I18nVariables, RedirectTo, VIEWS } from '@supabase/auth-ui-shared'
58+
import { RedirectTo, VIEWS } from '@supabase/auth-ui-shared'
5959
60-
import { AuthViewKey, type Appearance, type AuthViewInjection } from '../types'
60+
import {
61+
AuthViewKey,
62+
type Appearance,
63+
type AuthViewInjection,
64+
type AuthI18nVariables
65+
} from '../types'
6166
import { Anchor, Button, Container, Input, Label, Message } from '../ui/index'
6267
import { injectStrict } from '../utils'
6368
@@ -66,7 +71,7 @@ export interface ForgottenPasswordProps {
6671
supabaseClient: SupabaseClient
6772
redirectTo?: RedirectTo
6873
showLinks?: boolean
69-
i18n?: I18nVariables
74+
i18n?: AuthI18nVariables
7075
}
7176
7277
const props = withDefaults(defineProps<ForgottenPasswordProps>(), {})
@@ -79,7 +84,7 @@ const isLoading = ref(false)
7984
const { authView, setAuthView } = injectStrict<AuthViewInjection>(AuthViewKey)
8085
8186
const labels = computed(
82-
() => props.i18n?.[authView.value] as I18nVariables['forgotten_password']
87+
() => props.i18n?.[authView.value] as AuthI18nVariables['forgotten_password']
8388
)
8489
8590
const handleSubmit = async (e: Event) => {

packages/auth/MagicLink.vue

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,23 @@
88
}"
99
>
1010
<Container direction="vertical" gap="large" :appearance="appearance">
11-
<div>
12-
<Label htmlFor="email" :appearance="appearance">
13-
{{ labels?.email_input_label }}
14-
</Label>
15-
<Input
16-
id="email"
17-
type="email"
18-
name="email"
19-
autoComplete="email"
20-
autofocus
21-
:placeholder="labels?.email_input_placeholder"
22-
:appearance="appearance"
23-
v-model="email"
24-
/>
25-
</div>
11+
<Container direction="vertical" gap="large" :appearance="appearance">
12+
<div>
13+
<Label htmlFor="email" :appearance="appearance">
14+
{{ labels?.email_input_label }}
15+
</Label>
16+
<Input
17+
id="email"
18+
type="email"
19+
name="email"
20+
autoComplete="email"
21+
autofocus
22+
:placeholder="labels?.email_input_placeholder"
23+
:appearance="appearance"
24+
v-model="email"
25+
/>
26+
</div>
27+
</Container>
2628

2729
<Button
2830
type="submit"
@@ -55,9 +57,14 @@
5557
<script lang="ts" setup>
5658
import { ref, computed } from 'vue'
5759
import { SupabaseClient } from '@supabase/supabase-js'
58-
import { I18nVariables, RedirectTo, VIEWS } from '@supabase/auth-ui-shared'
60+
import { RedirectTo, VIEWS } from '@supabase/auth-ui-shared'
5961
60-
import { AuthViewKey, type Appearance, type AuthViewInjection } from '../types'
62+
import {
63+
AuthViewKey,
64+
type Appearance,
65+
type AuthViewInjection,
66+
type AuthI18nVariables
67+
} from '../types'
6168
import { Anchor, Button, Container, Input, Label, Message } from '../ui/index'
6269
import { injectStrict } from '../utils'
6370
import { useSupabaseUser } from './UserContextProvider'
@@ -67,7 +74,7 @@ export interface MagicLinkProps {
6774
supabaseClient: SupabaseClient
6875
redirectTo?: RedirectTo
6976
showLinks?: boolean
70-
i18n?: I18nVariables
77+
i18n?: AuthI18nVariables
7178
}
7279
7380
const props = withDefaults(defineProps<MagicLinkProps>(), {})
@@ -82,7 +89,7 @@ const isLoading = ref(false)
8289
const { authView, setAuthView } = injectStrict<AuthViewInjection>(AuthViewKey)
8390
8491
const labels = computed(
85-
() => props.i18n?.[authView.value] as I18nVariables['magic_link']
92+
() => props.i18n?.[authView.value] as AuthI18nVariables['magic_link']
8693
)
8794
8895
const handleSubmit = async (e: Event) => {
@@ -93,11 +100,14 @@ const handleSubmit = async (e: Event) => {
93100
const isAnonymous = supabaseUser.value?.is_anonymous
94101
let signInError: Error | null = null
95102
if (isAnonymous) {
96-
const { error: err } = await props.supabaseClient.auth.updateUser({
97-
email: email.value
98-
}, {
99-
emailRedirectTo: props.redirectTo
100-
})
103+
const { error: err } = await props.supabaseClient.auth.updateUser(
104+
{
105+
email: email.value
106+
},
107+
{
108+
emailRedirectTo: props.redirectTo
109+
}
110+
)
101111
signInError = err
102112
} else {
103113
const { error: err } = await props.supabaseClient.auth.signInWithOtp({

packages/auth/SocialAuth.vue

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,17 @@
3838
import { computed, ref } from 'vue'
3939
import { Provider, SupabaseClient } from '@supabase/supabase-js'
4040
import {
41-
I18nVariables,
4241
ProviderScopes,
4342
SocialLayout,
4443
template
4544
} from '@supabase/auth-ui-shared'
4645
47-
import { Appearance, AuthViewInjection, AuthViewKey } from '../types'
46+
import {
47+
AuthViewKey,
48+
type Appearance,
49+
type AuthViewInjection,
50+
type AuthI18nVariables
51+
} from '../types'
4852
import { Divider, Button, Container } from '@/ui'
4953
import { Icons } from '@/icons'
5054
import { injectStrict } from '../utils'
@@ -61,7 +65,7 @@ export interface SocialAuthProps {
6165
redirectTo?: RedirectTo
6266
onlyThirdPartyProviders?: boolean
6367
view?: 'sign_in' | 'sign_up' | 'magic_link'
64-
i18n?: I18nVariables
68+
i18n?: AuthI18nVariables
6569
appearance?: Appearance
6670
}
6771
@@ -87,7 +91,8 @@ const currentView = computed(() => {
8791
})
8892
8993
const labels = computed(
90-
() => props.i18n?.[currentView.value] as I18nVariables['sign_in' | 'sign_up']
94+
() =>
95+
props.i18n?.[currentView.value] as AuthI18nVariables['sign_in' | 'sign_up']
9196
)
9297
9398
const handleProviderSignIn = async (provider: Provider) => {
@@ -100,20 +105,21 @@ const handleProviderSignIn = async (provider: Provider) => {
100105
scopes: props.providerScopes?.[provider],
101106
queryParams: props.queryParams
102107
}
103-
108+
104109
let signInError: Error | null = null
105-
110+
106111
if (isAnonymous) {
107112
const { data, error: err } = await props.supabaseClient.auth.linkIdentity({
108113
provider,
109114
options
110115
})
111116
signInError = err
112117
} else {
113-
const { data, error: err } = await props.supabaseClient.auth.signInWithOAuth({
114-
provider,
115-
options
116-
})
118+
const { data, error: err } =
119+
await props.supabaseClient.auth.signInWithOAuth({
120+
provider,
121+
options
122+
})
117123
signInError = err
118124
}
119125

0 commit comments

Comments
 (0)