Skip to content

Commit 12e0bcd

Browse files
committed
feat: add example client script demonstrating flow control, step monitoring, run retrieval,
and event subscription - Introduces a new example TypeScript file with multiple usage scenarios - Implements functions to start flows, monitor steps, retrieve previous runs, and subscribe to events - Demonstrates typed interactions with the client library and proper event handling - Provides a comprehensive usage guide for the client library features in a single script
1 parent 05e392d commit 12e0bcd

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed

pkgs/client/examples/basic.ts

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
import { createClient } from '@supabase/supabase-js';
2+
import { AnalyzeWebsite } from '@pgflow/dsl/src/example-flow.js';
3+
import { PgflowClient } from '../src/lib/PgflowClient';
4+
import { FlowRunStatus, FlowStepStatus } from '../src/lib/types';
5+
6+
// Create example client
7+
const supabaseUrl = 'https://example.supabase.co';
8+
const supabaseKey = 'your-supabase-key';
9+
const supabase = createClient(supabaseUrl, supabaseKey);
10+
11+
// Create PgflowClient instance
12+
const client = new PgflowClient(supabase);
13+
14+
/**
15+
* Example 1: Start a flow and wait for completion
16+
*/
17+
async function startFlowAndWait() {
18+
console.log('Starting flow...');
19+
20+
// Start the flow with specific input - TypeScript will enforce correct input shape
21+
const run = await client.startFlow(AnalyzeWebsite.slug, {
22+
url: 'https://example.com',
23+
});
24+
25+
console.log(`Flow started with ID: ${run.run_id}`);
26+
27+
// Access run properties with proper typing
28+
console.log(`Current status: ${run.status}`);
29+
console.log(`Input: ${JSON.stringify(run.input)}`);
30+
31+
// Wait for the run to reach a terminal state
32+
console.log('Waiting for flow to complete...');
33+
const completed = await run.waitForStatus(FlowRunStatus.Completed, {
34+
timeoutMs: 30000,
35+
});
36+
// Output is fully typed according to flow definition
37+
console.log(`Flow completed!`);
38+
console.log(`Output: ${JSON.stringify(completed.output)}`);
39+
40+
return completed;
41+
}
42+
43+
/**
44+
* Example 2: Monitor individual steps
45+
*/
46+
async function monitorSteps() {
47+
// Start the flow - use Flow type directly rather than typeof
48+
const run = await client.startFlow(
49+
AnalyzeWebsite.slug,
50+
{
51+
url: 'https://example.com/blog',
52+
}
53+
);
54+
55+
console.log(`Monitoring steps for flow: ${run.run_id}`);
56+
57+
// Access a specific step - step slug is typed
58+
const sentimentStep = run.step('sentiment');
59+
60+
// Register event handlers with proper typing
61+
sentimentStep.on('started', (event) => {
62+
console.log(`Sentiment analysis started at: ${event.started_at}`);
63+
});
64+
65+
sentimentStep.on('completed', (event) => {
66+
// Output is typed according to step definition
67+
// Need to cast the output to the expected type
68+
console.log(`Sentiment score: ${(event.output as { score: number }).score}`);
69+
});
70+
71+
// Wait for the step to complete
72+
await sentimentStep.waitForStatus(FlowStepStatus.Completed, {
73+
timeoutMs: 20000,
74+
});
75+
76+
// Get step state
77+
console.log(`Step status: ${sentimentStep.status}`);
78+
console.log(`Step output: ${JSON.stringify(sentimentStep.output)}`);
79+
80+
return run;
81+
}
82+
83+
/**
84+
* Example 3: Get a previous run
85+
*/
86+
async function getRun(runId: string) {
87+
console.log(`Looking up run: ${runId}`);
88+
89+
// Fetch an existing run
90+
const run = await client.getRun(runId);
91+
92+
if (!run) {
93+
console.log(`Run not found: ${runId}`);
94+
return null;
95+
}
96+
97+
console.log(`Found run: ${run.run_id}`);
98+
console.log(`Status: ${run.status}`);
99+
100+
// Check all steps
101+
console.log('Steps:');
102+
for (const stepSlug of ['website', 'sentiment', 'summary', 'saveToDb']) {
103+
const step = run.step(stepSlug);
104+
console.log(` ${stepSlug}: ${step.status}`);
105+
106+
if (step.status === FlowStepStatus.Completed) {
107+
console.log(` Output: ${JSON.stringify(step.output)}`);
108+
} else if (step.status === FlowStepStatus.Failed) {
109+
console.log(` Error: ${step.error_message}`);
110+
}
111+
}
112+
113+
return run;
114+
}
115+
116+
/**
117+
* Example 4: Using event listeners and run lifecycle
118+
*/
119+
async function subscribeToRunEvents() {
120+
// Start the flow
121+
const run = await client.startFlow(AnalyzeWebsite.slug, {
122+
url: 'https://example.com/subscribe',
123+
});
124+
125+
console.log(`Subscribed to run: ${run.run_id}`);
126+
127+
// Register global events listener
128+
run.on('*', (event) => {
129+
console.log(`Event received: ${event.status}`);
130+
});
131+
132+
// Register specific event handlers
133+
run.on('completed', (event) => {
134+
console.log(`Run completed at: ${event.completed_at}`);
135+
console.log(`Output: ${JSON.stringify(event.output)}`);
136+
});
137+
138+
run.on('failed', (event) => {
139+
console.log(`Run failed at: ${event.failed_at}`);
140+
console.log(`Error: ${event.error_message}`);
141+
});
142+
143+
// Wait for completion and then clean up
144+
await run.waitForStatus(FlowRunStatus.Completed);
145+
146+
// Dispose the run when done to clean up resources
147+
run.dispose();
148+
149+
return run.run_id;
150+
}
151+
152+
/**
153+
* Main function to run all examples
154+
*/
155+
async function main() {
156+
try {
157+
console.log('=== Example 1: Start flow and wait ===');
158+
const completedRun = await startFlowAndWait();
159+
160+
console.log('\n=== Example 2: Monitor steps ===');
161+
await monitorSteps();
162+
163+
console.log('\n=== Example 3: Get previous run ===');
164+
await getRun(completedRun.run_id);
165+
166+
console.log('\n=== Example 4: Subscribe to events ===');
167+
await subscribeToRunEvents();
168+
} catch (error) {
169+
console.error('Error running examples:', error);
170+
} finally {
171+
// Clean up all resources
172+
client.disposeAll();
173+
}
174+
}
175+
176+
// Only execute if run directly
177+
if (require.main === module) {
178+
main().catch(console.error);
179+
}
180+
181+
export { startFlowAndWait, monitorSteps, getRun, subscribeToRunEvents };

0 commit comments

Comments
 (0)