@nordsym/apiclaw 1.0.0 → 1.1.0
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/AGENTS.md +74 -0
- package/HEARTBEAT.md +4 -0
- package/IDENTITY.md +22 -0
- package/README.md +197 -202
- package/SOUL.md +36 -0
- package/STATUS.md +237 -0
- package/TOOLS.md +36 -0
- package/USER.md +17 -0
- package/{backend/convex → convex}/_generated/api.d.ts +6 -6
- package/convex/credits.ts +211 -0
- package/convex/http.ts +490 -0
- package/convex/providers.ts +516 -0
- package/convex/purchases.ts +183 -0
- package/convex/schema.ts +180 -0
- package/convex.json +3 -0
- package/dist/credentials.d.ts +19 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +158 -0
- package/dist/credentials.js.map +1 -0
- package/dist/credits.d.ts +14 -11
- package/dist/credits.d.ts.map +1 -1
- package/dist/credits.js +151 -99
- package/dist/credits.js.map +1 -1
- package/dist/discovery.d.ts +7 -16
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +33 -40
- package/dist/discovery.js.map +1 -1
- package/dist/execute.d.ts +19 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +285 -0
- package/dist/execute.js.map +1 -0
- package/dist/index.js +106 -30
- package/dist/index.js.map +1 -1
- package/dist/proxy.d.ts +6 -0
- package/dist/proxy.d.ts.map +1 -0
- package/dist/proxy.js +19 -0
- package/dist/proxy.js.map +1 -0
- package/dist/registry/apis.json +95362 -202
- package/dist/registry/apis_expanded.json +100853 -0
- package/dist/stripe.d.ts +68 -0
- package/dist/stripe.d.ts.map +1 -0
- package/dist/stripe.js +196 -0
- package/dist/stripe.js.map +1 -0
- package/dist/test.d.ts +3 -2
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +105 -75
- package/dist/test.js.map +1 -1
- package/dist/types.d.ts +0 -28
- package/dist/types.d.ts.map +1 -1
- package/dist/webhook.d.ts +2 -0
- package/dist/webhook.d.ts.map +1 -0
- package/dist/webhook.js +90 -0
- package/dist/webhook.js.map +1 -0
- package/landing/DESIGN.md +343 -0
- package/landing/package-lock.json +1190 -40
- package/landing/package.json +5 -2
- package/landing/public/android-chrome-192x192.png +0 -0
- package/landing/public/android-chrome-512x512.png +0 -0
- package/landing/public/apple-touch-icon.png +0 -0
- package/landing/public/demo.gif +0 -0
- package/landing/public/demo.mp4 +0 -0
- package/landing/public/favicon-16x16.png +0 -0
- package/landing/public/favicon-32x32.png +0 -0
- package/landing/public/favicon.ico +0 -0
- package/landing/public/favicon.svg +3 -0
- package/landing/public/icon.svg +47 -0
- package/landing/public/logo-mono.svg +37 -0
- package/landing/public/logo-simple.svg +45 -0
- package/landing/public/logo.svg +84 -0
- package/landing/public/og-image.png +0 -0
- package/landing/public/og-template.html +184 -0
- package/landing/public/site.webmanifest +31 -0
- package/landing/scripts/generate-assets.js +284 -0
- package/landing/scripts/generate-pngs.js +48 -0
- package/landing/scripts/generate-stats.js +42 -0
- package/landing/src/app/admin/page.tsx +348 -0
- package/landing/src/app/api/auth/magic-link/route.ts +73 -0
- package/landing/src/app/api/auth/session/route.ts +38 -0
- package/landing/src/app/api/auth/verify/route.ts +43 -0
- package/landing/src/app/api/og/route.tsx +74 -0
- package/landing/src/app/globals.css +439 -100
- package/landing/src/app/layout.tsx +37 -9
- package/landing/src/app/page.tsx +640 -552
- package/landing/src/app/providers/dashboard/login/page.tsx +176 -0
- package/landing/src/app/providers/dashboard/page.tsx +589 -0
- package/landing/src/app/providers/dashboard/verify/page.tsx +106 -0
- package/landing/src/app/providers/layout.tsx +14 -0
- package/landing/src/app/providers/page.tsx +402 -0
- package/landing/src/app/providers/register/page.tsx +670 -0
- package/landing/src/components/ProviderDashboard.tsx +794 -0
- package/landing/src/hooks/useDashboardData.ts +99 -0
- package/landing/src/lib/apis.json +116054 -0
- package/landing/src/lib/convex-client.ts +106 -0
- package/landing/src/lib/mock-data.ts +285 -0
- package/landing/src/lib/stats.json +6 -0
- package/landing/tailwind.config.ts +12 -11
- package/landing/tsconfig.tsbuildinfo +1 -0
- package/package.json +21 -20
- package/scripts/SYMBOT-FIX.md +238 -0
- package/scripts/demo-simulation.py +177 -0
- package/scripts/expand-more.py +502 -0
- package/scripts/expand-registry.py +434 -0
- package/scripts/history-sanitizer.ts +272 -0
- package/scripts/mass-scrape.py +1308 -0
- package/scripts/sync-and-deploy.sh +36 -0
- package/src/credentials.ts +177 -0
- package/src/credits.ts +190 -122
- package/src/discovery.ts +45 -58
- package/src/execute.ts +350 -0
- package/src/index.ts +113 -31
- package/src/proxy.ts +24 -0
- package/src/registry/apis.json +95362 -202
- package/src/registry/apis_expanded.json +100853 -0
- package/src/stripe.ts +243 -0
- package/src/test.ts +127 -89
- package/src/types.ts +0 -34
- package/src/webhook.ts +107 -0
- package/.github/ISSUE_TEMPLATE/add-api.yml +0 -123
- package/BRIEFING.md +0 -30
- package/backend/convex/apiKeys.ts +0 -75
- package/backend/convex/purchases.ts +0 -74
- package/backend/convex/schema.ts +0 -45
- package/backend/convex/transactions.ts +0 -57
- package/backend/convex/users.ts +0 -94
- package/backend/package-lock.json +0 -521
- package/backend/package.json +0 -15
- package/dist/registry/parse_apis.py +0 -146
- package/dist/revenuecat.d.ts +0 -61
- package/dist/revenuecat.d.ts.map +0 -1
- package/dist/revenuecat.js +0 -166
- package/dist/revenuecat.js.map +0 -1
- package/dist/webhooks/revenuecat.d.ts +0 -48
- package/dist/webhooks/revenuecat.d.ts.map +0 -1
- package/dist/webhooks/revenuecat.js +0 -119
- package/dist/webhooks/revenuecat.js.map +0 -1
- package/docs/revenuecat-setup.md +0 -89
- package/landing/src/app/api/keys/route.ts +0 -71
- package/landing/src/app/api/log/route.ts +0 -37
- package/landing/src/app/api/stats/route.ts +0 -37
- package/landing/src/app/page.tsx.bak +0 -567
- package/landing/src/components/AddKeyModal.tsx +0 -159
- package/newsletter-template.html +0 -71
- package/outreach/OUTREACH-SYSTEM.md +0 -211
- package/outreach/email-template.html +0 -179
- package/outreach/targets.md +0 -133
- package/src/registry/parse_apis.py +0 -146
- package/src/revenuecat.ts +0 -239
- package/src/webhooks/revenuecat.ts +0 -187
- /package/{backend/convex → convex}/README.md +0 -0
- /package/{backend/convex → convex}/_generated/api.js +0 -0
- /package/{backend/convex → convex}/_generated/dataModel.d.ts +0 -0
- /package/{backend/convex → convex}/_generated/server.d.ts +0 -0
- /package/{backend/convex → convex}/_generated/server.js +0 -0
- /package/{backend/convex → convex}/tsconfig.json +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Simple Convex HTTP client for the dashboard
|
|
2
|
+
|
|
3
|
+
const CONVEX_URL = process.env.NEXT_PUBLIC_CONVEX_URL || "https://brilliant-puffin-712.eu-west-1.convex.cloud";
|
|
4
|
+
|
|
5
|
+
export async function convexQuery<T>(path: string, args: Record<string, unknown>): Promise<T> {
|
|
6
|
+
const response = await fetch(`${CONVEX_URL}/api/query`, {
|
|
7
|
+
method: "POST",
|
|
8
|
+
headers: { "Content-Type": "application/json" },
|
|
9
|
+
body: JSON.stringify({ path, args }),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
if (!response.ok) {
|
|
13
|
+
throw new Error(`Convex query failed: ${response.statusText}`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return response.json();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function convexMutation<T>(path: string, args: Record<string, unknown>): Promise<T> {
|
|
20
|
+
const response = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: { "Content-Type": "application/json" },
|
|
23
|
+
body: JSON.stringify({ path, args }),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
throw new Error(`Convex mutation failed: ${response.statusText}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return response.json();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Provider dashboard types
|
|
34
|
+
export interface ProviderSession {
|
|
35
|
+
providerId: string;
|
|
36
|
+
email: string;
|
|
37
|
+
name: string;
|
|
38
|
+
stripeOnboardingComplete?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ProviderAPI {
|
|
42
|
+
_id: string;
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
category: string;
|
|
46
|
+
status: string;
|
|
47
|
+
openApiUrl?: string;
|
|
48
|
+
docsUrl?: string;
|
|
49
|
+
pricingModel: string;
|
|
50
|
+
pricingNotes?: string;
|
|
51
|
+
discoveryCount?: number;
|
|
52
|
+
createdAt: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface DailyStats {
|
|
56
|
+
date: string;
|
|
57
|
+
calls: number;
|
|
58
|
+
revenue: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface Analytics {
|
|
62
|
+
totalCalls: number;
|
|
63
|
+
uniqueAgents: number;
|
|
64
|
+
totalRevenue: number;
|
|
65
|
+
callsByDay: DailyStats[];
|
|
66
|
+
topAgents: { agentId: string; calls: number }[];
|
|
67
|
+
callsByRegion: Record<string, number>;
|
|
68
|
+
apis: { id: string; name: string; calls: number; status: string }[];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface Earnings {
|
|
72
|
+
pendingAmount: number;
|
|
73
|
+
totalEarned: number;
|
|
74
|
+
totalPaidOut: number;
|
|
75
|
+
stripeConnected: boolean;
|
|
76
|
+
stripeOnboardingComplete: boolean;
|
|
77
|
+
payouts: {
|
|
78
|
+
id: string;
|
|
79
|
+
amount: number;
|
|
80
|
+
status: string;
|
|
81
|
+
periodStart: number;
|
|
82
|
+
periodEnd: number;
|
|
83
|
+
createdAt: number;
|
|
84
|
+
completedAt?: number;
|
|
85
|
+
}[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Get session
|
|
89
|
+
export async function getSession(token: string): Promise<ProviderSession | null> {
|
|
90
|
+
return convexQuery("providers:getSession", { token });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Get provider APIs
|
|
94
|
+
export async function getProviderAPIs(providerId: string): Promise<ProviderAPI[]> {
|
|
95
|
+
return convexQuery("providers:getProviderAPIs", { providerId });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Get analytics
|
|
99
|
+
export async function getAnalytics(token: string, period?: string): Promise<Analytics | null> {
|
|
100
|
+
return convexQuery("providers:getAnalytics", { token, period });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Get earnings
|
|
104
|
+
export async function getEarnings(token: string): Promise<Earnings | null> {
|
|
105
|
+
return convexQuery("providers:getEarnings", { token });
|
|
106
|
+
}
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// Mock data for the provider dashboard demo
|
|
2
|
+
// This simulates what would come from Convex in production
|
|
3
|
+
|
|
4
|
+
export interface Provider {
|
|
5
|
+
id: string;
|
|
6
|
+
email: string;
|
|
7
|
+
name: string;
|
|
8
|
+
company?: string;
|
|
9
|
+
avatarUrl?: string;
|
|
10
|
+
stripeOnboardingComplete: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Api {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
category: string;
|
|
18
|
+
icon: string;
|
|
19
|
+
baseUrl: string;
|
|
20
|
+
docsUrl?: string;
|
|
21
|
+
authType: string;
|
|
22
|
+
pricingModel: string;
|
|
23
|
+
pricePerCall?: number;
|
|
24
|
+
monthlyPrice?: number;
|
|
25
|
+
rateLimitPerMinute?: number;
|
|
26
|
+
regions?: string[];
|
|
27
|
+
tags?: string[];
|
|
28
|
+
status: "active" | "paused";
|
|
29
|
+
calls: number;
|
|
30
|
+
createdAt: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface DailyStats {
|
|
34
|
+
date: string;
|
|
35
|
+
calls: number;
|
|
36
|
+
revenue: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface TopAgent {
|
|
40
|
+
agentId: string;
|
|
41
|
+
calls: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface Analytics {
|
|
45
|
+
totalCalls: number;
|
|
46
|
+
totalCallsWeek: number;
|
|
47
|
+
totalCallsMonth: number;
|
|
48
|
+
uniqueAgents: number;
|
|
49
|
+
totalRevenue: number;
|
|
50
|
+
revenueWeek: number;
|
|
51
|
+
revenueMonth: number;
|
|
52
|
+
callsByDay: DailyStats[];
|
|
53
|
+
topAgents: TopAgent[];
|
|
54
|
+
callsByRegion: Record<string, number>;
|
|
55
|
+
apis: { id: string; name: string; calls: number; status: string }[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface Payout {
|
|
59
|
+
id: string;
|
|
60
|
+
amount: number;
|
|
61
|
+
status: "pending" | "processing" | "completed" | "failed";
|
|
62
|
+
periodStart: number;
|
|
63
|
+
periodEnd: number;
|
|
64
|
+
createdAt: number;
|
|
65
|
+
completedAt?: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface Earnings {
|
|
69
|
+
pendingAmount: number;
|
|
70
|
+
totalEarned: number;
|
|
71
|
+
totalPaidOut: number;
|
|
72
|
+
stripeConnected: boolean;
|
|
73
|
+
stripeOnboardingComplete: boolean;
|
|
74
|
+
payouts: Payout[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Generate realistic mock data
|
|
78
|
+
function generateCallsByDay(days: number): DailyStats[] {
|
|
79
|
+
const result: DailyStats[] = [];
|
|
80
|
+
const now = new Date();
|
|
81
|
+
|
|
82
|
+
for (let i = days - 1; i >= 0; i--) {
|
|
83
|
+
const date = new Date(now);
|
|
84
|
+
date.setDate(date.getDate() - i);
|
|
85
|
+
|
|
86
|
+
// Growth trend with some variance and weekend dips
|
|
87
|
+
const dayOfWeek = date.getDay();
|
|
88
|
+
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
|
|
89
|
+
const baseCalls = 150 + (days - i) * 3.5;
|
|
90
|
+
const variance = Math.random() * 60 - 30;
|
|
91
|
+
const weekendFactor = isWeekend ? 0.6 : 1;
|
|
92
|
+
const calls = Math.max(20, Math.round((baseCalls + variance) * weekendFactor));
|
|
93
|
+
const revenue = calls * 0.00085; // ~$0.00085 per call average
|
|
94
|
+
|
|
95
|
+
result.push({
|
|
96
|
+
date: date.toISOString().split("T")[0],
|
|
97
|
+
calls,
|
|
98
|
+
revenue: Math.round(revenue * 100) / 100,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function getMockProvider(): Provider {
|
|
106
|
+
return {
|
|
107
|
+
id: "provider_demo_123",
|
|
108
|
+
email: "demo@example.com",
|
|
109
|
+
name: "Demo Provider",
|
|
110
|
+
company: "WeatherTech Inc.",
|
|
111
|
+
stripeOnboardingComplete: true,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function getMockApis(): Api[] {
|
|
116
|
+
return [
|
|
117
|
+
{
|
|
118
|
+
id: "api_weather_001",
|
|
119
|
+
name: "WeatherAPI Pro",
|
|
120
|
+
description: "Real-time weather data for 200+ countries. Includes forecasts, historical data, and severe weather alerts.",
|
|
121
|
+
category: "Weather",
|
|
122
|
+
icon: "🌤️",
|
|
123
|
+
baseUrl: "https://api.weatherpro.example.com",
|
|
124
|
+
docsUrl: "https://docs.weatherpro.example.com",
|
|
125
|
+
authType: "api_key",
|
|
126
|
+
pricingModel: "per_call",
|
|
127
|
+
pricePerCall: 0.1, // cents
|
|
128
|
+
rateLimitPerMinute: 1000,
|
|
129
|
+
regions: ["US", "EU", "APAC"],
|
|
130
|
+
tags: ["weather", "forecast", "climate", "alerts"],
|
|
131
|
+
status: "active",
|
|
132
|
+
calls: 8247,
|
|
133
|
+
createdAt: Date.now() - 60 * 24 * 60 * 60 * 1000,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: "api_geo_002",
|
|
137
|
+
name: "GeoLocator API",
|
|
138
|
+
description: "IP geolocation and address lookup. High accuracy with ISP and organization data.",
|
|
139
|
+
category: "Location",
|
|
140
|
+
icon: "📍",
|
|
141
|
+
baseUrl: "https://api.geolocator.example.com",
|
|
142
|
+
docsUrl: "https://docs.geolocator.example.com",
|
|
143
|
+
authType: "bearer",
|
|
144
|
+
pricingModel: "per_call",
|
|
145
|
+
pricePerCall: 0.05,
|
|
146
|
+
rateLimitPerMinute: 500,
|
|
147
|
+
regions: ["US", "EU"],
|
|
148
|
+
tags: ["geo", "location", "ip", "lookup"],
|
|
149
|
+
status: "active",
|
|
150
|
+
calls: 4521,
|
|
151
|
+
createdAt: Date.now() - 45 * 24 * 60 * 60 * 1000,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: "api_translate_003",
|
|
155
|
+
name: "TranslateNow API",
|
|
156
|
+
description: "Neural machine translation for 100+ languages. Includes language detection.",
|
|
157
|
+
category: "Translation",
|
|
158
|
+
icon: "🌐",
|
|
159
|
+
baseUrl: "https://api.translatenow.example.com",
|
|
160
|
+
authType: "api_key",
|
|
161
|
+
pricingModel: "per_call",
|
|
162
|
+
pricePerCall: 0.2,
|
|
163
|
+
rateLimitPerMinute: 200,
|
|
164
|
+
regions: ["US", "EU", "APAC"],
|
|
165
|
+
tags: ["translation", "language", "nlp"],
|
|
166
|
+
status: "paused",
|
|
167
|
+
calls: 1832,
|
|
168
|
+
createdAt: Date.now() - 30 * 24 * 60 * 60 * 1000,
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function getMockAnalytics(): Analytics {
|
|
174
|
+
const callsByDay = generateCallsByDay(60);
|
|
175
|
+
const last7Days = callsByDay.slice(-7);
|
|
176
|
+
const last30Days = callsByDay.slice(-30);
|
|
177
|
+
|
|
178
|
+
const totalCalls = callsByDay.reduce((sum, d) => sum + d.calls, 0);
|
|
179
|
+
const totalCallsWeek = last7Days.reduce((sum, d) => sum + d.calls, 0);
|
|
180
|
+
const totalCallsMonth = last30Days.reduce((sum, d) => sum + d.calls, 0);
|
|
181
|
+
|
|
182
|
+
const totalRevenue = callsByDay.reduce((sum, d) => sum + d.revenue, 0);
|
|
183
|
+
const revenueWeek = last7Days.reduce((sum, d) => sum + d.revenue, 0);
|
|
184
|
+
const revenueMonth = last30Days.reduce((sum, d) => sum + d.revenue, 0);
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
totalCalls,
|
|
188
|
+
totalCallsWeek,
|
|
189
|
+
totalCallsMonth,
|
|
190
|
+
uniqueAgents: 23,
|
|
191
|
+
totalRevenue: Math.round(totalRevenue * 100) / 100,
|
|
192
|
+
revenueWeek: Math.round(revenueWeek * 100) / 100,
|
|
193
|
+
revenueMonth: Math.round(revenueMonth * 100) / 100,
|
|
194
|
+
callsByDay,
|
|
195
|
+
topAgents: [
|
|
196
|
+
{ agentId: "agent_claude_prod", calls: 3421 },
|
|
197
|
+
{ agentId: "agent_gpt4_beta", calls: 2847 },
|
|
198
|
+
{ agentId: "agent_custom_001", calls: 1923 },
|
|
199
|
+
{ agentId: "agent_automation_x", calls: 1456 },
|
|
200
|
+
{ agentId: "agent_databot", calls: 987 },
|
|
201
|
+
{ agentId: "agent_insights_ai", calls: 743 },
|
|
202
|
+
{ agentId: "agent_pipeline_v2", calls: 521 },
|
|
203
|
+
{ agentId: "agent_scraper_pro", calls: 302 },
|
|
204
|
+
],
|
|
205
|
+
callsByRegion: {
|
|
206
|
+
US: 6234,
|
|
207
|
+
EU: 4521,
|
|
208
|
+
APAC: 2345,
|
|
209
|
+
LATAM: 500,
|
|
210
|
+
},
|
|
211
|
+
apis: [
|
|
212
|
+
{ id: "api_weather_001", name: "WeatherAPI Pro", calls: 8247, status: "active" },
|
|
213
|
+
{ id: "api_geo_002", name: "GeoLocator API", calls: 4521, status: "active" },
|
|
214
|
+
{ id: "api_translate_003", name: "TranslateNow API", calls: 1832, status: "paused" },
|
|
215
|
+
],
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function getMockEarnings(): Earnings {
|
|
220
|
+
const now = Date.now();
|
|
221
|
+
const dayMs = 24 * 60 * 60 * 1000;
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
pendingAmount: 47.82,
|
|
225
|
+
totalEarned: 423.45,
|
|
226
|
+
totalPaidOut: 375.63,
|
|
227
|
+
stripeConnected: true,
|
|
228
|
+
stripeOnboardingComplete: true,
|
|
229
|
+
payouts: [
|
|
230
|
+
{
|
|
231
|
+
id: "po_001",
|
|
232
|
+
amount: 142.50,
|
|
233
|
+
status: "completed",
|
|
234
|
+
periodStart: now - 60 * dayMs,
|
|
235
|
+
periodEnd: now - 30 * dayMs,
|
|
236
|
+
createdAt: now - 29 * dayMs,
|
|
237
|
+
completedAt: now - 27 * dayMs,
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
id: "po_002",
|
|
241
|
+
amount: 118.63,
|
|
242
|
+
status: "completed",
|
|
243
|
+
periodStart: now - 90 * dayMs,
|
|
244
|
+
periodEnd: now - 60 * dayMs,
|
|
245
|
+
createdAt: now - 59 * dayMs,
|
|
246
|
+
completedAt: now - 57 * dayMs,
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
id: "po_003",
|
|
250
|
+
amount: 114.50,
|
|
251
|
+
status: "completed",
|
|
252
|
+
periodStart: now - 120 * dayMs,
|
|
253
|
+
periodEnd: now - 90 * dayMs,
|
|
254
|
+
createdAt: now - 89 * dayMs,
|
|
255
|
+
completedAt: now - 87 * dayMs,
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// API credentials mock
|
|
262
|
+
export interface ApiCredentials {
|
|
263
|
+
apiKey: string;
|
|
264
|
+
secretKey?: string;
|
|
265
|
+
createdAt: number;
|
|
266
|
+
lastUsed?: number;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export function getMockCredentials(apiId: string): ApiCredentials {
|
|
270
|
+
return {
|
|
271
|
+
apiKey: `apiclaw_live_${apiId.slice(-8)}_${generateRandomString(24)}`,
|
|
272
|
+
secretKey: `sk_live_${generateRandomString(32)}`,
|
|
273
|
+
createdAt: Date.now() - 45 * 24 * 60 * 60 * 1000,
|
|
274
|
+
lastUsed: Date.now() - 2 * 60 * 60 * 1000,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function generateRandomString(length: number): string {
|
|
279
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
280
|
+
let result = "";
|
|
281
|
+
for (let i = 0; i < length; i++) {
|
|
282
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
283
|
+
}
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
@@ -4,20 +4,21 @@ const config: Config = {
|
|
|
4
4
|
content: [
|
|
5
5
|
"./src/**/*.{js,ts,jsx,tsx,mdx}",
|
|
6
6
|
],
|
|
7
|
+
darkMode: 'class',
|
|
7
8
|
theme: {
|
|
8
9
|
extend: {
|
|
9
10
|
colors: {
|
|
10
|
-
background: "
|
|
11
|
-
surface: "
|
|
12
|
-
"surface-elevated": "
|
|
13
|
-
border: "
|
|
14
|
-
"border-subtle": "
|
|
15
|
-
"text-primary": "
|
|
16
|
-
"text-secondary": "
|
|
17
|
-
"text-muted": "
|
|
18
|
-
accent: "
|
|
19
|
-
"accent-hover": "#
|
|
20
|
-
"accent-dim": "rgba(
|
|
11
|
+
background: "var(--background)",
|
|
12
|
+
surface: "var(--surface)",
|
|
13
|
+
"surface-elevated": "var(--surface-elevated)",
|
|
14
|
+
border: "var(--border)",
|
|
15
|
+
"border-subtle": "var(--border)",
|
|
16
|
+
"text-primary": "var(--text-primary)",
|
|
17
|
+
"text-secondary": "var(--text-secondary)",
|
|
18
|
+
"text-muted": "var(--text-muted)",
|
|
19
|
+
accent: "var(--accent)",
|
|
20
|
+
"accent-hover": "#dc2626",
|
|
21
|
+
"accent-dim": "rgba(239, 68, 68, 0.15)",
|
|
21
22
|
},
|
|
22
23
|
fontFamily: {
|
|
23
24
|
sans: ["Inter", "system-ui", "sans-serif"],
|