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.
- package/AGENTS.md +54 -0
- package/README.md +117 -1
- package/dist/cli.js +2869 -0
- package/dist/factory.cjs +3303 -0
- package/dist/factory.cjs.map +1 -0
- package/dist/factory.d.cts +662 -0
- package/dist/factory.d.ts +662 -0
- package/dist/factory.js +3292 -0
- package/dist/factory.js.map +1 -0
- package/dist/plug-client.cjs +99 -0
- package/dist/plug-client.cjs.map +1 -0
- package/dist/plug-client.d.cts +71 -0
- package/dist/plug-client.d.ts +71 -0
- package/dist/plug-client.js +96 -0
- package/dist/plug-client.js.map +1 -0
- package/dist/templates/agent-skill.md +73 -0
- package/dist/templates/agents.md +41 -0
- package/dist/templates/cache.example.ts +11 -0
- package/dist/templates/cache.ts +58 -0
- package/dist/templates/catch.example.ts +36 -0
- package/dist/templates/catch.ts +119 -0
- package/dist/templates/config-page.tsx +20 -0
- package/dist/templates/debug-index-page.tsx +101 -0
- package/dist/templates/debug-page.tsx +48 -0
- package/dist/templates/graph-page.tsx +11 -0
- package/dist/templates/hub.tsx +450 -0
- package/dist/templates/inflow.example.ts +61 -0
- package/dist/templates/inflow.ts +98 -0
- package/dist/templates/khotan-config.ts +49 -0
- package/dist/templates/khotan-route.ts +13 -0
- package/dist/templates/logs-page.tsx +9 -0
- package/dist/templates/logs.tsx +20 -0
- package/dist/templates/mapping-browser.tsx +761 -0
- package/dist/templates/mappings-page.tsx +9 -0
- package/dist/templates/outflow.example.ts +52 -0
- package/dist/templates/outflow.ts +90 -0
- package/dist/templates/pass.example.ts +51 -0
- package/dist/templates/pass.ts +134 -0
- package/dist/templates/plug-debugger.tsx +1185 -0
- package/dist/templates/plug.example.ts +93 -0
- package/dist/templates/plug.ts +806 -0
- package/dist/templates/relay.example.ts +71 -0
- package/dist/templates/relay.ts +104 -0
- package/dist/templates/runs-table.tsx +592 -0
- package/dist/templates/schema.ts +505 -0
- package/dist/templates/skill-dashboard.md +144 -0
- package/dist/templates/skill-plug.md +216 -0
- package/dist/templates/skill-setup.md +161 -0
- package/dist/templates/skill-webhook.md +196 -0
- package/dist/templates/topology-canvas.tsx +1406 -0
- package/dist/templates/var-panel.tsx +276 -0
- package/dist/templates/webhook-events-table.tsx +241 -0
- package/dist/templates/wire-panel.tsx +216 -0
- package/dist/templates/wire.ts +155 -0
- 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
|
+
}
|