khotan-data 0.0.1 → 0.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.
Files changed (55) hide show
  1. package/AGENTS.md +54 -0
  2. package/README.md +117 -1
  3. package/dist/cli.js +2869 -0
  4. package/dist/factory.cjs +3303 -0
  5. package/dist/factory.cjs.map +1 -0
  6. package/dist/factory.d.cts +662 -0
  7. package/dist/factory.d.ts +662 -0
  8. package/dist/factory.js +3292 -0
  9. package/dist/factory.js.map +1 -0
  10. package/dist/plug-client.cjs +99 -0
  11. package/dist/plug-client.cjs.map +1 -0
  12. package/dist/plug-client.d.cts +71 -0
  13. package/dist/plug-client.d.ts +71 -0
  14. package/dist/plug-client.js +96 -0
  15. package/dist/plug-client.js.map +1 -0
  16. package/dist/templates/agent-skill.md +73 -0
  17. package/dist/templates/agents.md +41 -0
  18. package/dist/templates/cache.example.ts +11 -0
  19. package/dist/templates/cache.ts +58 -0
  20. package/dist/templates/catch.example.ts +36 -0
  21. package/dist/templates/catch.ts +119 -0
  22. package/dist/templates/config-page.tsx +20 -0
  23. package/dist/templates/debug-index-page.tsx +101 -0
  24. package/dist/templates/debug-page.tsx +48 -0
  25. package/dist/templates/graph-page.tsx +11 -0
  26. package/dist/templates/hub.tsx +450 -0
  27. package/dist/templates/inflow.example.ts +61 -0
  28. package/dist/templates/inflow.ts +98 -0
  29. package/dist/templates/khotan-config.ts +49 -0
  30. package/dist/templates/khotan-route.ts +13 -0
  31. package/dist/templates/logs-page.tsx +9 -0
  32. package/dist/templates/logs.tsx +20 -0
  33. package/dist/templates/mapping-browser.tsx +761 -0
  34. package/dist/templates/mappings-page.tsx +9 -0
  35. package/dist/templates/outflow.example.ts +52 -0
  36. package/dist/templates/outflow.ts +90 -0
  37. package/dist/templates/pass.example.ts +51 -0
  38. package/dist/templates/pass.ts +134 -0
  39. package/dist/templates/plug-debugger.tsx +1185 -0
  40. package/dist/templates/plug.example.ts +93 -0
  41. package/dist/templates/plug.ts +806 -0
  42. package/dist/templates/relay.example.ts +71 -0
  43. package/dist/templates/relay.ts +104 -0
  44. package/dist/templates/runs-table.tsx +592 -0
  45. package/dist/templates/schema.ts +505 -0
  46. package/dist/templates/skill-dashboard.md +144 -0
  47. package/dist/templates/skill-plug.md +216 -0
  48. package/dist/templates/skill-setup.md +161 -0
  49. package/dist/templates/skill-webhook.md +196 -0
  50. package/dist/templates/topology-canvas.tsx +1406 -0
  51. package/dist/templates/var-panel.tsx +276 -0
  52. package/dist/templates/webhook-events-table.tsx +241 -0
  53. package/dist/templates/wire-panel.tsx +216 -0
  54. package/dist/templates/wire.ts +155 -0
  55. package/package.json +46 -5
@@ -0,0 +1,119 @@
1
+ // ============================================================================
2
+ // Catch — durable webhook event processing via Vercel Workflow
3
+ // Generated by khotan CLI · https://github.com/khotan-data
4
+ //
5
+ // This file defines the catchEvent() builder and types. Create per-service
6
+ // catch files (e.g. pollinate-catch.ts) using this builder to handle verified
7
+ // webhook events with durable, retryable workflow steps.
8
+ //
9
+ // Catch workflows receive a CatchContext with the parsed event payload,
10
+ // event type, and headers. Steps have full Node.js access — import your
11
+ // own db, services, etc.
12
+ // ============================================================================
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // Context — serializable data passed to the workflow
16
+ // ---------------------------------------------------------------------------
17
+
18
+ export interface CatchContext {
19
+ /** Parsed webhook payload */
20
+ event: Record<string, unknown>;
21
+ /** Event type extracted from payload (e.g. "order.created") */
22
+ eventType: string;
23
+ /** Incoming request headers */
24
+ headers: Record<string, string>;
25
+ /** Khotan run ID created for this webhook handler execution */
26
+ khotanRunId: string;
27
+ /** Internal Khotan instance identifier for helper APIs */
28
+ khotanInstanceId: string;
29
+ }
30
+
31
+ // ---------------------------------------------------------------------------
32
+ // Workflow type — the function signature your workflow must conform to
33
+ // ---------------------------------------------------------------------------
34
+
35
+ export type CatchWorkflow = (ctx: CatchContext) => Promise<void>;
36
+
37
+ // ---------------------------------------------------------------------------
38
+ // Config — passed to the catchEvent() builder
39
+ // ---------------------------------------------------------------------------
40
+
41
+ export interface CatchConfig {
42
+ /** Unique name for this catch handler (used for DB tracking and Hub display) */
43
+ name: string;
44
+ /** Event types this catch should receive */
45
+ events?: string[];
46
+ /** Workflow function that processes the event */
47
+ workflow: CatchWorkflow;
48
+ }
49
+
50
+ // ---------------------------------------------------------------------------
51
+ // Registration — returned by catchEvent(), consumed by factory config
52
+ // ---------------------------------------------------------------------------
53
+
54
+ export interface CatchRegistration {
55
+ type: "catch";
56
+ name: string;
57
+ events?: string[];
58
+ workflow: CatchWorkflow;
59
+ }
60
+
61
+ // ---------------------------------------------------------------------------
62
+ // Builder
63
+ // ---------------------------------------------------------------------------
64
+
65
+ export function catchEvent(config: CatchConfig): CatchRegistration {
66
+ return {
67
+ type: "catch",
68
+ name: config.name,
69
+ events: config.events,
70
+ workflow: config.workflow,
71
+ };
72
+ }
73
+
74
+ // ---------------------------------------------------------------------------
75
+ // Usage Example (create a file like webhooks/pollinate-catch.ts)
76
+ // ---------------------------------------------------------------------------
77
+ //
78
+ // import { khotanCache } from "khotan-data/factory";
79
+ // import { catchEvent, type CatchContext } from "./catch";
80
+ // Khotan already records webhook deliveries in khotan_webhook_events and links
81
+ // them to khotan_runs. Use your catch workflow for app-specific side effects
82
+ // and optionally khotanCache(ctx, "name") for dedupe or cursor state.
83
+ //
84
+ // async function pollinateCatchWorkflow(ctx: CatchContext) {
85
+ // "use workflow";
86
+ //
87
+ // async function notifyOps() {
88
+ // "use step";
89
+ // const cache = khotanCache(ctx, "pollinate-webhook-markers");
90
+ // const eventId = String(ctx.event["id"] ?? "");
91
+ // if (eventId && (await cache.get<boolean>(eventId))) return;
92
+ //
93
+ // console.log("Handled webhook", {
94
+ // eventType: ctx.eventType,
95
+ // khotanRunId: ctx.khotanRunId,
96
+ // });
97
+ //
98
+ // if (eventId) {
99
+ // await cache.set(eventId, true);
100
+ // }
101
+ // }
102
+ //
103
+ // await notifyOps();
104
+ // }
105
+ //
106
+ // export const pollinateCatch = catchEvent({
107
+ // name: "pollinate-orders",
108
+ // events: ["order.created"],
109
+ // workflow: pollinateCatchWorkflow,
110
+ // });
111
+ //
112
+ // Then register in your khotan config:
113
+ //
114
+ // plugs: [{
115
+ // name: "pollinate",
116
+ // plug: pollinatePlug,
117
+ // wires: [pollinateWire],
118
+ // catches: [pollinateCatch],
119
+ // }]
@@ -0,0 +1,20 @@
1
+ import { KhotanHub } from "@/components/khotan/hub";
2
+
3
+ function getWebhookUrl(): string {
4
+ return (
5
+ process.env.KHOTAN_WEBHOOK_URL ||
6
+ process.env.NGROK_URL ||
7
+ process.env.NEXT_PUBLIC_APP_URL ||
8
+ "http://localhost:3000"
9
+ );
10
+ }
11
+
12
+ export default function KhotanConfigPage() {
13
+ const webhookUrl = getWebhookUrl();
14
+
15
+ return (
16
+ <main className="container mx-auto max-w-5xl px-4 py-10">
17
+ <KhotanHub webhookUrl={webhookUrl} />
18
+ </main>
19
+ );
20
+ }
@@ -0,0 +1,101 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+ import Link from "next/link";
5
+
6
+ // ============================================================================
7
+ // Debug Index — Lists all registered plugs for debugging
8
+ // Generated by khotan CLI · https://github.com/khotan-data
9
+ //
10
+ // Place at: app/debug/page.tsx
11
+ // Requires KHOTAN_DEBUG env var to be set for the debug route to respond.
12
+ // ============================================================================
13
+
14
+ interface Plug {
15
+ id: string;
16
+ name: string;
17
+ baseUrl: string;
18
+ authType: string;
19
+ status: "connected" | "error" | "idle";
20
+ }
21
+
22
+ export default function DebugIndexPage() {
23
+ const [plugs, setPlugs] = useState<Plug[]>([]);
24
+ const [loading, setLoading] = useState(true);
25
+ const [debugEnabled, setDebugEnabled] = useState<boolean | null>(null);
26
+
27
+ useEffect(() => {
28
+ Promise.all([
29
+ fetch("/api/khotan/debug").then((r) => r.ok),
30
+ fetch("/api/khotan/plugs").then((r) => (r.ok ? r.json() : [])),
31
+ ])
32
+ .then(([enabled, data]) => {
33
+ setDebugEnabled(enabled);
34
+ setPlugs(data as Plug[]);
35
+ })
36
+ .catch(() => setDebugEnabled(false))
37
+ .finally(() => setLoading(false));
38
+ }, []);
39
+
40
+ if (loading) {
41
+ return (
42
+ <main className="container mx-auto max-w-3xl px-4 py-10">
43
+ <div className="h-8 w-48 animate-pulse rounded bg-muted" />
44
+ </main>
45
+ );
46
+ }
47
+
48
+ if (!debugEnabled) {
49
+ return (
50
+ <main className="container mx-auto max-w-3xl px-4 py-10">
51
+ <h1 className="text-2xl font-bold tracking-tight mb-4">Debug</h1>
52
+ <p className="text-muted-foreground">
53
+ Debug mode is not enabled. Set{" "}
54
+ <code className="bg-muted px-1.5 py-0.5 rounded text-sm">
55
+ KHOTAN_DEBUG=1
56
+ </code>{" "}
57
+ in your environment and restart the server.
58
+ </p>
59
+ </main>
60
+ );
61
+ }
62
+
63
+ return (
64
+ <main className="container mx-auto max-w-3xl px-4 py-10">
65
+ <div className="mb-6">
66
+ <a
67
+ href="/config"
68
+ className="text-sm text-muted-foreground hover:text-foreground"
69
+ >
70
+ ← Back to Hub
71
+ </a>
72
+ </div>
73
+ <h1 className="text-2xl font-bold tracking-tight mb-6">Debug</h1>
74
+ <p className="text-muted-foreground mb-6">
75
+ Select a plug to test requests through its real code path.
76
+ </p>
77
+ <div className="grid gap-3">
78
+ {plugs.map((plug) => (
79
+ <Link
80
+ key={plug.id}
81
+ href={`/debug/${plug.name}`}
82
+ className="flex items-center justify-between rounded-lg border border-border p-4 transition-colors hover:border-foreground/30 hover:bg-muted/50"
83
+ >
84
+ <div>
85
+ <p className="font-medium">{plug.name}</p>
86
+ <p className="text-xs text-muted-foreground truncate">
87
+ {plug.baseUrl}
88
+ </p>
89
+ </div>
90
+ <div className="flex items-center gap-2">
91
+ <span className="text-xs text-muted-foreground">
92
+ {plug.authType}
93
+ </span>
94
+ <span className="text-muted-foreground">→</span>
95
+ </div>
96
+ </Link>
97
+ ))}
98
+ </div>
99
+ </main>
100
+ );
101
+ }
@@ -0,0 +1,48 @@
1
+ "use client";
2
+
3
+ import { useParams } from "next/navigation";
4
+ import { PlugDebugger } from "@/components/khotan/plug-debugger";
5
+
6
+ // ============================================================================
7
+ // Debug Page — Route for plug debugging
8
+ // Generated by khotan CLI · https://github.com/khotan-data
9
+ //
10
+ // Place at: app/debug/[plugName]/page.tsx
11
+ // Requires KHOTAN_DEBUG env var to be set for the debug route to respond.
12
+ // ============================================================================
13
+
14
+ export default function PlugDebugPage() {
15
+ const params = useParams<{ plugName: string }>();
16
+ const plugName = params.plugName;
17
+
18
+ if (!plugName) {
19
+ return (
20
+ <main className="container mx-auto max-w-6xl px-4 py-10">
21
+ <p className="text-muted-foreground">No plug specified.</p>
22
+ </main>
23
+ );
24
+ }
25
+
26
+ return (
27
+ <main className="container mx-auto max-w-6xl px-4 py-10">
28
+ <div className="flex items-center justify-between mb-6">
29
+ <a
30
+ href="/debug"
31
+ className="text-sm text-muted-foreground hover:text-foreground"
32
+ >
33
+ ← All Plugs
34
+ </a>
35
+ <a
36
+ href="/config"
37
+ className="text-xs text-muted-foreground hover:text-foreground"
38
+ >
39
+ Hub
40
+ </a>
41
+ </div>
42
+ <h1 className="text-2xl font-bold tracking-tight mb-6">
43
+ Debug: {plugName}
44
+ </h1>
45
+ <PlugDebugger plugName={plugName} />
46
+ </main>
47
+ );
48
+ }
@@ -0,0 +1,11 @@
1
+ import { KhotanTopologyCanvas } from "@/components/khotan/topology-canvas";
2
+
3
+ export default function KhotanGraphPage() {
4
+ return (
5
+ <main className="min-h-screen bg-[radial-gradient(circle_at_top,_rgba(248,250,252,0.94),_rgba(241,245,249,0.82)_38%,_rgba(226,232,240,0.7))]">
6
+ <div className="mx-auto max-w-[1720px] px-4 py-8 md:px-6 xl:py-10">
7
+ <KhotanTopologyCanvas />
8
+ </div>
9
+ </main>
10
+ );
11
+ }