Docs/UI library vue nuxt clients (#38279)
* docs: add vue client to ui-library * docs: add missing vue client to llms.txt * docs: add nuxt client to ui-library * docs: wrong env variable names * docs: fix dependencies * docs: update client-nuxtjs.json * Reinstall the deps so that the pnpm-lock.yaml has less changes. * Add blocks/vue package. * Remove the vue blocks from ui-library. * Copy the vue blocks into ui-library. * Clean up unneeded files. * Regenerate the pnpm-lock file from master. * Fix prettier errors. * docs: update shadcn-vue cli * docs: reusable server client * Small things * docs: improvments after CR --------- Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> Co-authored-by: Terry Sutton <saltcod@gmail.com>
This commit is contained in:
committed by
GitHub
parent
5f533247e1
commit
99499164dc
@@ -12,9 +12,11 @@ interface BlockItemProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const BlockItem = ({ name }: BlockItemProps) => {
|
export const BlockItem = ({ name }: BlockItemProps) => {
|
||||||
|
const framework = name.includes('vue') || name.includes('nuxtjs') ? 'vue' : 'react'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<Command name={name} highlight />
|
<Command name={name} highlight framework={framework} />
|
||||||
<OpenInV0Button name={name} className="w-fit shrink-0 mt-4" />
|
<OpenInV0Button name={name} className="w-fit shrink-0 mt-4" />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,13 +8,15 @@ import { useLocalStorage } from './use-local-storage'
|
|||||||
interface CommandCopyProps {
|
interface CommandCopyProps {
|
||||||
name: string
|
name: string
|
||||||
highlight?: boolean
|
highlight?: boolean
|
||||||
|
// For Vue, we need to use the `shadcn-vue` package instead of `shadcn`
|
||||||
|
framework?: 'react' | 'vue'
|
||||||
}
|
}
|
||||||
|
|
||||||
type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun'
|
type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun'
|
||||||
|
|
||||||
const LOCAL_STORAGE_KEY = 'package-manager-copy-command'
|
const LOCAL_STORAGE_KEY = 'package-manager-copy-command'
|
||||||
|
|
||||||
export function Command({ name, highlight }: CommandCopyProps) {
|
export function Command({ name, highlight, framework = 'react' }: CommandCopyProps) {
|
||||||
const [value, setValue] = useLocalStorage(LOCAL_STORAGE_KEY, 'npm')
|
const [value, setValue] = useLocalStorage(LOCAL_STORAGE_KEY, 'npm')
|
||||||
|
|
||||||
const getBaseUrl = () => {
|
const getBaseUrl = () => {
|
||||||
@@ -30,12 +32,27 @@ export function Command({ name, highlight }: CommandCopyProps) {
|
|||||||
const baseUrl = getBaseUrl()
|
const baseUrl = getBaseUrl()
|
||||||
const componentPath = `${process.env.NEXT_PUBLIC_BASE_PATH ?? ''}/r/${name}.json`
|
const componentPath = `${process.env.NEXT_PUBLIC_BASE_PATH ?? ''}/r/${name}.json`
|
||||||
|
|
||||||
const commands: Record<PackageManager, string> = {
|
const commands: Record<PackageManager, string> =
|
||||||
npm: `npx shadcn@latest add ${baseUrl}${componentPath}`,
|
framework === 'react'
|
||||||
pnpm: `pnpm dlx shadcn@latest add ${baseUrl}${componentPath}`,
|
? {
|
||||||
yarn: `yarn dlx shadcn@latest add ${baseUrl}${componentPath}`,
|
npm: `npx shadcn@latest add ${baseUrl}${componentPath}`,
|
||||||
bun: `bunx --bun shadcn@latest add ${baseUrl}${componentPath}`,
|
pnpm: `pnpm dlx shadcn@latest add ${baseUrl}${componentPath}`,
|
||||||
}
|
yarn: `yarn dlx shadcn@latest add ${baseUrl}${componentPath}`,
|
||||||
|
bun: `bunx --bun shadcn@latest add ${baseUrl}${componentPath}`,
|
||||||
|
}
|
||||||
|
: framework === 'vue'
|
||||||
|
? {
|
||||||
|
npm: `npx shadcn-vue@latest add ${baseUrl}${componentPath}`,
|
||||||
|
pnpm: `pnpm dlx shadcn-vue@latest add ${baseUrl}${componentPath}`,
|
||||||
|
yarn: `yarn dlx shadcn-vue@latest add ${baseUrl}${componentPath}`,
|
||||||
|
bun: `bunx --bun shadcn-vue@latest add ${baseUrl}${componentPath}`,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
npm: `npx shadcn@latest add ${baseUrl}${componentPath}`,
|
||||||
|
pnpm: `pnpm dlx shadcn@latest add ${baseUrl}${componentPath}`,
|
||||||
|
yarn: `yarn dlx shadcn@latest add ${baseUrl}${componentPath}`,
|
||||||
|
bun: `bunx --bun shadcn@latest add ${baseUrl}${componentPath}`,
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs_Shadcn_ value={value} onValueChange={setValue} className="w-full">
|
<Tabs_Shadcn_ value={value} onValueChange={setValue} className="w-full">
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const componentPages: SidebarNavGroup = {
|
|||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
title: 'Client',
|
title: 'Client',
|
||||||
supportedFrameworks: ['nextjs', 'react-router', 'tanstack', 'react'],
|
supportedFrameworks: ['nextjs', 'react-router', 'tanstack', 'react', 'vue', 'nuxtjs'],
|
||||||
href: '/docs/nextjs/client',
|
href: '/docs/nextjs/client',
|
||||||
items: [],
|
items: [],
|
||||||
commandItemLabel: 'Supabase Client',
|
commandItemLabel: 'Supabase Client',
|
||||||
@@ -141,4 +141,6 @@ export const frameworkTitles: Record<string, string> = {
|
|||||||
'react-router': 'React Router',
|
'react-router': 'React Router',
|
||||||
tanstack: 'TanStack Start',
|
tanstack: 'TanStack Start',
|
||||||
react: 'React SPA',
|
react: 'React SPA',
|
||||||
|
vue: 'Vue',
|
||||||
|
nuxtjs: 'Nuxt.js',
|
||||||
}
|
}
|
||||||
|
|||||||
44
apps/ui-library/content/docs/nuxtjs/client.mdx
Normal file
44
apps/ui-library/content/docs/nuxtjs/client.mdx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
title: Supabase Client Libraries
|
||||||
|
description: Supabase client for Nuxt.js
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
<BlockItem name="supabase-client-nuxtjs" description="Supabase Client for Nuxt.js" />
|
||||||
|
|
||||||
|
## Folder structure
|
||||||
|
|
||||||
|
<RegistryBlock itemName="supabase-client-nuxtjs" />
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
This block installs a Supabase client for connecting your Nuxt.js project to Supabase. It's designed to fully supports server-side rendering (SSR).
|
||||||
|
|
||||||
|
If you've already set up your Supabase client—either using the `npm create nuxt@latest` template or another method—you can continue using your existing setup.
|
||||||
|
|
||||||
|
### Getting started
|
||||||
|
|
||||||
|
After installing the block, you'll have the following environment variables in your `.env.local` file:
|
||||||
|
|
||||||
|
```env
|
||||||
|
NUXT_PUBLIC_SUPABASE_URL=
|
||||||
|
NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY=
|
||||||
|
```
|
||||||
|
|
||||||
|
- If you're using supabase.com, you can find these values in the [Connect modal](https://supabase.com/dashboard/project/_?showConnect=true&tab=frameworks&framework=vuejs&using=supabasejs) under App Frameworks or in your project's [API keys](https://supabase.com/dashboard/project/_/settings/api-keys).
|
||||||
|
|
||||||
|
- If you're using a local instance of Supabase, you can find these values by running `supabase start` or `supabase status` (if you already have it running).
|
||||||
|
|
||||||
|
- Nuxt recommends [NuxtSupabase](https://supabase.nuxtjs.org/) module to integrate Nuxt application with Supabase. It’s an alternative to this approach, but both approaches are fine.
|
||||||
|
|
||||||
|
<Callout type="warning" className="mt-4">
|
||||||
|
{' '}
|
||||||
|
This Supabase client is built for SSR with the Nuxt.js. If you're building a Vue SPA, use the [Vue
|
||||||
|
SPA client](/ui/docs/vue/client) instead.{' '}
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
## Further reading
|
||||||
|
|
||||||
|
- [Use Supabase with Nuxt](https://supabase.com/docs/guides/getting-started/quickstarts/nuxtjs)
|
||||||
|
- [Build a User Management App with Nuxt 3](https://supabase.com/docs/guides/getting-started/tutorials/with-nuxt-3)
|
||||||
59
apps/ui-library/content/docs/vue/client.mdx
Normal file
59
apps/ui-library/content/docs/vue/client.mdx
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
title: Supabase Client Libraries
|
||||||
|
description: Supabase client for Vue Single Page Applications
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
<BlockItem name="supabase-client-vue" description="Supabase Client for Vue SPA" />
|
||||||
|
|
||||||
|
## Folder structure
|
||||||
|
|
||||||
|
<RegistryBlock itemName="supabase-client-vue" />
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
This block installs a Supabase client for connecting your Vue project to Supabase. It's designed for use in client-side components.
|
||||||
|
|
||||||
|
If you've already set up a Supabase client in your project, you can just continue using that existing setup.
|
||||||
|
|
||||||
|
### Getting started
|
||||||
|
|
||||||
|
After installing the block, you'll have the following environment variables in your `.env.local` file:
|
||||||
|
|
||||||
|
```env
|
||||||
|
VITE_SUPABASE_URL=
|
||||||
|
VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY=
|
||||||
|
```
|
||||||
|
|
||||||
|
- If you're using supabase.com, you can find these values in the [Connect modal](https://supabase.com/dashboard/project/_?showConnect=true&tab=frameworks&framework=vuejs&using=supabasejs) under App Frameworks or in your project's [API keys](https://supabase.com/dashboard/project/_/settings/api-keys).
|
||||||
|
|
||||||
|
- If you're using a local instance of Supabase, you can find these values by running `supabase start` or `supabase status` (if you already have it running).
|
||||||
|
|
||||||
|
You can use the client in your Vue component like following:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
import { createClient } from './lib/supabase/client'
|
||||||
|
|
||||||
|
const profile = ref(null)
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const { data, error } = await createClient.from('profiles').select('*').single()
|
||||||
|
|
||||||
|
if (!error) profile.value = data
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
{{ profile }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Further reading
|
||||||
|
|
||||||
|
- [Generating TypeScript types for your client](https://supabase.com/docs/guides/api/rest/generating-types)
|
||||||
|
- [Use Supabase with Vue](https://supabase.com/docs/guides/getting-started/quickstarts/vue)
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
"dev": "next dev --port 3004",
|
"dev": "next dev --port 3004",
|
||||||
"build": "pnpm run content:build && pnpm run build:registry && pnpm run build:llms && next build --turbopack",
|
"build": "pnpm run content:build && pnpm run build:registry && pnpm run build:llms && next build --turbopack",
|
||||||
"build:registry": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/build-registry.mts && prettier --cache --write registry.json && rimraf -G public/r && shadcn build && tsx scripts/clean-registry.ts",
|
"build:registry": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/build-registry.mts && prettier --cache --write registry.json && rimraf -G public/r && shadcn build && cp node_modules/@supabase/vue-blocks/public/r/* public/r && tsx scripts/clean-registry.ts",
|
||||||
"build:llms": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/build-llms-txt.ts",
|
"build:llms": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/build-llms-txt.ts",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
@@ -50,6 +50,7 @@
|
|||||||
"@supabase/postgrest-js": "*",
|
"@supabase/postgrest-js": "*",
|
||||||
"@supabase/supa-mdx-lint": "0.2.6-alpha",
|
"@supabase/supa-mdx-lint": "0.2.6-alpha",
|
||||||
"@tanstack/react-query": "^5.83.0",
|
"@tanstack/react-query": "^5.83.0",
|
||||||
|
"@supabase/vue-blocks": "workspace:*",
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.11.0",
|
||||||
"class-variance-authority": "*",
|
"class-variance-authority": "*",
|
||||||
"cmdk": "^1.0.0",
|
"cmdk": "^1.0.0",
|
||||||
|
|||||||
@@ -81,3 +81,7 @@ Library of components for your project. The components integrate with Supabase a
|
|||||||
- Real-time cursor sharing for collaborative applications
|
- Real-time cursor sharing for collaborative applications
|
||||||
- [Social Authentication](https://supabase.com/ui/docs/tanstack/social-auth)
|
- [Social Authentication](https://supabase.com/ui/docs/tanstack/social-auth)
|
||||||
- Social authentication block for Tanstack Start
|
- Social authentication block for Tanstack Start
|
||||||
|
- [Supabase Client Libraries](https://supabase.com/ui/docs/vue/client)
|
||||||
|
- Supabase client for Vue Single Page Applications
|
||||||
|
- [Supabase Client Libraries](https://supabase.com/ui/docs/nuxtjs/client)
|
||||||
|
- Supabase client for Nuxt.js
|
||||||
|
|||||||
42
apps/ui-library/public/r/supabase-client-nuxtjs.json
Normal file
42
apps/ui-library/public/r/supabase-client-nuxtjs.json
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||||
|
"name": "supabase-client-nuxtjs",
|
||||||
|
"type": "registry:lib",
|
||||||
|
"title": "Supabase Client for Nuxt.js",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": [
|
||||||
|
"@supabase/ssr@latest",
|
||||||
|
"@supabase/supabase-js@latest"
|
||||||
|
],
|
||||||
|
"registryDependencies": [],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/lib/supabase/client.ts",
|
||||||
|
"content": "import { createBrowserClient } from '@supabase/ssr'\n\nexport function createClient() {\n return createBrowserClient(\n process.env.NUXT_PUBLIC_SUPABASE_URL!,\n process.env.NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY!\n )\n}\n",
|
||||||
|
"type": "registry:lib"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/middleware/is-authenticated.ts",
|
||||||
|
"content": "import { defineNuxtRouteMiddleware, navigateTo, useRequestEvent } from 'nuxt/app'\nimport { createSupabaseServerClient } from '../supabase/client'\n\nexport default defineNuxtRouteMiddleware(async (to) => {\n const event = useRequestEvent()\n\n // create Supabase SSR client directly here\n const supabase = createSupabaseServerClient(event);\n\n // check current user\n const { data: { user } } = await supabase.auth.getUser()\n\n if (!user && to.path !== '/login') {\n return navigateTo('/login')\n }\n})\n",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/middleware/is-authenticated.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/api/profile.get.ts",
|
||||||
|
"content": "import { createError, defineEventHandler } from 'h3';\nimport { createSupabaseServerClient } from '../supabase/client';\n\nexport default defineEventHandler(async (event) => {\n // Create Supabase SSR client\n const supabase = createSupabaseServerClient(event)\n\n // Example: get user session\n const {\n data: { user },\n } = await supabase.auth.getUser();\n\n if (!user) {\n return { error: 'Not authenticated' };\n }\n\n // Fetch profile row\n const { data, error } = await supabase\n .from('profiles')\n .select('*')\n .eq('id', user.id)\n .single();\n\n if (error) {\n throw createError({ statusCode: 500, statusMessage: error.message });\n }\n\n return { profile: data };\n});\n",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/api/profile.get.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/supabase/client.ts",
|
||||||
|
"content": "import { createServerClient } from '@supabase/ssr'\nimport { getCookie, setCookie, deleteCookie, H3Event, EventHandlerRequest } from 'h3'\n\nexport const createSupabaseServerClient = (event: H3Event<EventHandlerRequest> | undefined) => {\n return createServerClient(\n process.env.NUXT_PUBLIC_SUPABASE_URL!,\n process.env.NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY!,\n {\n cookies: {\n get: (key) => getCookie(event!, key),\n set: (key, value, options) => setCookie(event!, key, value, options),\n remove: (key, options) => deleteCookie(event!, key, options),\n },\n }\n )\n}",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/supabase/client.ts"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"envVars": {
|
||||||
|
"NUXT_PUBLIC_SUPABASE_URL": "",
|
||||||
|
"NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY": ""
|
||||||
|
},
|
||||||
|
"docs": "You'll need to set the following environment variables in your project: `NUXT_PUBLIC_SUPABASE_URL` and `NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY`."
|
||||||
|
}
|
||||||
23
apps/ui-library/public/r/supabase-client-vue.json
Normal file
23
apps/ui-library/public/r/supabase-client-vue.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||||
|
"name": "supabase-client-vue",
|
||||||
|
"type": "registry:lib",
|
||||||
|
"title": "Supabase Client for Vue",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": [
|
||||||
|
"@supabase/supabase-js@latest"
|
||||||
|
],
|
||||||
|
"registryDependencies": [],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/vue/lib/supabase/client.ts",
|
||||||
|
"content": "/// <reference types=\"vite/types/importMeta.d.ts\" />\nimport { createClient as createSupabaseClient } from '@supabase/supabase-js'\n\nexport function createClient() {\n return createSupabaseClient(\n import.meta.env.VITE_SUPABASE_URL!,\n import.meta.env.VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY!\n )\n}\n",
|
||||||
|
"type": "registry:lib"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"envVars": {
|
||||||
|
"VITE_SUPABASE_URL": "",
|
||||||
|
"VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY": ""
|
||||||
|
},
|
||||||
|
"docs": "You'll need to set the following environment variables in your project: `VITE_SUPABASE_URL` and `VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY`."
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
type supportedFrameworks = 'nextjs' | 'react-router' | 'tanstack' | 'react'
|
type supportedFrameworks = 'nextjs' | 'react-router' | 'tanstack' | 'react' | 'vue' | 'nuxtjs'
|
||||||
export interface NavItem {
|
export interface NavItem {
|
||||||
title: string
|
title: string
|
||||||
href?: string
|
href?: string
|
||||||
|
|||||||
38
blocks/vue/.gitignore
vendored
Normal file
38
blocks/vue/.gitignore
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
.yarn/install-state.gz
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
.contentlayer
|
||||||
33
blocks/vue/__registry__/index.tsx
Normal file
33
blocks/vue/__registry__/index.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
// @ts-nocheck
|
||||||
|
// This file is autogenerated by scripts/build-registry.ts
|
||||||
|
// Do not edit this file directly.
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
export const Index: Record<string, any> = {
|
||||||
|
"default": {
|
||||||
|
|
||||||
|
"supabase-client-nuxtjs": {
|
||||||
|
name: "supabase-client-nuxtjs",
|
||||||
|
type: "registry:lib",
|
||||||
|
registryDependencies: [],
|
||||||
|
source: "",
|
||||||
|
files: ["registry/default/clients/nuxtjs/lib/supabase/client.ts","registry/default/clients/nuxtjs/lib/supabase/middleware.ts","registry/default/clients/nuxtjs/lib/supabase/server.ts"],
|
||||||
|
category: "undefined",
|
||||||
|
subcategory: "undefined",
|
||||||
|
chunks: []
|
||||||
|
}
|
||||||
|
,
|
||||||
|
"supabase-client-vue": {
|
||||||
|
name: "supabase-client-vue",
|
||||||
|
type: "registry:lib",
|
||||||
|
registryDependencies: [],
|
||||||
|
source: "",
|
||||||
|
files: ["registry/default/clients/vue/lib/supabase/client.ts"],
|
||||||
|
category: "undefined",
|
||||||
|
subcategory: "undefined",
|
||||||
|
chunks: []
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
21
blocks/vue/components.json
Normal file
21
blocks/vue/components.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "new-york",
|
||||||
|
"rsc": true,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "tailwind.config.js",
|
||||||
|
"css": "app/globals.css",
|
||||||
|
"baseColor": "gray",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/registry/default/components",
|
||||||
|
"utils": "@/lib/utils",
|
||||||
|
"ui": "@/registry/default/components/ui",
|
||||||
|
"lib": "@/lib",
|
||||||
|
"hooks": "@/hooks"
|
||||||
|
},
|
||||||
|
"iconLibrary": "lucide"
|
||||||
|
}
|
||||||
86
blocks/vue/lib/process-registry.ts
Normal file
86
blocks/vue/lib/process-registry.ts
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import * as fs from 'fs'
|
||||||
|
|
||||||
|
export interface RegistryNode {
|
||||||
|
name: string
|
||||||
|
path: string
|
||||||
|
originalPath: string
|
||||||
|
type: 'directory' | 'file'
|
||||||
|
children?: RegistryNode[]
|
||||||
|
content?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RegistryFile {
|
||||||
|
path: string
|
||||||
|
target?: string
|
||||||
|
type: string
|
||||||
|
content: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_PATHS = {
|
||||||
|
component: '/components',
|
||||||
|
hook: '/hooks',
|
||||||
|
util: '/lib',
|
||||||
|
} as const
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a flat registry array into a hierarchical file tree structure
|
||||||
|
*/
|
||||||
|
export function generateRegistryTree(registryPath: string): RegistryNode[] {
|
||||||
|
const registry = JSON.parse(fs.readFileSync(registryPath, 'utf-8')) as { files: RegistryFile[] }
|
||||||
|
const tree: RegistryNode[] = []
|
||||||
|
|
||||||
|
const sortedRegistry = [...registry.files].sort((a, b) => a.path.localeCompare(b.path))
|
||||||
|
|
||||||
|
for (const file of sortedRegistry) {
|
||||||
|
const itemPath = file.target || getDefaultPath(file)
|
||||||
|
const pathParts = itemPath.split('/').filter(Boolean)
|
||||||
|
let currentLevel = tree
|
||||||
|
|
||||||
|
for (let i = 0; i < pathParts.length; i++) {
|
||||||
|
const part = pathParts[i]
|
||||||
|
const isLast = i === pathParts.length - 1
|
||||||
|
const path = '/' + pathParts.slice(0, i + 1).join('/')
|
||||||
|
|
||||||
|
let node = currentLevel.find((n) => n.name === part)
|
||||||
|
|
||||||
|
// Remove any paths in the file content that point to the block directory.
|
||||||
|
const content = file.content
|
||||||
|
.replaceAll(/@\/registry\/default\/blocks\/.+?\//gi, '@/')
|
||||||
|
.replaceAll(/@\/registry\/default\/fixtures\//gi, '@/')
|
||||||
|
.replaceAll(/@\/registry\/default\//gi, '@/')
|
||||||
|
.replaceAll(/@\/clients\/.+?\//gi, '@/')
|
||||||
|
|
||||||
|
if (!node) {
|
||||||
|
node = {
|
||||||
|
name: part,
|
||||||
|
path,
|
||||||
|
originalPath: file.path,
|
||||||
|
type: isLast ? 'file' : 'directory',
|
||||||
|
...(isLast ? { content } : { children: [] }),
|
||||||
|
}
|
||||||
|
currentLevel.push(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLast) {
|
||||||
|
node.children = node.children || []
|
||||||
|
currentLevel = node.children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the default path for an item based on its type
|
||||||
|
*/
|
||||||
|
function getDefaultPath(item: RegistryFile): string {
|
||||||
|
const type = item.type.toLowerCase() || ''
|
||||||
|
const basePath = DEFAULT_PATHS[type as keyof typeof DEFAULT_PATHS] || ''
|
||||||
|
// clean all paths that start with paths specific to this repo organization
|
||||||
|
const filePath = item.path
|
||||||
|
.replace(/registry\/default\/blocks\/.+?\//, '')
|
||||||
|
.replace(/registry\/default\/clients\/.+?\//, '')
|
||||||
|
|
||||||
|
return `${basePath}/${filePath}`
|
||||||
|
}
|
||||||
23
blocks/vue/package.json
Normal file
23
blocks/vue/package.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "@supabase/vue-blocks",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"preinstall": "npx only-allow pnpm",
|
||||||
|
"build": "prettier --cache --write registry.json && rimraf -G public/r && shadcn build && tsx scripts/clean-registry.ts",
|
||||||
|
"clean": "rimraf node_modules .next .turbo",
|
||||||
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"h3": "^1.15.4",
|
||||||
|
"nuxt": "^4.0.3",
|
||||||
|
"@supabase/ssr": "^0.6.1",
|
||||||
|
"@supabase/supabase-js": "^2.49.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"shadcn": "^2.10.0",
|
||||||
|
"tsconfig": "workspace:*",
|
||||||
|
"vite": "catalog:"
|
||||||
|
}
|
||||||
|
}
|
||||||
42
blocks/vue/public/r/supabase-client-nuxtjs.json
Normal file
42
blocks/vue/public/r/supabase-client-nuxtjs.json
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||||
|
"name": "supabase-client-nuxtjs",
|
||||||
|
"type": "registry:lib",
|
||||||
|
"title": "Supabase Client for Nuxt.js",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": [
|
||||||
|
"@supabase/ssr@latest",
|
||||||
|
"@supabase/supabase-js@latest"
|
||||||
|
],
|
||||||
|
"registryDependencies": [],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/lib/supabase/client.ts",
|
||||||
|
"content": "import { createBrowserClient } from '@supabase/ssr'\n\nexport function createClient() {\n return createBrowserClient(\n process.env.NUXT_PUBLIC_SUPABASE_URL!,\n process.env.NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY!\n )\n}\n",
|
||||||
|
"type": "registry:lib"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/middleware/is-authenticated.ts",
|
||||||
|
"content": "import { defineNuxtRouteMiddleware, navigateTo, useRequestEvent } from 'nuxt/app'\nimport { createSupabaseServerClient } from '../supabase/client'\n\nexport default defineNuxtRouteMiddleware(async (to) => {\n const event = useRequestEvent()\n\n // create Supabase SSR client directly here\n const supabase = createSupabaseServerClient(event);\n\n // check current user\n const { data: { user } } = await supabase.auth.getUser()\n\n if (!user && to.path !== '/login') {\n return navigateTo('/login')\n }\n})\n",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/middleware/is-authenticated.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/api/profile.get.ts",
|
||||||
|
"content": "import { createError, defineEventHandler } from 'h3';\nimport { createSupabaseServerClient } from '../supabase/client';\n\nexport default defineEventHandler(async (event) => {\n // Create Supabase SSR client\n const supabase = createSupabaseServerClient(event)\n\n // Example: get user session\n const {\n data: { user },\n } = await supabase.auth.getUser();\n\n if (!user) {\n return { error: 'Not authenticated' };\n }\n\n // Fetch profile row\n const { data, error } = await supabase\n .from('profiles')\n .select('*')\n .eq('id', user.id)\n .single();\n\n if (error) {\n throw createError({ statusCode: 500, statusMessage: error.message });\n }\n\n return { profile: data };\n});\n",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/api/profile.get.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/supabase/client.ts",
|
||||||
|
"content": "import { createServerClient } from '@supabase/ssr'\nimport { getCookie, setCookie, deleteCookie, H3Event, EventHandlerRequest } from 'h3'\n\nexport const createSupabaseServerClient = (event: H3Event<EventHandlerRequest> | undefined) => {\n return createServerClient(\n process.env.NUXT_PUBLIC_SUPABASE_URL!,\n process.env.NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY!,\n {\n cookies: {\n get: (key) => getCookie(event!, key),\n set: (key, value, options) => setCookie(event!, key, value, options),\n remove: (key, options) => deleteCookie(event!, key, options),\n },\n }\n )\n}",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/supabase/client.ts"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"envVars": {
|
||||||
|
"NUXT_PUBLIC_SUPABASE_URL": "",
|
||||||
|
"NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY": ""
|
||||||
|
},
|
||||||
|
"docs": "You'll need to set the following environment variables in your project: `NUXT_PUBLIC_SUPABASE_URL` and `NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY`."
|
||||||
|
}
|
||||||
23
blocks/vue/public/r/supabase-client-vue.json
Normal file
23
blocks/vue/public/r/supabase-client-vue.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||||
|
"name": "supabase-client-vue",
|
||||||
|
"type": "registry:lib",
|
||||||
|
"title": "Supabase Client for Vue",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": [
|
||||||
|
"@supabase/supabase-js@latest"
|
||||||
|
],
|
||||||
|
"registryDependencies": [],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/vue/lib/supabase/client.ts",
|
||||||
|
"content": "/// <reference types=\"vite/types/importMeta.d.ts\" />\nimport { createClient as createSupabaseClient } from '@supabase/supabase-js'\n\nexport function createClient() {\n return createSupabaseClient(\n import.meta.env.VITE_SUPABASE_URL!,\n import.meta.env.VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY!\n )\n}\n",
|
||||||
|
"type": "registry:lib"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"envVars": {
|
||||||
|
"VITE_SUPABASE_URL": "",
|
||||||
|
"VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY": ""
|
||||||
|
},
|
||||||
|
"docs": "You'll need to set the following environment variables in your project: `VITE_SUPABASE_URL` and `VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY`."
|
||||||
|
}
|
||||||
62
blocks/vue/registry.json
Normal file
62
blocks/vue/registry.json
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema/registry.json",
|
||||||
|
"name": "Supabase UI Library",
|
||||||
|
"homepage": "https://supabase.com/ui",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||||
|
"name": "supabase-client-nuxtjs",
|
||||||
|
"type": "registry:lib",
|
||||||
|
"title": "Supabase Client for Nuxt.js",
|
||||||
|
"description": "",
|
||||||
|
"registryDependencies": [],
|
||||||
|
"dependencies": ["@supabase/ssr@latest", "@supabase/supabase-js@latest"],
|
||||||
|
"docs": "You'll need to set the following environment variables in your project: `NUXT_PUBLIC_SUPABASE_URL` and `NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY`.",
|
||||||
|
"envVars": {
|
||||||
|
"NUXT_PUBLIC_SUPABASE_URL": "",
|
||||||
|
"NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY": ""
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/lib/supabase/client.ts",
|
||||||
|
"type": "registry:lib"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/middleware/is-authenticated.ts",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/middleware/is-authenticated.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/api/profile.get.ts",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/api/profile.get.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/supabase/client.ts",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/supabase/client.ts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||||
|
"name": "supabase-client-vue",
|
||||||
|
"type": "registry:lib",
|
||||||
|
"title": "Supabase Client for Vue",
|
||||||
|
"description": "",
|
||||||
|
"registryDependencies": [],
|
||||||
|
"dependencies": ["@supabase/supabase-js@latest"],
|
||||||
|
"docs": "You'll need to set the following environment variables in your project: `VITE_SUPABASE_URL` and `VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY`.",
|
||||||
|
"envVars": {
|
||||||
|
"VITE_SUPABASE_URL": "",
|
||||||
|
"VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY": ""
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/vue/lib/supabase/client.ts",
|
||||||
|
"type": "registry:lib"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
5
blocks/vue/registry/clients.ts
Normal file
5
blocks/vue/registry/clients.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { type Registry } from 'shadcn/registry'
|
||||||
|
import nuxtjs from './default/clients/nuxtjs/registry-item.json' with { type: 'json' }
|
||||||
|
import vue from './default/clients/vue/registry-item.json' with { type: 'json' }
|
||||||
|
|
||||||
|
export const clients = [nuxtjs, vue] as Registry['items']
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { createBrowserClient } from '@supabase/ssr'
|
||||||
|
|
||||||
|
export function createClient() {
|
||||||
|
return createBrowserClient(
|
||||||
|
process.env.NUXT_PUBLIC_SUPABASE_URL!,
|
||||||
|
process.env.NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY!
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||||
|
"name": "supabase-client-nuxtjs",
|
||||||
|
"type": "registry:lib",
|
||||||
|
"title": "Supabase Client for Nuxt.js",
|
||||||
|
"description": "",
|
||||||
|
"registryDependencies": [],
|
||||||
|
"dependencies": ["@supabase/ssr@latest", "@supabase/supabase-js@latest"],
|
||||||
|
"docs": "You'll need to set the following environment variables in your project: `NUXT_PUBLIC_SUPABASE_URL` and `NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY`.",
|
||||||
|
"envVars": {
|
||||||
|
"NUXT_PUBLIC_SUPABASE_URL": "",
|
||||||
|
"NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY": ""
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/lib/supabase/client.ts",
|
||||||
|
"type": "registry:lib"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/middleware/is-authenticated.ts",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/middleware/is-authenticated.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/api/profile.get.ts",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/api/profile.get.ts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/nuxtjs/server/supabase/client.ts",
|
||||||
|
"type": "registry:file",
|
||||||
|
"target": "server/supabase/client.ts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { createError, defineEventHandler } from 'h3';
|
||||||
|
import { createSupabaseServerClient } from '../supabase/client';
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
// Create Supabase SSR client
|
||||||
|
const supabase = createSupabaseServerClient(event)
|
||||||
|
|
||||||
|
// Example: get user session
|
||||||
|
const {
|
||||||
|
data: { user },
|
||||||
|
} = await supabase.auth.getUser();
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return { error: 'Not authenticated' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch profile row
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from('profiles')
|
||||||
|
.select('*')
|
||||||
|
.eq('id', user.id)
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw createError({ statusCode: 500, statusMessage: error.message });
|
||||||
|
}
|
||||||
|
|
||||||
|
return { profile: data };
|
||||||
|
});
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { defineNuxtRouteMiddleware, navigateTo, useRequestEvent } from 'nuxt/app'
|
||||||
|
import { createSupabaseServerClient } from '../supabase/client'
|
||||||
|
|
||||||
|
export default defineNuxtRouteMiddleware(async (to) => {
|
||||||
|
const event = useRequestEvent()
|
||||||
|
|
||||||
|
// create Supabase SSR client directly here
|
||||||
|
const supabase = createSupabaseServerClient(event);
|
||||||
|
|
||||||
|
// check current user
|
||||||
|
const { data: { user } } = await supabase.auth.getUser()
|
||||||
|
|
||||||
|
if (!user && to.path !== '/login') {
|
||||||
|
return navigateTo('/login')
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { createServerClient } from '@supabase/ssr'
|
||||||
|
import { getCookie, setCookie, deleteCookie, H3Event, EventHandlerRequest } from 'h3'
|
||||||
|
|
||||||
|
export const createSupabaseServerClient = (event: H3Event<EventHandlerRequest> | undefined) => {
|
||||||
|
return createServerClient(
|
||||||
|
process.env.NUXT_PUBLIC_SUPABASE_URL!,
|
||||||
|
process.env.NUXT_PUBLIC_SUPABASE_PUBLISHABLE_OR_ANON_KEY!,
|
||||||
|
{
|
||||||
|
cookies: {
|
||||||
|
get: (key) => getCookie(event!, key),
|
||||||
|
set: (key, value, options) => setCookie(event!, key, value, options),
|
||||||
|
remove: (key, options) => deleteCookie(event!, key, options),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/// <reference types="vite/types/importMeta.d.ts" />
|
||||||
|
import { createClient as createSupabaseClient } from '@supabase/supabase-js'
|
||||||
|
|
||||||
|
export function createClient() {
|
||||||
|
return createSupabaseClient(
|
||||||
|
import.meta.env.VITE_SUPABASE_URL!,
|
||||||
|
import.meta.env.VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY!
|
||||||
|
)
|
||||||
|
}
|
||||||
20
blocks/vue/registry/default/clients/vue/registry-item.json
Normal file
20
blocks/vue/registry/default/clients/vue/registry-item.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||||
|
"name": "supabase-client-vue",
|
||||||
|
"type": "registry:lib",
|
||||||
|
"title": "Supabase Client for Vue",
|
||||||
|
"description": "",
|
||||||
|
"registryDependencies": [],
|
||||||
|
"dependencies": ["@supabase/supabase-js@latest"],
|
||||||
|
"docs": "You'll need to set the following environment variables in your project: `VITE_SUPABASE_URL` and `VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY`.",
|
||||||
|
"envVars": {
|
||||||
|
"VITE_SUPABASE_URL": "",
|
||||||
|
"VITE_SUPABASE_PUBLISHABLE_OR_ANON_KEY": ""
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "registry/default/clients/vue/lib/supabase/client.ts",
|
||||||
|
"type": "registry:lib"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
9
blocks/vue/registry/index.ts
Normal file
9
blocks/vue/registry/index.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { type Registry } from 'shadcn/registry'
|
||||||
|
|
||||||
|
import { clients } from './clients'
|
||||||
|
|
||||||
|
export const registry = {
|
||||||
|
name: 'Supabase UI Library',
|
||||||
|
homepage: 'https://supabase.com/ui',
|
||||||
|
items: [...clients],
|
||||||
|
} satisfies Registry
|
||||||
55
blocks/vue/scripts/clean-registry.ts
Normal file
55
blocks/vue/scripts/clean-registry.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import * as fs from 'fs'
|
||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
|
function processJsonFile(filePath: string) {
|
||||||
|
try {
|
||||||
|
// Read the file
|
||||||
|
const content = fs.readFileSync(filePath, 'utf8')
|
||||||
|
const json = JSON.parse(content)
|
||||||
|
|
||||||
|
// Convert to string to do replacement
|
||||||
|
let stringified = JSON.stringify(json, null, 2)
|
||||||
|
|
||||||
|
// Perform the replacement
|
||||||
|
stringified = stringified
|
||||||
|
.replace(/\/ui\/example\/password-based-auth/g, '')
|
||||||
|
.replace(/\/example\/password-based-auth/g, '')
|
||||||
|
.replaceAll(
|
||||||
|
"import { Link } from '@/registry/default/components/ui/link'",
|
||||||
|
"import Link from 'next/link'"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Write back to file
|
||||||
|
fs.writeFileSync(filePath, stringified)
|
||||||
|
console.log(`✓ Updated ${filePath}`)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error processing ${filePath}:`, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function processDirectory(directoryPath: string) {
|
||||||
|
const files = fs.readdirSync(directoryPath)
|
||||||
|
|
||||||
|
files.forEach((file) => {
|
||||||
|
const fullPath = path.join(directoryPath, file)
|
||||||
|
const stat = fs.statSync(fullPath)
|
||||||
|
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
processDirectory(fullPath)
|
||||||
|
} else if (path.extname(file) === '.json') {
|
||||||
|
processJsonFile(fullPath)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start processing from the specified directory
|
||||||
|
const targetDir = path.join(process.cwd(), 'public/r')
|
||||||
|
|
||||||
|
if (!fs.existsSync(targetDir)) {
|
||||||
|
console.error('Target directory does not exist:', targetDir)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Starting JSON file processing...')
|
||||||
|
processDirectory(targetDir)
|
||||||
|
console.log('Processing complete!')
|
||||||
20
blocks/vue/tsconfig.base.json
Normal file
20
blocks/vue/tsconfig.base.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"display": "Default",
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": false,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"inlineSources": false,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"preserveWatchOutput": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
31
blocks/vue/tsconfig.json
Normal file
31
blocks/vue/tsconfig.json
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"extends": "tsconfig/base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"incremental": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./*"]
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules", "./scripts/build-registry.mts"]
|
||||||
|
}
|
||||||
13
blocks/vue/tsconfig.scripts.json
Normal file
13
blocks/vue/tsconfig.scripts.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es6",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"isolatedModules": false
|
||||||
|
},
|
||||||
|
"include": [".contentlayer/generated", "scripts/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
4248
pnpm-lock.yaml
generated
4248
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
|||||||
packages:
|
packages:
|
||||||
- 'apps/*'
|
- 'apps/*'
|
||||||
- 'packages/*'
|
- 'packages/*'
|
||||||
|
- 'blocks/*'
|
||||||
- 'e2e/*'
|
- 'e2e/*'
|
||||||
|
|
||||||
catalog:
|
catalog:
|
||||||
|
|||||||
Reference in New Issue
Block a user