mirror of
https://github.com/supabase/supabase.git
synced 2026-05-07 23:19:23 +08:00
chore: format files (#43668)
Format files. Run `pnpm format` at root. --------- Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
This commit is contained in:
committed by
GitHub
parent
f49ed14dfb
commit
77e5180c5c
6
.github/workflows/prettier.yml
vendored
6
.github/workflows/prettier.yml
vendored
@@ -21,8 +21,10 @@ jobs:
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
|
||||
with:
|
||||
sparse-checkout: |
|
||||
apps
|
||||
patches
|
||||
apps
|
||||
packages
|
||||
blocks
|
||||
patches
|
||||
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
name: Install pnpm
|
||||
with:
|
||||
|
||||
@@ -19,6 +19,7 @@ Replication currently supports **BigQuery** as the only managed destination. See
|
||||
We are working on adding more destinations in the future. Availability may continue to vary based on the planned roll-out strategy.
|
||||
|
||||
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
|
||||
|
||||
## What happened to Analytics Buckets replication?
|
||||
|
||||
We are currently working on a new Supabase Warehouse product designed to address the limitations of the previous Analytics Buckets. Our goal is to build a solution we can confidently stand behind, rather than continuing to support an approach that does not meet the quality and flexibility we want for our users.
|
||||
|
||||
@@ -44,10 +44,7 @@ When the rate limit is exceeded, calling another Edge Function throws a `RateLim
|
||||
```typescript
|
||||
import { createClient } from 'jsr:@supabase/supabase-js@2'
|
||||
|
||||
const supabase = createClient(
|
||||
Deno.env.get('SUPABASE_URL')!,
|
||||
Deno.env.get('SUPABASE_ANON_KEY')!
|
||||
)
|
||||
const supabase = createClient(Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_ANON_KEY')!)
|
||||
|
||||
Deno.serve(async (req) => {
|
||||
try {
|
||||
@@ -87,17 +84,14 @@ Deno.serve(async (req) => {
|
||||
```typescript
|
||||
Deno.serve(async (req) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${Deno.env.get('SUPABASE_URL')}/functions/v1/other-function`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${Deno.env.get('SUPABASE_ANON_KEY')}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ foo: 'bar' }),
|
||||
}
|
||||
)
|
||||
const response = await fetch(`${Deno.env.get('SUPABASE_URL')}/functions/v1/other-function`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${Deno.env.get('SUPABASE_ANON_KEY')}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ foo: 'bar' }),
|
||||
})
|
||||
return response
|
||||
} catch (err) {
|
||||
if (err instanceof Deno.errors.RateLimitError) {
|
||||
@@ -136,16 +130,9 @@ You can also use `retryAfterMs` to implement automatic retries within your funct
|
||||
```typescript
|
||||
import { createClient } from 'jsr:@supabase/supabase-js@2'
|
||||
|
||||
const supabase = createClient(
|
||||
Deno.env.get('SUPABASE_URL')!,
|
||||
Deno.env.get('SUPABASE_ANON_KEY')!
|
||||
)
|
||||
const supabase = createClient(Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_ANON_KEY')!)
|
||||
|
||||
async function invokeWithRetry(
|
||||
functionName: string,
|
||||
payload: object,
|
||||
maxRetries = 3
|
||||
) {
|
||||
async function invokeWithRetry(functionName: string, payload: object, maxRetries = 3) {
|
||||
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
||||
try {
|
||||
const { data, error } = await supabase.functions.invoke(functionName, {
|
||||
@@ -279,15 +266,15 @@ async function processWithDelay(items: any[]) {
|
||||
|
||||
## Common patterns and their impact
|
||||
|
||||
| Pattern | Budget consumption | Recommendation |
|
||||
| --- | --- | --- |
|
||||
| Simple chain (A to B to C) | Low | Generally safe |
|
||||
| Fan-out (A to B, C, D, E) | Moderate | Limit concurrency |
|
||||
| Deep recursion (A to A to A...) | High | Set max depth |
|
||||
| Unbounded loops | Very high | Avoid, use queues |
|
||||
| Pattern | Budget consumption | Recommendation |
|
||||
| ------------------------------- | ------------------ | ----------------- |
|
||||
| Simple chain (A to B to C) | Low | Generally safe |
|
||||
| Fan-out (A to B, C, D, E) | Moderate | Limit concurrency |
|
||||
| Deep recursion (A to A to A...) | High | Set max depth |
|
||||
| Unbounded loops | Very high | Avoid, use queues |
|
||||
|
||||
## Increasing rate limits
|
||||
|
||||
Currently, all plans have the same rate limit budget. We are working on introducing custom limits for different use cases.
|
||||
|
||||
If you need a higher rate limit for your project, [contact support](/dashboard/support/new) with details about your use case.
|
||||
If you need a higher rate limit for your project, [contact support](/dashboard/support/new) with details about your use case.
|
||||
|
||||
@@ -27,11 +27,11 @@ property which gets populated automatically by Supabase Auth if the user logged
|
||||
|
||||
The `CurrentUserAvatar` component is designed to be used anywhere in your app. Add the `<CurrentUserAvatar />` component to your page and it will render the avatar of the current user, with a fallback.
|
||||
|
||||
```html
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
// Asumes you have Header component created
|
||||
import Header from '@/components/Header.vue'
|
||||
// Assumes you have Header component created
|
||||
import CurrentUserAvatar from '@/components/CurrentUserAvatar.vue'
|
||||
import Header from '@/components/Header.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -42,18 +42,18 @@ The File Upload component makes it easy to add file uploads to your app, with bu
|
||||
|
||||
- Simply add this `<Dropzone />` component to your page and it will handle the rest.
|
||||
|
||||
```html
|
||||
```vue
|
||||
<script setup>
|
||||
import { Dropzone, DropzoneContent, DropzoneEmptyState } from '@/components/dropzone'
|
||||
import { useSupabaseUpload } from '@/composables/use-supabase-upload'
|
||||
import { Dropzone, DropzoneContent, DropzoneEmptyState } from '@/components/dropzone'
|
||||
import { useSupabaseUpload } from '@/composables/use-supabase-upload'
|
||||
|
||||
const upload = useSupabaseUpload({
|
||||
bucketName: 'test',
|
||||
path: 'test',
|
||||
allowedMimeTypes: ['image/*'],
|
||||
maxFiles: 2,
|
||||
maxFileSize: 1000 * 1000 * 10, // 10MB,
|
||||
})
|
||||
const upload = useSupabaseUpload({
|
||||
bucketName: 'test',
|
||||
path: 'test',
|
||||
allowedMimeTypes: ['image/*'],
|
||||
maxFiles: 2,
|
||||
maxFileSize: 1000 * 1000 * 10, // 10MB,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -22,9 +22,9 @@ This block assumes that you have already installed a Supabase client for Nuxt fr
|
||||
|
||||
The `RealtimeAvatarStack` component renders stacked avatars which are connected to Supabase Realtime. It uses the Presence feature of Supabase Realtime. You can use this to show currently online users in a chatroom, game session or collaborative app.
|
||||
|
||||
```html
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
// Asumes you have Header component created
|
||||
// Assumes you have Header component created
|
||||
import Header from '@/components/Header.vue'
|
||||
import RealtimeAvatarStack from '@/components/RealtimeAvatarStack.vue'
|
||||
</script>
|
||||
|
||||
@@ -37,9 +37,9 @@ The Realtime Cursors component lets users share their cursor position with other
|
||||
|
||||
The Realtime Cursor component is designed to be used in a room. It can be used to build real-time collaborative applications. Add the `<RealtimeCursors />` component to your page and it will render realtime cursors from other users in the room.
|
||||
|
||||
```html
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import RealtimeCursors from '@/components/RealtimeCursors.vue'
|
||||
import RealtimeCursors from '@/components/RealtimeCursors.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -24,11 +24,11 @@ property which gets populated automatically by Supabase Auth if the user logged
|
||||
|
||||
The `CurrentUserAvatar` component is designed to be used anywhere in your app. Add the `<CurrentUserAvatar />` component to your page and it will render the avatar of the current user, with a fallback.
|
||||
|
||||
```html
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
// Asumes you have Header component created
|
||||
import Header from '@/components/Header.vue'
|
||||
// Assumes you have Header component created
|
||||
import CurrentUserAvatar from '@/components/CurrentUserAvatar.vue'
|
||||
import Header from '@/components/Header.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -42,18 +42,18 @@ The File Upload component makes it easy to add file uploads to your app, with bu
|
||||
|
||||
- Simply add this `<Dropzone />` component to your page and it will handle the rest.
|
||||
|
||||
```html
|
||||
```vue
|
||||
<script setup>
|
||||
import { Dropzone, DropzoneContent, DropzoneEmptyState } from '@/components/dropzone'
|
||||
import { useSupabaseUpload } from '@/composables/use-supabase-upload'
|
||||
import { Dropzone, DropzoneContent, DropzoneEmptyState } from '@/components/dropzone'
|
||||
import { useSupabaseUpload } from '@/composables/use-supabase-upload'
|
||||
|
||||
const upload = useSupabaseUpload({
|
||||
bucketName: 'test',
|
||||
path: 'test',
|
||||
allowedMimeTypes: ['image/*'],
|
||||
maxFiles: 2,
|
||||
maxFileSize: 1000 * 1000 * 10, // 10MB,
|
||||
})
|
||||
const upload = useSupabaseUpload({
|
||||
bucketName: 'test',
|
||||
path: 'test',
|
||||
allowedMimeTypes: ['image/*'],
|
||||
maxFiles: 2,
|
||||
maxFileSize: 1000 * 1000 * 10, // 10MB,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -22,9 +22,9 @@ This block assumes that you have already installed a Supabase client for Vue fro
|
||||
|
||||
The `RealtimeAvatarStack` component renders stacked avatars which are connected to Supabase Realtime. It uses the Presence feature of Supabase Realtime. You can use this to show currently online users in a chatroom, game session or collaborative app.
|
||||
|
||||
```html
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
// Asumes you have Header component created
|
||||
// Assumes you have Header component created
|
||||
import Header from '@/components/Header.vue'
|
||||
import RealtimeAvatarStack from '@/components/RealtimeAvatarStack.vue'
|
||||
</script>
|
||||
|
||||
@@ -37,9 +37,9 @@ The Realtime Cursors component lets users share their cursor position with other
|
||||
|
||||
The Realtime Cursor component is designed to be used in a room. It can be used to build real-time collaborative applications. Add the `<RealtimeCursors />` component to your page and it will render realtime cursors from other users in the room.
|
||||
|
||||
```html
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import RealtimeCursors from '@/components/RealtimeCursors.vue'
|
||||
import RealtimeCursors from '@/components/RealtimeCursors.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
},
|
||||
{
|
||||
"path": "registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserName.ts",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserName() {\n const name = ref<string | null>(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserName() {\n const name = ref<string | null>(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": "app/composables/useCurrentUserName.ts"
|
||||
},
|
||||
{
|
||||
"path": "registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserImage.ts",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserImage() {\n const image = ref<string | null>(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserImage() {\n const image = ref<string | null>(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": "app/composables/useCurrentUserImage.ts"
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
},
|
||||
{
|
||||
"path": "registry/default/current-user-avatar/vue/composables/useCurrentUserName.ts",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserName() {\n const name = ref<string | null>(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserName() {\n const name = ref<string | null>(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": "composables/useCurrentUserName.ts"
|
||||
},
|
||||
{
|
||||
"path": "registry/default/current-user-avatar/vue/composables/useCurrentUserImage.ts",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserImage() {\n const image = ref<string | null>(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserImage() {\n const image = ref<string | null>(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": "composables/useCurrentUserImage.ts"
|
||||
}
|
||||
|
||||
@@ -26,19 +26,19 @@
|
||||
},
|
||||
{
|
||||
"path": "registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserImage.ts",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserImage() {\n const image = ref<string | null>(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserImage() {\n const image = ref<string | null>(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": "app/composables/useCurrentUserImage.ts"
|
||||
},
|
||||
{
|
||||
"path": "registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserName.ts",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserName() {\n const name = ref<string | null>(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserName() {\n const name = ref<string | null>(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": "app/composables/useCurrentUserName.ts"
|
||||
},
|
||||
{
|
||||
"path": "registry/default/realtime-avatar-stack/nuxtjs/app/composables/useRealtimePresenceRoom.ts",
|
||||
"content": "import { ref, watch, onUnmounted } from 'vue'\nimport { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'\n\nimport { useCurrentUserImage } from './useCurrentUserImage'\nimport { useCurrentUserName } from './useCurrentUserName'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nconst supabase = createClient()\n\nexport type RealtimeUser = {\n id: string\n name: string\n image: string\n}\n\nexport function useRealtimePresenceRoom(roomName: string) {\n const { image: currentUserImage } = useCurrentUserImage()\n const { name: currentUserName } = useCurrentUserName()\n\n const users = ref<Record<string, RealtimeUser>>({})\n\n let room: ReturnType<typeof supabase.channel> | null = null\n\n function setupRoom() {\n if (!roomName) return\n\n room = supabase.channel(roomName)\n\n room\n .on('presence', { event: 'sync' }, () => {\n const newState =\n room?.presenceState<{ image: string; name: string }>() ?? {}\n\n const newUsers = Object.fromEntries(\n Object.entries(newState).map(([key, values]) => {\n const typedValues = values as Array<{ image: string; name: string }>\n return [\n key,\n {\n id: key,\n name: typedValues[0].name,\n image: typedValues[0].image,\n },\n ]\n })\n ) as Record<string, RealtimeUser>\n\n users.value = newUsers\n })\n .subscribe(async (status: REALTIME_SUBSCRIBE_STATES) => {\n if (status === REALTIME_SUBSCRIBE_STATES.SUBSCRIBED && room) {\n await room.track({\n name: currentUserName.value,\n image: currentUserImage.value,\n })\n } else {\n users.value = {}\n }\n })\n }\n\n function cleanup() {\n if (room) {\n room.unsubscribe()\n room = null\n }\n }\n\n watch(\n [() => roomName, currentUserName, currentUserImage],\n () => {\n cleanup()\n setupRoom()\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n cleanup()\n })\n\n return { users }\n}\n",
|
||||
"content": "import { ref, watch, onUnmounted } from 'vue'\nimport { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'\n\nimport { useCurrentUserImage } from './useCurrentUserImage'\nimport { useCurrentUserName } from './useCurrentUserName'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nconst supabase = createClient()\n\nexport type RealtimeUser = {\n id: string\n name: string\n image: string\n}\n\nexport function useRealtimePresenceRoom(roomName: string) {\n const { image: currentUserImage } = useCurrentUserImage()\n const { name: currentUserName } = useCurrentUserName()\n\n const users = ref<Record<string, RealtimeUser>>({})\n\n let room: ReturnType<typeof supabase.channel> | null = null\n\n function setupRoom() {\n if (!roomName) return\n\n room = supabase.channel(roomName)\n\n room\n .on('presence', { event: 'sync' }, () => {\n const newState = room?.presenceState<{ image: string; name: string }>() ?? {}\n\n const newUsers = Object.fromEntries(\n Object.entries(newState).map(([key, values]) => {\n const typedValues = values as Array<{ image: string; name: string }>\n return [\n key,\n {\n id: key,\n name: typedValues[0].name,\n image: typedValues[0].image,\n },\n ]\n })\n ) as Record<string, RealtimeUser>\n\n users.value = newUsers\n })\n .subscribe(async (status: REALTIME_SUBSCRIBE_STATES) => {\n if (status === REALTIME_SUBSCRIBE_STATES.SUBSCRIBED && room) {\n await room.track({\n name: currentUserName.value,\n image: currentUserImage.value,\n })\n } else {\n users.value = {}\n }\n })\n }\n\n function cleanup() {\n if (room) {\n room.unsubscribe()\n room = null\n }\n }\n\n watch(\n [() => roomName, currentUserName, currentUserImage],\n () => {\n cleanup()\n setupRoom()\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n cleanup()\n })\n\n return { users }\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": "app/composables/useRealtimePresenceRoom.ts"
|
||||
}
|
||||
|
||||
@@ -26,19 +26,19 @@
|
||||
},
|
||||
{
|
||||
"path": "registry/default/realtime-avatar-stack/vue/composables/useCurrentUserImage.ts",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserImage() {\n const image = ref<string | null>(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserImage() {\n const image = ref<string | null>(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": "composables/useCurrentUserImage.ts"
|
||||
},
|
||||
{
|
||||
"path": "registry/default/realtime-avatar-stack/vue/composables/useCurrentUserName.ts",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserName() {\n const name = ref<string | null>(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
|
||||
"content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserName() {\n const name = ref<string | null>(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": "composables/useCurrentUserName.ts"
|
||||
},
|
||||
{
|
||||
"path": "registry/default/realtime-avatar-stack/vue/composables/useRealtimePresenceRoom.ts",
|
||||
"content": "import { ref, watch, onUnmounted } from 'vue'\nimport { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'\n\nimport { useCurrentUserImage } from './useCurrentUserImage'\nimport { useCurrentUserName } from './useCurrentUserName'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nconst supabase = createClient()\n\nexport type RealtimeUser = {\n id: string\n name: string\n image: string\n}\n\nexport function useRealtimePresenceRoom(roomName: string) {\n const { image: currentUserImage } = useCurrentUserImage()\n const { name: currentUserName } = useCurrentUserName()\n\n const users = ref<Record<string, RealtimeUser>>({})\n\n let room: ReturnType<typeof supabase.channel> | null = null\n\n function setupRoom() {\n if (!roomName) return\n\n room = supabase.channel(roomName)\n\n room\n .on('presence', { event: 'sync' }, () => {\n const newState =\n room?.presenceState<{ image: string; name: string }>() ?? {}\n\n const newUsers = Object.fromEntries(\n Object.entries(newState).map(([key, values]) => {\n const typedValues = values as Array<{ image: string; name: string }>\n if (typedValues.length > 0) {\n return [\n key,\n {\n id: key,\n name: typedValues[0].name,\n image: typedValues[0].image,\n },\n ]\n } else {\n return [\n key,\n {\n id: key,\n name: '',\n image: '',\n },\n ]\n }\n })\n ) as Record<string, RealtimeUser>\n\n users.value = newUsers\n })\n .subscribe(async (status: REALTIME_SUBSCRIBE_STATES) => {\n if (status === REALTIME_SUBSCRIBE_STATES.SUBSCRIBED && room) {\n await room.track({\n name: currentUserName.value,\n image: currentUserImage.value,\n })\n } else {\n users.value = {}\n }\n })\n }\n\n function cleanup() {\n if (room) {\n room.unsubscribe()\n room = null\n }\n }\n\n watch(\n [() => roomName, currentUserName, currentUserImage],\n () => {\n cleanup()\n setupRoom()\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n cleanup()\n })\n\n return { users }\n}\n",
|
||||
"content": "import { ref, watch, onUnmounted } from 'vue'\nimport { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'\n\nimport { useCurrentUserImage } from './useCurrentUserImage'\nimport { useCurrentUserName } from './useCurrentUserName'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nconst supabase = createClient()\n\nexport type RealtimeUser = {\n id: string\n name: string\n image: string\n}\n\nexport function useRealtimePresenceRoom(roomName: string) {\n const { image: currentUserImage } = useCurrentUserImage()\n const { name: currentUserName } = useCurrentUserName()\n\n const users = ref<Record<string, RealtimeUser>>({})\n\n let room: ReturnType<typeof supabase.channel> | null = null\n\n function setupRoom() {\n if (!roomName) return\n\n room = supabase.channel(roomName)\n\n room\n .on('presence', { event: 'sync' }, () => {\n const newState = room?.presenceState<{ image: string; name: string }>() ?? {}\n\n const newUsers = Object.fromEntries(\n Object.entries(newState).map(([key, values]) => {\n const typedValues = values as Array<{ image: string; name: string }>\n if (typedValues.length > 0) {\n return [\n key,\n {\n id: key,\n name: typedValues[0].name,\n image: typedValues[0].image,\n },\n ]\n } else {\n return [\n key,\n {\n id: key,\n name: '',\n image: '',\n },\n ]\n }\n })\n ) as Record<string, RealtimeUser>\n\n users.value = newUsers\n })\n .subscribe(async (status: REALTIME_SUBSCRIBE_STATES) => {\n if (status === REALTIME_SUBSCRIBE_STATES.SUBSCRIBED && room) {\n await room.track({\n name: currentUserName.value,\n image: currentUserImage.value,\n })\n } else {\n users.value = {}\n }\n })\n }\n\n function cleanup() {\n if (room) {\n room.unsubscribe()\n room = null\n }\n }\n\n watch(\n [() => roomName, currentUserName, currentUserImage],\n () => {\n cleanup()\n setupRoom()\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n cleanup()\n })\n\n return { users }\n}\n",
|
||||
"type": "registry:component",
|
||||
"target": "composables/useRealtimePresenceRoom.ts"
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@ import { type RegistryItem } from 'shadcn/schema'
|
||||
import nuxtjs from './default/current-user-avatar/nuxtjs/registry-item.json' with { type: 'json' }
|
||||
import vue from './default/current-user-avatar/vue/registry-item.json' with { type: 'json' }
|
||||
|
||||
export const currentUserAvatar = [nuxtjs, vue] as RegistryItem[]
|
||||
export const currentUserAvatar = [nuxtjs, vue] as RegistryItem[]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
// @ts-ignore
|
||||
import { createClient } from "@/lib/supabase/client"
|
||||
import { createClient } from '@/lib/supabase/client'
|
||||
|
||||
export function useCurrentUserImage() {
|
||||
const image = ref<string | null>(null)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
// @ts-ignore
|
||||
import { createClient } from "@/lib/supabase/client"
|
||||
import { createClient } from '@/lib/supabase/client'
|
||||
|
||||
export function useCurrentUserName() {
|
||||
const name = ref<string | null>(null)
|
||||
|
||||
@@ -22,4 +22,4 @@
|
||||
}
|
||||
],
|
||||
"dependencies": ["@supabase/supabase-js@latest"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
// @ts-ignore
|
||||
import { createClient } from "@/lib/supabase/client"
|
||||
import { createClient } from '@/lib/supabase/client'
|
||||
|
||||
export function useCurrentUserImage() {
|
||||
const image = ref<string | null>(null)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
// @ts-ignore
|
||||
import { createClient } from "@/lib/supabase/client"
|
||||
import { createClient } from '@/lib/supabase/client'
|
||||
|
||||
export function useCurrentUserName() {
|
||||
const name = ref<string | null>(null)
|
||||
|
||||
@@ -22,4 +22,4 @@
|
||||
}
|
||||
],
|
||||
"dependencies": ["@supabase/supabase-js@latest"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
// @ts-ignore
|
||||
import { createClient } from "@/lib/supabase/client"
|
||||
import { createClient } from '@/lib/supabase/client'
|
||||
|
||||
export function useCurrentUserImage() {
|
||||
const image = ref<string | null>(null)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
// @ts-ignore
|
||||
import { createClient } from "@/lib/supabase/client"
|
||||
import { createClient } from '@/lib/supabase/client'
|
||||
|
||||
export function useCurrentUserName() {
|
||||
const name = ref<string | null>(null)
|
||||
|
||||
@@ -4,7 +4,7 @@ import { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'
|
||||
import { useCurrentUserImage } from './useCurrentUserImage'
|
||||
import { useCurrentUserName } from './useCurrentUserName'
|
||||
// @ts-ignore
|
||||
import { createClient } from "@/lib/supabase/client"
|
||||
import { createClient } from '@/lib/supabase/client'
|
||||
|
||||
const supabase = createClient()
|
||||
|
||||
@@ -29,8 +29,7 @@ export function useRealtimePresenceRoom(roomName: string) {
|
||||
|
||||
room
|
||||
.on('presence', { event: 'sync' }, () => {
|
||||
const newState =
|
||||
room?.presenceState<{ image: string; name: string }>() ?? {}
|
||||
const newState = room?.presenceState<{ image: string; name: string }>() ?? {}
|
||||
|
||||
const newUsers = Object.fromEntries(
|
||||
Object.entries(newState).map(([key, values]) => {
|
||||
|
||||
@@ -32,4 +32,4 @@
|
||||
}
|
||||
],
|
||||
"dependencies": ["@supabase/supabase-js@latest"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
// @ts-ignore
|
||||
import { createClient } from "@/lib/supabase/client"
|
||||
import { createClient } from '@/lib/supabase/client'
|
||||
|
||||
export function useCurrentUserImage() {
|
||||
const image = ref<string | null>(null)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
// @ts-ignore
|
||||
import { createClient } from "@/lib/supabase/client"
|
||||
import { createClient } from '@/lib/supabase/client'
|
||||
|
||||
export function useCurrentUserName() {
|
||||
const name = ref<string | null>(null)
|
||||
|
||||
@@ -4,7 +4,7 @@ import { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'
|
||||
import { useCurrentUserImage } from './useCurrentUserImage'
|
||||
import { useCurrentUserName } from './useCurrentUserName'
|
||||
// @ts-ignore
|
||||
import { createClient } from "@/lib/supabase/client"
|
||||
import { createClient } from '@/lib/supabase/client'
|
||||
|
||||
const supabase = createClient()
|
||||
|
||||
@@ -29,8 +29,7 @@ export function useRealtimePresenceRoom(roomName: string) {
|
||||
|
||||
room
|
||||
.on('presence', { event: 'sync' }, () => {
|
||||
const newState =
|
||||
room?.presenceState<{ image: string; name: string }>() ?? {}
|
||||
const newState = room?.presenceState<{ image: string; name: string }>() ?? {}
|
||||
|
||||
const newUsers = Object.fromEntries(
|
||||
Object.entries(newState).map(([key, values]) => {
|
||||
|
||||
@@ -32,4 +32,4 @@
|
||||
}
|
||||
],
|
||||
"dependencies": ["@supabase/supabase-js@latest"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,14 @@ import { socialAuth } from './social-auth'
|
||||
import { currentUserAvatar } from './current-user-avatar'
|
||||
import { realtimeAvatarStack } from './realtime-avatar-stack'
|
||||
|
||||
const blocks = [...clients, ...passwordBasedAuth, ...socialAuth, ...dropzone, ...realtimeCursor, ...currentUserAvatar, ...realtimeAvatarStack]
|
||||
const blocks = [
|
||||
...clients,
|
||||
...passwordBasedAuth,
|
||||
...socialAuth,
|
||||
...dropzone,
|
||||
...realtimeCursor,
|
||||
...currentUserAvatar,
|
||||
...realtimeAvatarStack,
|
||||
]
|
||||
|
||||
export { blocks }
|
||||
|
||||
@@ -3,4 +3,4 @@ import { type RegistryItem } from 'shadcn/schema'
|
||||
import nuxtjs from './default/realtime-avatar-stack/nuxtjs/registry-item.json' with { type: 'json' }
|
||||
import vue from './default/realtime-avatar-stack/vue/registry-item.json' with { type: 'json' }
|
||||
|
||||
export const realtimeAvatarStack = [nuxtjs, vue] as RegistryItem[]
|
||||
export const realtimeAvatarStack = [nuxtjs, vue] as RegistryItem[]
|
||||
|
||||
Reference in New Issue
Block a user