@pgflow/client 0.4.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/CHANGELOG.md +108 -0
- package/LICENSE +202 -0
- package/README.md +380 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +971 -0
- package/dist/index.js.map +1 -0
- package/dist/package.json +46 -0
- package/dist/pgflow-client.browser.js +2 -0
- package/dist/pgflow-client.browser.js.map +1 -0
- package/dist/src/browser.d.ts +7 -0
- package/dist/src/browser.d.ts.map +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/lib/FlowRun.d.ts +117 -0
- package/dist/src/lib/FlowRun.d.ts.map +1 -0
- package/dist/src/lib/FlowStep.d.ts +82 -0
- package/dist/src/lib/FlowStep.d.ts.map +1 -0
- package/dist/src/lib/PgflowClient.d.ts +73 -0
- package/dist/src/lib/PgflowClient.d.ts.map +1 -0
- package/dist/src/lib/SupabaseBroadcastAdapter.d.ts +65 -0
- package/dist/src/lib/SupabaseBroadcastAdapter.d.ts.map +1 -0
- package/dist/src/lib/eventAdapters.d.ts +21 -0
- package/dist/src/lib/eventAdapters.d.ts.map +1 -0
- package/dist/src/lib/types.d.ts +308 -0
- package/dist/src/lib/types.d.ts.map +1 -0
- package/package.json +46 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var G=e=>{throw TypeError(e)};var N=(e,t,s)=>t.has(e)||G("Cannot "+s);var r=(e,t,s)=>(N(e,t,"read from private field"),s?s.call(e):t.get(e)),c=(e,t,s)=>t.has(e)?G("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,s),g=(e,t,s,n)=>(N(e,t,"write to private field"),n?n.call(e,s):t.set(e,s),s),w=(e,t,s)=>(N(e,t,"access private method"),s);var j=(e,t,s,n)=>({set _(i){g(e,t,i,s)},get _(){return r(e,t,n)}});Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const st=require("uuid"),L=require("nanoevents");var u=(e=>(e.Started="started",e.Completed="completed",e.Failed="failed",e))(u||{});function rt(e){return!!e&&typeof e=="object"&&"run_id"in e&&"flow_slug"in e&&!("step_slug"in e)&&"status"in e&&(e.status==="started"||e.status==="completed"||e.status==="failed")}function nt(e){return e.status==="started"}function it(e){return e.status==="completed"}function at(e){return e.status==="failed"}var l=(e=>(e.Created="created",e.Started="started",e.Completed="completed",e.Failed="failed",e))(l||{});function J(e){return!!e&&typeof e=="object"&&"run_id"in e&&"step_slug"in e&&"status"in e&&(e.status==="started"||e.status==="completed"||e.status==="failed")}function ut(e){return J(e)&&e.status==="started"&&"event_type"in e&&e.event_type==="step:started"}function ot(e){return J(e)&&e.status==="completed"&&"event_type"in e&&e.event_type==="step:completed"}function lt(e){return J(e)&&e.status==="failed"&&"event_type"in e&&e.event_type==="step:failed"}var S,C,F,M,I,f,v,V,H,X,Y,Z,k,z;class dt{constructor(t,s={}){c(this,f);c(this,S);c(this,C,new Map);c(this,F,L.createNanoEvents());c(this,M);c(this,I);c(this,k,new Map);g(this,S,t),g(this,M,s.reconnectDelayMs??2e3),g(this,I,s.schedule??setTimeout)}async fetchFlowDefinition(t){const[s,n]=await Promise.all([r(this,S).schema("pgflow").from("flows").select("*").eq("flow_slug",t).single(),r(this,S).schema("pgflow").from("steps").select("*").eq("flow_slug",t).order("step_index",{ascending:!0})]);if(s.error)throw s.error;if(!s.data)throw new Error(`Flow "${t}" not found`);if(n.error)throw n.error;const i=Array.isArray(n.data)?n.data:[];return{flow:s.data,steps:i}}onRunEvent(t){const s=r(this,F).on("runEvent",t);return()=>{try{s()}catch(n){console.warn("Could not unsubscribe from run event - emitter may have been disposed",n)}}}onStepEvent(t){const s=r(this,F).on("stepEvent",t);return()=>{try{s()}catch(n){console.warn("Could not unsubscribe from step event - emitter may have been disposed",n)}}}async subscribeToRun(t){const s=`pgflow:run:${t}`;if(r(this,C).has(t)){const _=r(this,k).get(t);if(_)return _;w(this,f,z).call(this,t)}const n=r(this,S).channel(s);n.on("broadcast",{event:"*"},w(this,f,v).bind(this)),n.on("system",{event:"closed"},()=>{console.log(`Channel ${s} closed`)}),n.on("system",{event:"error"},_=>{console.log(`Channel ${s} error:`,_),w(this,f,H).call(this,t,s,n,_.error)}),console.log(`Subscribing to channel ${s}...`),await new Promise((_,h)=>{const d=setTimeout(()=>{h(new Error(`Subscription timeout for channel ${s}`))},2e4);n.subscribe(m=>{console.log(`Channel ${s} subscription status:`,m),m==="SUBSCRIBED"&&(clearTimeout(d),_())})}),r(this,C).set(t,n);const a=()=>this.unsubscribe(t);return r(this,k).set(t,a),a}unsubscribe(t){w(this,f,z).call(this,t)}async getRunWithStates(t){const{data:s,error:n}=await r(this,S).schema("pgflow").rpc("get_run_with_states",{run_id:t});if(n)throw n;if(!s)throw new Error(`No data returned for run ${t}`);return s}}S=new WeakMap,C=new WeakMap,F=new WeakMap,M=new WeakMap,I=new WeakMap,f=new WeakSet,v=function(t){const{event:s,payload:n}=t,i=n;w(this,f,V).call(this,i),s.startsWith("run:")?r(this,F).emit("runEvent",i):s.startsWith("step:")&&r(this,F).emit("stepEvent",i)},V=function(t){if("output"in t&&typeof t.output=="string")try{t.output=JSON.parse(t.output)}catch{}if("input"in t&&typeof t.input=="string")try{t.input=JSON.parse(t.input)}catch{}},H=async function(t,s,n,i){console.error(`Channel ${s} error:`,i),r(this,I).call(this,async()=>{r(this,C).has(t)&&await w(this,f,Y).call(this,t,s)},r(this,M))},X=function(t,s){const n=r(this,S).channel(s);return n.on("broadcast",{event:"*"},w(this,f,v).bind(this)),n},Y=async function(t,s){console.log(`Attempting to reconnect to ${s}`);try{const n=await this.getRunWithStates(t);w(this,f,Z).call(this,t,n);const i=w(this,f,X).call(this,t,s);i.on("system",{event:"subscribed"},()=>{console.log(`Reconnected and subscribed to channel ${s}`)}),i.on("system",{event:"closed"},()=>{console.log(`Reconnected channel ${s} closed`)}),i.on("system",{event:"error"},a=>w(this,f,H).call(this,t,s,i,a.error)),i.subscribe(),r(this,C).set(t,i)}catch(n){console.error(`Failed to reconnect to ${s}:`,n)}},Z=function(t,s){if(!s||!s.run)return;const n={event_type:`run:${s.run.status}`,...s.run};if(r(this,F).emit("runEvent",n),s.steps&&Array.isArray(s.steps))for(const i of s.steps){const a={event_type:`step:${i.status}`,...i};r(this,F).emit("stepEvent",a)}},k=new WeakMap,z=function(t){const s=r(this,C).get(t);s&&(s.unsubscribe(),r(this,C).delete(t),r(this,k).delete(t))};var p,$,W,O,tt;class ct{constructor(t){c(this,O);c(this,p);c(this,$,L.createNanoEvents());c(this,W,{[l.Created]:0,[l.Started]:1,[l.Completed]:2,[l.Failed]:3});g(this,p,t)}get run_id(){return r(this,p).run_id}get step_slug(){return r(this,p).step_slug}get status(){return r(this,p).status}get started_at(){return r(this,p).started_at}get completed_at(){return r(this,p).completed_at}get failed_at(){return r(this,p).failed_at}get output(){return r(this,p).output}get error(){return r(this,p).error}get error_message(){return r(this,p).error_message}on(t,s){return r(this,$).on(t,s)}waitForStatus(t,s){const n=(s==null?void 0:s.timeoutMs)??3e5,{signal:i}=s||{};return this.status===t?Promise.resolve(this):new Promise((a,_)=>{let h,d=!1;n>0&&(h=setTimeout(()=>{d||(d=!0,P(),_(new Error(`Timeout waiting for step ${this.step_slug} to reach status '${t}'`)))},n));let m;if(i){const E=()=>{d||(d=!0,h&&clearTimeout(h),P(),_(new Error(`Aborted waiting for step ${this.step_slug} to reach status '${t}'`)))};i.addEventListener("abort",E),m=()=>{i.removeEventListener("abort",E)}}const P=this.on("*",E=>{if(E.status===t){if(d)return;d=!0,h&&clearTimeout(h),m&&m(),P(),a(this)}})})}updateState(t){if(t.step_slug!==r(this,p).step_slug||t.run_id!==r(this,p).run_id||!w(this,O,tt).call(this,r(this,p).status,t.status))return!1;switch(t.status){case l.Started:g(this,p,{...r(this,p),status:l.Started,started_at:typeof t.started_at=="string"?new Date(t.started_at):new Date}),r(this,$).emit("started",t);break;case l.Completed:g(this,p,{...r(this,p),status:l.Completed,completed_at:typeof t.completed_at=="string"?new Date(t.completed_at):new Date,output:t.output}),r(this,$).emit("completed",t);break;case l.Failed:g(this,p,{...r(this,p),status:l.Failed,failed_at:typeof t.failed_at=="string"?new Date(t.failed_at):new Date,error_message:typeof t.error_message=="string"?t.error_message:"Unknown error",error:new Error(typeof t.error_message=="string"?t.error_message:"Unknown error")}),r(this,$).emit("failed",t);break;default:return!1}return r(this,$).emit("*",t),!0}}p=new WeakMap,$=new WeakMap,W=new WeakMap,O=new WeakSet,tt=function(t,s){if(t===l.Completed||t===l.Failed)return!1;const n=r(this,W)[t];return r(this,W)[s]>n};var o,R,A,q,U,D,T,B,et;class K{constructor(t){c(this,T);c(this,o);c(this,R,L.createNanoEvents());c(this,A,new Map);c(this,q,{[u.Started]:0,[u.Completed]:1,[u.Failed]:2});c(this,U,!1);c(this,D,0);g(this,o,t)}get run_id(){return r(this,o).run_id}get flow_slug(){return r(this,o).flow_slug}get status(){return r(this,o).status}get started_at(){return r(this,o).started_at}get completed_at(){return r(this,o).completed_at}get failed_at(){return r(this,o).failed_at}get input(){return r(this,o).input}get output(){return r(this,o).output}get error(){return r(this,o).error}get error_message(){return r(this,o).error_message}get remaining_steps(){return r(this,o).remaining_steps}on(t,s){j(this,D)._++;const n=r(this,R).on(t,s);return()=>{n(),j(this,D)._--,w(this,T,B).call(this)}}step(t){const s=r(this,A).get(t);if(s)return s;const n=new ct({run_id:this.run_id,step_slug:t,status:l.Created,output:null,error:null,error_message:null,started_at:null,completed_at:null,failed_at:null});return r(this,A).set(t,n),n}hasStep(t){return r(this,A).has(t)}waitForStatus(t,s){const n=(s==null?void 0:s.timeoutMs)??3e5,{signal:i}=s||{};return this.status===t?Promise.resolve(this):new Promise((a,_)=>{let h,d=!1;n>0&&(h=setTimeout(()=>{d||(d=!0,P(),_(new Error(`Timeout waiting for run ${this.run_id} to reach status '${t}'`)))},n));let m;if(i){const E=()=>{d||(d=!0,h&&clearTimeout(h),P(),_(new Error(`Aborted waiting for run ${this.run_id} to reach status '${t}'`)))};i.addEventListener("abort",E),m=()=>{i.removeEventListener("abort",E)}}const P=this.on("*",E=>{if(E.status===t){if(d)return;d=!0,h&&clearTimeout(h),m&&m(),P(),a(this)}})})}updateState(t){if(t.run_id!==r(this,o).run_id||!w(this,T,et).call(this,r(this,o).status,t.status))return!1;switch(t.status){case u.Started:g(this,o,{...r(this,o),status:u.Started,started_at:typeof t.started_at=="string"?new Date(t.started_at):new Date,remaining_steps:"remaining_steps"in t?Number(t.remaining_steps):r(this,o).remaining_steps}),r(this,R).emit("started",t);break;case u.Completed:g(this,o,{...r(this,o),status:u.Completed,completed_at:typeof t.completed_at=="string"?new Date(t.completed_at):new Date,output:t.output,remaining_steps:0}),r(this,R).emit("completed",t),w(this,T,B).call(this);break;case u.Failed:g(this,o,{...r(this,o),status:u.Failed,failed_at:typeof t.failed_at=="string"?new Date(t.failed_at):new Date,error_message:typeof t.error_message=="string"?t.error_message:"Unknown error",error:new Error(typeof t.error_message=="string"?t.error_message:"Unknown error")}),r(this,R).emit("failed",t),w(this,T,B).call(this);break;default:return!1}return r(this,R).emit("*",t),!0}updateStepState(t,s){return this.step(t).updateState(s)}dispose(){r(this,U)||(r(this,A).clear(),g(this,R,L.createNanoEvents()),g(this,D,0),g(this,U,!0))}}o=new WeakMap,R=new WeakMap,A=new WeakMap,q=new WeakMap,U=new WeakMap,D=new WeakMap,T=new WeakSet,B=function(){r(this,U)||this.status!==u.Completed&&this.status!==u.Failed||r(this,D)===0&&this.dispose()},et=function(t,s){if(t===u.Completed||t===u.Failed)return!1;const n=r(this,q)[t];return r(this,q)[s]>n};function pt(e){switch(e.status){case u.Started:return{event_type:"run:started",run_id:e.run_id,flow_slug:e.flow_slug,status:u.Started,started_at:e.started_at,remaining_steps:e.remaining_steps,input:e.input};case u.Completed:return{event_type:"run:completed",run_id:e.run_id,flow_slug:e.flow_slug,status:u.Completed,completed_at:e.completed_at,output:e.output};case u.Failed:return{event_type:"run:failed",run_id:e.run_id,flow_slug:e.flow_slug,status:u.Failed,failed_at:e.failed_at,error_message:e.error_message}}}function ht(e){switch(e.status){case l.Started:return{event_type:"step:started",run_id:e.run_id,step_slug:e.step_slug,status:l.Started,started_at:e.started_at};case l.Completed:return{event_type:"step:completed",run_id:e.run_id,step_slug:e.step_slug,status:l.Completed,completed_at:e.completed_at,output:e.output};case l.Failed:return{event_type:"step:failed",run_id:e.run_id,step_slug:e.step_slug,status:l.Failed,failed_at:e.failed_at,error_message:e.error_message}}}function _t(e){switch(e.status){case"started":return{event_type:"run:started",run_id:e.run_id,flow_slug:e.flow_slug,status:u.Started,started_at:e.started_at,remaining_steps:e.remaining_steps,input:e.input};case"completed":return{event_type:"run:completed",run_id:e.run_id,flow_slug:e.flow_slug,status:u.Completed,completed_at:e.completed_at,output:e.output};case"failed":return{event_type:"run:failed",run_id:e.run_id,flow_slug:e.flow_slug,status:u.Failed,failed_at:e.failed_at,error_message:"Flow failed"};default:throw new Error(`Unknown run status: ${e.status}`)}}function Q(e){switch(e.status){case"created":case"started":return{event_type:"step:started",run_id:e.run_id,step_slug:e.step_slug,status:l.Started,started_at:e.started_at};case"completed":return{event_type:"step:completed",run_id:e.run_id,step_slug:e.step_slug,status:l.Completed,completed_at:e.completed_at,output:{}};case"failed":return{event_type:"step:failed",run_id:e.run_id,step_slug:e.step_slug,status:l.Failed,failed_at:e.failed_at,error_message:e.error_message||"Step failed"};default:throw new Error(`Unknown step status: ${e.status}`)}}var x,b,y;class ft{constructor(t){c(this,x);c(this,b);c(this,y,new Map);g(this,x,t),g(this,b,new dt(t)),r(this,b).onRunEvent(s=>{const n=r(this,y).get(s.run_id);n&&n.updateState(pt(s))}),r(this,b).onStepEvent(s=>{const n=r(this,y).get(s.run_id);if(n){const i=s.step_slug;n.step(i).updateState(ht(s))}})}async startFlow(t,s,n){const i=n||st.v4(),a={run_id:i,flow_slug:t,status:u.Started,input:s,output:null,error:null,error_message:null,started_at:null,completed_at:null,failed_at:null,remaining_steps:-1},_=new K(a);r(this,y).set(i,_),await r(this,b).subscribeToRun(i);const{data:h,error:d}=await r(this,x).schema("pgflow").rpc("start_flow_with_states",{flow_slug:t,input:s,run_id:i});if(d)throw this.dispose(i),d;if(h.run&&_.updateState(_t(h.run)),h.steps&&Array.isArray(h.steps))for(const m of h.steps)_.step(m.step_slug).updateState(Q(m));return _}dispose(t){const s=r(this,y).get(t);s&&(r(this,b).unsubscribe(t),s.dispose(),r(this,y).delete(t))}disposeAll(){for(const t of r(this,y).keys())this.dispose(t)}async fetchFlowDefinition(t){return r(this,b).fetchFlowDefinition(t)}onRunEvent(t){return r(this,b).onRunEvent(t)}onStepEvent(t){return r(this,b).onStepEvent(t)}async subscribeToRun(t){return await r(this,b).subscribeToRun(t)}async getRunWithStates(t){return r(this,b).getRunWithStates(t)}async getRun(t){const s=r(this,y).get(t);if(s)return s;try{const{run:n,steps:i}=await this.getRunWithStates(t);if(!n)return null;const a=n;if(!a.run_id||!a.flow_slug||!a.status)throw new Error("Invalid run data: missing required fields");if(!Object.values(u).includes(a.status))throw new Error(`Invalid run data: invalid status '${a.status}'`);const h={run_id:a.run_id,flow_slug:a.flow_slug,status:a.status,input:a.input,output:a.output,error:a.error_message?new Error(a.error_message):null,error_message:a.error_message||null,started_at:a.started_at?new Date(a.started_at):null,completed_at:a.completed_at?new Date(a.completed_at):null,failed_at:a.failed_at?new Date(a.failed_at):null,remaining_steps:a.remaining_steps||0},d=new K(h);if(r(this,y).set(t,d),await r(this,b).subscribeToRun(t),i&&Array.isArray(i))for(const m of i){if(!m.step_slug||!m.status)throw new Error("Invalid step data: missing required fields");d.step(m.step_slug).updateState(Q(m))}return d}catch(n){if(console.error("Error getting run:",n),n instanceof Error&&(n.message.includes("Invalid run data")||n.message.includes("Invalid step data")))throw n;return null}}}x=new WeakMap,b=new WeakMap,y=new WeakMap;exports.FlowRunStatus=u;exports.FlowStepStatus=l;exports.PgflowClient=ft;exports.isFlowRunCompletedEvent=it;exports.isFlowRunEvent=rt;exports.isFlowRunFailedEvent=at;exports.isFlowRunStartedEvent=nt;exports.isStepCompletedEvent=ot;exports.isStepEvent=J;exports.isStepFailedEvent=lt;exports.isStepStartedEvent=ut;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/lib/types.ts","../src/lib/SupabaseBroadcastAdapter.ts","../src/lib/FlowStep.ts","../src/lib/FlowRun.ts","../src/lib/eventAdapters.ts","../src/lib/PgflowClient.ts"],"sourcesContent":["import type {\n AnyFlow,\n ExtractFlowInput,\n ExtractFlowOutput,\n ExtractFlowSteps,\n StepOutput,\n} from '@pgflow/dsl';\nimport type {\n Json,\n RunRow,\n StepStateRow,\n FlowRow,\n StepRow,\n} from '@pgflow/core';\nimport type { FlowRun } from './FlowRun.js';\n\n/**\n * Flow run status enum\n */\nexport enum FlowRunStatus {\n Started = 'started',\n Completed = 'completed',\n Failed = 'failed',\n}\n\n/**\n * Flow run event data types - individual event shapes (no circular reference)\n */\nexport type FlowRunEventData<TFlow extends AnyFlow> = {\n started: {\n event_type: 'run:started';\n run_id: string;\n flow_slug: string;\n input: ExtractFlowInput<TFlow>;\n status: FlowRunStatus.Started;\n started_at: string;\n remaining_steps: number;\n };\n completed: {\n event_type: 'run:completed';\n run_id: string;\n flow_slug: string;\n output: ExtractFlowOutput<TFlow>;\n status: FlowRunStatus.Completed;\n completed_at: string;\n };\n failed: {\n event_type: 'run:failed';\n run_id: string;\n flow_slug: string;\n error_message: string;\n status: FlowRunStatus.Failed;\n failed_at: string;\n };\n};\n\n/**\n * Strong discriminated union for all flow run events (no circular reference)\n */\nexport type FlowRunEvent<TFlow extends AnyFlow> =\n FlowRunEventData<TFlow>[keyof FlowRunEventData<TFlow>];\n\n/**\n * Type guard to check if an unknown value is a valid FlowRunEvent\n */\nexport function isFlowRunEvent<TFlow extends AnyFlow>(\n value: unknown\n): value is FlowRunEvent<TFlow> {\n return (\n !!value &&\n typeof value === 'object' &&\n 'run_id' in value &&\n 'flow_slug' in value &&\n !('step_slug' in value) &&\n 'status' in value &&\n (value.status === FlowRunStatus.Started ||\n value.status === FlowRunStatus.Completed ||\n value.status === FlowRunStatus.Failed)\n );\n}\n\n/**\n * Type guard for started events\n */\nexport function isFlowRunStartedEvent<TFlow extends AnyFlow>(\n event: FlowRunEvent<TFlow>\n): event is FlowRunEventData<TFlow>['started'] {\n return event.status === FlowRunStatus.Started;\n}\n\n/**\n * Type guard for completed events\n */\nexport function isFlowRunCompletedEvent<TFlow extends AnyFlow>(\n event: FlowRunEvent<TFlow>\n): event is FlowRunEventData<TFlow>['completed'] {\n return event.status === FlowRunStatus.Completed;\n}\n\n/**\n * Type guard for failed events\n */\nexport function isFlowRunFailedEvent<TFlow extends AnyFlow>(\n event: FlowRunEvent<TFlow>\n): event is FlowRunEventData<TFlow>['failed'] {\n return event.status === FlowRunStatus.Failed;\n}\n\n/**\n * Flow run event types matching nanoevents expectations (wildcard added separately)\n */\nexport type FlowRunEvents<TFlow extends AnyFlow> = {\n [K in keyof FlowRunEventData<TFlow>]: (\n event: FlowRunEventData<TFlow>[K]\n ) => void;\n} & {\n '*': (event: FlowRunEvent<TFlow>) => void;\n};\n\n/**\n * Flow step status enum\n */\nexport enum FlowStepStatus {\n Created = 'created',\n Started = 'started',\n Completed = 'completed',\n Failed = 'failed',\n}\n\n/**\n * Step event data types (no circular reference)\n */\nexport type StepEventData<\n TFlow extends AnyFlow,\n TStepSlug extends keyof ExtractFlowSteps<TFlow> & string\n> = {\n started: {\n event_type: 'step:started';\n run_id: string;\n step_slug: TStepSlug;\n status: FlowStepStatus.Started;\n started_at: string;\n };\n completed: {\n event_type: 'step:completed';\n run_id: string;\n step_slug: TStepSlug;\n output: StepOutput<TFlow, TStepSlug>;\n status: FlowStepStatus.Completed;\n completed_at: string;\n };\n failed: {\n event_type: 'step:failed';\n run_id: string;\n step_slug: TStepSlug;\n error_message: string;\n status: FlowStepStatus.Failed;\n failed_at: string;\n };\n};\n\n/**\n * Strong discriminated union for all step events (no circular reference)\n */\nexport type StepEvent<\n TFlow extends AnyFlow,\n TStepSlug extends keyof ExtractFlowSteps<TFlow> & string\n> = StepEventData<TFlow, TStepSlug>[keyof StepEventData<TFlow, TStepSlug>];\n\n/**\n * Type guard to check if an unknown value is a valid StepEvent\n */\nexport function isStepEvent<\n TFlow extends AnyFlow,\n TStepSlug extends keyof ExtractFlowSteps<TFlow> & string\n>(value: unknown): value is StepEvent<TFlow, TStepSlug> {\n return (\n !!value &&\n typeof value === 'object' &&\n 'run_id' in value &&\n 'step_slug' in value &&\n 'status' in value &&\n (value.status === FlowStepStatus.Started ||\n value.status === FlowStepStatus.Completed ||\n value.status === FlowStepStatus.Failed)\n );\n}\n\n/**\n * Type guard for started step events\n */\nexport function isStepStartedEvent<\n TFlow extends AnyFlow,\n TStepSlug extends keyof ExtractFlowSteps<TFlow> & string\n>(event: unknown): event is StepEventData<TFlow, TStepSlug>['started'] {\n return (\n isStepEvent<TFlow, TStepSlug>(event) &&\n event.status === FlowStepStatus.Started &&\n 'event_type' in event &&\n event.event_type === 'step:started'\n );\n}\n\n/**\n * Type guard for completed step events\n */\nexport function isStepCompletedEvent<\n TFlow extends AnyFlow,\n TStepSlug extends keyof ExtractFlowSteps<TFlow> & string\n>(event: unknown): event is StepEventData<TFlow, TStepSlug>['completed'] {\n return (\n isStepEvent<TFlow, TStepSlug>(event) &&\n event.status === FlowStepStatus.Completed &&\n 'event_type' in event &&\n event.event_type === 'step:completed'\n );\n}\n\n/**\n * Type guard for failed step events\n */\nexport function isStepFailedEvent<\n TFlow extends AnyFlow,\n TStepSlug extends keyof ExtractFlowSteps<TFlow> & string\n>(event: unknown): event is StepEventData<TFlow, TStepSlug>['failed'] {\n return (\n isStepEvent<TFlow, TStepSlug>(event) &&\n event.status === FlowStepStatus.Failed &&\n 'event_type' in event &&\n event.event_type === 'step:failed'\n );\n}\n\n/**\n * Step event types matching nanoevents expectations (wildcard added separately)\n */\nexport type StepEvents<\n TFlow extends AnyFlow,\n TStepSlug extends keyof ExtractFlowSteps<TFlow> & string\n> = {\n [K in keyof StepEventData<TFlow, TStepSlug>]: (\n event: StepEventData<TFlow, TStepSlug>[K]\n ) => void;\n} & {\n '*': (event: StepEvent<TFlow, TStepSlug>) => void;\n};\n\n/**\n * Function returned by event subscriptions to remove the listener\n */\nexport type Unsubscribe = () => void;\n\n/**\n * Broadcast run event types for Supabase realtime\n */\nexport type BroadcastRunStartedEvent = {\n event_type: 'run:started';\n run_id: string;\n flow_slug: string;\n status: FlowRunStatus.Started;\n input: Json;\n started_at: string;\n remaining_steps: number;\n error_message?: string; // Adding for type compatibility\n};\n\nexport type BroadcastRunCompletedEvent = {\n event_type: 'run:completed';\n run_id: string;\n flow_slug: string;\n status: FlowRunStatus.Completed;\n output: Json;\n completed_at: string;\n error_message?: string; // Adding for type compatibility\n};\n\nexport type BroadcastRunFailedEvent = {\n event_type: 'run:failed';\n run_id: string;\n flow_slug: string;\n status: FlowRunStatus.Failed;\n error_message: string;\n failed_at: string;\n};\n\nexport type BroadcastRunEvent =\n | BroadcastRunStartedEvent\n | BroadcastRunCompletedEvent\n | BroadcastRunFailedEvent;\n\n/**\n * Broadcast step event types for Supabase realtime\n */\nexport type BroadcastStepStartedEvent = {\n event_type: 'step:started';\n run_id: string;\n step_slug: string;\n status: FlowStepStatus.Started;\n started_at: string;\n remaining_tasks: number;\n remaining_deps: number;\n error_message?: string; // Adding for type compatibility\n output?: Json; // Adding for type compatibility\n};\n\nexport type BroadcastStepCompletedEvent = {\n event_type: 'step:completed';\n run_id: string;\n step_slug: string;\n status: FlowStepStatus.Completed;\n output: Json;\n completed_at: string;\n error_message?: string; // Adding for type compatibility\n};\n\nexport type BroadcastStepFailedEvent = {\n event_type: 'step:failed';\n run_id: string;\n step_slug: string;\n status: FlowStepStatus.Failed;\n error_message: string;\n failed_at: string;\n output?: Json; // Adding for type compatibility\n};\n\nexport type BroadcastStepEvent =\n | BroadcastStepStartedEvent\n | BroadcastStepCompletedEvent\n | BroadcastStepFailedEvent;\n\n/**\n * Flow run state\n */\nexport type FlowRunState<TFlow extends AnyFlow> = {\n run_id: string;\n flow_slug: string;\n status: FlowRunStatus;\n input: ExtractFlowInput<TFlow>;\n output: ExtractFlowOutput<TFlow> | null;\n error: Error | null;\n error_message: string | null;\n started_at: Date | null;\n completed_at: Date | null;\n failed_at: Date | null;\n remaining_steps: number;\n};\n\n/**\n * Flow step state\n */\nexport type FlowStepState<\n TFlow extends AnyFlow,\n TStepSlug extends keyof ExtractFlowSteps<TFlow> & string\n> = {\n run_id: string;\n step_slug: TStepSlug;\n status: FlowStepStatus;\n output: StepOutput<TFlow, TStepSlug> | null;\n error: Error | null;\n error_message: string | null;\n started_at: Date | null;\n completed_at: Date | null;\n failed_at: Date | null;\n};\n\n/**\n * Interface for realtime updates (used by client library)\n */\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport interface IFlowRealtime<TFlow = unknown> {\n /**\n * Fetch flow definition metadata (looks up flows and steps tables)\n */\n fetchFlowDefinition(flow_slug: string): Promise<{\n flow: FlowRow;\n steps: StepRow[];\n }>;\n\n /**\n * Register a callback for run events\n * @returns Function to unsubscribe from the event\n */\n onRunEvent(callback: (event: BroadcastRunEvent) => void): Unsubscribe;\n\n /**\n * Register a callback for step events\n * @returns Function to unsubscribe from the event\n */\n onStepEvent(callback: (event: BroadcastStepEvent) => void): Unsubscribe;\n\n /**\n * Subscribe to a flow run's events\n */\n subscribeToRun(run_id: string): Promise<Unsubscribe>;\n\n /**\n * Fetch current state of a run and its steps\n */\n getRunWithStates(\n run_id: string\n ): Promise<{ run: RunRow; steps: StepStateRow[] }>;\n}\n\n/**\n * Generic base interface for flow runs that uses proper event types\n */\nexport interface FlowRunBase<TEvt = unknown> {\n readonly run_id: string;\n updateState(event: TEvt): boolean;\n step(stepSlug: string): FlowStepBase<unknown>;\n hasStep(stepSlug: string): boolean;\n dispose(): void;\n}\n\n/**\n * Generic base interface for flow steps that uses proper event types\n */\nexport interface FlowStepBase<TEvt = unknown> {\n updateState(event: TEvt): boolean;\n}\n\n/**\n * Utility type for broadcast events\n */\nexport type BroadcastEvent = BroadcastRunEvent | BroadcastStepEvent;\n\n/**\n * Composite interface for client\n */\nexport interface IFlowClient<TFlow extends AnyFlow = AnyFlow>\n extends IFlowRealtime<TFlow> {\n /**\n * Start a flow with optional run_id\n *\n * @param flow_slug - Flow slug to start\n * @param input - Input data for the flow\n * @param run_id - Optional run ID (will be generated if not provided)\n * @returns Promise that resolves with the FlowRun instance\n */\n startFlow<TSpecificFlow extends TFlow>(\n flow_slug: string,\n input: ExtractFlowInput<TSpecificFlow>,\n run_id?: string\n ): Promise<FlowRun<TSpecificFlow>>;\n\n /**\n * Get a flow run by ID\n *\n * @param run_id - ID of the run to get\n * @returns Promise that resolves with the FlowRun instance or null if not found\n */\n getRun<TSpecificFlow extends TFlow = TFlow>(\n run_id: string\n ): Promise<FlowRun<TSpecificFlow> | null>;\n}\n","import type { RealtimeChannel, SupabaseClient } from '@supabase/supabase-js';\nimport type { FlowRow, StepRow, RunRow, StepStateRow } from '@pgflow/core';\nimport { createNanoEvents } from 'nanoevents';\nimport type {\n IFlowRealtime,\n BroadcastRunEvent,\n BroadcastStepEvent,\n Unsubscribe,\n} from './types.js';\n\n// Define the events interface for the adapter\ninterface AdapterEvents {\n runEvent: (event: BroadcastRunEvent) => void;\n stepEvent: (event: BroadcastStepEvent) => void;\n}\n\n/**\n * Adapter to handle realtime communication with Supabase\n */\nexport class SupabaseBroadcastAdapter implements IFlowRealtime {\n #supabase: SupabaseClient;\n #channels: Map<string, RealtimeChannel> = new Map();\n #emitter = createNanoEvents<AdapterEvents>();\n #reconnectionDelay: number;\n #schedule: typeof setTimeout;\n \n\n /**\n * Creates a new instance of SupabaseBroadcastAdapter\n *\n * @param supabase - Supabase client instance\n */\n constructor(\n supabase: SupabaseClient,\n opts: { reconnectDelayMs?: number; schedule?: typeof setTimeout } = {}\n ) {\n this.#supabase = supabase;\n this.#reconnectionDelay = opts.reconnectDelayMs ?? 2000;\n this.#schedule = opts.schedule ?? setTimeout;\n }\n \n /**\n * Handle broadcast messages from Supabase\n * @param payload - The message payload\n */\n #handleBroadcastMessage(msg: { \n event: string; \n payload: BroadcastRunEvent | BroadcastStepEvent;\n }): void {\n const { event, payload } = msg;\n \n // run_id is already inside the payload coming from the database trigger\n // so just preserve it without overwriting\n const eventData = payload;\n\n // Auto-parse JSON strings in broadcast data (realtime sends JSONB as strings)\n this.#parseJsonFields(eventData);\n\n if (event.startsWith('run:')) {\n // Handle run events\n this.#emitter.emit('runEvent', eventData as BroadcastRunEvent);\n } else if (event.startsWith('step:')) {\n // Handle step events\n this.#emitter.emit('stepEvent', eventData as BroadcastStepEvent);\n }\n }\n\n /**\n * Parse JSON string fields in broadcast event data\n * @param eventData - The event data object to parse\n */\n #parseJsonFields(eventData: Record<string, unknown>): void {\n // Parse output field if it's a JSON string\n if ('output' in eventData && typeof eventData.output === 'string') {\n try {\n eventData.output = JSON.parse(eventData.output);\n } catch {\n // Keep as string if not valid JSON\n }\n }\n \n // Parse input field if it's a JSON string\n if ('input' in eventData && typeof eventData.input === 'string') {\n try {\n eventData.input = JSON.parse(eventData.input);\n } catch {\n // Keep as string if not valid JSON\n }\n }\n }\n\n \n /**\n * Handle channel errors and reconnection\n * @param run_id - The run ID\n * @param channelName - The channel name\n * @param channel - The RealtimeChannel instance\n * @param error - The error object\n */\n async #handleChannelError(\n run_id: string,\n channelName: string,\n channel: RealtimeChannel,\n error: unknown\n ): Promise<void> {\n console.error(`Channel ${channelName} error:`, error);\n \n // Schedule reconnection attempt\n this.#schedule(async () => {\n if (this.#channels.has(run_id)) {\n await this.#reconnectChannel(run_id, channelName);\n }\n }, this.#reconnectionDelay);\n }\n \n /**\n * Creates and configures a channel for a run\n * @param run_id - The run ID\n * @param channelName - The channel name\n * @returns The configured RealtimeChannel\n */\n #createAndConfigureChannel(run_id: string, channelName: string): RealtimeChannel {\n const channel = this.#supabase.channel(channelName);\n \n // Listen to *all* broadcast messages; filter inside the handler.\n // Using the 3-arg overload with event filter for proper Supabase v2 client compatibility.\n channel.on('broadcast', { event: '*' }, this.#handleBroadcastMessage.bind(this));\n \n // Note: Lifecycle event listeners (subscribed, closed, error) are handled \n // by the calling code to avoid conflicts when multiple listeners try to \n // handle the same events.\n \n return channel;\n }\n \n /**\n * Reconnect to a channel and refresh state\n * @param run_id - The run ID\n * @param channelName - The channel name\n */\n async #reconnectChannel(\n run_id: string,\n channelName: string\n ): Promise<void> {\n console.log(`Attempting to reconnect to ${channelName}`);\n \n try {\n // Fetch current state to avoid missing events during disconnection\n const currentState = await this.getRunWithStates(run_id);\n \n // Update state based on current data\n this.#refreshStateFromSnapshot(run_id, currentState);\n \n // Create a new channel as the old one can't be reused\n const newChannel = this.#createAndConfigureChannel(run_id, channelName);\n \n // Set up lifecycle event handlers for reconnection\n newChannel.on('system', { event: 'subscribed' }, () => {\n console.log(`Reconnected and subscribed to channel ${channelName}`);\n });\n \n newChannel.on('system', { event: 'closed' }, () => {\n console.log(`Reconnected channel ${channelName} closed`);\n });\n \n newChannel.on('system', { event: 'error' }, (payload) => \n this.#handleChannelError(run_id, channelName, newChannel, payload.error)\n );\n \n // Subscribe and update the channels map\n newChannel.subscribe();\n this.#channels.set(run_id, newChannel);\n } catch (e) {\n console.error(`Failed to reconnect to ${channelName}:`, e);\n }\n }\n \n /**\n * Refresh client state from a state snapshot\n * @param run_id - The run ID\n * @param state - The state snapshot\n */\n #refreshStateFromSnapshot(\n run_id: string,\n state: { run: RunRow; steps: StepStateRow[] } | null\n ): void {\n if (!state || !state.run) return;\n \n // Create proper run event with correct event_type\n const runEvent: BroadcastRunEvent = {\n event_type: `run:${state.run.status}`,\n ...state.run\n } as unknown as BroadcastRunEvent;\n \n // Emit run event\n this.#emitter.emit('runEvent', runEvent);\n \n // Emit events for each step state\n if (state.steps && Array.isArray(state.steps)) {\n for (const step of state.steps) {\n // Create proper step event with correct event_type\n const stepEvent: BroadcastStepEvent = {\n event_type: `step:${step.status}`,\n ...step\n } as unknown as BroadcastStepEvent;\n \n // Emit step event\n this.#emitter.emit('stepEvent', stepEvent);\n }\n }\n }\n\n /**\n * Fetches flow definition metadata from the database\n *\n * @param flow_slug - Flow slug to fetch\n */\n async fetchFlowDefinition(flow_slug: string): Promise<{\n flow: FlowRow;\n steps: StepRow[];\n }> {\n // Fetch flow details and steps in parallel\n const [flowResult, stepsResult] = await Promise.all([\n this.#supabase\n .schema('pgflow')\n .from('flows')\n .select('*')\n .eq('flow_slug', flow_slug)\n .single(),\n this.#supabase\n .schema('pgflow')\n .from('steps')\n .select('*')\n .eq('flow_slug', flow_slug)\n .order('step_index', { ascending: true })\n ]);\n\n // Handle flow result\n if (flowResult.error) throw flowResult.error;\n if (!flowResult.data) throw new Error(`Flow \"${flow_slug}\" not found`);\n\n // Handle steps result\n if (stepsResult.error) throw stepsResult.error;\n \n // Ensure steps is always an array, even if it's null or undefined\n const stepsArray = Array.isArray(stepsResult.data) ? stepsResult.data : [];\n\n return {\n flow: flowResult.data as FlowRow,\n steps: stepsArray as StepRow[],\n };\n }\n\n /**\n * Registers a callback for run events\n *\n * @param callback - Function to call when run events are received\n * @returns Function to unsubscribe from the event\n */\n onRunEvent(callback: (event: BroadcastRunEvent) => void): Unsubscribe {\n // Add a guard to prevent errors if called after emitter is deleted\n const unsubscribe = this.#emitter.on('runEvent', callback);\n return () => {\n try {\n unsubscribe();\n } catch (e) {\n console.warn('Could not unsubscribe from run event - emitter may have been disposed', e);\n }\n };\n }\n\n /**\n * Registers a callback for step events\n *\n * @param callback - Function to call when step events are received\n * @returns Function to unsubscribe from the event\n */\n onStepEvent(callback: (event: BroadcastStepEvent) => void): Unsubscribe {\n // Add a guard to prevent errors if called after emitter is deleted\n const unsubscribe = this.#emitter.on('stepEvent', callback);\n return () => {\n try {\n unsubscribe();\n } catch (e) {\n console.warn('Could not unsubscribe from step event - emitter may have been disposed', e);\n }\n };\n }\n\n // Store unsubscribe functions per run ID for reference equality\n #unsubscribeFunctions: Map<string, () => void> = new Map();\n\n /**\n * Subscribes to a flow run's events\n *\n * @param run_id - Run ID to subscribe to\n * @returns Function to unsubscribe\n */\n async subscribeToRun(run_id: string): Promise<() => void> {\n const channelName = `pgflow:run:${run_id}`;\n\n // If already subscribed, return the existing unsubscribe function\n if (this.#channels.has(run_id)) {\n const existingUnsubscribe = this.#unsubscribeFunctions.get(run_id);\n if (existingUnsubscribe) {\n return existingUnsubscribe;\n }\n // If channel exists but no unsubscribe function, something went wrong\n // Let's clean up and recreate\n this.#unsubscribe(run_id);\n }\n\n const channel = this.#supabase.channel(channelName);\n \n // Listen to *all* broadcast messages; filter inside the handler.\n // Using the 3-arg overload with event filter for proper Supabase v2 client compatibility.\n channel.on('broadcast', { event: '*' }, this.#handleBroadcastMessage.bind(this));\n \n // Set up error handling\n channel.on('system', { event: 'closed' }, () => {\n console.log(`Channel ${channelName} closed`);\n });\n channel.on('system', { event: 'error' }, (payload) => {\n console.log(`Channel ${channelName} error:`, payload);\n this.#handleChannelError(run_id, channelName, channel, payload.error);\n });\n \n // Subscribe to channel and wait for confirmation (like the working realtime-send test)\n console.log(`Subscribing to channel ${channelName}...`);\n \n const subscriptionPromise = new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(`Subscription timeout for channel ${channelName}`));\n }, 20000); // Increased from 5s to 20s for slower CI environments\n \n channel.subscribe((status) => {\n console.log(`Channel ${channelName} subscription status:`, status);\n if (status === 'SUBSCRIBED') {\n clearTimeout(timeout);\n resolve();\n }\n // Don't reject on CHANNEL_ERROR - it's a transient state\n // Only reject on timeout\n });\n });\n \n // Wait for the 'SUBSCRIBED' acknowledgment to avoid race conditions\n await subscriptionPromise;\n \n this.#channels.set(run_id, channel);\n\n const unsubscribe = () => this.unsubscribe(run_id);\n this.#unsubscribeFunctions.set(run_id, unsubscribe);\n return unsubscribe;\n }\n \n /**\n * Unsubscribes from a run's events\n * \n * @param run_id - Run ID to unsubscribe from\n */\n unsubscribe(run_id: string): void {\n this.#unsubscribe(run_id);\n }\n\n /**\n * Fetches current state of a run and its steps\n *\n * @param run_id - Run ID to fetch\n */\n async getRunWithStates(run_id: string): Promise<{\n run: RunRow;\n steps: StepStateRow[];\n }> {\n // Call the RPC function which returns a JSONB object\n const { data, error } = await this.#supabase\n .schema('pgflow')\n .rpc('get_run_with_states', { run_id });\n\n if (error) throw error;\n if (!data) throw new Error(`No data returned for run ${run_id}`);\n \n return data as { run: RunRow; steps: StepStateRow[] };\n }\n\n /**\n * Unsubscribes from a run's events\n *\n * @param run_id - Run ID to unsubscribe from\n */\n #unsubscribe(run_id: string): void {\n const channel = this.#channels.get(run_id);\n if (channel) {\n // Close the channel\n channel.unsubscribe();\n this.#channels.delete(run_id);\n \n // Also clean up the unsubscribe function reference\n this.#unsubscribeFunctions.delete(run_id);\n \n // We don't need to explicitly remove event listeners from the emitter\n // as they will be garbage collected when no longer referenced.\n // The event listeners are bound to specific callbacks provided by the client,\n // which will retain references if they're still in use.\n }\n }\n}\n","import { createNanoEvents } from 'nanoevents';\nimport type { AnyFlow, ExtractFlowSteps, StepOutput } from '@pgflow/dsl';\nimport { FlowStepStatus } from './types.js';\nimport type { \n FlowStepState, \n StepEvents, \n Unsubscribe, \n FlowStepBase,\n StepEvent\n} from './types.js';\n\n/**\n * Represents a single step in a flow run\n */\nexport class FlowStep<\n TFlow extends AnyFlow,\n TStepSlug extends keyof ExtractFlowSteps<TFlow> & string\n> implements FlowStepBase<StepEvent<TFlow, TStepSlug>> {\n #state: FlowStepState<TFlow, TStepSlug>;\n #events = createNanoEvents<StepEvents<TFlow, TStepSlug>>();\n #statusPrecedence: Record<FlowStepStatus, number> = {\n [FlowStepStatus.Created]: 0,\n [FlowStepStatus.Started]: 1,\n [FlowStepStatus.Completed]: 2,\n [FlowStepStatus.Failed]: 3,\n };\n\n /**\n * Creates a new FlowStep instance\n * \n * @param initialState - Initial state for the step\n */\n constructor(initialState: FlowStepState<TFlow, TStepSlug>) {\n this.#state = initialState;\n }\n\n /**\n * Get the run ID this step belongs to\n */\n get run_id(): string {\n return this.#state.run_id;\n }\n\n /**\n * Get the step slug\n */\n get step_slug(): TStepSlug {\n return this.#state.step_slug;\n }\n\n /**\n * Get the current status\n */\n get status(): FlowStepStatus {\n return this.#state.status;\n }\n\n /**\n * Get the started_at timestamp\n */\n get started_at(): Date | null {\n return this.#state.started_at;\n }\n\n /**\n * Get the completed_at timestamp\n */\n get completed_at(): Date | null {\n return this.#state.completed_at;\n }\n\n /**\n * Get the failed_at timestamp\n */\n get failed_at(): Date | null {\n return this.#state.failed_at;\n }\n\n /**\n * Get the step output\n */\n get output(): StepOutput<TFlow, TStepSlug> | null {\n return this.#state.output;\n }\n\n /**\n * Get the error object\n */\n get error(): Error | null {\n return this.#state.error;\n }\n\n /**\n * Get the error message\n */\n get error_message(): string | null {\n return this.#state.error_message;\n }\n\n /**\n * Register an event handler for a step event\n * \n * @param event - Event type to listen for\n * @param callback - Callback function to execute when event is emitted\n * @returns Function to unsubscribe from the event\n */\n on<E extends keyof StepEvents<TFlow, TStepSlug>>(\n event: E,\n callback: StepEvents<TFlow, TStepSlug>[E]\n ): Unsubscribe {\n return this.#events.on(event, callback);\n }\n\n /**\n * Wait for the step to reach a specific status\n * \n * @param targetStatus - The status to wait for\n * @param options - Optional timeout and abort signal\n * @returns Promise that resolves with the step instance when the status is reached\n */\n waitForStatus(\n targetStatus: FlowStepStatus.Started | FlowStepStatus.Completed | FlowStepStatus.Failed,\n options?: { timeoutMs?: number; signal?: AbortSignal }\n ): Promise<this> {\n const timeoutMs = options?.timeoutMs ?? 5 * 60 * 1000; // Default 5 minutes\n const { signal } = options || {};\n\n // If we already have the target status, resolve immediately\n if (this.status === targetStatus) {\n return Promise.resolve(this);\n }\n\n // Otherwise, wait for the status to change\n return new Promise((resolve, reject) => {\n let timeoutId: NodeJS.Timeout | undefined;\n let cleanedUp = false;\n \n // Set up timeout if provided\n if (timeoutMs > 0) {\n timeoutId = setTimeout(() => {\n if (cleanedUp) return; // Prevent firing if already cleaned up\n cleanedUp = true;\n unbind();\n reject(new Error(`Timeout waiting for step ${this.step_slug} to reach status '${targetStatus}'`));\n }, timeoutMs);\n }\n \n // Set up abort signal if provided\n let abortCleanup: (() => void) | undefined;\n if (signal) {\n const abortHandler = () => {\n if (cleanedUp) return; // Prevent double cleanup\n cleanedUp = true;\n if (timeoutId) clearTimeout(timeoutId);\n unbind();\n reject(new Error(`Aborted waiting for step ${this.step_slug} to reach status '${targetStatus}'`));\n };\n \n signal.addEventListener('abort', abortHandler);\n abortCleanup = () => {\n signal.removeEventListener('abort', abortHandler);\n };\n }\n \n // Subscribe to all events\n const unbind = this.on('*', (event) => {\n if (event.status === targetStatus) {\n if (cleanedUp) return; // Prevent double cleanup\n cleanedUp = true;\n if (timeoutId) clearTimeout(timeoutId);\n if (abortCleanup) abortCleanup();\n unbind();\n resolve(this);\n }\n });\n });\n }\n\n /**\n * Updates the step state based on an event\n * \n * @internal This method is only intended for use by FlowRun and tests.\n * Applications should not call this directly - state updates should come from\n * database events through the PgflowClient.\n * \n * TODO: After v1.0, make this method private and refactor tests to use PgflowClient\n * with event emission instead of direct state manipulation.\n */\n updateState(event: StepEvent<TFlow, TStepSlug>): boolean {\n // Validate event is for this step\n if (event.step_slug !== this.#state.step_slug) {\n return false;\n }\n \n // Validate event is for this run\n if (event.run_id !== this.#state.run_id) {\n return false;\n }\n \n // Check if the event status has higher precedence than current status\n if (!this.#shouldUpdateStatus(this.#state.status, event.status)) {\n return false;\n }\n\n // Update state based on event type using narrowing type guards\n switch (event.status) {\n case FlowStepStatus.Started:\n this.#state = {\n ...this.#state,\n status: FlowStepStatus.Started,\n started_at: typeof event.started_at === 'string' ? new Date(event.started_at) : new Date(),\n };\n this.#events.emit('started', event);\n break;\n\n case FlowStepStatus.Completed:\n this.#state = {\n ...this.#state,\n status: FlowStepStatus.Completed,\n completed_at: typeof event.completed_at === 'string' ? new Date(event.completed_at) : new Date(),\n output: event.output as StepOutput<TFlow, TStepSlug>,\n };\n this.#events.emit('completed', event);\n break;\n\n case FlowStepStatus.Failed:\n this.#state = {\n ...this.#state,\n status: FlowStepStatus.Failed,\n failed_at: typeof event.failed_at === 'string' ? new Date(event.failed_at) : new Date(),\n error_message: typeof event.error_message === 'string' ? event.error_message : 'Unknown error',\n error: new Error(typeof event.error_message === 'string' ? event.error_message : 'Unknown error'),\n };\n this.#events.emit('failed', event);\n break;\n\n default: {\n // Exhaustiveness check - should never happen with proper types\n // @ts-expect-error Intentional exhaustiveness check\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const _exhaustivenessCheck: never = event;\n return false;\n }\n }\n\n // Also emit to the catch-all listener\n this.#events.emit('*', event);\n \n return true;\n }\n\n /**\n * Determines if a status should be updated based on precedence\n * \n * @param currentStatus - Current status\n * @param newStatus - New status\n * @returns true if the status should be updated, false otherwise\n */\n #shouldUpdateStatus(currentStatus: FlowStepStatus, newStatus: FlowStepStatus): boolean {\n // Don't allow changes to terminal states\n if (currentStatus === FlowStepStatus.Completed || currentStatus === FlowStepStatus.Failed) {\n return false; // Terminal states should never change\n }\n \n const currentPrecedence = this.#statusPrecedence[currentStatus];\n const newPrecedence = this.#statusPrecedence[newStatus];\n\n // Only allow transitions to higher precedence non-terminal status\n return newPrecedence > currentPrecedence;\n }\n}","import { createNanoEvents } from 'nanoevents';\nimport type {\n AnyFlow,\n ExtractFlowInput,\n ExtractFlowOutput,\n ExtractFlowSteps,\n} from '@pgflow/dsl';\nimport { FlowRunStatus, FlowStepStatus } from './types.js';\nimport type {\n FlowRunState,\n FlowRunEvents,\n Unsubscribe,\n FlowRunBase,\n FlowStepBase,\n FlowRunEvent,\n StepEvent,\n} from './types.js';\nimport { FlowStep } from './FlowStep.js';\n\n/**\n * Represents a single execution of a flow\n */\nexport class FlowRun<TFlow extends AnyFlow>\n implements FlowRunBase<FlowRunEvent<TFlow>>\n{\n #state: FlowRunState<TFlow>;\n #events = createNanoEvents<FlowRunEvents<TFlow>>();\n #steps = new Map<string, FlowStepBase>();\n #statusPrecedence: Record<FlowRunStatus, number> = {\n [FlowRunStatus.Started]: 0,\n [FlowRunStatus.Completed]: 1,\n [FlowRunStatus.Failed]: 2,\n };\n #disposed = false;\n\n /**\n * Creates a new FlowRun instance\n *\n * @param initialState - Initial state for the run\n */\n constructor(initialState: FlowRunState<TFlow>) {\n this.#state = initialState;\n }\n\n /**\n * Get the run ID\n */\n get run_id(): string {\n return this.#state.run_id;\n }\n\n /**\n * Get the flow slug\n */\n get flow_slug(): string {\n return this.#state.flow_slug;\n }\n\n /**\n * Get the current status\n */\n get status(): FlowRunStatus {\n return this.#state.status;\n }\n\n /**\n * Get the started_at timestamp\n */\n get started_at(): Date | null {\n return this.#state.started_at;\n }\n\n /**\n * Get the completed_at timestamp\n */\n get completed_at(): Date | null {\n return this.#state.completed_at;\n }\n\n /**\n * Get the failed_at timestamp\n */\n get failed_at(): Date | null {\n return this.#state.failed_at;\n }\n\n /**\n * Get the flow input\n */\n get input(): ExtractFlowInput<TFlow> {\n return this.#state.input;\n }\n\n /**\n * Get the flow output\n */\n get output(): ExtractFlowOutput<TFlow> | null {\n return this.#state.output;\n }\n\n /**\n * Get the error object\n */\n get error(): Error | null {\n return this.#state.error;\n }\n\n /**\n * Get the error message\n */\n get error_message(): string | null {\n return this.#state.error_message;\n }\n\n /**\n * Get the number of remaining steps\n */\n get remaining_steps(): number {\n return this.#state.remaining_steps;\n }\n\n /**\n * Register an event handler for a run event\n *\n * @param event - Event type to listen for\n * @param callback - Callback function to execute when event is emitted\n * @returns Function to unsubscribe from the event\n */\n on<E extends keyof FlowRunEvents<TFlow>>(\n event: E,\n callback: FlowRunEvents<TFlow>[E]\n ): Unsubscribe {\n this.#listenerCount++;\n\n // Wrap the unsubscribe function to track listener count\n const unsubscribe = this.#events.on(event, callback);\n\n return () => {\n unsubscribe();\n this.#listenerCount--;\n this.#checkAutoDispose();\n };\n }\n\n /**\n * Get a FlowStep instance for a specific step\n *\n * @param stepSlug - Step slug to get\n * @returns FlowStep instance for the specified step\n */\n step<TStepSlug extends keyof ExtractFlowSteps<TFlow> & string>(\n stepSlug: TStepSlug\n ): FlowStep<TFlow, TStepSlug> {\n // Look up if we already have this step cached\n const existingStep = this.#steps.get(stepSlug as string);\n if (existingStep) {\n // Safe to cast since we only store steps with matching slugs\n return existingStep as unknown as FlowStep<TFlow, TStepSlug>;\n }\n\n // Create a new step instance with default state\n const step = new FlowStep<TFlow, TStepSlug>({\n run_id: this.run_id,\n step_slug: stepSlug,\n status: FlowStepStatus.Created,\n output: null,\n error: null,\n error_message: null,\n started_at: null,\n completed_at: null,\n failed_at: null,\n });\n\n // Cache the step\n this.#steps.set(\n stepSlug as string,\n step as FlowStepBase<StepEvent<TFlow, TStepSlug>>\n );\n\n return step;\n }\n\n /**\n * Check if this run has a specific step\n *\n * @param stepSlug - Step slug to check\n * @returns true if the step exists, false otherwise\n */\n hasStep(stepSlug: string): boolean {\n // Check if we have this step cached\n return this.#steps.has(stepSlug);\n }\n\n /**\n * Wait for the run to reach a specific status\n *\n * @param targetStatus - The status to wait for\n * @param options - Optional timeout and abort signal\n * @returns Promise that resolves with the run instance when the status is reached\n */\n waitForStatus(\n targetStatus: FlowRunStatus.Completed | FlowRunStatus.Failed,\n options?: { timeoutMs?: number; signal?: AbortSignal }\n ): Promise<this> {\n const timeoutMs = options?.timeoutMs ?? 5 * 60 * 1000; // Default 5 minutes\n const { signal } = options || {};\n\n // If we already have the target status, resolve immediately\n if (this.status === targetStatus) {\n return Promise.resolve(this);\n }\n\n // Otherwise, wait for the status to change\n return new Promise((resolve, reject) => {\n let timeoutId: NodeJS.Timeout | undefined;\n let cleanedUp = false;\n\n // Set up timeout if provided\n if (timeoutMs > 0) {\n timeoutId = setTimeout(() => {\n if (cleanedUp) return; // Prevent firing if already cleaned up\n cleanedUp = true;\n unbind();\n reject(\n new Error(\n `Timeout waiting for run ${this.run_id} to reach status '${targetStatus}'`\n )\n );\n }, timeoutMs);\n }\n\n // Set up abort signal if provided\n let abortCleanup: (() => void) | undefined;\n if (signal) {\n const abortHandler = () => {\n if (cleanedUp) return; // Prevent double cleanup\n cleanedUp = true;\n if (timeoutId) clearTimeout(timeoutId);\n unbind();\n reject(\n new Error(\n `Aborted waiting for run ${this.run_id} to reach status '${targetStatus}'`\n )\n );\n };\n\n signal.addEventListener('abort', abortHandler);\n abortCleanup = () => {\n signal.removeEventListener('abort', abortHandler);\n };\n }\n\n // Subscribe to all events\n const unbind = this.on('*', (event) => {\n if (event.status === targetStatus) {\n if (cleanedUp) return; // Prevent double cleanup\n cleanedUp = true;\n if (timeoutId) clearTimeout(timeoutId);\n if (abortCleanup) abortCleanup();\n unbind();\n resolve(this);\n }\n });\n });\n }\n\n /**\n * Updates the run state based on an event\n * \n * @internal This method is only intended for use by PgflowClient and tests.\n * Applications should not call this directly - state updates should come from\n * database events through the PgflowClient.\n * \n * TODO: After v1.0, make this method private and refactor tests to use PgflowClient\n * with event emission instead of direct state manipulation.\n */\n updateState(event: FlowRunEvent<TFlow>): boolean {\n // Validate the event is for this run\n if (event.run_id !== this.#state.run_id) {\n return false;\n }\n\n // Check if the event status has higher precedence than current status\n if (!this.#shouldUpdateStatus(this.#state.status, event.status)) {\n return false;\n }\n\n // Update state based on event type using narrowing type guards\n switch (event.status) {\n case FlowRunStatus.Started:\n this.#state = {\n ...this.#state,\n status: FlowRunStatus.Started,\n started_at:\n typeof event.started_at === 'string'\n ? new Date(event.started_at)\n : new Date(),\n remaining_steps:\n 'remaining_steps' in event\n ? Number(event.remaining_steps)\n : this.#state.remaining_steps,\n };\n this.#events.emit('started', event);\n break;\n\n case FlowRunStatus.Completed:\n this.#state = {\n ...this.#state,\n status: FlowRunStatus.Completed,\n completed_at:\n typeof event.completed_at === 'string'\n ? new Date(event.completed_at)\n : new Date(),\n output: event.output as ExtractFlowOutput<TFlow>,\n remaining_steps: 0,\n };\n this.#events.emit('completed', event);\n\n // Check for auto-dispose\n this.#checkAutoDispose();\n break;\n\n case FlowRunStatus.Failed:\n this.#state = {\n ...this.#state,\n status: FlowRunStatus.Failed,\n failed_at:\n typeof event.failed_at === 'string'\n ? new Date(event.failed_at)\n : new Date(),\n error_message:\n typeof event.error_message === 'string'\n ? event.error_message\n : 'Unknown error',\n error: new Error(\n typeof event.error_message === 'string'\n ? event.error_message\n : 'Unknown error'\n ),\n };\n this.#events.emit('failed', event);\n\n // Check for auto-dispose\n this.#checkAutoDispose();\n break;\n\n default: {\n // Exhaustiveness check - should never happen with proper types\n // @ts-expect-error Intentional exhaustiveness check\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const _exhaustivenessCheck: never = event;\n return false;\n }\n }\n\n // Also emit to the catch-all listener\n this.#events.emit('*', event);\n\n return true;\n }\n\n /**\n * Updates a step state based on an event\n *\n * @param stepSlug - Step slug to update\n * @param event - Event data to update the step with\n * @returns true if the state was updated, false otherwise\n */\n updateStepState<TStepSlug extends keyof ExtractFlowSteps<TFlow> & string>(\n stepSlug: TStepSlug,\n event: StepEvent<TFlow, TStepSlug>\n ): boolean {\n const step = this.step(stepSlug);\n return step.updateState(event);\n }\n\n // Track number of listeners\n #listenerCount = 0;\n\n /**\n * Checks if auto-dispose should be triggered (when in terminal state with no listeners)\n */\n #checkAutoDispose(): void {\n // Don't auto-dispose multiple times\n if (this.#disposed) {\n return;\n }\n\n // Only auto-dispose in terminal states\n if (\n this.status !== FlowRunStatus.Completed &&\n this.status !== FlowRunStatus.Failed\n ) {\n return;\n }\n\n // If there are no listeners, auto-dispose\n if (this.#listenerCount === 0) {\n this.dispose();\n }\n }\n\n /**\n * Determines if a status should be updated based on precedence\n *\n * @param currentStatus - Current status\n * @param newStatus - New status\n * @returns true if the status should be updated, false otherwise\n */\n #shouldUpdateStatus(\n currentStatus: FlowRunStatus,\n newStatus: FlowRunStatus\n ): boolean {\n // Don't allow changes to terminal states\n if (\n currentStatus === FlowRunStatus.Completed ||\n currentStatus === FlowRunStatus.Failed\n ) {\n return false; // Terminal states should never change\n }\n\n const currentPrecedence = this.#statusPrecedence[currentStatus];\n const newPrecedence = this.#statusPrecedence[newStatus];\n\n // Only allow transitions to higher precedence non-terminal status\n return newPrecedence > currentPrecedence;\n }\n\n /**\n * Clean up all resources held by this run\n */\n dispose(): void {\n if (this.#disposed) {\n return;\n }\n\n // Clear the map to allow garbage collection of steps\n this.#steps.clear();\n\n // Create a new events object - this effectively clears all listeners\n // without accessing the private internals of nanoevents\n this.#events = createNanoEvents<FlowRunEvents<TFlow>>();\n this.#listenerCount = 0;\n\n // Mark as disposed\n this.#disposed = true;\n }\n}\n","import type {\n AnyFlow,\n ExtractFlowInput,\n ExtractFlowOutput,\n ExtractFlowSteps,\n StepOutput,\n} from '@pgflow/dsl';\nimport type { RunRow, StepStateRow } from '@pgflow/core';\nimport {\n FlowStepStatus,\n FlowRunStatus,\n} from './types.js';\nimport type {\n BroadcastRunEvent,\n BroadcastStepEvent,\n FlowRunEvent,\n StepEvent,\n} from './types.js';\n\n/**\n * Convert a broadcast run event to a typed run event\n */\nexport function toTypedRunEvent<TFlow extends AnyFlow>(\n evt: BroadcastRunEvent\n): FlowRunEvent<TFlow> {\n switch (evt.status) {\n case FlowRunStatus.Started:\n return {\n event_type: 'run:started',\n run_id: evt.run_id,\n flow_slug: evt.flow_slug,\n status: FlowRunStatus.Started,\n started_at: evt.started_at,\n remaining_steps: evt.remaining_steps,\n input: evt.input as ExtractFlowInput<TFlow>,\n };\n case FlowRunStatus.Completed:\n return {\n event_type: 'run:completed',\n run_id: evt.run_id,\n flow_slug: evt.flow_slug,\n status: FlowRunStatus.Completed,\n completed_at: evt.completed_at,\n output: evt.output as ExtractFlowOutput<TFlow>,\n };\n case FlowRunStatus.Failed:\n return {\n event_type: 'run:failed',\n run_id: evt.run_id,\n flow_slug: evt.flow_slug,\n status: FlowRunStatus.Failed,\n failed_at: evt.failed_at,\n error_message: evt.error_message,\n };\n }\n}\n\n/**\n * Convert a broadcast step event to a typed step event\n */\nexport function toTypedStepEvent<\n TFlow extends AnyFlow,\n TStepSlug extends keyof ExtractFlowSteps<TFlow> & string,\n>(evt: BroadcastStepEvent): StepEvent<TFlow, TStepSlug> {\n switch (evt.status) {\n case FlowStepStatus.Started:\n return {\n event_type: 'step:started',\n run_id: evt.run_id,\n step_slug: evt.step_slug as TStepSlug,\n status: FlowStepStatus.Started,\n started_at: evt.started_at,\n };\n case FlowStepStatus.Completed:\n return {\n event_type: 'step:completed',\n run_id: evt.run_id,\n step_slug: evt.step_slug as TStepSlug,\n status: FlowStepStatus.Completed,\n completed_at: evt.completed_at,\n output: evt.output as StepOutput<TFlow, TStepSlug>,\n };\n case FlowStepStatus.Failed:\n return {\n event_type: 'step:failed',\n run_id: evt.run_id,\n step_slug: evt.step_slug as TStepSlug,\n status: FlowStepStatus.Failed,\n failed_at: evt.failed_at,\n error_message: evt.error_message,\n };\n }\n}\n\n/**\n * Convert a database run row to a typed run event\n */\nexport function runRowToTypedEvent<TFlow extends AnyFlow>(\n row: RunRow\n): FlowRunEvent<TFlow> {\n switch (row.status) {\n case 'started':\n return {\n event_type: 'run:started',\n run_id: row.run_id,\n flow_slug: row.flow_slug,\n status: FlowRunStatus.Started,\n started_at: row.started_at!,\n remaining_steps: row.remaining_steps,\n input: row.input as ExtractFlowInput<TFlow>,\n };\n case 'completed':\n return {\n event_type: 'run:completed',\n run_id: row.run_id,\n flow_slug: row.flow_slug,\n status: FlowRunStatus.Completed,\n completed_at: row.completed_at!,\n output: row.output as ExtractFlowOutput<TFlow>,\n };\n case 'failed':\n return {\n event_type: 'run:failed',\n run_id: row.run_id,\n flow_slug: row.flow_slug,\n status: FlowRunStatus.Failed,\n failed_at: row.failed_at!,\n error_message: 'Flow failed', // Database doesn't have error_message for runs\n };\n default:\n throw new Error(`Unknown run status: ${row.status}`);\n }\n}\n\n/**\n * Convert a database step state row to a typed step event\n */\nexport function stepStateRowToTypedEvent<\n TFlow extends AnyFlow,\n TStepSlug extends keyof ExtractFlowSteps<TFlow> & string,\n>(row: StepStateRow): StepEvent<TFlow, TStepSlug> {\n switch (row.status) {\n case 'created':\n case 'started':\n return {\n event_type: 'step:started',\n run_id: row.run_id,\n step_slug: row.step_slug as TStepSlug,\n status: FlowStepStatus.Started,\n started_at: row.started_at!,\n };\n case 'completed':\n return {\n event_type: 'step:completed',\n run_id: row.run_id,\n step_slug: row.step_slug as TStepSlug,\n status: FlowStepStatus.Completed,\n completed_at: row.completed_at!,\n output: {} as StepOutput<TFlow, TStepSlug>, // Database doesn't have output in step_states\n };\n case 'failed':\n return {\n event_type: 'step:failed',\n run_id: row.run_id,\n step_slug: row.step_slug as TStepSlug,\n status: FlowStepStatus.Failed,\n failed_at: row.failed_at!,\n error_message: row.error_message || 'Step failed',\n };\n default:\n throw new Error(`Unknown step status: ${row.status}`);\n }\n}","import { v4 as uuidv4 } from 'uuid';\nimport type { SupabaseClient } from '@supabase/supabase-js';\nimport type { AnyFlow, ExtractFlowInput } from '@pgflow/dsl';\nimport type { RunRow } from '@pgflow/core';\nimport { FlowRunStatus } from './types.js';\nimport type { \n IFlowClient, \n FlowRunState, \n BroadcastRunEvent, \n BroadcastStepEvent, \n Unsubscribe, \n FlowRunBase\n} from './types.js';\nimport { SupabaseBroadcastAdapter } from './SupabaseBroadcastAdapter.js';\nimport { FlowRun } from './FlowRun.js';\nimport { toTypedRunEvent, toTypedStepEvent, runRowToTypedEvent, stepStateRowToTypedEvent } from './eventAdapters.js';\n\n/**\n * Client for interacting with pgflow\n */\nexport class PgflowClient<TFlow extends AnyFlow = AnyFlow> implements IFlowClient<TFlow> {\n #supabase: SupabaseClient;\n #realtimeAdapter: SupabaseBroadcastAdapter;\n // Use the widest event type - keeps the compiler happy but\n // still provides the structural API we need (updateState/step/...)\n #runs = new Map<string, FlowRunBase<unknown>>();\n\n /**\n * Creates a new PgflowClient instance\n *\n * @param supabaseClient - Supabase client instance\n */\n constructor(supabaseClient: SupabaseClient) {\n this.#supabase = supabaseClient;\n this.#realtimeAdapter = new SupabaseBroadcastAdapter(supabaseClient);\n\n // Set up global event listeners - properly typed\n this.#realtimeAdapter.onRunEvent((event: BroadcastRunEvent) => {\n const run = this.#runs.get(event.run_id);\n if (run) {\n // Convert broadcast event to typed event before updating state\n run.updateState(toTypedRunEvent(event));\n }\n });\n\n this.#realtimeAdapter.onStepEvent((event: BroadcastStepEvent) => {\n const run = this.#runs.get(event.run_id);\n if (run) {\n // Always materialize the step before updating to avoid event loss\n // This ensures we cache all steps even if they were never explicitly requested\n const stepSlug = event.step_slug;\n run.step(stepSlug).updateState(toTypedStepEvent(event));\n }\n });\n }\n\n /**\n * Start a flow with optional run_id\n *\n * @param flow_slug - Flow slug to start\n * @param input - Input data for the flow\n * @param run_id - Optional run ID (will be generated if not provided)\n * @returns Promise that resolves with the FlowRun instance\n */\n async startFlow<TSpecificFlow extends TFlow>(\n flow_slug: string,\n input: ExtractFlowInput<TSpecificFlow>,\n run_id?: string\n ): Promise<FlowRun<TSpecificFlow>> {\n // Generate a run_id if not provided\n const id = run_id || uuidv4();\n\n // Create initial state for the flow run\n const initialState: FlowRunState<TSpecificFlow> = {\n run_id: id,\n flow_slug,\n status: FlowRunStatus.Started,\n input: input as ExtractFlowInput<TSpecificFlow>,\n output: null,\n error: null,\n error_message: null,\n started_at: null,\n completed_at: null,\n failed_at: null,\n remaining_steps: -1, // Use -1 to indicate unknown until first snapshot arrives\n };\n\n // Create the flow run instance\n const run = new FlowRun<TSpecificFlow>(initialState);\n\n // Store the run\n this.#runs.set(id, run);\n\n // Set up subscription for run and step events (wait for subscription confirmation)\n await this.#realtimeAdapter.subscribeToRun(id);\n\n // Start the flow with the predetermined run_id (only after subscription is ready)\n const { data, error } = await this.#supabase.schema('pgflow').rpc('start_flow_with_states', {\n flow_slug: flow_slug,\n input: input as Record<string, unknown>,\n run_id: id\n });\n\n if (error) {\n // Clean up subscription and run instance\n this.dispose(id);\n throw error;\n }\n\n // Update the run state with the complete initial state snapshot\n if (data.run) {\n run.updateState(runRowToTypedEvent<TSpecificFlow>(data.run));\n }\n\n // Update step states from the initial snapshot\n if (data.steps && Array.isArray(data.steps)) {\n for (const stepState of data.steps) {\n run.step(stepState.step_slug).updateState(stepStateRowToTypedEvent<TSpecificFlow, any>(stepState));\n }\n }\n\n return run;\n }\n\n /**\n * Dispose a specific flow run\n *\n * @param runId - Run ID to dispose\n */\n dispose(runId: string): void {\n const run = this.#runs.get(runId);\n if (run) {\n // First unsubscribe from the realtime adapter\n this.#realtimeAdapter.unsubscribe(runId);\n \n // Then dispose the run\n run.dispose();\n \n // Finally remove from the runs map\n this.#runs.delete(runId);\n }\n }\n\n /**\n * Dispose all flow runs\n */\n disposeAll(): void {\n for (const runId of this.#runs.keys()) {\n this.dispose(runId);\n }\n }\n\n // Delegate IFlowRealtime methods to the adapter\n\n /**\n * Fetch flow definition metadata\n */\n async fetchFlowDefinition(flow_slug: string) {\n return this.#realtimeAdapter.fetchFlowDefinition(flow_slug);\n }\n\n /**\n * Register a callback for run events\n * @returns Function to unsubscribe from the event\n */\n onRunEvent(callback: (event: BroadcastRunEvent) => void): Unsubscribe {\n return this.#realtimeAdapter.onRunEvent(callback);\n }\n\n /**\n * Register a callback for step events\n * @returns Function to unsubscribe from the event\n */\n onStepEvent(callback: (event: BroadcastStepEvent) => void): Unsubscribe {\n return this.#realtimeAdapter.onStepEvent(callback);\n }\n\n /**\n * Subscribe to a flow run's events\n */\n async subscribeToRun(run_id: string): Promise<() => void> {\n return await this.#realtimeAdapter.subscribeToRun(run_id);\n }\n\n /**\n * Fetch current state of a run and its steps\n */\n async getRunWithStates(run_id: string) {\n return this.#realtimeAdapter.getRunWithStates(run_id);\n }\n \n /**\n * Get a flow run by ID\n * \n * @param run_id - ID of the run to get\n * @returns Promise that resolves with the FlowRun instance or null if not found\n */\n async getRun<TSpecificFlow extends TFlow = TFlow>(run_id: string): Promise<FlowRun<TSpecificFlow> | null> {\n // Check if we already have this run cached\n const existingRun = this.#runs.get(run_id);\n if (existingRun) {\n return existingRun as FlowRun<TSpecificFlow>;\n }\n \n try {\n // Fetch the run state from the database\n const { run, steps } = await this.getRunWithStates(run_id);\n \n if (!run) {\n return null;\n }\n \n // Create initial state for the flow run\n // Use type assertion since RunRow doesn't include error_message field\n const runData = run as unknown as (RunRow & { error_message?: string });\n \n // Validate required fields\n if (!runData.run_id || !runData.flow_slug || !runData.status) {\n throw new Error('Invalid run data: missing required fields');\n }\n \n // Validate status is a valid FlowRunStatus\n const validStatuses = Object.values(FlowRunStatus);\n if (!validStatuses.includes(runData.status as FlowRunStatus)) {\n throw new Error(`Invalid run data: invalid status '${runData.status}'`);\n }\n \n const initialState: FlowRunState<TSpecificFlow> = {\n run_id: runData.run_id,\n flow_slug: runData.flow_slug,\n status: runData.status as FlowRunStatus,\n input: runData.input as ExtractFlowInput<TSpecificFlow>,\n output: runData.output as any,\n error: runData.error_message ? new Error(runData.error_message) : null,\n error_message: runData.error_message || null,\n started_at: runData.started_at ? new Date(runData.started_at) : null,\n completed_at: runData.completed_at ? new Date(runData.completed_at) : null,\n failed_at: runData.failed_at ? new Date(runData.failed_at) : null,\n remaining_steps: runData.remaining_steps || 0,\n };\n \n // Create the flow run instance\n const flowRun = new FlowRun<TSpecificFlow>(initialState);\n \n // Store the run\n this.#runs.set(run_id, flowRun);\n \n // Set up subscription for run and step events\n await this.#realtimeAdapter.subscribeToRun(run_id);\n \n // Initialize steps\n if (steps && Array.isArray(steps)) {\n for (const stepState of steps) {\n // Validate step has required fields\n if (!stepState.step_slug || !stepState.status) {\n throw new Error('Invalid step data: missing required fields');\n }\n \n // Convert database step state to typed event\n flowRun.step(stepState.step_slug).updateState(stepStateRowToTypedEvent<AnyFlow, any>(stepState));\n }\n }\n \n return flowRun;\n } catch (error) {\n console.error('Error getting run:', error);\n // Re-throw if it's a validation error\n if (error instanceof Error && (error.message.includes('Invalid run data') || error.message.includes('Invalid step data'))) {\n throw error;\n }\n return null;\n }\n }\n \n}\n"],"names":["FlowRunStatus","isFlowRunEvent","value","isFlowRunStartedEvent","event","isFlowRunCompletedEvent","isFlowRunFailedEvent","FlowStepStatus","isStepEvent","isStepStartedEvent","isStepCompletedEvent","isStepFailedEvent","SupabaseBroadcastAdapter","supabase","opts","__privateAdd","_SupabaseBroadcastAdapter_instances","_supabase","_channels","_emitter","createNanoEvents","_reconnectionDelay","_schedule","_unsubscribeFunctions","__privateSet","flow_slug","flowResult","stepsResult","__privateGet","stepsArray","callback","unsubscribe","e","run_id","channelName","existingUnsubscribe","__privateMethod","unsubscribe_fn","channel","handleBroadcastMessage_fn","payload","handleChannelError_fn","resolve","reject","timeout","status","data","error","msg","eventData","parseJsonFields_fn","reconnectChannel_fn","createAndConfigureChannel_fn","currentState","refreshStateFromSnapshot_fn","newChannel","state","runEvent","step","stepEvent","FlowStep","initialState","_FlowStep_instances","_state","_events","_statusPrecedence","targetStatus","options","timeoutMs","signal","timeoutId","cleanedUp","unbind","abortCleanup","abortHandler","shouldUpdateStatus_fn","currentStatus","newStatus","currentPrecedence","FlowRun","_FlowRun_instances","_steps","_disposed","_listenerCount","__privateWrapper","checkAutoDispose_fn","stepSlug","existingStep","toTypedRunEvent","evt","toTypedStepEvent","runRowToTypedEvent","row","stepStateRowToTypedEvent","PgflowClient","supabaseClient","_realtimeAdapter","_runs","run","input","id","uuidv4","stepState","runId","existingRun","steps","runData","flowRun"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './src/index'
|