@nordsym/apiclaw 1.2.2 → 1.2.3

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.
Files changed (77) hide show
  1. package/AGENTS.md +50 -33
  2. package/README.md +22 -12
  3. package/SOUL.md +60 -19
  4. package/STATUS.md +91 -169
  5. package/convex/_generated/api.d.ts +6 -0
  6. package/convex/directCall.ts +598 -0
  7. package/convex/providers.ts +341 -26
  8. package/convex/schema.ts +87 -0
  9. package/convex/usage.ts +260 -0
  10. package/convex/waitlist.ts +55 -0
  11. package/data/combined-02-26.json +22102 -0
  12. package/data/night-expansion-02-26-06-batch2.json +1898 -0
  13. package/data/night-expansion-02-26-06-batch3.json +1410 -0
  14. package/data/night-expansion-02-26-06.json +3146 -0
  15. package/data/night-expansion-02-26-full.json +9726 -0
  16. package/data/night-expansion-02-26-v2.json +330 -0
  17. package/data/night-expansion-02-26.json +171 -0
  18. package/dist/crypto.d.ts +7 -0
  19. package/dist/crypto.d.ts.map +1 -0
  20. package/dist/crypto.js +67 -0
  21. package/dist/crypto.js.map +1 -0
  22. package/dist/execute-dynamic.d.ts +116 -0
  23. package/dist/execute-dynamic.d.ts.map +1 -0
  24. package/dist/execute-dynamic.js +456 -0
  25. package/dist/execute-dynamic.js.map +1 -0
  26. package/dist/execute.d.ts +2 -1
  27. package/dist/execute.d.ts.map +1 -1
  28. package/dist/execute.js +35 -5
  29. package/dist/execute.js.map +1 -1
  30. package/dist/index.js +33 -4
  31. package/dist/index.js.map +1 -1
  32. package/dist/registry/apis.json +2081 -3
  33. package/docs/PRD-customer-key-passthrough.md +184 -0
  34. package/landing/public/badges/available-on-apiclaw.svg +14 -0
  35. package/landing/scripts/generate-stats.js +75 -4
  36. package/landing/src/app/admin/page.tsx +1 -1
  37. package/landing/src/app/api/auth/magic-link/route.ts +1 -1
  38. package/landing/src/app/api/auth/session/route.ts +1 -1
  39. package/landing/src/app/api/auth/verify/route.ts +1 -1
  40. package/landing/src/app/api/og/route.tsx +5 -3
  41. package/landing/src/app/docs/page.tsx +5 -4
  42. package/landing/src/app/earn/page.tsx +14 -11
  43. package/landing/src/app/globals.css +16 -15
  44. package/landing/src/app/layout.tsx +2 -2
  45. package/landing/src/app/page.tsx +425 -254
  46. package/landing/src/app/providers/dashboard/[apiId]/actions/[actionId]/edit/page.tsx +600 -0
  47. package/landing/src/app/providers/dashboard/[apiId]/actions/new/page.tsx +583 -0
  48. package/landing/src/app/providers/dashboard/[apiId]/actions/page.tsx +301 -0
  49. package/landing/src/app/providers/dashboard/[apiId]/direct-call/page.tsx +659 -0
  50. package/landing/src/app/providers/dashboard/[apiId]/page.tsx +381 -0
  51. package/landing/src/app/providers/dashboard/[apiId]/test/page.tsx +418 -0
  52. package/landing/src/app/providers/dashboard/layout.tsx +292 -0
  53. package/landing/src/app/providers/dashboard/page.tsx +353 -290
  54. package/landing/src/app/providers/register/page.tsx +87 -10
  55. package/landing/src/components/AiClientDropdown.tsx +85 -0
  56. package/landing/src/components/ConfigHelperModal.tsx +113 -0
  57. package/landing/src/components/HeroTabs.tsx +187 -0
  58. package/landing/src/components/ShareIntegrationModal.tsx +198 -0
  59. package/landing/src/hooks/useDashboardData.ts +53 -1
  60. package/landing/src/lib/apis.json +46554 -174
  61. package/landing/src/lib/convex-client.ts +22 -3
  62. package/landing/src/lib/stats.json +4 -4
  63. package/landing/tsconfig.tsbuildinfo +1 -1
  64. package/night-expansion-02-26-06-batch2.py +368 -0
  65. package/night-expansion-02-26-06-batch3.py +299 -0
  66. package/night-expansion-02-26-06.py +756 -0
  67. package/package.json +1 -1
  68. package/scripts/bulk-add-public-apis-v2.py +418 -0
  69. package/scripts/night-expansion-02-26-v2.py +296 -0
  70. package/scripts/night-expansion-02-26.py +890 -0
  71. package/scripts/seed-complete-api.js +181 -0
  72. package/scripts/seed-demo-api.sh +44 -0
  73. package/src/crypto.ts +75 -0
  74. package/src/execute-dynamic.ts +589 -0
  75. package/src/execute.ts +41 -5
  76. package/src/index.ts +38 -4
  77. package/src/registry/apis.json +2081 -3
@@ -0,0 +1,292 @@
1
+ "use client";
2
+
3
+ import { useState, useEffect } from "react";
4
+ import Link from "next/link";
5
+ import { usePathname, useRouter } from "next/navigation";
6
+ import {
7
+ BarChart3,
8
+ Zap,
9
+ CreditCard,
10
+ Settings,
11
+ LogOut,
12
+ ChevronLeft,
13
+ Menu,
14
+ X,
15
+ Sun,
16
+ Moon,
17
+ Home,
18
+ PlayCircle,
19
+ RefreshCw,
20
+ Loader2,
21
+ } from "lucide-react";
22
+
23
+ interface NavItem {
24
+ label: string;
25
+ href: string;
26
+ icon: typeof Home;
27
+ exact?: boolean;
28
+ }
29
+
30
+ const mainNavItems: NavItem[] = [
31
+ { label: "Overview", href: "/providers/dashboard?tab=overview", icon: Home },
32
+ { label: "APIs", href: "/providers/dashboard?tab=apis", icon: Zap },
33
+ { label: "Analytics", href: "/providers/dashboard?tab=analytics", icon: BarChart3 },
34
+ ];
35
+
36
+ export default function DashboardLayout({
37
+ children,
38
+ }: {
39
+ children: React.ReactNode;
40
+ }) {
41
+ const pathname = usePathname();
42
+ const router = useRouter();
43
+ const [sidebarOpen, setSidebarOpen] = useState(false);
44
+ const [isDark, setIsDark] = useState(false);
45
+ const [providerName, setProviderName] = useState<string | null>(null);
46
+ const [isLoading, setIsLoading] = useState(true);
47
+
48
+ useEffect(() => {
49
+ // Check theme
50
+ const saved = localStorage.getItem("theme");
51
+ const prefersDark = saved === "dark";
52
+ setIsDark(prefersDark);
53
+ document.documentElement.classList.toggle("dark", prefersDark);
54
+
55
+ // Get provider info from localStorage
56
+ const providerData = localStorage.getItem("apiclaw_provider");
57
+ if (providerData) {
58
+ try {
59
+ const parsed = JSON.parse(providerData);
60
+ setProviderName(parsed.name || parsed.email || "Provider");
61
+ } catch {
62
+ setProviderName("Provider");
63
+ }
64
+ }
65
+ setIsLoading(false);
66
+ }, []);
67
+
68
+ const toggleTheme = () => {
69
+ const newTheme = !isDark;
70
+ setIsDark(newTheme);
71
+ document.documentElement.classList.toggle("dark", newTheme);
72
+ localStorage.setItem("theme", newTheme ? "dark" : "light");
73
+ };
74
+
75
+ const handleLogout = () => {
76
+ localStorage.removeItem("apiclaw_session");
77
+ localStorage.removeItem("apiclaw_provider");
78
+ router.push("/providers/dashboard/login");
79
+ };
80
+
81
+ // Check if current route is API detail page
82
+ const apiIdMatch = pathname.match(/\/providers\/dashboard\/([^/]+)/);
83
+ const currentApiId = apiIdMatch ? apiIdMatch[1] : null;
84
+ const isApiDetailPage = currentApiId && currentApiId !== "login" && currentApiId !== "verify";
85
+
86
+ // Don't show layout for login/verify pages
87
+ if (pathname.includes("/login") || pathname.includes("/verify")) {
88
+ return <>{children}</>;
89
+ }
90
+
91
+ if (isLoading) {
92
+ return (
93
+ <div className="min-h-screen flex items-center justify-center">
94
+ <Loader2 className="w-8 h-8 text-accent animate-spin" />
95
+ </div>
96
+ );
97
+ }
98
+
99
+ return (
100
+ <div className="min-h-screen bg-background">
101
+ {/* Mobile header */}
102
+ <header className="lg:hidden fixed top-0 w-full z-50 bg-background/90 backdrop-blur-xl border-b border-border">
103
+ <div className="flex items-center justify-between px-4 py-3">
104
+ <button
105
+ onClick={() => setSidebarOpen(true)}
106
+ className="p-2 rounded-lg hover:bg-surface transition"
107
+ >
108
+ <Menu className="w-5 h-5" />
109
+ </button>
110
+ <Link href="/" className="flex items-center gap-2">
111
+ <div className="w-8 h-8 rounded-lg bg-accent/20 flex items-center justify-center text-lg">
112
+ 🦞
113
+ </div>
114
+ <span className="font-bold">APIClaw</span>
115
+ </Link>
116
+ <button
117
+ onClick={toggleTheme}
118
+ className="p-2 rounded-lg hover:bg-surface transition"
119
+ >
120
+ {isDark ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
121
+ </button>
122
+ </div>
123
+ </header>
124
+
125
+ {/* Mobile sidebar overlay */}
126
+ {sidebarOpen && (
127
+ <div
128
+ className="lg:hidden fixed inset-0 bg-black/50 z-40"
129
+ onClick={() => setSidebarOpen(false)}
130
+ />
131
+ )}
132
+
133
+ {/* Sidebar */}
134
+ <aside
135
+ className={`fixed top-0 left-0 z-50 h-full w-64 bg-surface-elevated border-r border-border transform transition-transform duration-300 lg:translate-x-0 ${
136
+ sidebarOpen ? "translate-x-0" : "-translate-x-full"
137
+ }`}
138
+ >
139
+ <div className="flex flex-col h-full">
140
+ {/* Logo */}
141
+ <div className="flex items-center justify-between p-4 border-b border-border">
142
+ <Link href="/" className="flex items-center gap-3">
143
+ <div className="w-10 h-10 rounded-xl bg-accent/20 flex items-center justify-center text-2xl">
144
+ 🦞
145
+ </div>
146
+ <span className="font-bold text-lg">APIClaw</span>
147
+ </Link>
148
+ <button
149
+ onClick={() => setSidebarOpen(false)}
150
+ className="lg:hidden p-2 rounded-lg hover:bg-surface transition"
151
+ >
152
+ <X className="w-5 h-5" />
153
+ </button>
154
+ </div>
155
+
156
+ {/* Provider info */}
157
+ <div className="px-4 py-3 border-b border-border">
158
+ <p className="text-sm text-text-muted">Logged in as</p>
159
+ <p className="font-medium truncate">{providerName || "Provider"}</p>
160
+ </div>
161
+
162
+ {/* Navigation */}
163
+ <nav className="flex-1 p-4 space-y-1">
164
+ {mainNavItems.map((item) => (
165
+ <Link
166
+ key={item.label}
167
+ href={item.href}
168
+ className={`flex items-center gap-3 px-3 py-2 rounded-lg transition ${
169
+ (item.exact ? pathname === item.href : pathname.startsWith(item.href.split('?')[0])) && !isApiDetailPage
170
+ ? "bg-accent text-white"
171
+ : "text-text-secondary hover:bg-surface hover:text-text-primary"
172
+ }`}
173
+ onClick={() => setSidebarOpen(false)}
174
+ >
175
+ <item.icon className="w-5 h-5" />
176
+ <span>{item.label}</span>
177
+ </Link>
178
+ ))}
179
+
180
+ {isApiDetailPage && (
181
+ <>
182
+ <div className="pt-4 pb-2">
183
+ <p className="px-3 text-xs font-semibold text-text-muted uppercase tracking-wider">
184
+ Current API
185
+ </p>
186
+ </div>
187
+ <Link
188
+ href={`/providers/dashboard/${currentApiId}`}
189
+ className={`flex items-center gap-3 px-3 py-2 rounded-lg transition ${
190
+ pathname === `/providers/dashboard/${currentApiId}`
191
+ ? "bg-accent text-white"
192
+ : "text-text-secondary hover:bg-surface hover:text-text-primary"
193
+ }`}
194
+ onClick={() => setSidebarOpen(false)}
195
+ >
196
+ <Zap className="w-5 h-5" />
197
+ <span>Overview</span>
198
+ </Link>
199
+ <Link
200
+ href={`/providers/dashboard/${currentApiId}/direct-call`}
201
+ className={`flex items-center gap-3 px-3 py-2 rounded-lg transition ${
202
+ pathname.includes("/direct-call")
203
+ ? "bg-accent text-white"
204
+ : "text-text-secondary hover:bg-surface hover:text-text-primary"
205
+ }`}
206
+ onClick={() => setSidebarOpen(false)}
207
+ >
208
+ <PlayCircle className="w-5 h-5" />
209
+ <span>Direct Call</span>
210
+ </Link>
211
+ <Link
212
+ href={`/providers/dashboard/${currentApiId}/actions`}
213
+ className={`flex items-center gap-3 px-3 py-2 rounded-lg transition ${
214
+ pathname.includes("/actions")
215
+ ? "bg-accent text-white"
216
+ : "text-text-secondary hover:bg-surface hover:text-text-primary"
217
+ }`}
218
+ onClick={() => setSidebarOpen(false)}
219
+ >
220
+ <Settings className="w-5 h-5" />
221
+ <span>Actions</span>
222
+ </Link>
223
+ <Link
224
+ href={`/providers/dashboard/${currentApiId}/test`}
225
+ className={`flex items-center gap-3 px-3 py-2 rounded-lg transition ${
226
+ pathname.includes("/test")
227
+ ? "bg-accent text-white"
228
+ : "text-text-secondary hover:bg-surface hover:text-text-primary"
229
+ }`}
230
+ onClick={() => setSidebarOpen(false)}
231
+ >
232
+ <RefreshCw className="w-5 h-5" />
233
+ <span>Test Console</span>
234
+ </Link>
235
+ </>
236
+ )}
237
+ </nav>
238
+
239
+ {/* Bottom section */}
240
+ <div className="p-4 border-t border-border space-y-2">
241
+ <button
242
+ onClick={toggleTheme}
243
+ className="hidden lg:flex w-full items-center gap-3 px-3 py-2 rounded-lg text-text-secondary hover:bg-surface hover:text-text-primary transition"
244
+ >
245
+ {isDark ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
246
+ <span>{isDark ? "Light Mode" : "Dark Mode"}</span>
247
+ </button>
248
+ <button
249
+ onClick={handleLogout}
250
+ className="w-full flex items-center gap-3 px-3 py-2 rounded-lg text-text-secondary hover:bg-surface hover:text-red-500 transition"
251
+ >
252
+ <LogOut className="w-5 h-5" />
253
+ <span>Sign Out</span>
254
+ </button>
255
+ </div>
256
+ </div>
257
+ </aside>
258
+
259
+ {/* Main content */}
260
+ <main className="lg:ml-64 min-h-screen pt-14 lg:pt-0">
261
+ {/* Desktop header */}
262
+ <header className="hidden lg:flex items-center justify-between px-8 py-4 border-b border-border bg-background/90 backdrop-blur-xl sticky top-0 z-40">
263
+ <div className="flex items-center gap-3">
264
+ {isApiDetailPage && (
265
+ <Link
266
+ href="/providers/dashboard"
267
+ className="flex items-center gap-2 text-text-muted hover:text-text-primary transition"
268
+ >
269
+ <ChevronLeft className="w-5 h-5" />
270
+ <span>Back to Dashboard</span>
271
+ </Link>
272
+ )}
273
+ {!isApiDetailPage && (
274
+ <h1 className="text-xl font-bold">Provider Dashboard</h1>
275
+ )}
276
+ </div>
277
+ <div className="flex items-center gap-4">
278
+ <Link href="/providers/register" className="btn-secondary !py-2 !px-4 text-sm">
279
+ <Zap className="w-4 h-4" />
280
+ Add API
281
+ </Link>
282
+ </div>
283
+ </header>
284
+
285
+ {/* Page content */}
286
+ <div className="p-4 lg:p-8">
287
+ {children}
288
+ </div>
289
+ </main>
290
+ </div>
291
+ );
292
+ }