├── README.md ├── CHANGELOG.md ├── vercel.json ├── apps ├── playground │ ├── .npmrc │ ├── server │ │ ├── tsconfig.json │ │ ├── middleware │ │ │ └── clerk.ts │ │ └── api │ │ │ └── protected.ts │ ├── .env.example │ ├── public │ │ └── favicon.ico │ ├── tsconfig.json │ ├── pages │ │ ├── clerk-loaded.vue │ │ ├── controls.vue │ │ ├── guest.vue │ │ ├── signed-in.vue │ │ ├── custom-pages.vue │ │ ├── options.client.vue │ │ ├── index.vue │ │ └── user-button.vue │ ├── app.vue │ ├── nuxt.config.ts │ ├── .gitignore │ ├── components │ │ ├── Version.vue │ │ └── CustomUserButton.vue │ ├── package.json │ └── README.md └── docs │ ├── .vitepress │ ├── theme │ │ ├── index.js │ │ └── MyLayout.vue │ ├── components │ │ └── Banner.vue │ └── config.mts │ ├── package.json │ ├── components │ ├── control │ │ ├── clerk-loading.md │ │ ├── redirect-to-userprofile.md │ │ ├── signed-out.md │ │ ├── redirect-to-createorganization.md │ │ ├── signed-in.md │ │ ├── redirect-to-organizationprofile.md │ │ ├── clerk-loaded.md │ │ ├── redirect-to-signup.md │ │ ├── redirect-to-signin.md │ │ └── protect.md │ ├── organization │ │ ├── create-organization.md │ │ ├── organization-switcher.md │ │ ├── organization-list.md │ │ └── organization-profile.md │ ├── user │ │ ├── user-profile.md │ │ └── user-button.md │ ├── unstyled │ │ ├── sign-in-button.md │ │ ├── sign-up-button.md │ │ └── sign-out-button.md │ └── authentication │ │ ├── google-one-tap.md │ │ ├── sign-up.md │ │ └── sign-in.md │ ├── index.md │ ├── composables │ ├── use-clerk.md │ ├── use-session-list.md │ ├── use-session.md │ ├── use-auth.md │ ├── use-sign-up.md │ ├── use-sign-in.md │ ├── use-organization.md │ └── use-user.md │ ├── what-is-vue-clerk.md │ ├── guides │ ├── nuxt.md │ ├── custom-pages │ │ ├── organization-profile.md │ │ └── user-profile.md │ └── custom-menu-items │ │ └── user-button.md │ ├── getting-started.md │ └── plugin.md ├── pnpm-workspace.yaml ├── packages ├── vue-clerk │ ├── vitest.setup.ts │ ├── global.d.ts │ ├── src │ │ ├── utils │ │ │ ├── index.ts │ │ │ ├── deprecate.ts │ │ │ ├── isConstructor.ts │ │ │ ├── toComputedRefs.ts │ │ │ └── useClerkLoaded.ts │ │ ├── internal.ts │ │ ├── env.d.ts │ │ ├── composables │ │ │ ├── useClerk.ts │ │ │ ├── usePolymorphicRef.ts │ │ │ ├── useClerkProvider.ts │ │ │ ├── useSessionList.ts │ │ │ ├── useUser.ts │ │ │ ├── useSession.ts │ │ │ ├── useSignIn.ts │ │ │ ├── useSignUp.ts │ │ │ ├── useOrganization.ts │ │ │ └── useAuth.ts │ │ ├── polyfills.ts │ │ ├── plugin.ts │ │ ├── errors │ │ │ ├── messages.ts │ │ │ └── errorThrower.ts │ │ ├── components │ │ │ ├── WithClerk.vue │ │ │ ├── WithUser.vue │ │ │ ├── WithSession.vue │ │ │ ├── SignInWithMetamaskButton.vue │ │ │ ├── __tests__ │ │ │ │ ├── SignOutButton.test.ts │ │ │ │ ├── SignIn.test.ts │ │ │ │ ├── SignUp.test.ts │ │ │ │ ├── UserProfile.test.ts │ │ │ │ ├── OrganizationProfile.test.ts │ │ │ │ ├── SignInWithMetamaskButton.test.ts │ │ │ │ ├── OrganizationSwitcher.test.ts │ │ │ │ ├── UserButton.test.ts │ │ │ │ ├── SignInButton.test.ts │ │ │ │ └── SignUpButton.test.ts │ │ │ ├── SignInButton.vue │ │ │ ├── SignOutButton.vue │ │ │ ├── SignUpButton.vue │ │ │ ├── uiComponents.ts │ │ │ ├── UserProfile.ts │ │ │ ├── OrganizationProfile.ts │ │ │ ├── controlComponents.ts │ │ │ └── UserButton.ts │ │ ├── keys.ts │ │ ├── types.ts │ │ ├── index.ts │ │ └── provideClerkToVueApp.ts │ ├── vitest.config.mts │ ├── tsconfig.json │ ├── tsup.config.ts │ ├── LICENSE │ ├── README.md │ └── package.json └── nuxt │ ├── tsconfig.json │ ├── src │ ├── runtime │ │ ├── server │ │ │ ├── middleware.ts │ │ │ ├── index.ts │ │ │ ├── api │ │ │ │ └── current-user.get.ts │ │ │ ├── clerkClient.ts │ │ │ ├── utils.ts │ │ │ └── clerkMiddleware.ts │ │ ├── composables │ │ │ └── useCurrentUser.ts │ │ ├── middleware │ │ │ ├── guest.ts │ │ │ └── auth.ts │ │ └── plugins │ │ │ └── clerk.ts │ ├── nuxt-types.d.ts │ └── module.ts │ ├── README.md │ ├── scripts │ └── watch.mjs │ └── package.json ├── eslint.config.mjs ├── .gitignore ├── .changeset ├── config.json └── README.md ├── scripts └── nuke.sh ├── turbo.json ├── package.json ├── .github └── workflows │ ├── dependabot.yml │ ├── preview.yml │ ├── ci.yml │ └── release.yml └── LICENSE /README.md: -------------------------------------------------------------------------------- 1 | packages/vue-clerk/README.md -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | packages/vue-clerk/CHANGELOG.md -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "cleanUrls": true 3 | } 4 | -------------------------------------------------------------------------------- /apps/playground/.npmrc: -------------------------------------------------------------------------------- 1 | strict-peer-dependencies=false 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - apps/* 3 | - packages/* 4 | -------------------------------------------------------------------------------- /packages/vue-clerk/vitest.setup.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom' 2 | -------------------------------------------------------------------------------- /packages/nuxt/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.nuxt/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /apps/playground/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.nuxt/tsconfig.server.json" 3 | } 4 | -------------------------------------------------------------------------------- /apps/playground/.env.example: -------------------------------------------------------------------------------- 1 | CLERK_PUBLISHABLE_KEY=your_publishable_key 2 | CLERK_SECRET_KEY=your_secret_key 3 | -------------------------------------------------------------------------------- /packages/vue-clerk/global.d.ts: -------------------------------------------------------------------------------- 1 | declare const PACKAGE_NAME: string 2 | declare const PACKAGE_VERSION: string 3 | -------------------------------------------------------------------------------- /apps/playground/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wobsoriano/vue-clerk/HEAD/apps/playground/public/favicon.ico -------------------------------------------------------------------------------- /apps/playground/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://nuxt.com/docs/guide/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /packages/nuxt/src/runtime/server/middleware.ts: -------------------------------------------------------------------------------- 1 | import { clerkMiddleware } from './clerkMiddleware' 2 | 3 | export default clerkMiddleware() 4 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './isConstructor' 2 | export * from './toComputedRefs' 3 | export * from './useClerkLoaded' 4 | -------------------------------------------------------------------------------- /packages/nuxt/README.md: -------------------------------------------------------------------------------- 1 | # vue-clerk-nuxt 2 | 3 | Nuxt module for `vue-clerk`. See [this guide](https://www.vue-clerk.com/guides/nuxt) for more info. 4 | -------------------------------------------------------------------------------- /apps/playground/pages/clerk-loaded.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/internal.ts: -------------------------------------------------------------------------------- 1 | export { setErrorThrowerOptions } from './errors/errorThrower' 2 | 3 | export { setClerkJsLoadingErrorPackageName } from '@clerk/shared/loadClerkJsScript' 4 | -------------------------------------------------------------------------------- /packages/nuxt/src/runtime/server/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@clerk/backend' 2 | export { clerkClient } from './clerkClient' 3 | export { getAuth } from './clerkClient' 4 | export { clerkMiddleware } from './clerkMiddleware' 5 | -------------------------------------------------------------------------------- /apps/playground/pages/controls.vue: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /apps/playground/pages/guest.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/env.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import type { DefineComponent } from 'vue' 3 | 4 | const component: DefineComponent, Record, any> 5 | export default component 6 | } 7 | -------------------------------------------------------------------------------- /apps/playground/server/middleware/clerk.ts: -------------------------------------------------------------------------------- 1 | // import { clerkMiddleware } from 'vue-clerk/server' 2 | 3 | // export default clerkMiddleware((event) => { 4 | // console.log(event.context.auth) 5 | // }) 6 | export default eventHandler(() => {}) 7 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/composables/useClerk.ts: -------------------------------------------------------------------------------- 1 | import { useClerkProvider } from './useClerkProvider' 2 | 3 | export function useClerk() { 4 | const { clerk } = useClerkProvider() 5 | 6 | return clerk 7 | } 8 | 9 | export { 10 | useClerkProvider, 11 | } 12 | -------------------------------------------------------------------------------- /apps/docs/.vitepress/theme/index.js: -------------------------------------------------------------------------------- 1 | import DefaultTheme from 'vitepress/theme' 2 | import MyLayout from './MyLayout.vue' 3 | 4 | export default { 5 | extends: DefaultTheme, 6 | // override the Layout with a wrapper component that 7 | // injects the slots 8 | Layout: MyLayout, 9 | } 10 | -------------------------------------------------------------------------------- /packages/nuxt/src/runtime/composables/useCurrentUser.ts: -------------------------------------------------------------------------------- 1 | import type { User } from '@clerk/backend' 2 | import type { AsyncData } from 'nuxt/app' 3 | import { useFetch } from '#imports' 4 | 5 | export function useCurrentUser(): AsyncData { 6 | return useFetch('/api/_clerk/current-user') 7 | } 8 | -------------------------------------------------------------------------------- /packages/vue-clerk/vitest.config.mts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | export default defineConfig({ 5 | test: { 6 | globals: true, 7 | environment: 'jsdom', 8 | setupFiles: ['./vitest.setup.ts'], 9 | }, 10 | plugins: [vue()], 11 | }) 12 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/composables/usePolymorphicRef.ts: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export function usePolymorphicRef() { 4 | const node = ref(null) 5 | const setRef = (value: HTMLElement | null) => (node.value = value) 6 | 7 | return { 8 | node, 9 | setRef, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /apps/playground/app.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /apps/playground/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://nuxt.com/docs/api/configuration/nuxt-config 2 | export default defineNuxtConfig({ 3 | devtools: { enabled: false }, 4 | 5 | modules: ['vue-clerk/nuxt'], 6 | 7 | clerk: { 8 | // skipServerMiddleware: true 9 | }, 10 | 11 | compatibilityDate: '2024-07-26', 12 | }) 13 | -------------------------------------------------------------------------------- /apps/playground/.gitignore: -------------------------------------------------------------------------------- 1 | # Nuxt dev/build outputs 2 | .output 3 | .data 4 | .nuxt 5 | .nitro 6 | .cache 7 | dist 8 | 9 | # Node dependencies 10 | node_modules 11 | 12 | # Logs 13 | logs 14 | *.log 15 | 16 | # Misc 17 | .DS_Store 18 | .fleet 19 | .idea 20 | 21 | # Local env files 22 | .env 23 | .env.* 24 | !.env.example 25 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import antfu from '@antfu/eslint-config' 2 | 3 | export default antfu( 4 | { 5 | vue: true, 6 | typescript: true, 7 | }, 8 | { 9 | ignores: ['*.js'], 10 | }, 11 | { 12 | rules: { 13 | 'no-console': 'warn', 14 | 'node/prefer-global/process': 'warn', 15 | }, 16 | }, 17 | ) 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | .DS_Store 3 | .idea 4 | .env 5 | *.log 6 | *.tgz 7 | coverage 8 | dist 9 | lib-cov 10 | logs 11 | node_modules 12 | temp 13 | .vscode 14 | 15 | apps/docs/.vitepress/dist 16 | apps/docs/.vitepress/cache 17 | 18 | # turbo 19 | .turbo 20 | 21 | # Nuxt dev/build outputs 22 | .output 23 | .data 24 | .nuxt 25 | .nitro 26 | -------------------------------------------------------------------------------- /apps/playground/server/api/protected.ts: -------------------------------------------------------------------------------- 1 | import { clerkClient, getAuth } from 'vue-clerk/server' 2 | 3 | export default eventHandler((event) => { 4 | const auth = getAuth(event) 5 | 6 | if (!auth.userId) { 7 | setResponseStatus(event, 403) 8 | return 9 | } 10 | 11 | return clerkClient(event).users.getUser(auth.userId) 12 | }) 13 | -------------------------------------------------------------------------------- /apps/docs/.vitepress/theme/MyLayout.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | -------------------------------------------------------------------------------- /apps/docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "type": "module", 4 | "version": "1.9.5", 5 | "private": true, 6 | "scripts": { 7 | "dev": "vitepress dev", 8 | "build": "vitepress build", 9 | "preview": "vitepress serve" 10 | }, 11 | "dependencies": { 12 | "@vueuse/core": "12.2.0", 13 | "vitepress": "1.3.4" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apps/playground/components/Version.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 15 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.1/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": ["playground", "docs", "vue-clerk-nuxt"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/nuxt/src/runtime/server/api/current-user.get.ts: -------------------------------------------------------------------------------- 1 | import { eventHandler } from 'h3' 2 | import { clerkClient, getAuth } from '../clerkClient' 3 | 4 | export default eventHandler(async (event) => { 5 | const { userId } = getAuth(event) 6 | 7 | if (!userId) { 8 | return null 9 | } 10 | 11 | return await clerkClient(event).users.getUser(userId) 12 | }) 13 | -------------------------------------------------------------------------------- /apps/playground/pages/signed-in.vue: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Vite does not define `global` by default 3 | * One workaround is to use the `define` config prop 4 | * https://vitejs.dev/config/#define 5 | * We are solving this in the SDK level to reduce setup steps. 6 | */ 7 | if (typeof window !== 'undefined' && !window.global) 8 | window.global = typeof globalThis === 'undefined' ? window : globalThis 9 | 10 | export {} 11 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/plugin.ts: -------------------------------------------------------------------------------- 1 | import type { Plugin } from 'vue' 2 | import type { InitialState } from '@clerk/types' 3 | import type { IsomorphicClerkOptions } from './types' 4 | 5 | import { provideClerkToVueApp } from './provideClerkToVueApp' 6 | 7 | export const clerkPlugin: Plugin = { 8 | install(app, options: IsomorphicClerkOptions & { initialState?: InitialState }) { 9 | provideClerkToVueApp(app, options) 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/utils/deprecate.ts: -------------------------------------------------------------------------------- 1 | export function getDeprecationMessage() { 2 | return ` 3 | DEPRECATION NOTICE 4 | ================== 5 | 6 | The vue-clerk package has graduated to an official SDK! 7 | 8 | Please visit our migration guide: 9 | https://clerk.com/docs/references/vue/migrating-from-vue-community-sdk 10 | 11 | The community SDK will continue to work but will no longer 12 | receive updates or security patches. 13 | ` 14 | } 15 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/utils/isConstructor.ts: -------------------------------------------------------------------------------- 1 | /*! 2 | * Original code by Clerk, Inc. 3 | * MIT Licensed, Copyright 2022 Clerk, Inc., see https://github.com/clerk/javascript/blob/main/packages/react/LICENSE for details 4 | * 5 | * Credits to the Clerk team: 6 | * https://github.com/clerk/javascript/blob/main/packages/react/src/utils/isConstructor.ts 7 | */ 8 | 9 | export function isConstructor(f: any): f is T { 10 | return typeof f === 'function' 11 | } 12 | -------------------------------------------------------------------------------- /apps/playground/pages/custom-pages.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /packages/nuxt/scripts/watch.mjs: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import nodemon from 'nodemon' 3 | 4 | // Unbuild doesn't have a built in watcher mode, 5 | // so we can use nodemon to watch the source files and rebuild the project when they change. 6 | nodemon({ 7 | // eslint-disable-next-line node/prefer-global/process 8 | watch: [path.relative(process.cwd(), './src')], 9 | ext: '*', 10 | exec: 'pnpm run build', 11 | }).on('quit', () => { 12 | // eslint-disable-next-line node/prefer-global/process 13 | process.exit() 14 | }) 15 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/composables/useClerkProvider.ts: -------------------------------------------------------------------------------- 1 | import { inject } from 'vue' 2 | import type { VueClerkInjectionKeyType } from '../keys' 3 | import { VueClerkInjectionKey } from '../keys' 4 | 5 | export function useClerkProvider() { 6 | const ctx = inject(VueClerkInjectionKey) 7 | 8 | if (!ctx) { 9 | throw new Error( 10 | 'This composable can only be used when the Vue Clerk plugin is installed. Learn more: https://vue-clerk.com/plugin', 11 | ) 12 | } 13 | 14 | return ctx 15 | } 16 | -------------------------------------------------------------------------------- /scripts/nuke.sh: -------------------------------------------------------------------------------- 1 | rm -rf node_modules pnpm-lock.yaml .turbo 2 | 3 | safe_remove() { 4 | [ -d "$1" ] && rm -rf "$1" 5 | } 6 | 7 | dirs_to_remove=( 8 | "node_modules" 9 | "dist" 10 | ".nuxt" 11 | ".vitepress/cache" 12 | ".vitepress/dist" 13 | ".output" 14 | ".turbo" 15 | ) 16 | 17 | for base in packages apps; do 18 | for d in "$base"/*; do 19 | echo "Cleaning $d" 20 | for dir in "${dirs_to_remove[@]}"; do 21 | safe_remove "$d/$dir" 22 | done 23 | done 24 | done 25 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /apps/playground/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playground", 3 | "type": "module", 4 | "private": true, 5 | "scripts": { 6 | "build": "nuxt build", 7 | "dev": "nuxt dev", 8 | "generate": "nuxt generate", 9 | "preview": "nuxt preview" 10 | }, 11 | "dependencies": { 12 | "@clerk/backend": "^1.21.6", 13 | "@clerk/localizations": "^3.1.2", 14 | "@clerk/themes": "^2.1.35", 15 | "vue-clerk": "workspace:*" 16 | }, 17 | "devDependencies": { 18 | "@types/node": "^20.14.9", 19 | "nuxt": "^3.13.2" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "tasks": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "inputs": ["$TURBO_DEFAULT$", ".env*"], 7 | "outputs": [".nuxt/**", ".output/**", "dist/**"] 8 | }, 9 | "dev": { 10 | "cache": false, 11 | "persistent": true 12 | }, 13 | "playground#build": { 14 | "dependsOn": ["vue-clerk-nuxt#build"], 15 | "inputs": ["$TURBO_DEFAULT$", ".env*"], 16 | "outputs": [".nuxt/**", ".output/**", "dist/**"] 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /apps/docs/components/control/clerk-loading.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` renders its children while Clerk is loading, and is helpful for showing a custom loading state. 8 | 9 | ## Usage 10 | 11 | ```vue 12 | 15 | 16 | 25 | ``` 26 | -------------------------------------------------------------------------------- /packages/vue-clerk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "lib": ["esnext", "DOM"], 5 | "module": "esnext", 6 | "moduleResolution": "node", 7 | "resolveJsonModule": true, 8 | "types": ["vitest/globals"], 9 | "strict": true, 10 | "strictNullChecks": true, 11 | "declaration": true, 12 | "declarationDir": "./dist", 13 | "esModuleInterop": true, 14 | "skipDefaultLibCheck": true, 15 | "skipLibCheck": true 16 | }, 17 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "global.d.ts"] 18 | } 19 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/errors/messages.ts: -------------------------------------------------------------------------------- 1 | export const invalidStateError 2 | = 'Invalid state. Feel free to submit a bug or reach out to support here: https://clerk.com/support' 3 | 4 | export const unsupportedNonBrowserDomainOrProxyUrlFunction 5 | = 'Unsupported usage of isSatellite, domain or proxyUrl. The usage of isSatellite, domain or proxyUrl as function is not supported in non-browser environments.' 6 | 7 | export const useAuthHasRequiresRoleOrPermission 8 | = 'Missing parameters. `has` from `useAuth` requires a permission or role key to be passed. Example usage: `has({permission: "org:posts:edit"`' 9 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/utils/toComputedRefs.ts: -------------------------------------------------------------------------------- 1 | import { type ComputedRef, computed } from 'vue' 2 | 3 | export type ToComputedRefs = { 4 | [K in keyof T]: ComputedRef; 5 | } 6 | 7 | /** 8 | * Converts a computed ref to an object of computed refs. 9 | * This will allow the composables to be destructurable and still maintain reactivity. 10 | */ 11 | export function toComputedRefs( 12 | objectRef: ComputedRef, 13 | ): ToComputedRefs { 14 | const result = {} as any 15 | 16 | for (const key in objectRef.value) 17 | result[key] = computed(() => objectRef.value[key]) 18 | 19 | return result 20 | } 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-clerk-monorepo", 3 | "private": true, 4 | "packageManager": "pnpm@9.13.0", 5 | "scripts": { 6 | "build": "turbo run build", 7 | "build-packages": "turbo run build --filter=\"./packages/*\"", 8 | "dev": "turbo run dev ", 9 | "lint": "eslint .", 10 | "lint:fix": "eslint . --fix", 11 | "release": "pnpm build-packages && changeset publish", 12 | "nuke": "./scripts/nuke.sh" 13 | }, 14 | "devDependencies": { 15 | "@antfu/eslint-config": "^2.21.2", 16 | "@changesets/cli": "^2.27.7", 17 | "eslint": "^9.6.0", 18 | "turbo": "^2.2.3", 19 | "typescript": "^5.5.2" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/WithClerk.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 19 | 20 | 23 | -------------------------------------------------------------------------------- /apps/docs/components/control/redirect-to-userprofile.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` component will navigate to the user profile URL which has been configured in your application instance. The behavior will be just like a server-side (3xx) redirect, and will override the current location in the history stack. 8 | 9 | ## Usage 10 | 11 | ```vue 12 | 15 | 16 | 24 | ``` 25 | -------------------------------------------------------------------------------- /apps/docs/components/control/signed-out.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` component offers authentication checks as a cross-cutting concern. Any child nodes wrapped by a `` component will be rendered only if there's no User signed in to your application. 8 | 9 | ## Usage 10 | 11 | ```vue 12 | 15 | 16 | 28 | ``` 29 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/WithUser.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 20 | 21 | 24 | -------------------------------------------------------------------------------- /apps/docs/components/control/redirect-to-createorganization.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` component will navigate to the create organization flow which has been configured in your application instance. The behavior will be just like a server-side (3xx) redirect, and will override the current location in the history stack. 8 | 9 | ## Usage 10 | 11 | ```vue 12 | 15 | 16 | 24 | ``` 25 | -------------------------------------------------------------------------------- /apps/docs/components/control/signed-in.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` component offers authentication checks as a cross-cutting concern. Any children components wrapped by a `` component will be rendered only if there's a User with an active Session signed in your application. 8 | 9 | ## Usage 10 | 11 | ```vue 12 | 15 | 16 | 29 | ``` 30 | -------------------------------------------------------------------------------- /apps/playground/pages/options.client.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 28 | -------------------------------------------------------------------------------- /apps/docs/components/control/redirect-to-organizationprofile.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` component will navigate to the organization profile URL which has been configured in your application instance. The behavior will be just like a server-side (3xx) redirect, and will override the current location in the history stack. 8 | 9 | ## Usage 10 | 11 | ```vue 12 | 15 | 16 | 24 | ``` 25 | -------------------------------------------------------------------------------- /packages/nuxt/src/runtime/middleware/guest.ts: -------------------------------------------------------------------------------- 1 | import { useAuth } from 'vue-clerk' 2 | import { defineNuxtRouteMiddleware, navigateTo, useRuntimeConfig } from '#imports' 3 | 4 | export default defineNuxtRouteMiddleware((to) => { 5 | const { userId } = useAuth() 6 | 7 | // If user is not authenticated, no need to redirect 8 | if (!userId.value) { 9 | return 10 | } 11 | 12 | // Get config values 13 | const config = useRuntimeConfig().public.clerk 14 | 15 | // Chain of fallbacks for redirect URL 16 | const redirectUrl = to.meta.auth?.navigateAuthenticatedTo 17 | || to.meta.auth?.authenticatedRedirectUrl 18 | || config.signInForceRedirectUrl 19 | || config.signInFallbackRedirectUrl 20 | 21 | return navigateTo(redirectUrl) 22 | }) 23 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/WithSession.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 20 | 21 | 24 | -------------------------------------------------------------------------------- /apps/docs/components/organization/create-organization.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 |
8 | 9 | 10 | The `` component is used to render an organization creation UI that allows users to create brand new organizations within your application. 11 | 12 | ## Props 13 | 14 | Click [here](https://clerk.com/docs/components/organization/create-organization#properties) to see the full list of props available. 15 | 16 | ## Usage 17 | 18 | ```vue 19 | 22 | 23 | 26 | ``` 27 | -------------------------------------------------------------------------------- /apps/docs/components/user/user-profile.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 |
8 | UserProfile component sample 9 | 10 | The `` component is used to render a beautiful, full-featured account management UI that allows users to manage their profile and security settings. 11 | 12 | ## Props 13 | 14 | Click [here](https://clerk.com/docs/components/user/user-profile#properties) to see the full list of props available. 15 | 16 | ## Usage 17 | 18 | ```vue 19 | 22 | 23 | 26 | ``` 27 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/composables/useSessionList.ts: -------------------------------------------------------------------------------- 1 | import type { UseSessionListReturn } from '@clerk/types' 2 | import { computed } from 'vue' 3 | 4 | import type { ToComputedRefs } from '../utils' 5 | import { toComputedRefs } from '../utils' 6 | import { useClerkProvider } from './useClerkProvider' 7 | 8 | export function useSessionList(): ToComputedRefs { 9 | const { clerk, clientCtx } = useClerkProvider() 10 | 11 | const result = computed(() => { 12 | if (!clientCtx.value) 13 | return { isLoaded: false, sessions: undefined, setActive: undefined } 14 | 15 | return { 16 | isLoaded: true, 17 | sessions: clientCtx.value.sessions, 18 | setActive: clerk.setActive, 19 | } 20 | }) 21 | 22 | return toComputedRefs(result) 23 | } 24 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/composables/useUser.ts: -------------------------------------------------------------------------------- 1 | import type { UseUserReturn } from '@clerk/types' 2 | import { computed } from 'vue' 3 | import type { ToComputedRefs } from '../utils' 4 | import { toComputedRefs } from '../utils' 5 | import { useClerkProvider } from './useClerkProvider' 6 | 7 | export function useUser(): ToComputedRefs { 8 | const { userCtx } = useClerkProvider() 9 | 10 | const result = computed(() => { 11 | if (userCtx.value === undefined) 12 | return { isLoaded: false, isSignedIn: undefined, user: undefined } 13 | 14 | if (userCtx.value === null) 15 | return { isLoaded: true, isSignedIn: false, user: null } 16 | 17 | return { isLoaded: true, isSignedIn: true, user: userCtx.value } 18 | }) 19 | 20 | return toComputedRefs(result) 21 | } 22 | -------------------------------------------------------------------------------- /.github/workflows/dependabot.yml: -------------------------------------------------------------------------------- 1 | name: Add changeset to Dependabot updates 2 | 3 | on: 4 | pull_request_target: 5 | types: [opened, synchronize, labeled] 6 | 7 | jobs: 8 | dependabot: 9 | name: Update Dependabot PR 10 | runs-on: ubuntu-latest 11 | if: contains(github.event.pull_request.labels.*.name, 'dependencies') 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | ref: ${{ github.event.pull_request.head.ref }} 19 | - name: Update PR 20 | uses: StafflinePeoplePlus/dependabot-changesets@v0.1.5 21 | with: 22 | owner: wobsoriano 23 | repo: vue-clerk 24 | pr-number: ${{ github.event.pull_request.number }} 25 | token: ${{ secrets.GITHUB_TOKEN }} 26 | -------------------------------------------------------------------------------- /apps/docs/components/control/clerk-loaded.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` component guarantees that the Clerk object has loaded and will be available under `window.Clerk`. This allows you to wrap child components to access the `Clerk` object without the need to check it exists. 8 | 9 | ## Usage 10 | 11 | ```vue 12 | 15 | 16 | 21 | ``` 22 | 23 | ```vue 24 | 31 | 32 | 35 | ``` 36 | -------------------------------------------------------------------------------- /.github/workflows/preview.yml: -------------------------------------------------------------------------------- 1 | name: Preview 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | name: Build 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout Repo 11 | uses: actions/checkout@v4 12 | with: 13 | fetch-depth: 0 14 | - uses: pnpm/action-setup@v4 15 | with: 16 | version: 9.13.0 17 | 18 | - name: Setup Node.js 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: 20.x 22 | cache: pnpm 23 | 24 | - name: Install dependencies 25 | run: pnpm install --frozen-lockfile 26 | 27 | - name: Build 28 | run: pnpm build-packages 29 | 30 | - name: Create a snapshot version 31 | id: snapshot 32 | run: pnpm dlx pkg-pr-new publish './packages/vue-clerk' --compact 33 | -------------------------------------------------------------------------------- /packages/nuxt/src/runtime/plugins/clerk.ts: -------------------------------------------------------------------------------- 1 | import { clerkPlugin } from 'vue-clerk' 2 | import type { InitialState } from '@clerk/types' 3 | import { defineNuxtPlugin, navigateTo, useRuntimeConfig, useState } from '#imports' 4 | 5 | export default defineNuxtPlugin({ 6 | name: 'vue-clerk', 7 | setup(nuxtApp) { 8 | const initialState = useState('clerk-initial-state', () => undefined) 9 | 10 | if (import.meta.server) { 11 | initialState.value = nuxtApp.ssrContext?.event.context.__clerk_initial_state 12 | } 13 | 14 | nuxtApp.vueApp.use(clerkPlugin, { 15 | ...useRuntimeConfig().public.clerk, 16 | routerPush: (to: string) => navigateTo(to), 17 | routerReplace: (to: string) => navigateTo(to, { replace: true }), 18 | initialState: initialState.value, 19 | }) 20 | }, 21 | }) 22 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/composables/useSession.ts: -------------------------------------------------------------------------------- 1 | import type { UseSessionReturn } from '@clerk/types' 2 | import { computed } from 'vue' 3 | import type { ToComputedRefs } from '../utils' 4 | import { toComputedRefs } from '../utils' 5 | import { useClerkProvider } from './useClerkProvider' 6 | 7 | export function useSession(): ToComputedRefs { 8 | const { sessionCtx } = useClerkProvider() 9 | 10 | const result = computed(() => { 11 | if (sessionCtx.value === undefined) 12 | return { isLoaded: false, isSignedIn: undefined, session: undefined } 13 | 14 | if (sessionCtx.value === null) 15 | return { isLoaded: true, isSignedIn: false, session: null } 16 | 17 | return { isLoaded: true, isSignedIn: true, session: sessionCtx.value } 18 | }) 19 | 20 | return toComputedRefs(result) 21 | } 22 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/utils/useClerkLoaded.ts: -------------------------------------------------------------------------------- 1 | import { watch } from 'vue' 2 | 3 | import { useClerkProvider } from '../composables/useClerkProvider' 4 | import type { IsomorphicClerk } from '../isomorphicClerk' 5 | 6 | /** 7 | * Executes a callback when Clerk is loaded. 8 | * 9 | * @param callback - Function to execute once Clerk is loaded 10 | * @example 11 | * ```ts 12 | * useClerkLoaded((clerk) => { 13 | * clerk.redirectToSignUp(props); 14 | * }); 15 | * ``` 16 | */ 17 | export function useClerkLoaded(callback: (clerk: IsomorphicClerk) => void) { 18 | const { isClerkLoaded, clerk } = useClerkProvider() 19 | 20 | const stop = watch( 21 | isClerkLoaded, 22 | (loaded) => { 23 | if (!loaded) { 24 | return 25 | } 26 | 27 | callback(clerk) 28 | stop() 29 | }, 30 | { immediate: true }, 31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /apps/docs/components/control/redirect-to-signup.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` component will navigate to the sign up URL which has been configured in your application instance. The behavior will be just like a server-side (3xx) redirect, and will override the current location in the history stack. 8 | 9 | ## Props 10 | 11 | Click [here](https://clerk.com/docs/components/control/redirect-to-signup#properties) to see the full list of props available. 12 | 13 | ## Usage 14 | 15 | ```vue 16 | 19 | 20 | 28 | ``` 29 | -------------------------------------------------------------------------------- /packages/nuxt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-clerk-nuxt", 3 | "type": "module", 4 | "version": "0.0.0", 5 | "private": true, 6 | "license": "MIT", 7 | "scripts": { 8 | "dev": "node ./scripts/watch.mjs", 9 | "postinstall": "nuxt-module-build prepare", 10 | "build": "nuxt-module-build build && pnpm run move", 11 | "move": "rm -rf ../vue-clerk/dist/nuxt && cp -R dist ../vue-clerk/dist/nuxt" 12 | }, 13 | "dependencies": { 14 | "@clerk/backend": "^1.21.6", 15 | "@clerk/types": "^4.40.2", 16 | "@nuxt/kit": "^3.13.2", 17 | "@nuxt/schema": "^3.13.2", 18 | "h3": "^1.12.0", 19 | "vue-clerk": "workspace:*" 20 | }, 21 | "devDependencies": { 22 | "@nuxt/devtools": "1.4.2", 23 | "@nuxt/module-builder": "0.8.4", 24 | "@types/node": "^22.5.1", 25 | "nodemon": "^3.1.4", 26 | "nuxt": "3.13.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /apps/docs/components/control/redirect-to-signin.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` component will navigate to the sign in URL which has been configured in your application instance. The behavior will be just like a server-side (3xx) redirect, and will override the current location in the history stack. 8 | 9 | ## Props 10 | 11 | Click [here](https://clerk.com/docs/components/control/redirect-to-signin#properties) to see the full list of props available. 12 | 13 | ## Usage 14 | 15 | ```vue 16 | 19 | 20 | 29 | ``` 30 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/errors/errorThrower.ts: -------------------------------------------------------------------------------- 1 | /*! 2 | * Original code by Clerk, Inc. 3 | * MIT Licensed, Copyright 2022 Clerk, Inc., see https://github.com/clerk/javascript/blob/main/packages/react/LICENSE for details 4 | * 5 | * Credits to the Clerk team: 6 | * https://github.com/clerk/javascript/blob/main/packages/react/src/errors/errorThrower.ts 7 | */ 8 | 9 | import type { ErrorThrowerOptions } from '@clerk/shared/error' 10 | import { buildErrorThrower } from '@clerk/shared/error' 11 | 12 | const errorThrower = buildErrorThrower({ packageName: PACKAGE_NAME }) 13 | 14 | export { errorThrower } 15 | 16 | /** 17 | * Overrides options of the internal errorThrower (eg setting packageName prefix). 18 | * 19 | * @internal 20 | */ 21 | export function setErrorThrowerOptions(options: ErrorThrowerOptions) { 22 | errorThrower.setMessages(options).setPackageName(options) 23 | } 24 | -------------------------------------------------------------------------------- /packages/vue-clerk/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | import vuePlugin from 'unplugin-vue/esbuild' 4 | import autoPropsPlugin from '@vue.ts/tsx-auto-props/esbuild' 5 | import { name, version } from './package.json' 6 | 7 | export default defineConfig(() => { 8 | return { 9 | entry: { 10 | index: 'src/index.ts', 11 | internal: 'src/internal.ts', 12 | }, 13 | format: ['cjs', 'esm'], 14 | splitting: true, 15 | clean: false, 16 | minify: false, 17 | dts: false, 18 | esbuildPlugins: [ 19 | // Adds .vue files support 20 | vuePlugin(), 21 | // Adds runtime props type generation from TS types 22 | autoPropsPlugin({ 23 | include: ['**/*.ts'], 24 | }), 25 | ], 26 | define: { 27 | PACKAGE_NAME: `"${name}"`, 28 | PACKAGE_VERSION: `"${version}"`, 29 | }, 30 | } 31 | }) 32 | -------------------------------------------------------------------------------- /packages/nuxt/src/runtime/middleware/auth.ts: -------------------------------------------------------------------------------- 1 | import { useAuth } from 'vue-clerk' 2 | import type { CheckAuthorizationWithCustomPermissions } from '@clerk/types' 3 | import { defineNuxtRouteMiddleware, navigateTo } from '#imports' 4 | 5 | export default defineNuxtRouteMiddleware((to) => { 6 | const { userId, has } = useAuth() 7 | const { condition, permission, role, navigateUnauthenticatedTo, guestRedirectUrl } = to.meta?.auth || {} 8 | const redirectUrl = navigateUnauthenticatedTo || guestRedirectUrl 9 | 10 | if ((permission || role) && !has.value?.({ permission, role } as Parameters[0])) { 11 | return navigateTo(redirectUrl) 12 | } 13 | 14 | if (typeof condition === 'function' && !condition(has.value!)) { 15 | return navigateTo(redirectUrl) 16 | } 17 | 18 | if (!userId.value) { 19 | return navigateTo(redirectUrl) 20 | } 21 | }) 22 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/composables/useSignIn.ts: -------------------------------------------------------------------------------- 1 | import type { UseSignInReturn } from '@clerk/types' 2 | import { computed } from 'vue' 3 | import { eventMethodCalled } from '@clerk/shared/telemetry' 4 | import type { ToComputedRefs } from '../utils' 5 | import { toComputedRefs } from '../utils' 6 | import { useClerkProvider } from './useClerkProvider' 7 | 8 | export function useSignIn(): ToComputedRefs { 9 | const { clerk, clientCtx } = useClerkProvider() 10 | 11 | clerk.telemetry?.record(eventMethodCalled('useSignIn')) 12 | 13 | const result = computed(() => { 14 | if (!clientCtx.value) 15 | return { isLoaded: false, signIn: undefined, setActive: undefined } 16 | 17 | return { 18 | isLoaded: true, 19 | signIn: clientCtx.value.signIn, 20 | setActive: clerk.setActive, 21 | } 22 | }) 23 | 24 | return toComputedRefs(result) 25 | } 26 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/composables/useSignUp.ts: -------------------------------------------------------------------------------- 1 | import type { UseSignUpReturn } from '@clerk/types' 2 | import { computed } from 'vue' 3 | import { eventMethodCalled } from '@clerk/shared/telemetry' 4 | import type { ToComputedRefs } from '../utils' 5 | import { toComputedRefs } from '../utils' 6 | import { useClerkProvider } from './useClerkProvider' 7 | 8 | export function useSignUp(): ToComputedRefs { 9 | const { clerk, clientCtx } = useClerkProvider() 10 | 11 | clerk.telemetry?.record(eventMethodCalled('useSignUp')) 12 | 13 | const result = computed(() => { 14 | if (!clientCtx.value) 15 | return { isLoaded: false, signUp: undefined, setActive: undefined } 16 | 17 | return { 18 | isLoaded: true, 19 | signUp: clientCtx.value.signUp, 20 | setActive: clerk.setActive, 21 | } 22 | }) 23 | 24 | return toComputedRefs(result) 25 | } 26 | -------------------------------------------------------------------------------- /apps/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # https://vitepress.dev/reference/default-theme-home-page 3 | layout: home 4 | 5 | hero: 6 | name: "Vue Clerk" 7 | text: "Clerk composables and components" 8 | tagline: Easiest way to add authentication and user management to your Vue application 9 | actions: 10 | - theme: brand 11 | text: What is Vue Clerk? 12 | link: /what-is-vue-clerk 13 | - theme: alt 14 | text: Quickstart 15 | link: /getting-started 16 | - theme: alt 17 | text: View on GitHub 18 | link: https://github.com/wobsoriano/vue-clerk 19 | 20 | features: 21 | - title: Pre-built Components 22 | details: Components for sign up, sign in, user management, and more. 23 | - title: Composables 24 | details: Composables for working with user, session and more. 25 | - title: Authentication & Users 26 | details: Passwords, SSO, OTP, MFA and other advanced security features. 27 | --- 28 | -------------------------------------------------------------------------------- /apps/docs/composables/use-clerk.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # useClerk() 6 | 7 | The `useClerk()` composable provides access to the [`Clerk`](https://clerk.com/docs/references/javascript/clerk/clerk) object, giving you the ability to build alternatives to any Clerk Component. 8 | 9 | ::: warning 10 | This is intended to be used for advanced use cases, like building a completely custom OAuth flow or as an escape hatch for getting access to the `Clerk` object. 11 | ::: 12 | 13 | ## Returns 14 | 15 | The `useClerk()` composable returns the `Clerk` object, which includes all the methods and properties listed in the [`Clerk` reference](https://clerk.com/docs/references/javascript/clerk/clerk). 16 | 17 | ## Usage 18 | 19 | ```vue 20 | 25 | 26 | 31 | ``` 32 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/SignInWithMetamaskButton.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 31 | -------------------------------------------------------------------------------- /packages/nuxt/src/runtime/server/clerkClient.ts: -------------------------------------------------------------------------------- 1 | import { createClerkClient } from '@clerk/backend' 2 | import type { H3Event } from 'h3' 3 | import { isTruthy } from './utils' 4 | import { useRuntimeConfig } from '#imports' 5 | 6 | export function clerkClient(event: H3Event) { 7 | const runtimeConfig = useRuntimeConfig(event) 8 | return createClerkClient({ 9 | publishableKey: runtimeConfig.public.clerk.publishableKey, 10 | apiUrl: runtimeConfig.public.clerk.apiUrl, 11 | apiVersion: runtimeConfig.public.clerk.apiVersion, 12 | secretKey: runtimeConfig.clerk.secretKey, 13 | jwtKey: runtimeConfig.clerk.jwtKey, 14 | domain: runtimeConfig.public.clerk.domain, 15 | isSatellite: isTruthy(runtimeConfig.public.clerk.isSatellite), 16 | telemetry: { 17 | disabled: isTruthy(runtimeConfig.public.clerk.telemetry?.disabled), 18 | debug: isTruthy(runtimeConfig.public.clerk.telemetry?.debug), 19 | }, 20 | }) 21 | } 22 | 23 | export function getAuth(event: H3Event) { 24 | return event.context.auth 25 | } 26 | -------------------------------------------------------------------------------- /apps/playground/README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 Minimal Starter 2 | 3 | Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more. 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies: 8 | 9 | ```bash 10 | # npm 11 | npm install 12 | 13 | # pnpm 14 | pnpm install 15 | 16 | # yarn 17 | yarn install 18 | ``` 19 | 20 | ## Development Server 21 | 22 | Start the development server on `http://localhost:3000`: 23 | 24 | ```bash 25 | # npm 26 | npm run dev 27 | 28 | # pnpm 29 | pnpm run dev 30 | 31 | # yarn 32 | yarn dev 33 | ``` 34 | 35 | ## Production 36 | 37 | Build the application for production: 38 | 39 | ```bash 40 | # npm 41 | npm run build 42 | 43 | # pnpm 44 | pnpm run build 45 | 46 | # yarn 47 | yarn build 48 | ``` 49 | 50 | Locally preview production build: 51 | 52 | ```bash 53 | # npm 54 | npm run preview 55 | 56 | # pnpm 57 | pnpm run preview 58 | 59 | # yarn 60 | yarn preview 61 | ``` 62 | 63 | Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information. 64 | -------------------------------------------------------------------------------- /apps/docs/composables/use-session-list.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # useSessionList() 6 | 7 | The `useSessionList()` composable returns an array of [`Session`](https://clerk.com/docs/references/javascript/session) objects that have been registered on the client device. 8 | 9 | ## Returns 10 | 11 | Click [here](https://clerk.com/docs/references/react/use-session-list#use-session-list-returns) to see the full list of properties returned. 12 | 13 | ## Usage 14 | 15 | The following example demonstrates how to use the `useSessionList()` composable to retrieve a list of sessions that have been registered on the client device. The `isLoaded` property is used to handle the loading state, and the `sessions` property is used to display the number of times the user has visited the page. 16 | 17 | ```vue 18 | 23 | 24 | 32 | ``` 33 | -------------------------------------------------------------------------------- /packages/nuxt/src/runtime/server/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Taken from https://github.com/clerk/javascript/blob/7a298bed566b71043ac4b8bf3cf132ef3006cf36/packages/shared/src/underscore.ts#L90 3 | * 4 | * Returns true for `true`, true, positive numbers. 5 | * Returns false for `false`, false, 0, negative integers and anything else. 6 | */ 7 | export function isTruthy(value: unknown): boolean { 8 | // Return if Boolean 9 | if (typeof value === `boolean`) { 10 | return value 11 | } 12 | 13 | // Return false if null or undefined 14 | if (value === undefined || value === null) { 15 | return false 16 | } 17 | 18 | // If the String is true or false 19 | if (typeof value === `string`) { 20 | if (value.toLowerCase() === `true`) { 21 | return true 22 | } 23 | 24 | if (value.toLowerCase() === `false`) { 25 | return false 26 | } 27 | } 28 | 29 | // Now check if it's a number 30 | const number = Number.parseInt(value as string, 10) 31 | if (Number.isNaN(number)) { 32 | return false 33 | } 34 | 35 | if (number > 0) { 36 | return true 37 | } 38 | 39 | // Default to false 40 | return false 41 | } 42 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | test: 13 | runs-on: ${{ matrix.os }} 14 | strategy: 15 | matrix: 16 | node: [20.x] 17 | os: [ubuntu-latest, windows-latest, macos-latest] 18 | fail-fast: false 19 | 20 | steps: 21 | - name: Checkout Repo 22 | uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | - uses: pnpm/action-setup@v4 26 | with: 27 | version: 9.13.0 28 | 29 | - name: Set up Node.js ${{ matrix.node }} 30 | uses: actions/setup-node@v4 31 | with: 32 | node-version: ${{ matrix.node }} 33 | cache: pnpm 34 | 35 | - name: Install dependencies 36 | run: pnpm install --frozen-lockfile 37 | 38 | - name: Lint 39 | run: pnpm lint 40 | 41 | - name: Typecheck 42 | run: pnpm --filter vue-clerk typecheck 43 | 44 | - name: Build 45 | run: pnpm build-packages 46 | 47 | - name: Test 48 | run: pnpm --filter vue-clerk test 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Robert Soriano 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /apps/docs/composables/use-session.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # useSession() 6 | 7 | The `useSession()` composable provides access to the current user's [`Session`](https://clerk.com/docs/references/javascript/session) object, as well as helpers for setting the active session. 8 | 9 | ## Returns 10 | 11 | Click [here](https://clerk.com/docs/references/react/use-session#use-session-returns) to see the full list of properties returned. 12 | 13 | ## Usage 14 | 15 | The following example demonstrates how to use the `useSession()` composable to access the `SignIn` object, which has the `lastActiveAt` property on it. The `lastActiveAt` property is used to display the last active time of the current session to the user. 16 | 17 | ```vue 18 | 23 | 24 | 35 | ``` 36 | -------------------------------------------------------------------------------- /packages/vue-clerk/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Robert Soriano 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /apps/playground/pages/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 45 | -------------------------------------------------------------------------------- /apps/docs/components/unstyled/sign-in-button.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` component is a button that links to the sign-in page or displays the sign-in modal. 8 | 9 | ## Props 10 | 11 | Click [here](https://clerk.com/docs/components/unstyled/sign-in-button#sign-in-button-properties) to see the full list of props available. 12 | 13 | ## Slots 14 | 15 | |Name|Description| 16 | |:----|:----| 17 | |`default?`|children you want to wrap the `` in.| 18 | 19 | ## Usage 20 | 21 | ### Basic Usage 22 | 23 | ```vue 24 | 27 | 28 | 31 | ``` 32 | 33 | ### Custom Usage 34 | 35 | In some cases you will want to use your own button, or button text. You can do that by passing your own button as a child and passing the `handler` to the `click` event. 36 | 37 | ```vue 38 | 41 | 42 | 52 | ``` 53 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/__tests__/SignOutButton.test.ts: -------------------------------------------------------------------------------- 1 | import { vi } from 'vitest' 2 | import { render, screen } from '@testing-library/vue' 3 | import { userEvent } from '@testing-library/user-event' 4 | import { defineComponent, h } from 'vue' 5 | import SignOutButton from '../SignOutButton.vue' 6 | 7 | const mockSignOut = vi.fn() 8 | const originalError = console.error 9 | 10 | vi.mock('../../composables/useClerk', async () => { 11 | return { 12 | useClerk: () => ({ 13 | signOut: mockSignOut, 14 | }), 15 | } 16 | }) 17 | 18 | describe('', () => { 19 | beforeAll(() => { 20 | console.error = vi.fn() 21 | }) 22 | 23 | beforeEach(() => { 24 | mockSignOut.mockReset() 25 | }) 26 | 27 | afterAll(() => { 28 | console.error = originalError 29 | }) 30 | 31 | it('calls clerk.signOutOne when clicked', async () => { 32 | render(SignOutButton) 33 | const btn = screen.getByText('Sign out') 34 | await userEvent.click(btn) 35 | 36 | expect(mockSignOut).toHaveBeenCalled() 37 | }) 38 | 39 | it('uses text passed as children', async () => { 40 | const Button = defineComponent(() => { 41 | return () => h(SignOutButton, () => 'text') 42 | }) 43 | render(Button) 44 | screen.getByText('text') 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: ${{ github.workflow }}-${{ github.ref }} 9 | 10 | jobs: 11 | release: 12 | permissions: 13 | contents: write # to create release (changesets/action) 14 | pull-requests: write # to create pull request (changesets/action) 15 | name: Release 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout Repo 19 | uses: actions/checkout@v4 20 | with: 21 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 22 | fetch-depth: 0 23 | - uses: pnpm/action-setup@v4 24 | with: 25 | version: 9.13.0 26 | 27 | - name: Setup Node.js 28 | uses: actions/setup-node@v4 29 | with: 30 | node-version: 20.x 31 | cache: pnpm 32 | 33 | - name: Install dependencies 34 | run: pnpm install --frozen-lockfile 35 | 36 | - name: Create Release Pull Request or Publish to npm 37 | id: changesets 38 | uses: changesets/action@v1 39 | with: 40 | publish: pnpm release 41 | env: 42 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 43 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 44 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/keys.ts: -------------------------------------------------------------------------------- 1 | import type { ComputedRef, Ref } from 'vue' 2 | import type { ActJWTClaim, ActiveSessionResource, ClientResource, OrganizationCustomPermissionKey, OrganizationCustomRoleKey, OrganizationResource, UserResource } from '@clerk/types' 3 | import type { IsomorphicClerk } from './isomorphicClerk' 4 | 5 | export interface VueClerkInjectionKeyType { 6 | clerk: IsomorphicClerk 7 | isClerkLoaded: Ref 8 | authCtx: ComputedRef<{ 9 | userId: string | null | undefined 10 | sessionId: string | null | undefined 11 | actor: ActJWTClaim | null | undefined 12 | orgId: string | null | undefined 13 | orgRole: OrganizationCustomRoleKey | null | undefined 14 | orgSlug: string | null | undefined 15 | orgPermissions: OrganizationCustomPermissionKey[] | null | undefined 16 | }> 17 | clientCtx: ComputedRef 18 | sessionCtx: ComputedRef 19 | userCtx: ComputedRef 20 | organizationCtx: ComputedRef 21 | } 22 | 23 | // Using Symbols causes issues in Nuxt. Investigate further. 24 | // export const VueClerkInjectionKey = Symbol('VueClerk') as InjectionKey 25 | export const VueClerkInjectionKey = '$$_clerk' 26 | -------------------------------------------------------------------------------- /apps/docs/composables/use-auth.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # useAuth() 6 | 7 | The `useAuth()` composable is a convenient way to access the current auth state. This composable provides the minimal information needed for data-loading and helper methods to manage the current active session. 8 | 9 | ## Returns 10 | 11 | Click [here](https://clerk.com/docs/references/react/use-auth#use-auth-returns) to see the full list of properties returned. 12 | 13 | ## Usage 14 | 15 | The following example demonstrates how to use the `useAuth()` composable to access the current auth state, like whether the user is signed in or not. It also demonstrates a basic example of how you could use the `getToken()` method to retrieve a session token for fetching data from an external resource. 16 | 17 | ```vue 18 | 29 | 30 | 41 | ``` 42 | -------------------------------------------------------------------------------- /apps/docs/components/organization/organization-switcher.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 |
8 | 9 | 10 | The `` component allows a user to switch between their account types - their personal account and their joined organizations. This component is useful for applications that have a multi-tenant architecture, where users can be part of multiple organizations. 11 | 12 | Out of the box, this component will show notifications to the user if they have organization [invitations](https://clerk.com/docs/organizations/overview#organization-invitations) or [suggestions](https://clerk.com/docs/organizations/overview#suggestions). Admins will be able to see notifications for [requests](https://clerk.com/docs/organizations/overview#membership-requests) to join an organization. 13 | 14 | ## Props 15 | 16 | Click [here](https://clerk.com/docs/components/organization/organization-switcher#properties) to see the full list of props available. 17 | 18 | ## Usage 19 | 20 | ```vue 21 | 24 | 25 | 28 | ``` 29 | -------------------------------------------------------------------------------- /apps/docs/components/organization/organization-list.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 |
8 | 9 | 10 | The `` component is used to display organization related memberships, invitations, and suggestions for the user. 11 | 12 | ## Props 13 | 14 | Click [here](https://clerk.com/docs/components/organization/organization-list#properties) to see the full list of props available. 15 | 16 | ## Usage 17 | 18 | ```vue 19 | 22 | 23 | 30 | ``` 31 | 32 | ### Force organizations 33 | 34 | If you would like to prohibit people from using their personal accounts and force them to be part of an organization, the `hidePersonal` property forces your user to join or create an organization in order to continue. 35 | 36 | ```vue 37 | 40 | ``` 41 | -------------------------------------------------------------------------------- /apps/docs/components/unstyled/sign-up-button.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` component is a button that links to the sign-up page or displays the sign-up modal. 8 | 9 | ## Props 10 | 11 | Click [here](https://clerk.com/docs/components/unstyled/sign-up-button#sign-up-button-properties) to see the full list of props available. 12 | 13 | ## Slots 14 | 15 | |Name|Description| 16 | |:----|:----| 17 | |`default?`|children you want to wrap the `` in.| 18 | 19 | ## Usage 20 | 21 | ### Basic Usage 22 | 23 | ```vue 24 | 27 | 28 | 34 | ``` 35 | 36 | ### Custom Usage 37 | 38 | In some cases you will want to use your own button, or button text. You can do that by passing your own button as a child and passing the `handler` to the `click` event. 39 | 40 | ```vue 41 | 44 | 45 | 57 | ``` 58 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/__tests__/SignIn.test.ts: -------------------------------------------------------------------------------- 1 | import { expectTypeOf } from 'expect-type' 2 | import type { ComponentProps } from 'vue-component-type-helpers' 3 | 4 | import type { SignIn } from '../uiComponents' 5 | 6 | export type SignInComponentProps = ComponentProps 7 | 8 | describe('', () => { 9 | describe('type tests', () => { 10 | it('has path filled', () => { 11 | expectTypeOf({ path: '/sign-in' }).toMatchTypeOf() 12 | }) 13 | 14 | it('has path filled and routing has path as a value', () => { 15 | expectTypeOf({ 16 | path: '/sign-in', 17 | routing: 'path' as const, 18 | }).toMatchTypeOf() 19 | }) 20 | 21 | it('when path is filled, routing must only have path as value', () => { 22 | expectTypeOf({ 23 | path: '/sign-in', 24 | routing: 'virtual' as const, 25 | }).not.toMatchTypeOf() 26 | 27 | expectTypeOf({ 28 | path: '/sign-in', 29 | routing: 'hash' as const, 30 | }).not.toMatchTypeOf() 31 | }) 32 | 33 | it('when routing is hash or virtual path must be present', () => { 34 | expectTypeOf({ 35 | routing: 'hash' as const, 36 | }).toMatchTypeOf() 37 | }) 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/__tests__/SignUp.test.ts: -------------------------------------------------------------------------------- 1 | import { expectTypeOf } from 'expect-type' 2 | import type { ComponentProps } from 'vue-component-type-helpers' 3 | 4 | import type { SignUp } from '../uiComponents' 5 | 6 | export type SignUpComponentProps = ComponentProps 7 | 8 | describe('', () => { 9 | describe('type tests', () => { 10 | it('has path filled', () => { 11 | expectTypeOf({ path: '/sign-up' }).toMatchTypeOf() 12 | }) 13 | 14 | it('has path filled and routing has path as a value', () => { 15 | expectTypeOf({ 16 | path: '/sign-up', 17 | routing: 'path' as const, 18 | }).toMatchTypeOf() 19 | }) 20 | 21 | it('when path is filled, routing must only have path as value', () => { 22 | expectTypeOf({ 23 | path: '/sign-up', 24 | routing: 'virtual' as const, 25 | }).not.toMatchTypeOf() 26 | 27 | expectTypeOf({ 28 | path: '/sign-up', 29 | routing: 'hash' as const, 30 | }).not.toMatchTypeOf() 31 | }) 32 | 33 | it('when routing is hash or virtual path must be present', () => { 34 | expectTypeOf({ 35 | routing: 'hash' as const, 36 | }).toMatchTypeOf() 37 | }) 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /packages/vue-clerk/README.md: -------------------------------------------------------------------------------- 1 | # vue-clerk 2 | 3 | Vue Clerk is the easiest way to add authentication and user management to your Vue application. Add sign up, sign in, and profile management to your application in minutes. 4 | 5 | > [!IMPORTANT] 6 | > This project has graduated to an [official SDK](https://clerk.com/changelog/2025-01-07-vue-and-nuxt-sdk). Please proceed [here](https://clerk.com/docs/references/vue/migrating-from-vue-community-sdk) for migration instructions. 7 | 8 | ## Installation 9 | 10 | ```bash 11 | npm install vue-clerk 12 | ``` 13 | 14 | ## Usage 15 | 16 | Vue Clerk requires your application to have the [`clerkPlugin`](https://vue-clerk.com/plugin) installed. 17 | 18 | If using Vite, set `VITE_CLERK_PUBLISHABLE_KEY` to your Publishable key in your `.env.local` file to make the environment variable accessible on `process.env` and pass it as the `publishableKey` prop. 19 | 20 | ```vue 21 | 24 | 25 | 34 | ``` 35 | 36 | For further details and examples, please refer to the [Documentation](https://vue-clerk.vercel.app). 37 | 38 | ## License 39 | 40 | MIT 41 | -------------------------------------------------------------------------------- /apps/docs/components/authentication/google-one-tap.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | ::: info 8 | To use Google One Tap with Clerk, you must [enable Google as a social connection in the Clerk Dashboard](https://clerk.com/docs/authentication/social-connections/google#configuring-google-social-connection) and make sure to use custom credentials. 9 | ::: 10 | 11 | The `` component renders the [Google One Tap UI](https://developers.google.com/identity/gsi/web/guides/features) so that users can use a single button to sign-up or sign-in to your Clerk application with their Google accounts. 12 | 13 | By default, this component will redirect users back to the page where the authentication flow started. However, you can override this with [force redirect URL props](https://clerk.com/docs/components/authentication/google-one-tap#google-one-tap-props) or [force redirect URL environment variables](https://clerk.com/docs/deployments/clerk-environment-variables#sign-in-and-sign-up-redirects). 14 | 15 | ## Props 16 | 17 | Click [here](https://clerk.com/docs/components/authentication/google-one-tap#google-one-tap-props) to see the full list of props available. 18 | 19 | ## Usage 20 | 21 | ```vue 22 | 25 | 26 | 29 | ``` 30 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/SignInButton.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 46 | -------------------------------------------------------------------------------- /apps/docs/what-is-vue-clerk.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # What is Vue Clerk? 6 | 7 | Vue Clerk is a wrapper around ClerkJS. It's a way to integrate Clerk into your Vue application. 8 | 9 | Vue Clerk provides Vue implementations of [Clerk Components](https://clerk.com/components/sign-in); highly customizable, pre-built components that you can use to build beautiful user management applications. You can find display components for building [sign in](https://clerk.com/components/sign-in), [sign up](https://clerk.com/components/sign-up), [account switching](https://clerk.com/components/user-button) and [user profile management](https://clerk.com/components/user-profile) pages as well as flow [control components](https://clerk.com/docs/component-reference/clerk-loaded) that act as helpers for implementing a seamless authentication experience. 10 | 11 | Vue Clerk comes loaded with custom [composables](/composables/use-clerk.html). These composables give you access to the [Clerk object](https://clerk.com/docs/reference/clerkjs/clerk), and a set of useful helper methods for signing in and signing up. 12 | 13 | ::: info 14 | To reduce the time of going back and forth between the official [Clerk docs](https://clerk.com/docs) and the Vue Clerk docs, we have copied most of the content you will see here (including images) from the Clerk docs and added some Vue-specific information. 15 | ::: 16 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/SignOutButton.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 47 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/__tests__/UserProfile.test.ts: -------------------------------------------------------------------------------- 1 | import { expectTypeOf } from 'expect-type' 2 | import type { ComponentProps } from 'vue-component-type-helpers' 3 | 4 | import type { UserProfile } from '../uiComponents' 5 | 6 | export type UserProfileComponentProps = ComponentProps 7 | 8 | describe('', () => { 9 | describe('type tests', () => { 10 | it('has path filled', () => { 11 | expectTypeOf({ path: '/profile' }).toMatchTypeOf() 12 | }) 13 | 14 | it('has path filled and routing has path as a value', () => { 15 | expectTypeOf({ 16 | path: '/profile', 17 | routing: 'path' as const, 18 | }).toMatchTypeOf() 19 | }) 20 | 21 | it('when path is filled, routing must only have path as value', () => { 22 | expectTypeOf({ 23 | path: '/profile', 24 | routing: 'virtual' as const, 25 | }).not.toMatchTypeOf() 26 | 27 | expectTypeOf({ 28 | path: '/profile', 29 | routing: 'hash' as const, 30 | }).not.toMatchTypeOf() 31 | }) 32 | 33 | it('when routing is hash or virtual path must be present', () => { 34 | expectTypeOf({ 35 | routing: 'hash' as const, 36 | }).toMatchTypeOf() 37 | }) 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/SignUpButton.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 49 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/__tests__/OrganizationProfile.test.ts: -------------------------------------------------------------------------------- 1 | import { expectTypeOf } from 'expect-type' 2 | import type { ComponentProps } from 'vue-component-type-helpers' 3 | 4 | import type { OrganizationProfile } from '../uiComponents' 5 | 6 | export type OrganizationProfileComponentProps = ComponentProps 7 | 8 | describe('', () => { 9 | describe('type tests', () => { 10 | it('has path filled', () => { 11 | expectTypeOf({ path: '/org' }).toMatchTypeOf() 12 | }) 13 | 14 | it('has path filled and routing has path as a value', () => { 15 | expectTypeOf({ 16 | path: '/org', 17 | routing: 'path' as const, 18 | }).toMatchTypeOf() 19 | }) 20 | 21 | it('when path is filled, routing must only have path as value', () => { 22 | expectTypeOf({ 23 | path: '/org', 24 | routing: 'virtual' as const, 25 | }).not.toMatchTypeOf() 26 | 27 | expectTypeOf({ 28 | path: '/org', 29 | routing: 'hash' as const, 30 | }).not.toMatchTypeOf() 31 | }) 32 | 33 | it('when routing is hash or virtual path must be present', () => { 34 | expectTypeOf({ 35 | routing: 'hash' as const, 36 | }).toMatchTypeOf() 37 | }) 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/__tests__/SignInWithMetamaskButton.test.ts: -------------------------------------------------------------------------------- 1 | import { vi } from 'vitest' 2 | import { render, screen } from '@testing-library/vue' 3 | import { userEvent } from '@testing-library/user-event' 4 | import { defineComponent, h } from 'vue' 5 | import SignInWithMetamaskButton from '../SignInWithMetamaskButton.vue' 6 | 7 | const mockAuthenticatewithMetamask = vi.fn() 8 | const originalError = console.error 9 | 10 | vi.mock('../../composables/useClerk', async () => { 11 | return { 12 | useClerk: () => ({ 13 | authenticateWithMetamask: mockAuthenticatewithMetamask, 14 | }), 15 | } 16 | }) 17 | 18 | describe('', () => { 19 | beforeAll(() => { 20 | console.error = vi.fn() 21 | }) 22 | 23 | beforeEach(() => { 24 | mockAuthenticatewithMetamask.mockReset() 25 | }) 26 | 27 | afterAll(() => { 28 | console.error = originalError 29 | }) 30 | 31 | it('calls clerk.authenticateWithMetamask when clicked', async () => { 32 | render(SignInWithMetamaskButton) 33 | const btn = screen.getByText('Sign in with Metamask') 34 | await userEvent.click(btn) 35 | 36 | expect(mockAuthenticatewithMetamask).toHaveBeenCalled() 37 | }) 38 | 39 | it('uses text passed as children', async () => { 40 | const Button = defineComponent(() => { 41 | return () => h(SignInWithMetamaskButton, () => 'text') 42 | }) 43 | render(Button) 44 | screen.getByText('text') 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /apps/playground/pages/user-button.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 48 | -------------------------------------------------------------------------------- /apps/docs/composables/use-sign-up.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # useSignUp() 6 | 7 | The `useSignUp()` composable gives you access to the [`SignUp`](https://clerk.com/docs/references/javascript/sign-up/sign-up) object, which allows you to check the current state of a sign-up. This is also useful for creating a custom sign-up flow. 8 | 9 | ## Returns 10 | 11 | Click [here](https://clerk.com/docs/references/react/use-sign-up#use-sign-up-returns) to see the full list of properties returned. 12 | 13 | ## Usage 14 | 15 | ### Check the current state of a up 16 | 17 | Use the `useSignUp()` composable to check the current state of a sign-up. 18 | 19 | ```vue 20 | 25 | 26 | 34 | ``` 35 | 36 | ### Create a custom sign-up flow 37 | 38 | The `useSignUp()` composable can also be used to build fully custom sign-up flows, if Clerk's pre-built components don't meet your specific needs or if you require more control over the authentication flow. Different sign-up flows include email and password, email and phone codes, email links, and multifactor (MFA). To learn more about using the `useSignUp()` composable to create custom flows, check out the [custom flow guides](https://clerk.com/docs/custom-flows/overview). 39 | -------------------------------------------------------------------------------- /apps/docs/composables/use-sign-in.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # useSignIn() 6 | 7 | The `useSignIn()` composable provides access to the [`SignIn`](https://clerk.com/docs/references/javascript/sign-in/sign-in) object, which allows you to check the current state of a sign-in. This is also useful for creating a custom sign-in flow. 8 | 9 | ## Returns 10 | 11 | Click [here](https://clerk.com/docs/references/react/use-sign-in#use-sign-in-returns) to see the full list of properties returned. 12 | 13 | ## Usage 14 | 15 | ### Check the current state of a sign-in 16 | 17 | Use the `useSignIn()` composable to check the current state of a sign-in. 18 | 19 | ```vue 20 | 25 | 26 | 34 | ``` 35 | 36 | ### Create a custom sign-in flow 37 | 38 | The `useSignIn()` composable can also be used to build fully custom sign-in flows, if Clerk's pre-built components don't meet your specific needs or if you require more control over the authentication flow. Different sign-in flows include email and password, email and phone codes, email links, and multifactor (MFA). To learn more about using the `useSignIn()` composable to create custom flows, check out the [custom flow guides](https://clerk.com/docs/custom-flows/overview). 39 | -------------------------------------------------------------------------------- /apps/docs/components/organization/organization-profile.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 |
8 | 9 | 10 | The `` component is used to render a beautiful, full-featured organization management UI that allows users to manage their organization profile and security settings. 11 | 12 | Out of the box, this component's General tab displays the organization's information and the Leave organization button. Admins will be able to see the Update profile button, Verified domains section, and Delete organization button. 13 | 14 | The Members tab shows the organization's members along with their join dates and roles. Admins will have the ability to invite a member, change a member's role, or remove them from the organization. Admins will have tabs within the Members tab to view the organization's [invitations](https://clerk.com/docs/organizations/overview#organization-invitations) and [requests](https://clerk.com/docs/organizations/overview#membership-requests). 15 | 16 | ## Props 17 | 18 | Click [here](https://clerk.com/docs/components/organization/organization-profile#properties) to see the full list of props available. 19 | 20 | ## Usage 21 | 22 | ```vue 23 | 26 | 27 | 30 | ``` 31 | -------------------------------------------------------------------------------- /apps/docs/components/authentication/sign-up.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 |
8 | 9 | 10 | The `` component renders a UI for signing up users. The functionality of the `` component is controlled by the instance settings you specify in your [Clerk Dashboard](https://dashboard.clerk.com), such as [sign-in and sign-up options](https://clerk.com/docs/authentication/configuration/sign-up-sign-in-options) and [social connections](https://clerk.com/docs/authentication/social-connections/overview). You can further customize your `` component by passing additional properties at the time of rendering. 11 | 12 | ::: info 13 | The `` and `` components cannot render when a user is already signed in, unless the application allows multiple sessions. If a user is already signed in and the application only allows a single session, Clerk will redirect the user to the Home URL instead. 14 | ::: 15 | 16 | ## Props 17 | 18 | Click [here](https://clerk.com/docs/components/authentication/sign-up#properties) to see the full list of props available. 19 | 20 | ## Usage 21 | 22 | Below is basic implementation of the `` component. You can use this as a starting point for your own implementation 23 | 24 | ```vue 25 | 28 | 29 | 32 | ``` 33 | -------------------------------------------------------------------------------- /apps/docs/components/authentication/sign-in.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 |
8 | 9 | 10 | The `` component renders a UI for signing in users. The functionality of the `` component is controlled by the instance settings you specify in your [Clerk Dashboard](https://dashboard.clerk.com), such as [sign-in and sign-up options](https://clerk.com/docs/authentication/configuration/sign-up-sign-in-options) and [social connections](https://clerk.com/docs/authentication/social-connections/overview). You can further customize your `` component by passing additional properties at the time of rendering. 11 | 12 | ::: info 13 | The `` and `` components cannot render when a user is already signed in, unless the application allows multiple sessions. If a user is already signed in and the application only allows a single session, Clerk will redirect the user to the Home URL instead. 14 | ::: 15 | 16 | ## Props 17 | 18 | Click [here](https://clerk.com/docs/components/authentication/sign-in#properties) to see the full list of props available. 19 | 20 | ## Usage 21 | 22 | Below is basic implementation of the `` component. You can use this as a starting point for your own implementation. 23 | 24 | ```vue 25 | 28 | 29 | 32 | ``` 33 | -------------------------------------------------------------------------------- /apps/docs/.vitepress/components/Banner.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 29 | 30 | 48 | 49 | 73 | -------------------------------------------------------------------------------- /apps/docs/components/user/user-button.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 |
8 | 9 | 10 | The `` component is used to render the familiar user button UI popularized by Google. 11 | 12 | Clerk is the only provider with multi-session support, allowing users to sign into multiple accounts at once and switch between them. For multisession apps, the `` automatically supports instant account switching, without the need of a full page reload. For more information, you can check out the [Multi-session applications guide](https://clerk.com/docs/custom-flows/multi-session-applications#overview). 13 | 14 | ## Props 15 | 16 | Click [here](https://clerk.com/docs/components/user/user-button#properties) to see the full list of props available. 17 | 18 | ## Usage 19 | 20 | In the following example, `` is mounted inside a header component, which is a common pattern on many websites and applications. When the user is signed in, they will see their avatar and be able to open the popup menu. 21 | 22 | ```vue 23 | 26 | 27 | 38 | 39 | 46 | ``` 47 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/__tests__/OrganizationSwitcher.test.ts: -------------------------------------------------------------------------------- 1 | import { expectTypeOf } from 'expect-type' 2 | import type { ComponentProps } from 'vue-component-type-helpers' 3 | 4 | import type { OrganizationSwitcher } from '../uiComponents' 5 | 6 | export type OrganizationSwitcherComponentProps = ComponentProps 7 | 8 | describe('', () => { 9 | describe('type tests', () => { 10 | it('createOrganizationUrl is a string', () => { 11 | expectTypeOf({ 12 | createOrganizationUrl: '/', 13 | }).toMatchTypeOf() 14 | }) 15 | 16 | it('createOrganizationUrl is a string and createOrganizationMode is navigation', () => { 17 | expectTypeOf({ 18 | createOrganizationUrl: '/', 19 | createOrganizationMode: 'navigation' as const, 20 | }).toMatchTypeOf() 21 | }) 22 | 23 | it('createOrganizationUrl is a string and createOrganizationMode is not modal', () => { 24 | expectTypeOf({ 25 | createOrganizationUrl: '/', 26 | createOrganizationMode: 'modal' as const, 27 | }).not.toMatchTypeOf() 28 | }) 29 | 30 | it('createOrganizationMode is modal and path must not been present', () => { 31 | expectTypeOf({ 32 | createOrganizationMode: 'modal' as const, 33 | }).toMatchTypeOf() 34 | }) 35 | 36 | it('createOrganizationMode is navigation and path is not present', () => { 37 | expectTypeOf({ 38 | createOrganizationMode: 'navigation' as const, 39 | }).not.toMatchTypeOf() 40 | }) 41 | }) 42 | }) 43 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/components/__tests__/UserButton.test.ts: -------------------------------------------------------------------------------- 1 | import { expectTypeOf } from 'expect-type' 2 | import type { ComponentProps } from 'vue-component-type-helpers' 3 | 4 | import type { UserButton } from '../uiComponents' 5 | 6 | export type UserButtonComponentProps = ComponentProps 7 | 8 | describe('', () => { 9 | describe('type tests', () => { 10 | it('userProfileUrl is a string', () => { 11 | expectTypeOf({ userProfileUrl: '/' }).toMatchTypeOf() 12 | expectTypeOf<{ 13 | userProfileUrl: string 14 | }>().toMatchTypeOf() 15 | }) 16 | 17 | it('userProfileUrl url is a string and userProfileMode is navigation', () => { 18 | expectTypeOf({ 19 | userProfileUrl: '/', 20 | userProfileMode: 'navigation' as const, 21 | }).toMatchTypeOf() 22 | expectTypeOf<{ 23 | userProfileUrl: string 24 | }>().toMatchTypeOf() 25 | }) 26 | 27 | it('that when userProfileMode is navigation that userProfileUrl is filled', () => { 28 | expectTypeOf({ 29 | userProfileMode: 'navigation' as const, 30 | }).not.toMatchTypeOf() 31 | }) 32 | 33 | it('that when userProfileMode is modal that userProfileUrl is not filled', () => { 34 | expectTypeOf({ 35 | userProfileMode: 'modal' as const, 36 | userProfileUrl: '/', 37 | }).not.toMatchTypeOf() 38 | }) 39 | 40 | it('userProfileMode is modal', () => { 41 | expectTypeOf({ 42 | userProfileMode: 'modal' as const, 43 | }).toMatchTypeOf() 44 | }) 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/types.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | Clerk, 3 | ClerkOptions, 4 | ClientResource, 5 | DomainOrProxyUrl, 6 | LoadedClerk, 7 | MultiDomainAndOrProxy, 8 | SDKMetadata, 9 | Without, 10 | } from '@clerk/types' 11 | 12 | declare global { 13 | interface Window { 14 | __clerk_publishable_key?: string 15 | __clerk_proxy_url?: Clerk['proxyUrl'] 16 | __clerk_domain?: Clerk['domain'] 17 | } 18 | } 19 | 20 | export type IsomorphicClerkOptions = Without & { 21 | Clerk?: ClerkProp 22 | clerkJSUrl?: string 23 | clerkJSVariant?: 'headless' | '' 24 | clerkJSVersion?: string 25 | sdkMetadata?: SDKMetadata 26 | publishableKey: string 27 | } & MultiDomainAndOrProxy 28 | 29 | export interface BrowserClerkConstructor { 30 | new (publishableKey: string, options?: DomainOrProxyUrl): BrowserClerk 31 | } 32 | 33 | export interface HeadlessBrowserClerkConstructor { 34 | new (publishableKey: string, options?: DomainOrProxyUrl): HeadlessBrowserClerk 35 | } 36 | 37 | export type WithClerkProp = T & { clerk: LoadedClerk } 38 | 39 | // Clerk object 40 | export interface MountProps { 41 | mount: (node: HTMLDivElement, props: any) => void 42 | unmount: (node: HTMLDivElement) => void 43 | updateProps: (props: any) => void 44 | props?: any 45 | customPagesPortals?: any[] 46 | } 47 | 48 | export interface HeadlessBrowserClerk extends Clerk { 49 | load: (opts?: Without) => Promise 50 | updateClient: (client: ClientResource) => void 51 | } 52 | 53 | export interface BrowserClerk extends HeadlessBrowserClerk { 54 | onComponentsReady: Promise 55 | components: any 56 | } 57 | 58 | export type ClerkProp = 59 | | BrowserClerkConstructor 60 | | BrowserClerk 61 | | HeadlessBrowserClerk 62 | | HeadlessBrowserClerkConstructor 63 | | undefined 64 | | null 65 | -------------------------------------------------------------------------------- /apps/playground/components/CustomUserButton.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 48 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/index.ts: -------------------------------------------------------------------------------- 1 | import './polyfills' 2 | 3 | import { setClerkJsLoadingErrorPackageName } from '@clerk/shared/loadClerkJsScript' 4 | import { getDeprecationMessage } from './utils/deprecate' 5 | import SignInButton from './components/SignInButton.vue' 6 | import SignUpButton from './components/SignUpButton.vue' 7 | import SignOutButton from './components/SignOutButton.vue' 8 | import SignInWithMetamaskButton from './components/SignInWithMetamaskButton.vue' 9 | import WithUser from './components/WithUser.vue' 10 | import WithClerk from './components/WithClerk.vue' 11 | import WithSession from './components/WithSession.vue' 12 | 13 | setClerkJsLoadingErrorPackageName(PACKAGE_NAME) 14 | console.warn(getDeprecationMessage()) 15 | 16 | export { 17 | SignInButton, 18 | SignUpButton, 19 | SignOutButton, 20 | SignInWithMetamaskButton, 21 | WithClerk, 22 | WithSession, 23 | WithUser, 24 | } 25 | 26 | export { 27 | useAuth, 28 | } from './composables/useAuth' 29 | 30 | export { 31 | useUser, 32 | } from './composables/useUser' 33 | 34 | export { 35 | useSession, 36 | } from './composables/useSession' 37 | 38 | export { 39 | useClerk, 40 | } from './composables/useClerk' 41 | 42 | export { 43 | useClerkProvider, 44 | } from './composables/useClerkProvider' 45 | 46 | export { 47 | useSignIn, 48 | } from './composables/useSignIn' 49 | 50 | export { 51 | useSignUp, 52 | } from './composables/useSignUp' 53 | 54 | export { 55 | useSessionList, 56 | } from './composables/useSessionList' 57 | 58 | export { 59 | useOrganization, 60 | } from './composables/useOrganization' 61 | 62 | export { 63 | VueClerkInjectionKey, 64 | VueClerkInjectionKeyType, 65 | } from './keys' 66 | 67 | export type { 68 | IsomorphicClerkOptions, 69 | } from './types' 70 | 71 | export { 72 | clerkPlugin, 73 | } from './plugin' 74 | 75 | export { 76 | updateClerkOptions, 77 | provideClerkToVueApp, 78 | } from './provideClerkToVueApp' 79 | 80 | export * from './components/uiComponents' 81 | export * from './components/controlComponents' 82 | -------------------------------------------------------------------------------- /packages/vue-clerk/src/composables/useOrganization.ts: -------------------------------------------------------------------------------- 1 | import type { OrganizationMembershipResource, OrganizationResource } from '@clerk/types' 2 | import { computed } from 'vue' 3 | import type { ToComputedRefs } from '../utils' 4 | import { toComputedRefs } from '../utils' 5 | import { useClerkProvider } from './useClerkProvider' 6 | import { useSession } from './useSession' 7 | 8 | type UseOrganizationReturn = 9 | | { 10 | isLoaded: false 11 | organization: undefined 12 | membership: undefined 13 | } 14 | | { 15 | isLoaded: true 16 | organization: OrganizationResource 17 | membership: undefined 18 | } 19 | | { 20 | isLoaded: boolean 21 | organization: OrganizationResource | null 22 | membership: OrganizationMembershipResource | null | undefined 23 | } 24 | 25 | export function useOrganization(): ToComputedRefs { 26 | const { isClerkLoaded, organizationCtx } = useClerkProvider() 27 | const { session } = useSession() 28 | 29 | const result = computed(() => { 30 | if (organizationCtx.value === undefined) 31 | return { isLoaded: false, organization: undefined, membership: undefined } 32 | 33 | if (organizationCtx.value === null) 34 | return { isLoaded: true, organization: null, membership: null } 35 | 36 | /** In SSR context we include only the organization object when loadOrg is set to true. */ 37 | if (!isClerkLoaded.value) { 38 | return { 39 | isLoaded: true, 40 | organization: organizationCtx.value, 41 | membership: undefined, 42 | } 43 | } 44 | 45 | return { 46 | isLoaded: isClerkLoaded.value, 47 | organization: organizationCtx.value, 48 | membership: getCurrentOrganizationMembership( 49 | session.value!.user.organizationMemberships, 50 | organizationCtx.value.id, 51 | ), 52 | } 53 | }) 54 | 55 | return toComputedRefs(result) 56 | } 57 | 58 | function getCurrentOrganizationMembership( 59 | organizationMemberships: OrganizationMembershipResource[], 60 | activeOrganizationId: string, 61 | ) { 62 | return organizationMemberships.find( 63 | organizationMembership => organizationMembership.organization.id === activeOrganizationId, 64 | ) 65 | } 66 | -------------------------------------------------------------------------------- /packages/nuxt/src/nuxt-types.d.ts: -------------------------------------------------------------------------------- 1 | import type { IsomorphicClerkOptions } from 'vue-clerk' 2 | import type { ClerkOptions } from '@clerk/backend' 3 | import type { CheckAuthorizationWithCustomPermissions, OrganizationCustomPermissionKey, OrganizationCustomRoleKey } from '@clerk/types' 4 | 5 | type ClerkPublicRuntimeOptions = Pick< 6 | IsomorphicClerkOptions, 7 | 'publishableKey' 8 | | 'clerkJSUrl' 9 | | 'clerkJSVariant' 10 | | 'clerkJSVersion' 11 | | 'signInFallbackRedirectUrl' 12 | | 'signUpFallbackRedirectUrl' 13 | | 'signInForceRedirectUrl' 14 | | 'signUpForceRedirectUrl' 15 | | 'signInUrl' 16 | | 'signUpUrl' 17 | | 'proxyUrl' 18 | | 'isSatellite' 19 | | 'domain' 20 | > & Pick 21 | 22 | type ClerkRuntimeOptions = Pick 23 | 24 | declare module 'nuxt/schema' { 25 | interface RuntimeConfig { 26 | clerk: ClerkRuntimeOptions 27 | } 28 | 29 | interface PublicRuntimeConfig { 30 | clerk: ClerkPublicRuntimeOptions 31 | } 32 | } 33 | 34 | type ProtectParams = { 35 | condition?: never 36 | role: OrganizationCustomRoleKey 37 | permission?: never 38 | } | { 39 | condition?: never 40 | role?: never 41 | permission: OrganizationCustomPermissionKey 42 | } | { 43 | condition: (has: CheckAuthorizationWithCustomPermissions) => boolean 44 | role?: never 45 | permission?: never 46 | } | { 47 | condition?: never 48 | role?: never 49 | permission?: never 50 | } 51 | 52 | type MiddlewareMeta = ProtectParams & { 53 | /** 54 | * Where to redirect authenticated users 55 | * 56 | * @default undefined 57 | */ 58 | navigateAuthenticatedTo?: string 59 | /** 60 | * @deprecated Use `navigateAuthenticatedTo` instead 61 | */ 62 | authenticatedRedirectUrl?: string 63 | /** 64 | * Where to redirect unauthenticated users 65 | * 66 | * @default undefined 67 | */ 68 | navigateUnauthenticatedTo?: string 69 | /** 70 | * @deprecated Use `navigateUnauthenticatedTo` instead 71 | */ 72 | guestRedirectUrl?: string 73 | } 74 | 75 | declare module '#app' { 76 | interface PageMeta { 77 | auth?: MiddlewareMeta 78 | } 79 | } 80 | 81 | declare module 'vue-router' { 82 | interface RouteMeta { 83 | auth?: MiddlewareMeta 84 | } 85 | } 86 | 87 | export {} 88 | -------------------------------------------------------------------------------- /apps/docs/components/unstyled/sign-out-button.md: -------------------------------------------------------------------------------- 1 | --- 2 | outline: deep 3 | --- 4 | 5 | # `` 6 | 7 | The `` component is a button that signs a user out. By default, it is a `