khotan-data 0.0.1 → 0.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 +54 -0
- package/README.md +62 -0
- package/dist/cli.js +2585 -0
- package/dist/factory.cjs +2319 -0
- package/dist/factory.cjs.map +1 -0
- package/dist/factory.d.cts +475 -0
- package/dist/factory.d.ts +475 -0
- package/dist/factory.js +2311 -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/catch.example.ts +36 -0
- package/dist/templates/catch.ts +107 -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 +99 -0
- package/dist/templates/khotan-config.ts +40 -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/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 +124 -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 +61 -0
- package/dist/templates/relay.ts +95 -0
- package/dist/templates/runs-table.tsx +592 -0
- package/dist/templates/schema.ts +424 -0
- package/dist/templates/skill-dashboard.md +144 -0
- package/dist/templates/skill-plug.md +193 -0
- package/dist/templates/skill-setup.md +119 -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,99 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Inflow — durable external service → app data movement
|
|
3
|
+
// Generated by khotan CLI · https://github.com/khotan-data
|
|
4
|
+
//
|
|
5
|
+
// This file defines the inflow() builder and types. Create per-service flow
|
|
6
|
+
// files (e.g. shopify-products.ts) using this builder to pull records from an
|
|
7
|
+
// external service, transform them, and load them into your app with durable,
|
|
8
|
+
// retryable Vercel Workflow steps.
|
|
9
|
+
// ============================================================================
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
FlowRegistration,
|
|
13
|
+
FlowRunResult,
|
|
14
|
+
FlowWorkflowContext,
|
|
15
|
+
} from "khotan-data/factory";
|
|
16
|
+
|
|
17
|
+
export type InflowContext = FlowWorkflowContext & {
|
|
18
|
+
flow: FlowWorkflowContext["flow"] & { type: "inflow" };
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type InflowWorkflow = (
|
|
22
|
+
ctx: InflowContext,
|
|
23
|
+
) => Promise<FlowRunResult | void>;
|
|
24
|
+
|
|
25
|
+
export interface InflowConfig {
|
|
26
|
+
/** Unique name for this flow (used for DB tracking and Hub display) */
|
|
27
|
+
name: string;
|
|
28
|
+
/** Logical resource this flow feeds, e.g. "products" */
|
|
29
|
+
resource?: string;
|
|
30
|
+
/** Optional cron schedule used by scheduler integrations */
|
|
31
|
+
schedule?: string;
|
|
32
|
+
/** Durable workflow that extracts, transforms, and loads records */
|
|
33
|
+
workflow: InflowWorkflow;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function inflow(config: InflowConfig): FlowRegistration {
|
|
37
|
+
return {
|
|
38
|
+
name: config.name,
|
|
39
|
+
type: "inflow",
|
|
40
|
+
resource: config.resource,
|
|
41
|
+
schedule: config.schedule,
|
|
42
|
+
workflow: config.workflow as FlowRegistration["workflow"],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Usage Example (create a file like flows/shopify-products.ts)
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
//
|
|
50
|
+
// import { inflow, type InflowContext } from "./inflow";
|
|
51
|
+
// import { db } from "@/db";
|
|
52
|
+
// import { products } from "@/db/schema";
|
|
53
|
+
// import { shopifyPlug } from "../plugs/shopify";
|
|
54
|
+
// import { sendUpdate } from "khotan-data/factory";
|
|
55
|
+
//
|
|
56
|
+
// async function shopifyProductsWorkflow(ctx: InflowContext) {
|
|
57
|
+
// "use workflow";
|
|
58
|
+
//
|
|
59
|
+
// async function extractAndLoad() {
|
|
60
|
+
// "use step";
|
|
61
|
+
// console.log("Starting inflow", {
|
|
62
|
+
// flow: ctx.flow.name,
|
|
63
|
+
// khotanRunId: ctx.khotanRunId,
|
|
64
|
+
// runType: ctx.runType,
|
|
65
|
+
// });
|
|
66
|
+
// await sendUpdate({ message: "Starting Shopify products inflow" });
|
|
67
|
+
//
|
|
68
|
+
// const response = await shopifyPlug.get<{ data?: Array<{ id: string; sku?: string }> }>("/products", {
|
|
69
|
+
// vars: ctx.vars,
|
|
70
|
+
// });
|
|
71
|
+
// const records = Array.isArray(response.data) ? response.data : [];
|
|
72
|
+
// await sendUpdate({ message: `Fetched ${records.length} products`, extracted: records.length });
|
|
73
|
+
//
|
|
74
|
+
// if (records.length > 0) {
|
|
75
|
+
// await db.insert(products).values(
|
|
76
|
+
// records.map((record) => ({
|
|
77
|
+
// externalId: record.id,
|
|
78
|
+
// sku: record.sku ?? record.id,
|
|
79
|
+
// })),
|
|
80
|
+
// );
|
|
81
|
+
// }
|
|
82
|
+
//
|
|
83
|
+
// return {
|
|
84
|
+
// extracted: records.length,
|
|
85
|
+
// transformed: records.length,
|
|
86
|
+
// created: records.length,
|
|
87
|
+
// metadata: { source: ctx.flow.name },
|
|
88
|
+
// };
|
|
89
|
+
// }
|
|
90
|
+
//
|
|
91
|
+
// return extractAndLoad();
|
|
92
|
+
// }
|
|
93
|
+
//
|
|
94
|
+
// export const shopifyProductsInflow = inflow({
|
|
95
|
+
// name: "shopify-products-inflow",
|
|
96
|
+
// resource: "products",
|
|
97
|
+
// schedule: "0 * * * *",
|
|
98
|
+
// workflow: shopifyProductsWorkflow,
|
|
99
|
+
// });
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Khotan Config — register your plugs and flows here
|
|
3
|
+
// Generated by khotan CLI · https://github.com/khotan-data
|
|
4
|
+
//
|
|
5
|
+
// Import your Drizzle database instance and register plugs below.
|
|
6
|
+
// Restart the dev server after making changes.
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
import { khotan, drizzleAdapter } from "khotan-data/factory";
|
|
10
|
+
// TODO: Update this import to your Drizzle database instance
|
|
11
|
+
import { db } from "@/db";
|
|
12
|
+
|
|
13
|
+
const khotanData = khotan({
|
|
14
|
+
adapter: drizzleAdapter(db),
|
|
15
|
+
|
|
16
|
+
// Resources define logical entity types for cross-referencing across plugs.
|
|
17
|
+
// The connectField names the field used to match records (e.g. "sku").
|
|
18
|
+
resources: [
|
|
19
|
+
// Example resource registration:
|
|
20
|
+
//
|
|
21
|
+
// { name: "products", connectField: "sku", description: "Product catalog" },
|
|
22
|
+
// { name: "orders", connectField: "order_number" },
|
|
23
|
+
],
|
|
24
|
+
|
|
25
|
+
plugs: [
|
|
26
|
+
// Example plug registration:
|
|
27
|
+
//
|
|
28
|
+
// {
|
|
29
|
+
// name: "stripe",
|
|
30
|
+
// baseUrl: "https://api.stripe.com",
|
|
31
|
+
// authType: "bearer",
|
|
32
|
+
// flows: [
|
|
33
|
+
// { name: "products-inflow", type: "inflow", schedule: "0 * * * *", resource: "products" },
|
|
34
|
+
// { name: "invoices-inflow", type: "inflow", schedule: "0 0 * * *" },
|
|
35
|
+
// ],
|
|
36
|
+
// },
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export default khotanData;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Khotan API Route — catch-all handler for /api/khotan/*
|
|
3
|
+
// Generated by khotan CLI · https://github.com/khotan-data
|
|
4
|
+
//
|
|
5
|
+
// This file wires your khotan config into a Next.js App Router route.
|
|
6
|
+
// ============================================================================
|
|
7
|
+
|
|
8
|
+
import { toNextJsHandler } from "khotan-data/factory";
|
|
9
|
+
import khotanData from "@/khotan/khotan";
|
|
10
|
+
|
|
11
|
+
export const { GET, POST, PUT, PATCH, DELETE } = toNextJsHandler(
|
|
12
|
+
khotanData.handler,
|
|
13
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { KhotanRunsTable } from "./runs-table";
|
|
4
|
+
import { KhotanWebhookEventsTable } from "./webhook-events-table";
|
|
5
|
+
|
|
6
|
+
export function KhotanLogs({ pageSize = 10 }: { pageSize?: number } = {}) {
|
|
7
|
+
return (
|
|
8
|
+
<div className="space-y-6">
|
|
9
|
+
<div className="space-y-2">
|
|
10
|
+
<h2 className="text-2xl font-bold tracking-tight">Khotan Logs</h2>
|
|
11
|
+
<p className="text-sm text-muted-foreground">
|
|
12
|
+
Inspect recent flow runs and inbound webhook activity in one place.
|
|
13
|
+
</p>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<KhotanRunsTable pageSize={pageSize} />
|
|
17
|
+
<KhotanWebhookEventsTable pageSize={pageSize} />
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Example: Outflow
|
|
3
|
+
// Generated by khotan CLI · https://github.com/khotan-data
|
|
4
|
+
//
|
|
5
|
+
// Copy this file, rename it for your destination service/resource, and register
|
|
6
|
+
// the exported flow in {outputDir}/khotan.ts.
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
import { outflow, type OutflowContext } from "./outflow";
|
|
10
|
+
|
|
11
|
+
async function hubspotProductsWorkflow(ctx: OutflowContext) {
|
|
12
|
+
"use workflow";
|
|
13
|
+
|
|
14
|
+
async function loadAndPush() {
|
|
15
|
+
"use step";
|
|
16
|
+
console.log("Starting outflow", {
|
|
17
|
+
flow: ctx.flow.name,
|
|
18
|
+
khotanRunId: ctx.khotanRunId,
|
|
19
|
+
runType: ctx.runType,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Replace this with your app-specific DB query.
|
|
23
|
+
const records: Array<Record<string, unknown>> = [];
|
|
24
|
+
|
|
25
|
+
for (const record of records) {
|
|
26
|
+
await fetch("https://api.example.com/products", {
|
|
27
|
+
method: "POST",
|
|
28
|
+
headers: {
|
|
29
|
+
Authorization: `Bearer ${ctx.vars["apiToken"] ?? ""}`,
|
|
30
|
+
"Content-Type": "application/json",
|
|
31
|
+
},
|
|
32
|
+
body: JSON.stringify(record),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
extracted: records.length,
|
|
38
|
+
transformed: records.length,
|
|
39
|
+
created: records.length,
|
|
40
|
+
metadata: { destination: ctx.flow.name },
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return loadAndPush();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const hubspotProductsOutflow = outflow({
|
|
48
|
+
name: "hubspot-products-outflow",
|
|
49
|
+
resource: "products",
|
|
50
|
+
schedule: "0 * * * *",
|
|
51
|
+
workflow: hubspotProductsWorkflow,
|
|
52
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Outflow — durable app → external service data movement
|
|
3
|
+
// Generated by khotan CLI · https://github.com/khotan-data
|
|
4
|
+
//
|
|
5
|
+
// This file defines the outflow() builder and types. Create per-service flow
|
|
6
|
+
// files (e.g. crm-audiences.ts) using this builder to read app data and push it
|
|
7
|
+
// to an external service with durable, retryable Vercel Workflow steps.
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
FlowRegistration,
|
|
12
|
+
FlowRunResult,
|
|
13
|
+
FlowWorkflowContext,
|
|
14
|
+
} from "khotan-data/factory";
|
|
15
|
+
|
|
16
|
+
export type OutflowContext = FlowWorkflowContext & {
|
|
17
|
+
flow: FlowWorkflowContext["flow"] & { type: "outflow" };
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type OutflowWorkflow = (
|
|
21
|
+
ctx: OutflowContext,
|
|
22
|
+
) => Promise<FlowRunResult | void>;
|
|
23
|
+
|
|
24
|
+
export interface OutflowConfig {
|
|
25
|
+
/** Unique name for this flow (used for DB tracking and Hub display) */
|
|
26
|
+
name: string;
|
|
27
|
+
/** Logical resource this flow publishes, e.g. "products" */
|
|
28
|
+
resource?: string;
|
|
29
|
+
/** Optional cron schedule used by scheduler integrations */
|
|
30
|
+
schedule?: string;
|
|
31
|
+
/** Durable workflow that reads app data and writes it to the plug */
|
|
32
|
+
workflow: OutflowWorkflow;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function outflow(config: OutflowConfig): FlowRegistration {
|
|
36
|
+
return {
|
|
37
|
+
name: config.name,
|
|
38
|
+
type: "outflow",
|
|
39
|
+
resource: config.resource,
|
|
40
|
+
schedule: config.schedule,
|
|
41
|
+
workflow: config.workflow as FlowRegistration["workflow"],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Usage Example (create a file like flows/hubspot-products.ts)
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
//
|
|
49
|
+
// import { outflow, type OutflowContext } from "./outflow";
|
|
50
|
+
// import { db } from "@/db";
|
|
51
|
+
// import { products } from "@/db/schema";
|
|
52
|
+
// import { hubspotPlug } from "../plugs/hubspot";
|
|
53
|
+
//
|
|
54
|
+
// async function hubspotProductsWorkflow(ctx: OutflowContext) {
|
|
55
|
+
// "use workflow";
|
|
56
|
+
//
|
|
57
|
+
// async function loadAndPush() {
|
|
58
|
+
// "use step";
|
|
59
|
+
// console.log("Starting outflow", {
|
|
60
|
+
// flow: ctx.flow.name,
|
|
61
|
+
// khotanRunId: ctx.khotanRunId,
|
|
62
|
+
// runType: ctx.runType,
|
|
63
|
+
// });
|
|
64
|
+
//
|
|
65
|
+
// const records = await db.select().from(products);
|
|
66
|
+
//
|
|
67
|
+
// for (const record of records) {
|
|
68
|
+
// await hubspotPlug.post("/products", {
|
|
69
|
+
// vars: ctx.vars,
|
|
70
|
+
// body: record,
|
|
71
|
+
// });
|
|
72
|
+
// }
|
|
73
|
+
//
|
|
74
|
+
// return {
|
|
75
|
+
// extracted: records.length,
|
|
76
|
+
// transformed: records.length,
|
|
77
|
+
// created: records.length,
|
|
78
|
+
// metadata: { destination: ctx.flow.name },
|
|
79
|
+
// };
|
|
80
|
+
// }
|
|
81
|
+
//
|
|
82
|
+
// return loadAndPush();
|
|
83
|
+
// }
|
|
84
|
+
//
|
|
85
|
+
// export const hubspotProductsOutflow = outflow({
|
|
86
|
+
// name: "hubspot-products-outflow",
|
|
87
|
+
// resource: "products",
|
|
88
|
+
// schedule: "0 * * * *",
|
|
89
|
+
// workflow: hubspotProductsWorkflow,
|
|
90
|
+
// });
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Example: Pass
|
|
3
|
+
// Generated by khotan CLI · https://github.com/khotan-data
|
|
4
|
+
//
|
|
5
|
+
// Copy this file, rename it for your source/destination pair, and register the
|
|
6
|
+
// exported pass handler in {outputDir}/khotan.ts.
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
import { pass, type PassContext } from "./pass";
|
|
10
|
+
|
|
11
|
+
async function stripeToSlackWorkflow(ctx: PassContext) {
|
|
12
|
+
"use workflow";
|
|
13
|
+
|
|
14
|
+
async function forwardEvent() {
|
|
15
|
+
"use step";
|
|
16
|
+
console.log("Forwarding webhook event", {
|
|
17
|
+
eventType: ctx.eventType,
|
|
18
|
+
khotanRunId: ctx.khotanRunId,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
await fetch("https://slack.com/api/chat.postMessage", {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: {
|
|
24
|
+
Authorization: `Bearer ${ctx.destVars["botToken"] ?? ""}`,
|
|
25
|
+
"Content-Type": "application/json",
|
|
26
|
+
},
|
|
27
|
+
body: JSON.stringify({
|
|
28
|
+
channel: ctx.destVars["channelId"],
|
|
29
|
+
text: `Received ${ctx.eventType}`,
|
|
30
|
+
blocks: [
|
|
31
|
+
{
|
|
32
|
+
type: "section",
|
|
33
|
+
text: {
|
|
34
|
+
type: "mrkdwn",
|
|
35
|
+
text: `Received ${ctx.eventType} from Stripe`,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
}),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
await forwardEvent();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const stripeToSlack = pass({
|
|
47
|
+
name: "stripe-to-slack",
|
|
48
|
+
to: "slack",
|
|
49
|
+
events: ["invoice.paid"],
|
|
50
|
+
workflow: stripeToSlackWorkflow,
|
|
51
|
+
});
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Pass — durable webhook event forwarding via Vercel Workflow
|
|
3
|
+
// Generated by khotan CLI · https://github.com/khotan-data
|
|
4
|
+
//
|
|
5
|
+
// This file defines the pass() builder and types. Create per-service pass
|
|
6
|
+
// files (e.g. pollinate-to-slack.ts) using this builder to forward verified
|
|
7
|
+
// webhook events to another service with durable, retryable workflow steps.
|
|
8
|
+
//
|
|
9
|
+
// Pass workflows receive a PassContext with the parsed event, event type,
|
|
10
|
+
// headers, and destVars (variables for the destination plug). Steps have
|
|
11
|
+
// full Node.js access — construct destination plugs from destVars.
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Context — serializable data passed to the workflow
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
export interface PassContext {
|
|
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
|
+
/** Decrypted variables for the destination plug (auto-injected by factory) */
|
|
26
|
+
destVars: Record<string, string>;
|
|
27
|
+
/** Khotan run ID created for this webhook handler execution */
|
|
28
|
+
khotanRunId: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Workflow type — the function signature your workflow must conform to
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
export type PassWorkflow = (ctx: PassContext) => Promise<void>;
|
|
36
|
+
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Config — passed to the pass() builder
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
export interface PassConfig {
|
|
42
|
+
/** Unique name for this pass handler (used for DB tracking and Hub display) */
|
|
43
|
+
name: string;
|
|
44
|
+
/** Name of the destination plug to forward events to */
|
|
45
|
+
to: string;
|
|
46
|
+
/** Event types this pass should receive */
|
|
47
|
+
events?: string[];
|
|
48
|
+
/** Workflow function that handles the forwarding */
|
|
49
|
+
workflow: PassWorkflow;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Registration — returned by pass(), consumed by factory config
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
export interface PassRegistration {
|
|
57
|
+
type: "pass";
|
|
58
|
+
name: string;
|
|
59
|
+
to: string;
|
|
60
|
+
events?: string[];
|
|
61
|
+
workflow: PassWorkflow;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Builder
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
export function pass(config: PassConfig): PassRegistration {
|
|
69
|
+
return {
|
|
70
|
+
type: "pass",
|
|
71
|
+
name: config.name,
|
|
72
|
+
to: config.to,
|
|
73
|
+
events: config.events,
|
|
74
|
+
workflow: config.workflow,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Usage Example (create a file like webhooks/pollinate-to-slack.ts)
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
//
|
|
82
|
+
// import { pass, type PassContext } from "./pass";
|
|
83
|
+
// import { plug } from "../plugs/plug";
|
|
84
|
+
//
|
|
85
|
+
// async function pollinateToSlackWorkflow(ctx: PassContext) {
|
|
86
|
+
// "use workflow";
|
|
87
|
+
//
|
|
88
|
+
// async function forwardEvent() {
|
|
89
|
+
// "use step";
|
|
90
|
+
//
|
|
91
|
+
// // Construct destination plug from destVars
|
|
92
|
+
// const slackPlug = plug({
|
|
93
|
+
// name: "slack",
|
|
94
|
+
// baseUrl: "https://hooks.slack.com",
|
|
95
|
+
// authType: "bearer",
|
|
96
|
+
// auth: { bearer: { token: ctx.destVars["token"] ?? "" } },
|
|
97
|
+
// });
|
|
98
|
+
//
|
|
99
|
+
// await slackPlug.post("/services/webhook", {
|
|
100
|
+
// body: {
|
|
101
|
+
// text: `Received ${ctx.eventType} event from pollinate`,
|
|
102
|
+
// event: ctx.event,
|
|
103
|
+
// },
|
|
104
|
+
// });
|
|
105
|
+
// }
|
|
106
|
+
//
|
|
107
|
+
// await forwardEvent();
|
|
108
|
+
// }
|
|
109
|
+
//
|
|
110
|
+
// export const pollinateToSlack = pass({
|
|
111
|
+
// name: "pollinate-to-slack",
|
|
112
|
+
// to: "slack",
|
|
113
|
+
// events: ["order.created"],
|
|
114
|
+
// workflow: pollinateToSlackWorkflow,
|
|
115
|
+
// });
|
|
116
|
+
//
|
|
117
|
+
// Then register in your khotan config:
|
|
118
|
+
//
|
|
119
|
+
// plugs: [{
|
|
120
|
+
// name: "pollinate",
|
|
121
|
+
// plug: pollinatePlug,
|
|
122
|
+
// wires: [pollinateWire],
|
|
123
|
+
// passes: [pollinateToSlack],
|
|
124
|
+
// }]
|