@moontra/moonui 2.3.8 → 2.3.9
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/package.json
CHANGED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
// Pro Component Wrapper - Simplified Version
|
|
4
|
-
// Development: CLI auth required
|
|
5
|
-
// Production: License key validation with 24h cache
|
|
6
|
-
|
|
7
|
-
import React, { useState, useEffect } from 'react'
|
|
8
|
-
import { cn } from '../../lib/utils'
|
|
9
|
-
import { Badge } from './badge'
|
|
10
|
-
import { Lock, Terminal, AlertCircle } from 'lucide-react'
|
|
11
|
-
|
|
12
|
-
interface ProComponentWrapperProps {
|
|
13
|
-
children: React.ReactNode
|
|
14
|
-
componentId: string
|
|
15
|
-
componentName?: string
|
|
16
|
-
className?: string
|
|
17
|
-
fallback?: React.ReactNode
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface LicenseCache {
|
|
21
|
-
timestamp: number
|
|
22
|
-
hasProAccess: boolean
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const CACHE_KEY = 'moonui_license_cache'
|
|
26
|
-
const CACHE_DURATION = 24 * 60 * 60 * 1000 // 24 hours
|
|
27
|
-
|
|
28
|
-
export function ProComponentWrapper({
|
|
29
|
-
children,
|
|
30
|
-
componentId,
|
|
31
|
-
componentName,
|
|
32
|
-
className,
|
|
33
|
-
fallback
|
|
34
|
-
}: ProComponentWrapperProps) {
|
|
35
|
-
const [state, setState] = useState<{
|
|
36
|
-
hasAccess: boolean
|
|
37
|
-
loading: boolean
|
|
38
|
-
message?: string
|
|
39
|
-
}>({
|
|
40
|
-
hasAccess: false,
|
|
41
|
-
loading: true
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
// Check if development environment
|
|
46
|
-
const isDevelopment = () => {
|
|
47
|
-
if (typeof window === 'undefined') return false
|
|
48
|
-
|
|
49
|
-
const isLocalhost =
|
|
50
|
-
window.location.hostname === 'localhost' ||
|
|
51
|
-
window.location.hostname === '127.0.0.1' ||
|
|
52
|
-
window.location.hostname.includes('.local')
|
|
53
|
-
|
|
54
|
-
const isDevPort =
|
|
55
|
-
window.location.port === '3000' ||
|
|
56
|
-
window.location.port === '3001' ||
|
|
57
|
-
window.location.port === '8080' ||
|
|
58
|
-
window.location.port === '5173'
|
|
59
|
-
|
|
60
|
-
// Must be localhost with dev port
|
|
61
|
-
return process.env.NODE_ENV === 'development' && isLocalhost && isDevPort
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// DEVELOPMENT: Check CLI auth
|
|
65
|
-
if (isDevelopment()) {
|
|
66
|
-
const checkDevAuth = () => {
|
|
67
|
-
const cliToken = localStorage.getItem('moonui_cli_token')
|
|
68
|
-
const deviceId = localStorage.getItem('moonui_device_id')
|
|
69
|
-
|
|
70
|
-
if (!cliToken || !deviceId) {
|
|
71
|
-
setState({
|
|
72
|
-
hasAccess: false,
|
|
73
|
-
loading: false,
|
|
74
|
-
message: 'CLI authentication required'
|
|
75
|
-
})
|
|
76
|
-
return
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Token exists - allow access
|
|
80
|
-
setState({
|
|
81
|
-
hasAccess: true,
|
|
82
|
-
loading: false
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
checkDevAuth()
|
|
87
|
-
return
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// PRODUCTION: Check license cache
|
|
91
|
-
const checkProdLicense = () => {
|
|
92
|
-
try {
|
|
93
|
-
// Check cache first
|
|
94
|
-
const cached = localStorage.getItem(CACHE_KEY)
|
|
95
|
-
if (cached) {
|
|
96
|
-
const data = JSON.parse(cached) as LicenseCache
|
|
97
|
-
const now = Date.now()
|
|
98
|
-
|
|
99
|
-
// Cache still valid (24 hours)
|
|
100
|
-
if (data.timestamp && (now - data.timestamp) < CACHE_DURATION) {
|
|
101
|
-
setState({
|
|
102
|
-
hasAccess: data.hasProAccess,
|
|
103
|
-
loading: false
|
|
104
|
-
})
|
|
105
|
-
return
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// No valid cache - need license key
|
|
110
|
-
const licenseKey = process.env.NEXT_PUBLIC_MOONUI_LICENSE_KEY
|
|
111
|
-
|
|
112
|
-
if (!licenseKey) {
|
|
113
|
-
setState({
|
|
114
|
-
hasAccess: false,
|
|
115
|
-
loading: false,
|
|
116
|
-
message: 'No license key configured'
|
|
117
|
-
})
|
|
118
|
-
return
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Validate license async
|
|
122
|
-
validateLicense(licenseKey).then(result => {
|
|
123
|
-
// Save to cache
|
|
124
|
-
const cacheData: LicenseCache = {
|
|
125
|
-
timestamp: Date.now(),
|
|
126
|
-
hasProAccess: result.hasProAccess
|
|
127
|
-
}
|
|
128
|
-
localStorage.setItem(CACHE_KEY, JSON.stringify(cacheData))
|
|
129
|
-
|
|
130
|
-
setState({
|
|
131
|
-
hasAccess: result.hasProAccess,
|
|
132
|
-
loading: false
|
|
133
|
-
})
|
|
134
|
-
}).catch(error => {
|
|
135
|
-
console.error('License validation failed:', error)
|
|
136
|
-
|
|
137
|
-
// Try expired cache as fallback
|
|
138
|
-
const cached = localStorage.getItem(CACHE_KEY)
|
|
139
|
-
if (cached) {
|
|
140
|
-
const data = JSON.parse(cached) as LicenseCache
|
|
141
|
-
setState({
|
|
142
|
-
hasAccess: data.hasProAccess,
|
|
143
|
-
loading: false,
|
|
144
|
-
message: 'Using cached license'
|
|
145
|
-
})
|
|
146
|
-
} else {
|
|
147
|
-
setState({
|
|
148
|
-
hasAccess: false,
|
|
149
|
-
loading: false,
|
|
150
|
-
message: 'License validation failed'
|
|
151
|
-
})
|
|
152
|
-
}
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
} catch (error) {
|
|
156
|
-
console.error('License check error:', error)
|
|
157
|
-
setState({
|
|
158
|
-
hasAccess: false,
|
|
159
|
-
loading: false,
|
|
160
|
-
message: 'License check failed'
|
|
161
|
-
})
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
checkProdLicense()
|
|
166
|
-
}, [])
|
|
167
|
-
|
|
168
|
-
// Loading state
|
|
169
|
-
if (state.loading) {
|
|
170
|
-
return (
|
|
171
|
-
<div className={cn("animate-pulse bg-gray-200 dark:bg-gray-800 rounded-lg h-32", className)}>
|
|
172
|
-
<div className="flex items-center justify-center h-full">
|
|
173
|
-
<div className="text-sm text-gray-500">Loading...</div>
|
|
174
|
-
</div>
|
|
175
|
-
</div>
|
|
176
|
-
)
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Access granted
|
|
180
|
-
if (state.hasAccess) {
|
|
181
|
-
return <>{children}</>
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Development: Show CLI auth required
|
|
185
|
-
if (state.message === 'CLI authentication required') {
|
|
186
|
-
return (
|
|
187
|
-
<div className={cn("relative", className)}>
|
|
188
|
-
<div className="blur-sm grayscale opacity-60 pointer-events-none">
|
|
189
|
-
{fallback || children}
|
|
190
|
-
</div>
|
|
191
|
-
<div className="absolute inset-0 bg-gradient-to-br from-blue-500/10 via-transparent to-purple-500/10 border-2 border-dashed border-blue-400/30 rounded-lg flex items-center justify-center">
|
|
192
|
-
<div className="text-center space-y-3 p-6 bg-white/90 dark:bg-gray-900/90 rounded-lg">
|
|
193
|
-
<Badge variant="secondary" className="mb-2">
|
|
194
|
-
<Terminal className="w-3 h-3 mr-1" />
|
|
195
|
-
DEV AUTH REQUIRED
|
|
196
|
-
</Badge>
|
|
197
|
-
<h3 className="font-semibold">CLI Authentication Required</h3>
|
|
198
|
-
<p className="text-sm text-gray-600 dark:text-gray-400 max-w-xs">
|
|
199
|
-
Login with MoonUI CLI to use Pro components in development
|
|
200
|
-
</p>
|
|
201
|
-
<code className="block bg-black text-green-400 p-2 rounded text-xs font-mono">
|
|
202
|
-
npx moonui auth login
|
|
203
|
-
</code>
|
|
204
|
-
</div>
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Production: Show license required
|
|
211
|
-
return (
|
|
212
|
-
<div className={cn("relative", className)}>
|
|
213
|
-
<div className="blur-sm grayscale opacity-60 pointer-events-none">
|
|
214
|
-
{fallback || children}
|
|
215
|
-
</div>
|
|
216
|
-
<div className="absolute inset-0 bg-gradient-to-br from-amber-500/10 via-transparent to-orange-500/10 border-2 border-dashed border-amber-400/30 rounded-lg flex items-center justify-center">
|
|
217
|
-
<div className="text-center space-y-3 p-6 bg-white/90 dark:bg-gray-900/90 rounded-lg">
|
|
218
|
-
<Badge variant="destructive" className="mb-2">
|
|
219
|
-
<AlertCircle className="w-3 h-3 mr-1" />
|
|
220
|
-
LICENSE REQUIRED
|
|
221
|
-
</Badge>
|
|
222
|
-
<h3 className="font-semibold">{componentName || componentId}</h3>
|
|
223
|
-
<p className="text-sm text-gray-600 dark:text-gray-400 max-w-xs">
|
|
224
|
-
{state.message || 'Pro license required to use this component'}
|
|
225
|
-
</p>
|
|
226
|
-
<a
|
|
227
|
-
href="https://moonui.dev/pricing"
|
|
228
|
-
target="_blank"
|
|
229
|
-
rel="noopener noreferrer"
|
|
230
|
-
className="inline-block bg-gradient-to-r from-amber-500 to-orange-500 text-white px-4 py-2 rounded-lg text-sm font-medium hover:from-amber-600 hover:to-orange-600 transition-colors"
|
|
231
|
-
>
|
|
232
|
-
Get Pro License
|
|
233
|
-
</a>
|
|
234
|
-
</div>
|
|
235
|
-
</div>
|
|
236
|
-
</div>
|
|
237
|
-
)
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Validate license with API
|
|
241
|
-
async function validateLicense(licenseKey: string): Promise<{ hasProAccess: boolean }> {
|
|
242
|
-
const response = await fetch('/api/v1/license/validate', {
|
|
243
|
-
method: 'POST',
|
|
244
|
-
headers: {
|
|
245
|
-
'Content-Type': 'application/json'
|
|
246
|
-
},
|
|
247
|
-
body: JSON.stringify({
|
|
248
|
-
licenseKey,
|
|
249
|
-
domain: window.location.hostname
|
|
250
|
-
})
|
|
251
|
-
})
|
|
252
|
-
|
|
253
|
-
if (!response.ok) {
|
|
254
|
-
throw new Error('License validation failed')
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const data = await response.json()
|
|
258
|
-
return {
|
|
259
|
-
hasProAccess: data.hasProAccess || false
|
|
260
|
-
}
|
|
261
|
-
}
|