@nordsym/apiclaw 1.0.0 → 1.1.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/AGENTS.md +74 -0
- package/HEARTBEAT.md +4 -0
- package/IDENTITY.md +22 -0
- package/README.md +193 -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 +12 -6
- package/convex/analytics.ts +90 -0
- package/convex/credits.ts +211 -0
- package/convex/http.ts +578 -0
- package/convex/providers.ts +516 -0
- package/convex/purchases.ts +183 -0
- package/convex/ratelimit.ts +104 -0
- package/convex/schema.ts +220 -0
- package/convex/telemetry.ts +81 -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 +175 -31
- 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/telemetry.d.ts +28 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +50 -0
- package/dist/telemetry.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 +1196 -7
- package/landing/package.json +5 -1
- 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-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 +84 -0
- package/landing/src/app/globals.css +439 -100
- package/landing/src/app/layout.tsx +37 -7
- package/landing/src/app/page.tsx +627 -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 +184 -32
- 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/telemetry.ts +71 -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,176 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect } from "react";
|
|
4
|
+
import { Mail, Loader2, Check, ArrowRight, Sun, Moon } from "lucide-react";
|
|
5
|
+
import Link from "next/link";
|
|
6
|
+
import { useRouter } from "next/navigation";
|
|
7
|
+
|
|
8
|
+
export default function LoginPage() {
|
|
9
|
+
const router = useRouter();
|
|
10
|
+
const [isDark, setIsDark] = useState(false);
|
|
11
|
+
const [email, setEmail] = useState("");
|
|
12
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
13
|
+
const [isSent, setIsSent] = useState(false);
|
|
14
|
+
const [error, setError] = useState<string | null>(null);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
// Check if already logged in
|
|
18
|
+
const sessionToken = localStorage.getItem("apiclaw_session");
|
|
19
|
+
if (sessionToken) {
|
|
20
|
+
router.push("/providers/dashboard");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const saved = localStorage.getItem("theme");
|
|
25
|
+
const prefersDark = saved ? saved === "dark" : true;
|
|
26
|
+
setIsDark(prefersDark);
|
|
27
|
+
document.documentElement.classList.toggle("dark", prefersDark);
|
|
28
|
+
}, [router]);
|
|
29
|
+
|
|
30
|
+
const toggleTheme = () => {
|
|
31
|
+
const newTheme = !isDark;
|
|
32
|
+
setIsDark(newTheme);
|
|
33
|
+
document.documentElement.classList.toggle("dark", newTheme);
|
|
34
|
+
localStorage.setItem("theme", newTheme ? "dark" : "light");
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
setIsLoading(true);
|
|
40
|
+
setError(null);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const response = await fetch("/api/auth/magic-link", {
|
|
44
|
+
method: "POST",
|
|
45
|
+
headers: { "Content-Type": "application/json" },
|
|
46
|
+
body: JSON.stringify({ email }),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
throw new Error(data.error || "Failed to send magic link");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setIsSent(true);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
setError(err instanceof Error ? err.message : "Something went wrong");
|
|
57
|
+
} finally {
|
|
58
|
+
setIsLoading(false);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
if (isSent) {
|
|
63
|
+
return (
|
|
64
|
+
<main className="min-h-screen flex items-center justify-center px-6">
|
|
65
|
+
<div className="max-w-md w-full text-center">
|
|
66
|
+
<div className="w-20 h-20 rounded-full bg-accent/20 flex items-center justify-center mx-auto mb-8">
|
|
67
|
+
<Check className="w-10 h-10 text-accent" />
|
|
68
|
+
</div>
|
|
69
|
+
<h1 className="text-3xl font-bold mb-4">Check Your Email</h1>
|
|
70
|
+
<p className="text-text-secondary mb-2">
|
|
71
|
+
We've sent a magic link to:
|
|
72
|
+
</p>
|
|
73
|
+
<p className="font-semibold text-lg mb-8">{email}</p>
|
|
74
|
+
<p className="text-sm text-text-muted">
|
|
75
|
+
Click the link in the email to sign in. The link expires in 15 minutes.
|
|
76
|
+
</p>
|
|
77
|
+
<button
|
|
78
|
+
onClick={() => setIsSent(false)}
|
|
79
|
+
className="mt-8 text-accent hover:underline"
|
|
80
|
+
>
|
|
81
|
+
Use a different email
|
|
82
|
+
</button>
|
|
83
|
+
</div>
|
|
84
|
+
</main>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<main className="min-h-screen">
|
|
90
|
+
{/* Header */}
|
|
91
|
+
<header className="fixed top-0 w-full z-50 bg-background/90 backdrop-blur-xl border-b border-border-subtle">
|
|
92
|
+
<div className="max-w-6xl mx-auto px-6 py-4 flex items-center justify-between">
|
|
93
|
+
<Link href="/" className="flex items-center gap-3">
|
|
94
|
+
<div className="w-9 h-9 rounded-xl bg-accent/20 flex items-center justify-center text-xl">
|
|
95
|
+
🦞
|
|
96
|
+
</div>
|
|
97
|
+
<span className="font-bold text-lg tracking-tight">APIClaw</span>
|
|
98
|
+
</Link>
|
|
99
|
+
<button
|
|
100
|
+
onClick={toggleTheme}
|
|
101
|
+
className="p-2 rounded-lg hover:bg-[var(--surface)] transition"
|
|
102
|
+
aria-label="Toggle theme"
|
|
103
|
+
>
|
|
104
|
+
{isDark ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
|
|
105
|
+
</button>
|
|
106
|
+
</div>
|
|
107
|
+
</header>
|
|
108
|
+
|
|
109
|
+
<div className="pt-32 pb-24 px-6">
|
|
110
|
+
<div className="max-w-md mx-auto">
|
|
111
|
+
<div className="text-center mb-8">
|
|
112
|
+
<h1 className="text-3xl font-bold mb-2">Provider Dashboard</h1>
|
|
113
|
+
<p className="text-text-secondary">
|
|
114
|
+
Sign in to manage your APIs and view analytics
|
|
115
|
+
</p>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div className="rounded-2xl bg-surface-elevated border border-border p-8">
|
|
119
|
+
<form onSubmit={handleSubmit} className="space-y-6">
|
|
120
|
+
<div>
|
|
121
|
+
<label className="block text-sm font-medium mb-2">Email</label>
|
|
122
|
+
<div className="relative">
|
|
123
|
+
<Mail className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-text-muted" />
|
|
124
|
+
<input
|
|
125
|
+
type="email"
|
|
126
|
+
value={email}
|
|
127
|
+
onChange={(e) => {
|
|
128
|
+
setEmail(e.target.value);
|
|
129
|
+
setError(null);
|
|
130
|
+
}}
|
|
131
|
+
placeholder="you@company.com"
|
|
132
|
+
required
|
|
133
|
+
className="w-full pl-12 pr-4 py-3 rounded-xl bg-surface border border-border focus:border-accent focus:outline-none transition"
|
|
134
|
+
/>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
{error && (
|
|
139
|
+
<div className="p-3 rounded-lg bg-red-500/10 border border-red-500/30 text-red-500 text-sm">
|
|
140
|
+
{error}
|
|
141
|
+
</div>
|
|
142
|
+
)}
|
|
143
|
+
|
|
144
|
+
<button
|
|
145
|
+
type="submit"
|
|
146
|
+
disabled={isLoading || !email}
|
|
147
|
+
className="btn-primary w-full justify-center disabled:opacity-50"
|
|
148
|
+
>
|
|
149
|
+
{isLoading ? (
|
|
150
|
+
<>
|
|
151
|
+
<Loader2 className="w-5 h-5 animate-spin" />
|
|
152
|
+
Sending...
|
|
153
|
+
</>
|
|
154
|
+
) : (
|
|
155
|
+
<>
|
|
156
|
+
Send Magic Link
|
|
157
|
+
<ArrowRight className="w-5 h-5" />
|
|
158
|
+
</>
|
|
159
|
+
)}
|
|
160
|
+
</button>
|
|
161
|
+
</form>
|
|
162
|
+
|
|
163
|
+
<div className="mt-6 pt-6 border-t border-border text-center">
|
|
164
|
+
<p className="text-sm text-text-muted">
|
|
165
|
+
Don't have APIs listed?{" "}
|
|
166
|
+
<Link href="/providers/register" className="text-accent hover:underline">
|
|
167
|
+
Register as a provider
|
|
168
|
+
</Link>
|
|
169
|
+
</p>
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
</main>
|
|
175
|
+
);
|
|
176
|
+
}
|