@meeovi/auth 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+
2
+ ---
3
+
4
+ # 📦 `@meeovi/auth` — README.md
5
+
6
+ ```md
7
+ # @meeovi/auth
8
+
9
+ A unified authentication abstraction for Meeovi.
10
+ Supports Better Auth, Auth.js, Lucia, Ory, and custom auth backends.
11
+
12
+ ## ✨ Features
13
+
14
+ - Unified `useAuth()` composable
15
+ - Pluggable auth providers
16
+ - Runtime configuration
17
+ - Session helpers
18
+
19
+ ## 📦 Installation
20
+
21
+ ```sh
22
+ npm install @meeovi/auth
23
+
24
+ ⚙️ Configuration
25
+
26
+ import { setAuthConfig } from '@meeovi/auth'
27
+
28
+ setAuthConfig({
29
+ authProvider: 'better-auth',
30
+ authUrl: '/api/auth'
31
+ })
32
+ 🧩 Usage
33
+
34
+ import { useAuth } from '@meeovi/auth'
35
+
36
+ const { login, logout, session } = useAuth()
37
+
38
+ await login({ email, password })
39
+ 🔌 Providers
40
+
41
+ export interface AuthProvider {
42
+ login(credentials: any): Promise<any>
43
+ logout(): Promise<void>
44
+ session(): Promise<any>
45
+ }
46
+ Register:
47
+
48
+
49
+ registerAuthProvider('better-auth', { login, logout, session })
50
+ 🧱 Folder Structure
51
+ Code
52
+ src/
53
+ providers/
54
+ config.
55
+ registry.
56
+ useAuth.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meeovi/auth",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Authentication for M Framework.",
5
5
  "license": "ISC",
6
6
  "author": "",
@@ -15,10 +15,13 @@
15
15
  "@better-auth/passkey": "^1.4.10",
16
16
  "@better-auth/scim": "^1.4.15",
17
17
  "@better-auth/sso": "^1.4.12",
18
+ "@better-auth/stripe": "^1.4.15",
18
19
  "@polar-sh/better-auth": "^1.6.3",
19
20
  "better-auth": "^1.4.12",
20
21
  "mjml": "^4.18.0",
21
22
  "uncrypto": "^0.1.3",
22
- "uuid": "^13.0.0"
23
+ "uuid": "^13.0.0",
24
+ "vue": "^3.5.27",
25
+ "vue-router": "^4.6.4"
23
26
  }
24
27
  }
package/src/config.ts CHANGED
@@ -1,5 +1,6 @@
1
1
 
2
2
  export interface AuthConfig {
3
+ baseUrl: any
3
4
  authProvider: string
4
5
  authUrl?: string
5
6
  sessionCookieName?: string
@@ -8,7 +9,8 @@ export interface AuthConfig {
8
9
  let config: AuthConfig = {
9
10
  authProvider: 'better-auth',
10
11
  authUrl: '',
11
- sessionCookieName: 'meeovi_session'
12
+ sessionCookieName: 'session',
13
+ baseUrl: undefined
12
14
  }
13
15
 
14
16
  export function setAuthConfig(newConfig: Partial<AuthConfig>) {
@@ -0,0 +1,24 @@
1
+
2
+ export interface FrameworkContext {
3
+ getRequestURL?(): string
4
+ getRequestHeaders?(): Record<string, string>
5
+ getConfig?(): any
6
+ reloadApp?(): void
7
+ state?<T>(key: string, init: () => T): { value: T }
8
+ }
9
+
10
+ let ctx: FrameworkContext = {}
11
+
12
+ /**
13
+ * Frameworks (Nuxt, React, etc.) call this once during initialization.
14
+ */
15
+ export function setFrameworkContext(newCtx: FrameworkContext) {
16
+ ctx = { ...ctx, ...newCtx }
17
+ }
18
+
19
+ /**
20
+ * Auth providers use this to access framework-specific helpers.
21
+ */
22
+ export function getFrameworkContext(): FrameworkContext {
23
+ return ctx
24
+ }
package/src/plugins.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { stripeClient } from '@better-auth/stripe/client'
2
+ import { polarClient } from '@polar-sh/better-auth'
3
+ import { adminClient, inferAdditionalFields } from 'better-auth/client/plugins'
4
+
5
+ export type AuthPluginOptions = {
6
+ /** whether to enable subscription support for stripe plugin */
7
+ subscription?: boolean
8
+ }
9
+
10
+ export function getAuthPlugins(opts: AuthPluginOptions = {}) {
11
+ const { subscription = true } = opts
12
+
13
+ return [
14
+ inferAdditionalFields({
15
+ user: {
16
+ polarCustomerId: {
17
+ type: 'string'
18
+ }
19
+ }
20
+ }),
21
+ adminClient(),
22
+ polarClient(),
23
+ stripeClient({ subscription })
24
+ ]
25
+ }
@@ -0,0 +1,107 @@
1
+ import * as BetterAuth from 'better-auth'
2
+ import { registerAuthProvider } from '../registry'
3
+ import type { AuthProvider } from '../types'
4
+ import { getAuthConfig } from '../config'
5
+ import { getFrameworkContext } from '../framework'
6
+
7
+ // Create a single shared Better Auth client instance
8
+ let client: any = null
9
+
10
+ function resolveClientFactory() {
11
+ return (BetterAuth as any).Client ?? (BetterAuth as any).default ?? BetterAuth
12
+ }
13
+
14
+ function getClient() {
15
+ if (client) return client
16
+
17
+ const config = getAuthConfig()
18
+ const ctx = getFrameworkContext()
19
+
20
+ const Client = resolveClientFactory()
21
+ client = Client({
22
+ baseURL: config.baseUrl,
23
+ fetch: async (url: string | Request | URL, options: RequestInit = {}) => {
24
+ // Framework‑agnostic request wrapper
25
+ const baseHeaders = ctx.getRequestHeaders?.() || {}
26
+
27
+ let optionHeaders: Record<string, string> = {}
28
+
29
+ if (options.headers instanceof Headers) {
30
+ options.headers.forEach((value, key) => {
31
+ optionHeaders[key] = value
32
+ })
33
+ } else if (Array.isArray(options.headers)) {
34
+ for (const [k, v] of options.headers) {
35
+ optionHeaders[k] = v
36
+ }
37
+ } else if (typeof options.headers === 'object' && options.headers !== null) {
38
+ optionHeaders = options.headers as Record<string, string>
39
+ }
40
+
41
+ const headers = {
42
+ ...baseHeaders,
43
+ ...optionHeaders
44
+ }
45
+
46
+ return fetch(url, { ...options, headers })
47
+ }
48
+ })
49
+
50
+ return client
51
+ }
52
+
53
+ const BetterAuthProvider: AuthProvider = {
54
+ async login(credentials) {
55
+ const client = getClient()
56
+ const result = await client.signIn(credentials)
57
+
58
+ if (result.error) {
59
+ throw new Error(result.error.message || 'Login failed')
60
+ }
61
+
62
+ return result.data
63
+ },
64
+
65
+ async logout() {
66
+ const client = getClient()
67
+ await client.signOut()
68
+
69
+ const ctx = getFrameworkContext()
70
+ ctx.reloadApp?.()
71
+ },
72
+
73
+ async session() {
74
+ const client = getClient()
75
+ const result = await client.session()
76
+
77
+ if (result.error) {
78
+ return null
79
+ }
80
+
81
+ return result.data
82
+ },
83
+
84
+ async register(data) {
85
+ const client = getClient()
86
+ const result = await client.signUp(data)
87
+
88
+ if (result.error) {
89
+ throw new Error(result.error.message || 'Registration failed')
90
+ }
91
+
92
+ return result.data
93
+ },
94
+
95
+ async refresh() {
96
+ const client = getClient()
97
+ const result = await client.refresh()
98
+
99
+ if (result.error) {
100
+ throw new Error(result.error.message || 'Session refresh failed')
101
+ }
102
+
103
+ return result.data
104
+ }
105
+ }
106
+
107
+ registerAuthProvider('better-auth', BetterAuthProvider)
@@ -0,0 +1,22 @@
1
+ import type { AuthProvider } from './types'
2
+
3
+ const providers: Record<string, AuthProvider> = {}
4
+ let activeProvider: string | null = null
5
+
6
+ export function registerAuthProvider(name: string, provider: AuthProvider) {
7
+ providers[name] = provider
8
+ }
9
+
10
+ export function setActiveAuthProvider(name: string) {
11
+ if (!providers[name]) {
12
+ throw new Error(`Auth provider "${name}" is not registered`)
13
+ }
14
+ activeProvider = name
15
+ }
16
+
17
+ export function getAuthProvider(): AuthProvider {
18
+ if (!activeProvider) {
19
+ throw new Error('No active auth provider has been set')
20
+ }
21
+ return providers[activeProvider]
22
+ }
package/src/types.ts ADDED
@@ -0,0 +1,33 @@
1
+
2
+ export interface AuthSession {
3
+ user: {
4
+ id: string
5
+ email?: string
6
+ name?: string
7
+ avatarUrl?: string
8
+ [key: string]: any
9
+ }
10
+ expiresAt?: string
11
+ [key: string]: any
12
+ }
13
+
14
+ export interface AuthCredentials {
15
+ email: string
16
+ password: string
17
+ [key: string]: any
18
+ }
19
+
20
+ export interface AuthRegistration {
21
+ email: string
22
+ password: string
23
+ name?: string
24
+ [key: string]: any
25
+ }
26
+
27
+ export interface AuthProvider {
28
+ login(credentials: AuthCredentials): Promise<AuthSession>
29
+ logout(): Promise<void>
30
+ session(): Promise<AuthSession | null>
31
+ register?(data: AuthRegistration): Promise<AuthSession>
32
+ refresh?(): Promise<AuthSession>
33
+ }
package/src/useAuth.ts CHANGED
@@ -1,18 +1,112 @@
1
+ import type { Subscription } from '@better-auth/stripe'
2
+ import type { CustomerState } from '@polar-sh/sdk/models/components/customerstate.js'
3
+ import type {
4
+ BetterAuthClientOptions,
5
+ InferSessionFromClient,
6
+ User
7
+ } from 'better-auth/client'
1
8
  import { createAuthClient } from 'better-auth/client'
2
- import { useRuntimeConfig } from '#imports'
9
+ import { getAuthPlugins } from './plugins'
3
10
 
4
- let client: any = null
11
+ export type UseAuthOptions = {
12
+ /** An existing auth client. If provided, it's used as-is. */
13
+ client?: any
14
+ /** Base URL for the auth client if creating one. */
15
+ baseURL?: string
16
+ /** Optional headers to send with requests. */
17
+ headers?: Record<string, string>
18
+ /** Payment provider: 'stripe' or 'polar'. If omitted, 'stripe' is assumed. */
19
+ payment?: 'stripe' | 'polar'
20
+ /** Optional app-level reload/redirect function (framework-specific). */
21
+ reload?: (opts: { path?: string }) => Promise<void>
22
+ }
23
+
24
+ export function useAuth(options: UseAuthOptions = {}) {
25
+ const { client: providedClient, baseURL, headers, payment = 'stripe', reload } = options
26
+
27
+ const client = providedClient || createAuthClient({
28
+ baseURL: baseURL || undefined,
29
+ fetchOptions: {
30
+ headers
31
+ },
32
+ plugins: getAuthPlugins({ subscription: true })
33
+ })
34
+
35
+ let session: InferSessionFromClient<BetterAuthClientOptions> | null = null
36
+ let user: User | null = null
37
+ let subscriptions: Subscription[] = []
38
+ let polarState: CustomerState | null = null
39
+ let sessionFetching = false
40
+
41
+ const fetchSession = async () => {
42
+ if (sessionFetching) return
43
+ sessionFetching = true
44
+ const { data } = await client.getSession()
45
+ session = data?.session || null
46
+
47
+ const userDefaults = {
48
+ image: null,
49
+ role: null,
50
+ banReason: null,
51
+ banned: null,
52
+ banExpires: null,
53
+ stripeCustomerId: null
54
+ }
55
+ user = data?.user ? Object.assign({}, userDefaults, data.user) : null
56
+ subscriptions = []
57
+ if (user) {
58
+ if (payment == 'stripe') {
59
+ const { data: subscriptionData } = await client.subscription.list()
60
+ subscriptions = subscriptionData || []
61
+ } else if (payment == 'polar') {
62
+ const { data: customerState } = await client.customer.state()
63
+ polarState = customerState
64
+ }
65
+ }
66
+ sessionFetching = false
67
+ return data
68
+ }
5
69
 
6
- export function useAuth() {
7
- if (!client) {
8
- const config = useRuntimeConfig()
9
- client = createAuthClient({ baseURL: config.public.authUrl })
70
+ if (client?.$store?.listen) {
71
+ client.$store.listen('$sessionSignal', async (signal: any) => {
72
+ if (!signal) return
73
+ await fetchSession()
74
+ })
10
75
  }
11
76
 
12
77
  return {
13
- login: client.login,
14
- logout: client.logout,
15
- register: client.register,
16
- session: client.session
78
+ session,
79
+ user,
80
+ subscription: client.subscription,
81
+ subscriptions,
82
+ loggedIn: () => !!session,
83
+ activeStripeSubscription: () => {
84
+ return subscriptions.find((sub: { status: string }) => sub.status === 'active' || sub.status === 'trialing')
85
+ },
86
+ activePolarSubscriptions: () => {
87
+ return polarState?.activeSubscriptions
88
+ },
89
+ signIn: client.signIn,
90
+ signUp: client.signUp,
91
+ forgetPassword: client.forgetPassword,
92
+ resetPassword: client.resetPassword,
93
+ sendVerificationEmail: client.sendVerificationEmail,
94
+ errorCodes: client.$ERROR_CODES,
95
+ async signOut({ redirectTo }: { redirectTo?: string } = {}) {
96
+ await client.signOut({
97
+ fetchOptions: {
98
+ onSuccess: async () => {
99
+ session = null
100
+ user = null
101
+ if (redirectTo && typeof reload === 'function') {
102
+ await reload({ path: redirectTo.toString() })
103
+ }
104
+ }
105
+ }
106
+ })
107
+ },
108
+ fetchSession,
109
+ payment,
110
+ client
17
111
  }
18
112
  }