@moontra/moonui-pro 2.37.5 → 2.37.6

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/dist/index.mjs CHANGED
@@ -2055,8 +2055,10 @@ function createAIProvider(provider, config) {
2055
2055
  // src/lib/auth-config.ts
2056
2056
  var IS_PRODUCTION = false;
2057
2057
  var AUTH_CONFIG = {
2058
- // Internal API endpoint (never external)
2059
- // Developers will implement this endpoint in their own project
2058
+ // CLI Auth Server endpoint (preferred)
2059
+ authServerEndpoint: process.env.NEXT_PUBLIC_MOONUI_AUTH_SERVER || "http://localhost:7878",
2060
+ // Internal API endpoint (fallback only - deprecated)
2061
+ // This will be removed in future versions
2060
2062
  internalEndpoint: "/api/moonui/validate-pro",
2061
2063
  // Cache configuration
2062
2064
  cache: {
package/dist/server.d.ts CHANGED
@@ -60,6 +60,7 @@ declare function performServerValidation(): Promise<{
60
60
  * It ensures zero external API calls from the browser.
61
61
  */
62
62
  declare const AUTH_CONFIG: {
63
+ readonly authServerEndpoint: string;
63
64
  readonly internalEndpoint: "/api/moonui/validate-pro";
64
65
  readonly cache: {
65
66
  readonly serverCacheDuration: number;
package/dist/server.mjs CHANGED
@@ -2965,8 +2965,10 @@ var import_headers = __toESM(require_headers3(), 1);
2965
2965
  // src/lib/auth-config.ts
2966
2966
  var IS_PRODUCTION = false;
2967
2967
  var AUTH_CONFIG = {
2968
- // Internal API endpoint (never external)
2969
- // Developers will implement this endpoint in their own project
2968
+ // CLI Auth Server endpoint (preferred)
2969
+ authServerEndpoint: process.env.NEXT_PUBLIC_MOONUI_AUTH_SERVER || "http://localhost:7878",
2970
+ // Internal API endpoint (fallback only - deprecated)
2971
+ // This will be removed in future versions
2970
2972
  internalEndpoint: "/api/moonui/validate-pro",
2971
2973
  // Cache configuration
2972
2974
  cache: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moontra/moonui-pro",
3
- "version": "2.37.5",
3
+ "version": "2.37.6",
4
4
  "description": "Premium React components for MoonUI - Advanced UI library with 50+ pro components including performance, interactive, and gesture components",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -12,7 +12,6 @@
12
12
  "dist",
13
13
  "scripts",
14
14
  "plugin",
15
- "templates",
16
15
  "README.md",
17
16
  "LICENSE"
18
17
  ],
@@ -40,8 +39,7 @@
40
39
  "types": "./plugin/index.d.ts",
41
40
  "import": "./plugin/index.js",
42
41
  "require": "./plugin/index.js"
43
- },
44
- "./templates/validate-pro-route": "./templates/validate-pro-route.ts"
42
+ }
45
43
  },
46
44
  "scripts": {
47
45
  "build": "tsup && node scripts/postbuild.js",
@@ -1,157 +0,0 @@
1
- /**
2
- * MoonUI Pro - Server Validation API Route Template
3
- *
4
- * INSTALLATION:
5
- * 1. Copy this file to your project: app/api/moonui/validate-pro/route.ts
6
- * 2. Set environment variable: MOONUI_LICENSE_KEY=your-license-key
7
- * 3. (Optional) Set encryption key: MOONUI_ENCRYPTION_KEY=your-secret-key
8
- *
9
- * This route handles server-side validation to prevent browser API calls.
10
- */
11
-
12
- import { NextRequest, NextResponse } from "next/server";
13
- import {
14
- performServerValidation,
15
- clearValidationCookies,
16
- generateServerDeviceFingerprint,
17
- setValidationInCookies,
18
- } from "@moontra/moonui-pro/server";
19
-
20
- // In-memory cache for rate limiting (use Redis in production)
21
- const validationCache = new Map<
22
- string,
23
- {
24
- count: number;
25
- resetAt: number;
26
- }
27
- >();
28
-
29
- // Rate limiting helper
30
- function checkRateLimit(identifier: string): boolean {
31
- const now = Date.now();
32
- const limit = validationCache.get(identifier);
33
-
34
- if (!limit || limit.resetAt < now) {
35
- // Reset or create new limit
36
- validationCache.set(identifier, {
37
- count: 1,
38
- resetAt: now + 60 * 1000, // 1 minute window
39
- });
40
- return true;
41
- }
42
-
43
- if (limit.count >= 10) {
44
- // Max 10 requests per minute
45
- return false;
46
- }
47
-
48
- limit.count++;
49
- return true;
50
- }
51
-
52
- /**
53
- * GET /api/moonui/validate-pro
54
- * Validates the current session
55
- */
56
- export async function GET(request: NextRequest) {
57
- try {
58
- // Generate device fingerprint for rate limiting
59
- const deviceId = await generateServerDeviceFingerprint();
60
-
61
- // Check rate limit
62
- if (!checkRateLimit(deviceId)) {
63
- return NextResponse.json(
64
- { error: "Rate limit exceeded", valid: false },
65
- { status: 429 }
66
- );
67
- }
68
-
69
- // Perform server-side validation
70
- const validation = await performServerValidation();
71
-
72
- // Return validation result
73
- // Client will read from cookies, not from this response
74
- return NextResponse.json({
75
- valid: validation.valid,
76
- hasProAccess: validation.hasProAccess,
77
- cached: validation.cached,
78
- });
79
- } catch (error) {
80
- console.error("[API] Validation error:", error);
81
- return NextResponse.json(
82
- { error: "Internal server error", valid: false },
83
- { status: 500 }
84
- );
85
- }
86
- }
87
-
88
- /**
89
- * POST /api/moonui/validate-pro
90
- * Validates a provided token
91
- */
92
- export async function POST(request: NextRequest) {
93
- try {
94
- const body = await request.json();
95
- const { token } = body;
96
-
97
- if (!token) {
98
- return NextResponse.json(
99
- { error: "Token required", valid: false },
100
- { status: 400 }
101
- );
102
- }
103
-
104
- // Generate device fingerprint
105
- const deviceId = await generateServerDeviceFingerprint();
106
-
107
- // Check rate limit
108
- if (!checkRateLimit(deviceId)) {
109
- return NextResponse.json(
110
- { error: "Rate limit exceeded", valid: false },
111
- { status: 429 }
112
- );
113
- }
114
-
115
- // Import server validation utilities
116
- const { validateWithMoonUIServer } = await import(
117
- "@moontra/moonui-pro/server"
118
- );
119
-
120
- // Validate token with MoonUI server
121
- const result = await validateWithMoonUIServer(token, deviceId);
122
-
123
- // If valid, set cookies for future requests
124
- if (result.valid) {
125
- await setValidationInCookies(result);
126
- }
127
-
128
- return NextResponse.json(result);
129
- } catch (error) {
130
- console.error("[API] Validation error:", error);
131
- return NextResponse.json(
132
- { error: "Internal server error", valid: false },
133
- { status: 500 }
134
- );
135
- }
136
- }
137
-
138
- /**
139
- * DELETE /api/moonui/validate-pro
140
- * Clears validation session
141
- */
142
- export async function DELETE(request: NextRequest) {
143
- try {
144
- await clearValidationCookies();
145
-
146
- return NextResponse.json({
147
- success: true,
148
- message: "Validation cleared",
149
- });
150
- } catch (error) {
151
- console.error("[API] Clear validation error:", error);
152
- return NextResponse.json(
153
- { error: "Failed to clear validation" },
154
- { status: 500 }
155
- );
156
- }
157
- }
@@ -1,475 +0,0 @@
1
- /**
2
- * MoonUI Pro - Server-side License Validation Route with Enhanced Security
3
- *
4
- * This route handles license validation on the server to prevent browser API calls.
5
- * Copy this file to: app/api/moonui/validate-pro/route.ts (App Router)
6
- * Or: pages/api/moonui/validate-pro.ts (Pages Router)
7
- *
8
- * Required environment variables:
9
- * - MOONUI_LICENSE_KEY: Your MoonUI Pro license key
10
- * - MOONUI_ENCRYPTION_KEY (optional): Custom encryption key for cookies
11
- * - MOONUI_SECURITY_HASH (auto-generated): Security checksum for validation
12
- *
13
- * SECURITY WARNING: Do not modify the validation logic.
14
- * Any tampering will be detected and reported.
15
- */
16
-
17
- import { NextRequest, NextResponse } from 'next/server';
18
- import { cookies, headers } from 'next/headers';
19
- import crypto from 'crypto';
20
- import os from 'os';
21
- import { execSync } from 'child_process';
22
-
23
- // Security checksum - DO NOT MODIFY
24
- const SECURITY_CHECKSUM = process.env.MOONUI_SECURITY_HASH ||
25
- crypto.createHash('sha256')
26
- .update(`moonui-pro-${process.env.MOONUI_LICENSE_KEY || 'default'}-validation`)
27
- .digest('hex');
28
-
29
- // Cache configuration
30
- const CACHE_DURATION = process.env.NODE_ENV === 'production'
31
- ? 24 * 60 * 60 * 1000 // 24 hours in production
32
- : 60 * 60 * 1000; // 1 hour in development
33
-
34
- // Rate limiting
35
- const rateLimitCache = new Map<string, { count: number; resetAt: number }>();
36
-
37
- // In-memory validation cache
38
- const validationCache = new Map<string, {
39
- valid: boolean;
40
- hasProAccess: boolean;
41
- timestamp: number;
42
- expiresAt: number;
43
- }>();
44
-
45
- /**
46
- * Get MAC address for hardware fingerprinting
47
- */
48
- function getMacAddress(): string {
49
- try {
50
- const platform = os.platform();
51
- let command: string;
52
-
53
- switch (platform) {
54
- case 'darwin':
55
- command = "ifconfig | grep ether | head -1 | awk '{print $2}'";
56
- break;
57
- case 'linux':
58
- command = "ip link show | grep ether | head -1 | awk '{print $2}'";
59
- break;
60
- case 'win32':
61
- command = 'getmac /NH /FO csv | findstr /r "^"';
62
- break;
63
- default:
64
- return 'unknown-mac';
65
- }
66
-
67
- const result = execSync(command, { encoding: 'utf8' }).trim();
68
- const match = result.match(/([a-f0-9:]+)/i);
69
-
70
- if (match && match[1]) {
71
- return match[1].replace(/[:-]/g, '').toLowerCase();
72
- }
73
-
74
- // Fallback to network interfaces
75
- const interfaces = os.networkInterfaces();
76
- for (const name in interfaces) {
77
- const iface = interfaces[name];
78
- if (iface) {
79
- for (const entry of iface) {
80
- if (entry.mac && entry.mac !== '00:00:00:00:00:00') {
81
- return entry.mac.replace(/[:-]/g, '').toLowerCase();
82
- }
83
- }
84
- }
85
- }
86
- return 'fallback-mac';
87
- } catch (error) {
88
- console.error('[Hardware] Error getting MAC:', error);
89
- return 'error-mac';
90
- }
91
- }
92
-
93
- /**
94
- * Generate hardware-based device fingerprint
95
- * Format: hw-{platform}-{macHash}-{cpuHash}
96
- */
97
- function generateHardwareFingerprint(): string {
98
- const platform = os.platform();
99
- const macAddress = getMacAddress();
100
- const cpuCount = os.cpus().length;
101
- const totalMem = Math.round(os.totalmem() / (1024 * 1024 * 1024)); // GB
102
- const hostname = os.hostname();
103
-
104
- // Create hashes
105
- const macHash = crypto.createHash('sha256')
106
- .update(macAddress)
107
- .digest('hex')
108
- .substring(0, 8);
109
-
110
- const systemHash = crypto.createHash('sha256')
111
- .update(`${cpuCount}:${totalMem}:${hostname}`)
112
- .digest('hex')
113
- .substring(0, 6);
114
-
115
- return `hw-${platform}-${macHash}-${systemHash}`;
116
- }
117
-
118
- /**
119
- * Generate a device fingerprint from request headers
120
- * Combines hardware fingerprint with browser characteristics
121
- */
122
- async function getDeviceFingerprint(request: NextRequest): Promise<string> {
123
- // In development with CLI auth, generate hardware-based fingerprint
124
- if (process.env.NODE_ENV === 'development') {
125
- // Use hardware fingerprint for maximum security
126
- const hardwareId = generateHardwareFingerprint();
127
-
128
- // If CLI device ID is set, validate it matches hardware
129
- if (process.env.NEXT_PUBLIC_MOONUI_DEVICE_ID) {
130
- const cliDeviceId = process.env.NEXT_PUBLIC_MOONUI_DEVICE_ID;
131
-
132
- // For backward compatibility, accept both old and new format
133
- if (cliDeviceId.startsWith('hw-')) {
134
- return cliDeviceId; // New hardware-based format
135
- } else {
136
- console.log('[MoonUI] Migrating to hardware-based device ID');
137
- return hardwareId; // Use new hardware ID
138
- }
139
- }
140
-
141
- return hardwareId;
142
- }
143
-
144
- // In production, use hardware fingerprint
145
- return generateHardwareFingerprint();
146
- }
147
-
148
- /**
149
- * Check rate limiting
150
- */
151
- function checkRateLimit(identifier: string): boolean {
152
- const now = Date.now();
153
- const limit = rateLimitCache.get(identifier);
154
-
155
- if (!limit || limit.resetAt < now) {
156
- rateLimitCache.set(identifier, {
157
- count: 1,
158
- resetAt: now + 60 * 1000, // Reset after 1 minute
159
- });
160
- return true;
161
- }
162
-
163
- if (limit.count >= 10) { // Max 10 requests per minute
164
- return false;
165
- }
166
-
167
- limit.count++;
168
- return true;
169
- }
170
-
171
- /**
172
- * Validate license with MoonUI server (server-to-server)
173
- */
174
- async function validateWithMoonUIServer(
175
- token: string,
176
- deviceId: string
177
- ): Promise<{ valid: boolean; hasProAccess: boolean; plan?: string }> {
178
- // Development mode with CLI authentication
179
- if (process.env.NODE_ENV === 'development') {
180
- // Check for CLI dev tokens
181
- const devToken = process.env.NEXT_PUBLIC_MOONUI_DEV_TOKEN;
182
- const devDeviceId = process.env.NEXT_PUBLIC_MOONUI_DEVICE_ID;
183
-
184
- console.log('[MoonUI Dev Auth] Checking CLI authentication:');
185
- console.log('[MoonUI Dev Auth] Device IDs match:', devDeviceId === deviceId);
186
-
187
- // STRICT DEVICE ID VALIDATION - Prevent token sharing
188
- if (devToken && devDeviceId && devDeviceId === deviceId) {
189
- try {
190
- // Decode the dev token
191
- const decoded = JSON.parse(Buffer.from(devToken, 'base64').toString());
192
-
193
- // Verify token structure and session
194
- if (!decoded.deviceId || !decoded.session || !decoded.security) {
195
- console.error('[MoonUI Security] Invalid token structure');
196
- return { valid: false, hasProAccess: false };
197
- }
198
-
199
- // Verify device ID in token matches
200
- if (decoded.deviceId !== devDeviceId) {
201
- console.error('[MoonUI Security] Token device ID mismatch');
202
- return { valid: false, hasProAccess: false };
203
- }
204
-
205
- // Verify session hasn't expired
206
- if (decoded.session?.expiresAt && decoded.session.expiresAt < Date.now()) {
207
- console.error('[MoonUI Security] Token session expired');
208
- return { valid: false, hasProAccess: false };
209
- }
210
-
211
- console.log('[MoonUI Dev Auth] Token validated successfully');
212
- console.log('[MoonUI Dev Auth] User plan:', decoded.user?.plan);
213
-
214
- if (decoded.user?.plan === 'pro_lifetime' || decoded.user?.hasProAccess) {
215
- console.log('[MoonUI Dev Auth] Pro access granted via CLI token');
216
- return {
217
- valid: true,
218
- hasProAccess: true,
219
- plan: decoded.user?.plan || 'lifetime'
220
- };
221
- }
222
- } catch (e) {
223
- console.error('[MoonUI Security] Error parsing dev token:', e);
224
- return { valid: false, hasProAccess: false };
225
- }
226
- } else if (devToken && !devDeviceId) {
227
- console.warn('[MoonUI Security] Token found but no device ID - possible token sharing attempt');
228
- return { valid: false, hasProAccess: false };
229
- } else if (devDeviceId !== deviceId) {
230
- console.warn('[MoonUI Security] Device ID mismatch - token not valid for this device');
231
- console.warn('[MoonUI Security] This token is locked to device:', devDeviceId);
232
- console.warn('[MoonUI Security] Current device:', deviceId);
233
- return { valid: false, hasProAccess: false };
234
- }
235
- }
236
-
237
- // Production validation with license key
238
- const licenseKey = process.env.MOONUI_LICENSE_KEY;
239
-
240
- if (!licenseKey) {
241
- console.error('[MoonUI] No license key configured');
242
- return { valid: false, hasProAccess: false };
243
- }
244
-
245
- try {
246
- const response = await fetch('https://api.moonui.dev/v1/license/validate', {
247
- method: 'POST',
248
- headers: {
249
- 'Content-Type': 'application/json',
250
- 'Authorization': `Bearer ${licenseKey}`,
251
- 'X-Device-ID': deviceId,
252
- },
253
- body: JSON.stringify({
254
- token: licenseKey,
255
- deviceId,
256
- domain: process.env.NEXT_PUBLIC_DOMAIN || 'localhost',
257
- timestamp: Date.now(),
258
- }),
259
- signal: AbortSignal.timeout(10000), // 10 second timeout
260
- });
261
-
262
- if (!response.ok) {
263
- console.error('[MoonUI] License validation failed:', response.status);
264
- return { valid: false, hasProAccess: false };
265
- }
266
-
267
- const data = await response.json();
268
-
269
- return {
270
- valid: data.valid,
271
- hasProAccess: data.valid && (
272
- data.user?.hasLifetimeAccess ||
273
- data.user?.features?.includes('pro_components') ||
274
- data.plan === 'pro_lifetime' ||
275
- false
276
- ),
277
- plan: data.user?.plan || data.plan,
278
- };
279
-
280
- } catch (error) {
281
- console.error('[MoonUI] Error validating license:', error);
282
- return { valid: false, hasProAccess: false };
283
- }
284
- }
285
-
286
- /**
287
- * Verify request integrity
288
- */
289
- function verifyRequestIntegrity(request: NextRequest): boolean {
290
- // Check for suspicious patterns
291
- const url = new URL(request.url);
292
-
293
- // Reject if trying to bypass with query params
294
- if (url.searchParams.has('bypass') ||
295
- url.searchParams.has('force') ||
296
- url.searchParams.has('admin')) {
297
- console.warn('[MoonUI Security] Suspicious query params detected');
298
- return false;
299
- }
300
-
301
- // Check request headers for tampering
302
- const suspiciousHeaders = [
303
- 'x-moonui-bypass',
304
- 'x-force-pro',
305
- 'x-admin-override',
306
- 'x-moonui-device-override',
307
- 'x-moonui-token-override'
308
- ];
309
-
310
- for (const header of suspiciousHeaders) {
311
- if (request.headers.has(header)) {
312
- console.warn(`[MoonUI Security] Suspicious header detected: ${header}`);
313
- return false;
314
- }
315
- }
316
-
317
- // Check for proxy/VPN indicators
318
- const proxyHeaders = [
319
- 'x-proxy-connection',
320
- 'x-forwarded-server',
321
- 'x-originating-ip',
322
- 'x-remote-ip'
323
- ];
324
-
325
- const hasProxy = proxyHeaders.some(header => request.headers.has(header));
326
- if (hasProxy) {
327
- console.warn('[MoonUI Security] Proxy/VPN detected - additional validation required');
328
- }
329
-
330
- return true;
331
- }
332
-
333
- /**
334
- * Generate validation signature for response
335
- */
336
- function generateValidationSignature(data: any): string {
337
- const payload = JSON.stringify({
338
- ...data,
339
- timestamp: Date.now(),
340
- checksum: SECURITY_CHECKSUM,
341
- });
342
-
343
- return crypto
344
- .createHash('sha256')
345
- .update(payload)
346
- .digest('hex')
347
- .substring(0, 16);
348
- }
349
-
350
- /**
351
- * Main API route handler with enhanced security
352
- */
353
- export async function GET(request: NextRequest) {
354
- try {
355
- // Security check
356
- if (!verifyRequestIntegrity(request)) {
357
- return NextResponse.json(
358
- {
359
- error: 'Invalid request',
360
- valid: false,
361
- hasProAccess: false
362
- },
363
- { status: 403 }
364
- );
365
- }
366
-
367
- // Generate device fingerprint
368
- const deviceId = await getDeviceFingerprint(request);
369
-
370
- // Check rate limiting
371
- if (!checkRateLimit(deviceId)) {
372
- return NextResponse.json(
373
- { error: 'Rate limit exceeded', valid: false },
374
- { status: 429 }
375
- );
376
- }
377
-
378
- // Check in-memory cache first
379
- const cacheKey = `validation:${deviceId}`;
380
- const cached = validationCache.get(cacheKey);
381
-
382
- if (cached && cached.expiresAt > Date.now()) {
383
- console.log('[MoonUI] Using cached validation result');
384
-
385
- return NextResponse.json({
386
- valid: cached.valid,
387
- hasProAccess: cached.hasProAccess,
388
- cached: true,
389
- });
390
- }
391
-
392
- // Get license token
393
- const licenseToken = process.env.MOONUI_LICENSE_KEY ||
394
- process.env.NEXT_PUBLIC_MOONUI_DEV_TOKEN ||
395
- '';
396
-
397
- // Validate with MoonUI server
398
- const validation = await validateWithMoonUIServer(licenseToken, deviceId);
399
-
400
- // Cache the result
401
- const expiresAt = Date.now() + CACHE_DURATION;
402
- validationCache.set(cacheKey, {
403
- ...validation,
404
- timestamp: Date.now(),
405
- expiresAt,
406
- });
407
-
408
- // Set status cookie for client (readable)
409
- const cookieStore = await cookies();
410
- cookieStore.set('moonui_pro_status', JSON.stringify({
411
- valid: validation.valid,
412
- hasProAccess: validation.hasProAccess,
413
- timestamp: Date.now(),
414
- }), {
415
- httpOnly: false, // Client needs to read this
416
- secure: process.env.NODE_ENV === 'production',
417
- sameSite: 'lax',
418
- maxAge: CACHE_DURATION / 1000, // Convert to seconds
419
- });
420
-
421
- // Prepare response data
422
- const responseData = {
423
- valid: validation.valid,
424
- hasProAccess: validation.hasProAccess,
425
- isAuthenticated: validation.valid,
426
- subscriptionPlan: validation.hasProAccess ? 'lifetime' : 'free',
427
- subscription: {
428
- status: validation.hasProAccess ? 'active' : 'inactive',
429
- plan: validation.hasProAccess ? 'lifetime' : 'free',
430
- },
431
- _signature: generateValidationSignature({
432
- valid: validation.valid,
433
- hasProAccess: validation.hasProAccess,
434
- deviceId: deviceId,
435
- }),
436
- };
437
-
438
- // Log security events
439
- if (validation.hasProAccess) {
440
- console.log(`[MoonUI Security] Pro access granted for device: ${deviceId.substring(0, 8)}...`);
441
- }
442
-
443
- return NextResponse.json(responseData);
444
-
445
- } catch (error) {
446
- console.error('[MoonUI] Validation error:', error);
447
-
448
- return NextResponse.json(
449
- {
450
- error: 'Internal server error',
451
- valid: false,
452
- hasProAccess: false,
453
- },
454
- { status: 500 }
455
- );
456
- }
457
- }
458
-
459
- // Support for Pages Router
460
- export async function handler(req: any, res: any) {
461
- if (req.method !== 'GET') {
462
- return res.status(405).json({ error: 'Method not allowed' });
463
- }
464
-
465
- // Convert to NextRequest for consistent handling
466
- const url = new URL(req.url!, `http://${req.headers.host}`);
467
- const request = new NextRequest(url, {
468
- headers: req.headers,
469
- });
470
-
471
- const response = await GET(request);
472
- const data = await response.json();
473
-
474
- return res.status(response.status).json(data);
475
- }