@fkws/klonk 0.0.4

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.
@@ -0,0 +1,301 @@
1
+ type Railroad<
2
+ OutputType,
3
+ ErrorType = Error
4
+ > = {
5
+ readonly success: true
6
+ readonly data: OutputType
7
+ } | {
8
+ readonly success: false
9
+ readonly error: ErrorType
10
+ };
11
+ declare abstract class Task<
12
+ InputType,
13
+ OutputType,
14
+ IdentType extends string
15
+ > {
16
+ ident: IdentType;
17
+ constructor(ident: IdentType);
18
+ abstract run(input: InputType): Promise<Railroad<OutputType>>;
19
+ }
20
+ type InputBuilder<
21
+ SourceType,
22
+ AllOutputTypes,
23
+ TaskInputType
24
+ > = (source: SourceType, outputs: AllOutputTypes) => TaskInputType;
25
+ interface Machine<
26
+ SourceType,
27
+ AllOutputTypes,
28
+ TaskInputType,
29
+ TaskOutputType,
30
+ IdentType extends string
31
+ > {
32
+ task: Task<TaskInputType, TaskOutputType, IdentType>;
33
+ builder: InputBuilder<SourceType, AllOutputTypes, TaskInputType>;
34
+ }
35
+ type NoInfer<T> = [T][T extends any ? 0 : never];
36
+ declare class Playlist<
37
+ AllOutputTypes extends Record<string, any>,
38
+ SourceType = unknown
39
+ > {
40
+ machines: Machine<any, any, any, any, string>[];
41
+ finalizer?: (source: SourceType, outputs: Record<string, any>) => void | Promise<void>;
42
+ constructor(machines?: Machine<any, any, any, any, string>[], finalizer?: (source: SourceType, outputs: Record<string, any>) => void | Promise<void>);
43
+ addTask<
44
+ TaskInputType,
45
+ TaskOutputType,
46
+ const IdentType extends string
47
+ >(task: Task<TaskInputType, TaskOutputType, IdentType> & {
48
+ ident: IdentType
49
+ }, builder: (source: SourceType, outputs: AllOutputTypes) => NoInfer<TaskInputType>): Playlist<AllOutputTypes & { [K in IdentType] : Railroad<TaskOutputType> }, SourceType>;
50
+ finally(finalizer: (source: SourceType, outputs: AllOutputTypes) => void | Promise<void>): this;
51
+ run(source: SourceType): Promise<AllOutputTypes>;
52
+ }
53
+ type TriggerEvent<
54
+ IdentType extends string,
55
+ T
56
+ > = {
57
+ triggerIdent: IdentType
58
+ data: T
59
+ };
60
+ declare class EventQueue<TEventType> {
61
+ size: number;
62
+ queue: TEventType[];
63
+ constructor(size: number);
64
+ push(item: TEventType): void;
65
+ shift(): TEventType | undefined;
66
+ get length(): number;
67
+ }
68
+ declare abstract class Trigger<
69
+ IdentType extends string,
70
+ TData
71
+ > {
72
+ readonly ident: IdentType;
73
+ protected readonly queue: EventQueue<TriggerEvent<IdentType, TData>>;
74
+ constructor(ident: IdentType, queueSize?: number);
75
+ abstract stop(): Promise<void>;
76
+ protected pushEvent(data: TData): void;
77
+ poll(): TriggerEvent<IdentType, TData> | null;
78
+ }
79
+ declare class Workflow<
80
+ AllTriggerEvents extends TriggerEvent<string, any>,
81
+ TAllOutputs extends Record<string, any>,
82
+ TPlaylist extends Playlist<TAllOutputs, AllTriggerEvents> | null
83
+ > {
84
+ playlist: TPlaylist;
85
+ triggers: Trigger<string, any>[];
86
+ constructor(triggers: Trigger<string, any>[], playlist: TPlaylist);
87
+ addTrigger<
88
+ const TIdent extends string,
89
+ TData
90
+ >(trigger: Trigger<TIdent, TData>): Workflow<AllTriggerEvents | TriggerEvent<TIdent, TData>, TAllOutputs, Playlist<TAllOutputs, AllTriggerEvents | TriggerEvent<TIdent, TData>> | null>;
91
+ setPlaylist<
92
+ TBuilderOutputs extends Record<string, any>,
93
+ TFinalPlaylist extends Playlist<TBuilderOutputs, AllTriggerEvents>
94
+ >(builder: (p: Playlist<{}, AllTriggerEvents>) => TFinalPlaylist): Workflow<AllTriggerEvents, TBuilderOutputs, TFinalPlaylist>;
95
+ start({ interval, callback }?: {
96
+ interval?: number
97
+ callback?: (source: AllTriggerEvents, outputs: TAllOutputs) => any
98
+ }): Promise<void>;
99
+ static create(): Workflow<never, {}, null>;
100
+ }
101
+ import { Logger } from "pino";
102
+ type Transition<TStateData> = {
103
+ to: StateNode<TStateData> | null
104
+ condition: (stateData: TStateData) => Promise<boolean>
105
+ weight?: number
106
+ };
107
+ /**
108
+ * A node in the finite state machine.
109
+ * Each node owns a `Playlist` that is executed upon entering the node and
110
+ * contains weighted conditional transitions to other nodes.
111
+ *
112
+ * @template TStateData - The shape of the external mutable state carried through the machine.
113
+ */
114
+ declare class StateNode<TStateData> {
115
+ transitions?: Transition<TStateData>[];
116
+ playlist: Playlist<any, TStateData>;
117
+ timeToNextTick: number;
118
+ ident: string;
119
+ tempTransitions?: {
120
+ to: string
121
+ condition: (stateData: TStateData) => Promise<boolean>
122
+ weight: number
123
+ }[];
124
+ retry: false | number;
125
+ maxRetries: false | number;
126
+ /**
127
+ * Create a `StateNode`.
128
+ *
129
+ * @param transitions - The resolved transitions from this node.
130
+ * @param playlist - The playlist to run when the node is entered.
131
+ */
132
+ constructor(transitions: Transition<TStateData>[], playlist: Playlist<any, TStateData>);
133
+ /**
134
+ * Convenience factory for a new `StateNode` with no transitions and an empty playlist.
135
+ *
136
+ * @template TStateData
137
+ * @returns A new, unconfigured `StateNode`.
138
+ */
139
+ static create<TStateData>(): StateNode<TStateData>;
140
+ /**
141
+ * Queue a transition to be resolved later during machine finalization.
142
+ * Use the target node `ident` instead of a direct reference; it will be
143
+ * resolved to a node instance by the machine.
144
+ *
145
+ * @param to - Target state `ident`.
146
+ * @param condition - Async predicate that decides if the transition should fire.
147
+ * @param weight - Higher weight wins when multiple conditions are true; ties keep insertion order.
148
+ * @returns This node for chaining.
149
+ */
150
+ addTransition({ to, condition, weight }: {
151
+ to: string
152
+ condition: (stateData: TStateData) => Promise<boolean>
153
+ weight: number
154
+ }): StateNode<TStateData>;
155
+ /**
156
+ * Set or build the playlist that runs when entering this node.
157
+ *
158
+ * Overload 1: supply an already constructed `Playlist`.
159
+ * Overload 2: supply a builder function receiving an empty `Playlist` and returning a configured one.
160
+ *
161
+ * @param arg - Either a `Playlist` instance or a builder function that returns one.
162
+ * @returns This node for chaining.
163
+ */
164
+ setPlaylist(playlist: Playlist<any, TStateData>): StateNode<TStateData>;
165
+ setPlaylist<
166
+ TBuilderOutputs extends Record<string, any>,
167
+ TFinalPlaylist extends Playlist<TBuilderOutputs, TStateData>
168
+ >(builder: (p: Playlist<{}, TStateData>) => TFinalPlaylist): StateNode<TStateData>;
169
+ /**
170
+ * Disable retry behavior for this node during `Machine.run` when no transition is available.
171
+ *
172
+ * @returns This node for chaining.
173
+ */
174
+ preventRetry(): StateNode<TStateData>;
175
+ /**
176
+ * Set the delay between retry attempts for this node during `Machine.run`.
177
+ *
178
+ * @param delayMs - Delay in milliseconds between retries.
179
+ * @returns This node for chaining.
180
+ */
181
+ retryDelayMs(delayMs: number): StateNode<TStateData>;
182
+ /**
183
+ * Set the maximum number of retries for this node during `Machine.run`.
184
+ * Use `preventRetry()` to disable retries entirely.
185
+ *
186
+ * @param maxRetries - Maximum number of retry attempts before giving up.
187
+ * @returns This node for chaining.
188
+ */
189
+ retryLimit(maxRetries: number): StateNode<TStateData>;
190
+ /**
191
+ * Assign a unique identifier for this node. Required for transition resolution.
192
+ *
193
+ * @param ident - Unique node identifier.
194
+ * @returns This node for chaining.
195
+ */
196
+ setIdent(ident: string): StateNode<TStateData>;
197
+ /**
198
+ * Depth-first search for a node by `ident` within the reachable subgraph from this node.
199
+ *
200
+ * @param ident - Identifier to search for.
201
+ * @param visited - Internal cycle-prevention list; callers can ignore.
202
+ * @returns The matching node or `null` if not found.
203
+ */
204
+ getByIdent(ident: string, visited?: string[]): StateNode<TStateData> | null;
205
+ /**
206
+ * Evaluate transitions and select the next node.
207
+ * Transitions are considered in order of descending weight, with insertion order as a tie-breaker.
208
+ *
209
+ * @param data - Current external state used by transition conditions.
210
+ * @returns The next node if a condition passes; otherwise `null`.
211
+ */
212
+ next(data: TStateData): Promise<StateNode<TStateData> | null>;
213
+ }
214
+ /**
215
+ * A finite state machine that coordinates execution of `StateNode` playlists
216
+ * and transitions between them based on async conditions.
217
+ *
218
+ * @template TStateData - The shape of the external mutable state carried through the machine.
219
+ */
220
+ declare class Machine2<TStateData> {
221
+ initialState: StateNode<TStateData> | null;
222
+ statesToCreate: StateNode<TStateData>[];
223
+ private currentState;
224
+ finalized: boolean;
225
+ logger?: Logger;
226
+ ident?: string;
227
+ /**
228
+ * Compute the set of reachable states starting from the initial state.
229
+ * Used by `run` to determine completion once all states have been visited.
230
+ *
231
+ * @returns An array of reachable `StateNode`s.
232
+ */
233
+ private getAllStates;
234
+ /**
235
+ * Sleep helper used for retry delays.
236
+ *
237
+ * @param ms - Milliseconds to wait.
238
+ * @returns A promise that resolves after the delay.
239
+ */
240
+ private sleep;
241
+ /**
242
+ * Convenience factory for a new `Machine`.
243
+ *
244
+ * @template TStateData
245
+ * @returns A new unfinalized machine instance.
246
+ */
247
+ static create<TStateData>(): Machine2<TStateData>;
248
+ /**
249
+ * Finalize the machine by resolving state transitions and locking configuration.
250
+ * Must be called before `start` or `run`.
251
+ *
252
+ * @param options - Finalization options.
253
+ * @param options.verbose - Enable pino logging for the machine lifecycle.
254
+ * @param options.ident - Optional fixed identifier; if omitted, a UUID is generated.
255
+ * @returns This machine for chaining.
256
+ * @throws If there is no initial state, no states have been added, a state is missing an ident, or idents are duplicated.
257
+ */
258
+ finalize({ verbose, ident }?: {
259
+ verbose?: boolean
260
+ ident?: string
261
+ }): Machine2<TStateData>;
262
+ /**
263
+ * Add a state to the machine.
264
+ *
265
+ * @param state - The state node to add.
266
+ * @param options - Options controlling how the state is added.
267
+ * @param options.initial - If true, marks this state as the initial state.
268
+ * @returns This machine for chaining.
269
+ */
270
+ addState(state: StateNode<TStateData>, options?: {
271
+ initial?: boolean
272
+ }): Machine2<TStateData>;
273
+ /**
274
+ * Start the machine in a repeated tick loop. Executes the current state's playlist,
275
+ * evaluates transitions, and schedules the next tick with `setTimeout`.
276
+ * The method returns immediately after initializing the loop.
277
+ *
278
+ * @param stateData - Mutable external state provided to playlists and transition conditions.
279
+ * @param options - Start options.
280
+ * @param options.interval - Tick interval in milliseconds (default 1000ms).
281
+ * @returns A promise that resolves once the loop has been initiated.
282
+ * @throws If the machine has not been finalized or no initial state is set.
283
+ */
284
+ start(stateData: TStateData, options?: {
285
+ interval?: number
286
+ }): Promise<void>;
287
+ /**
288
+ * Run the machine synchronously until it reaches a terminal condition:
289
+ * - A leaf state (no transitions)
290
+ * - No transition and retries disabled
291
+ * - Retry limit exhausted
292
+ * - Returning to the initial state
293
+ * - All reachable states have been visited
294
+ *
295
+ * @param stateData - Mutable external state provided to playlists and transition conditions.
296
+ * @returns A promise that resolves once the run completes.
297
+ * @throws If the machine has not been finalized or no initial state is set.
298
+ */
299
+ run(stateData: TStateData): Promise<TStateData>;
300
+ }
301
+ export { Workflow, TriggerEvent, Trigger, Task, StateNode, Railroad, Playlist, Machine2 as Machine };