slapflow 1.0.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -20,14 +20,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ BUILTIN_ACTIONS: () => BUILTIN_ACTIONS,
24
+ BUILTIN_ACTION_NAMES: () => BUILTIN_ACTION_NAMES,
25
+ BUILTIN_CONDITIONS: () => BUILTIN_CONDITIONS,
26
+ BUILTIN_CONDITION_NAMES: () => BUILTIN_CONDITION_NAMES,
23
27
  PubSub: () => PubSub,
24
28
  catchError: () => catchError,
25
- createActionsRegistry: () => createActionsRegistry,
26
- createConditionsRegistry: () => createConditionsRegistry,
27
29
  createFlow: () => createFlow,
28
30
  createMemoryTraceSink: () => createMemoryTraceSink,
29
31
  createPubSub: () => createPubSub,
30
32
  createWS: () => createWS,
33
+ createWebSocket: () => createWebSocket,
31
34
  defineConfig: () => defineConfig,
32
35
  defineErrorReporter: () => defineErrorReporter
33
36
  });
@@ -36,9 +39,6 @@ module.exports = __toCommonJS(index_exports);
36
39
  // src/helpers/config/defineConfig.ts
37
40
  var defineConfig = (config) => config;
38
41
 
39
- // src/helpers/trace/cloneData.ts
40
- var cloneData = (data) => ({ ...data });
41
-
42
42
  // src/helpers/trace/createMemoryTraceSink.ts
43
43
  var createMemoryTraceSink = () => {
44
44
  const items = [];
@@ -50,22 +50,9 @@ var createMemoryTraceSink = () => {
50
50
  };
51
51
  };
52
52
 
53
- // src/helpers/errors/slapError.ts
54
- var slapError = (code, message, extras = {}) => ({ code, message, ...extras });
55
-
56
53
  // src/helpers/errors/defineErrorReporter.ts
57
54
  var defineErrorReporter = (handlers) => typeof handlers === "function" ? handlers : handlers.report;
58
55
 
59
- // src/errors.ts
60
- var SyncAsyncError = class extends Error {
61
- slapError;
62
- constructor(error) {
63
- super(error.message);
64
- this.name = "SyncAsyncError";
65
- this.slapError = error;
66
- }
67
- };
68
-
69
56
  // src/helpers/ids/createId.ts
70
57
  var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
71
58
  var idLength = 12;
@@ -87,14 +74,35 @@ var isBusEvent = (event) => {
87
74
  return typeof candidate.id === "string" && typeof candidate.topic === "string" && typeof candidate.occurredAt === "number" && typeof candidate.serialized === "string" && "parsed" in candidate && (candidate.origin === void 0 || typeof candidate.origin === "string");
88
75
  };
89
76
 
77
+ // src/helpers/pubSub/matchesTopic.ts
78
+ var matchesTopic = (topic, pattern) => {
79
+ if (!pattern.includes("*")) {
80
+ return topic === pattern;
81
+ }
82
+ const topicParts = topic.split(".");
83
+ const patternParts = pattern.split(".");
84
+ if (topicParts.length !== patternParts.length) {
85
+ return false;
86
+ }
87
+ return patternParts.every((part, index) => part === "*" || part === topicParts[index]);
88
+ };
89
+
90
90
  // src/helpers/pubSub/serializeError.ts
91
91
  var serializeError = (error) => ({
92
92
  error: error instanceof Error ? error.message : String(error)
93
93
  });
94
94
 
95
- // src/pubSub.ts
95
+ // src/createPubSub.ts
96
96
  var createPubSub = (options = {}) => {
97
97
  const subscribers = /* @__PURE__ */ new Map();
98
+ const wildcardSubscribers = /* @__PURE__ */ new Map();
99
+ const runHandler = (event, handler) => {
100
+ try {
101
+ handler(event);
102
+ } catch (error) {
103
+ options.onError?.({ type: "subscriber", event, error });
104
+ }
105
+ };
98
106
  const dispatch = (event) => {
99
107
  let dispatchedEvent;
100
108
  if (!isBusEvent(event)) {
@@ -108,10 +116,13 @@ var createPubSub = (options = {}) => {
108
116
  const handlers = subscribers.get(event.topic);
109
117
  if (handlers) {
110
118
  for (const handler of [...handlers]) {
111
- try {
112
- handler(event);
113
- } catch (error) {
114
- options.onError?.({ type: "subscriber", event, error });
119
+ runHandler(event, handler);
120
+ }
121
+ }
122
+ for (const [pattern, wildcardHandlers] of wildcardSubscribers) {
123
+ if (matchesTopic(event.topic, pattern)) {
124
+ for (const handler of [...wildcardHandlers]) {
125
+ runHandler(event, handler);
115
126
  }
116
127
  }
117
128
  }
@@ -120,23 +131,24 @@ var createPubSub = (options = {}) => {
120
131
  return dispatchedEvent;
121
132
  };
122
133
  const on = (event, handler) => {
123
- const handlers = subscribers.get(event) ?? /* @__PURE__ */ new Set();
124
- const listener = handler;
125
- handlers.add(listener);
126
- subscribers.set(event, handlers);
134
+ const registry = event.includes("*") ? wildcardSubscribers : subscribers;
135
+ const handlers = registry.get(event) ?? /* @__PURE__ */ new Set();
136
+ handlers.add(handler);
137
+ registry.set(event, handlers);
127
138
  return () => off(event, handler);
128
139
  };
129
140
  const off = (event, handler) => {
141
+ const registry = event.includes("*") ? wildcardSubscribers : subscribers;
130
142
  if (handler) {
131
- const handlers = subscribers.get(event);
143
+ const handlers = registry.get(event);
132
144
  if (handlers) {
133
145
  handlers.delete(handler);
134
146
  if (handlers.size === 0) {
135
- subscribers.delete(event);
147
+ registry.delete(event);
136
148
  }
137
149
  }
138
150
  } else {
139
- subscribers.delete(event);
151
+ registry.delete(event);
140
152
  }
141
153
  };
142
154
  const emit = (topic, payload, emitOptions = {}) => {
@@ -178,6 +190,16 @@ var createPubSub = (options = {}) => {
178
190
  };
179
191
  var PubSub = createPubSub();
180
192
 
193
+ // src/helpers/errors/syncAsyncError.ts
194
+ var SyncAsyncError = class extends Error {
195
+ slapError;
196
+ constructor(error) {
197
+ super(error.message);
198
+ this.name = "SyncAsyncError";
199
+ this.slapError = error;
200
+ }
201
+ };
202
+
181
203
  // src/helpers/actions/coreDelay.ts
182
204
  var coreDelay = async ({
183
205
  props,
@@ -214,10 +236,7 @@ var coreEmit = ({
214
236
  };
215
237
 
216
238
  // src/helpers/actions/coreFail.ts
217
- var coreFail = ({
218
- props,
219
- runtime
220
- }) => runtime.fail(String(props.reason ?? "failed"), props.data);
239
+ var coreFail = ({ props, runtime }) => runtime.fail(String(props.reason ?? "failed"), props.data);
221
240
 
222
241
  // src/helpers/retry/getRetryDelay.ts
223
242
  var getRetryDelay = (attempt, options) => {
@@ -424,10 +443,7 @@ var corePatch = ({
424
443
  };
425
444
 
426
445
  // src/helpers/actions/coreSet.ts
427
- var coreSet = ({
428
- props,
429
- runtime
430
- }) => {
446
+ var coreSet = ({ props, runtime }) => {
431
447
  const path = props.path;
432
448
  if (typeof path === "string") {
433
449
  runtime.set(path, props.value);
@@ -448,13 +464,10 @@ var coreSetData = ({
448
464
  };
449
465
 
450
466
  // src/helpers/actions/coreStop.ts
451
- var coreStop = ({
452
- props,
453
- runtime
454
- }) => runtime.stop(String(props.reason ?? "stopped"));
467
+ var coreStop = ({ props, runtime }) => runtime.stop(String(props.reason ?? "stopped"));
455
468
 
456
- // src/registry/actions.ts
457
- var createActionsRegistry = () => /* @__PURE__ */ new Map([
469
+ // src/helpers/actions/index.ts
470
+ var BUILTIN_ACTIONS = [
458
471
  ["core.noop", coreNoop],
459
472
  ["core.stop", coreStop],
460
473
  ["core.fail", coreFail],
@@ -468,7 +481,8 @@ var createActionsRegistry = () => /* @__PURE__ */ new Map([
468
481
  ["core.emit", coreEmit],
469
482
  ["core.patch", corePatch],
470
483
  ["core.delay", coreDelay]
471
- ]);
484
+ ];
485
+ var BUILTIN_ACTION_NAMES = new Set(BUILTIN_ACTIONS.map(([name]) => name));
472
486
 
473
487
  // src/helpers/conditions/changedCondition.ts
474
488
  var changedCondition = (_args, current, previous) => !Object.is(current, previous);
@@ -562,8 +576,8 @@ var typeIsCondition = (_args, value, expected) => {
562
576
  return expected === "string" || expected === "number" || expected === "boolean" ? typeof value === expected : false;
563
577
  };
564
578
 
565
- // src/registry/conditions.ts
566
- var createConditionsRegistry = () => /* @__PURE__ */ new Map([
579
+ // src/helpers/conditions/index.ts
580
+ var BUILTIN_CONDITIONS = [
567
581
  ["eq", eqCondition],
568
582
  ["neq", neqCondition],
569
583
  ["gt", gtCondition],
@@ -580,7 +594,8 @@ var createConditionsRegistry = () => /* @__PURE__ */ new Map([
580
594
  ["typeIs", typeIsCondition],
581
595
  ["changed", changedCondition],
582
596
  ["cooldownReady", cooldownReadyCondition]
583
- ]);
597
+ ];
598
+ var BUILTIN_CONDITION_NAMES = new Set(BUILTIN_CONDITIONS.map(([name]) => name));
584
599
 
585
600
  // src/helpers/runner/applyResult.ts
586
601
  var applyResult = (result, state, mergeData) => {
@@ -594,6 +609,9 @@ var applyResult = (result, state, mergeData) => {
594
609
  state.events.push(...result.events);
595
610
  };
596
611
 
612
+ // src/helpers/errors/slapError.ts
613
+ var slapError = (code, message, extras = {}) => ({ code, message, ...extras });
614
+
597
615
  // src/helpers/path/resolveValue.ts
598
616
  var import_objwalk3 = require("objwalk");
599
617
 
@@ -1032,7 +1050,7 @@ var executeNext = (item, depth, state, environment) => {
1032
1050
  const id = typeof item === "string" ? item : item.strategy;
1033
1051
  if (typeof item !== "string" && item.when) {
1034
1052
  const runtime = createRuntime(state);
1035
- const condition = evaluateCondition(item.when, environment.conditionsRegistry, { ...state, runtime, strategy: id });
1053
+ const condition = evaluateCondition(item.when, environment.registry.conditions, { ...state, runtime, strategy: id });
1036
1054
  if (!condition.ok) {
1037
1055
  return { status: "failed", error: condition.error, patches: [], events: [] };
1038
1056
  }
@@ -1284,6 +1302,9 @@ var normalizeActionResult = (raw) => {
1284
1302
  };
1285
1303
  };
1286
1304
 
1305
+ // src/helpers/trace/cloneData.ts
1306
+ var cloneData = (data) => ({ ...data });
1307
+
1287
1308
  // src/helpers/runner/pushTrace.ts
1288
1309
  var pushTrace = (state, step, depth, strategyId, strategy, status, props, dataBefore, startedAt, reason) => {
1289
1310
  state.traceSink?.push({
@@ -1466,7 +1487,7 @@ var executeStrategy = (id, extraProps, depth, state, environment) => {
1466
1487
  events: []
1467
1488
  };
1468
1489
  }
1469
- const action = environment.actionsRegistry.get(strategy.fn);
1490
+ const action = environment.registry.actions.get(strategy.fn);
1470
1491
  if (!action) {
1471
1492
  return {
1472
1493
  status: "failed",
@@ -1521,7 +1542,7 @@ var executeStrategy = (id, extraProps, depth, state, environment) => {
1521
1542
  const dataBefore = cloneData(state.data);
1522
1543
  const traceStep = state.stepCounter.current + 1;
1523
1544
  const startedAt = Date.now();
1524
- const condition = evaluateCondition(strategy.when, environment.conditionsRegistry, {
1545
+ const condition = evaluateCondition(strategy.when, environment.registry.conditions, {
1525
1546
  ...state,
1526
1547
  runtime,
1527
1548
  strategy: id
@@ -1833,6 +1854,17 @@ var validateCondition = (expression, strategy, path, conditionsRegistry, errors)
1833
1854
  return;
1834
1855
  }
1835
1856
  const [operator, ...args] = expression;
1857
+ if (operator === "guard") {
1858
+ if (args.length !== 1 || typeof args[0] !== "string") {
1859
+ errors.push({
1860
+ code: "CONDITION_INVALID",
1861
+ message: "Guard reference must be a single string name",
1862
+ strategy,
1863
+ path
1864
+ });
1865
+ }
1866
+ return;
1867
+ }
1836
1868
  if (operator === "and" || operator === "or") {
1837
1869
  args.forEach((arg, index) => validateCondition(arg, strategy, `${path}.${index + 1}`, conditionsRegistry, errors));
1838
1870
  return;
@@ -1878,6 +1910,82 @@ var validateNextList = (config, list, path, strategy, conditionsRegistry, errors
1878
1910
  });
1879
1911
  };
1880
1912
 
1913
+ // src/helpers/validation/resolveGuards.ts
1914
+ var isGuardRef = (expression) => Array.isArray(expression) && expression.length === 2 && expression[0] === "guard" && typeof expression[1] === "string";
1915
+ var resolveRef = (config, name, visiting, path) => {
1916
+ if (visiting.includes(name)) {
1917
+ return {
1918
+ issue: { code: "GUARD_CYCLE", message: `Guard "${name}" is part of a reference cycle`, guard: name, path }
1919
+ };
1920
+ }
1921
+ const guard = config.guards?.[name];
1922
+ if (guard === void 0) {
1923
+ return { issue: { code: "GUARD_NOT_FOUND", message: `Guard "${name}" is not defined`, guard: name, path } };
1924
+ }
1925
+ return resolveExpression(config, guard, [...visiting, name], path);
1926
+ };
1927
+ var resolveExpression = (config, expression, visiting, path) => {
1928
+ if (isGuardRef(expression)) {
1929
+ return resolveRef(config, expression[1], visiting, path);
1930
+ }
1931
+ if (!Array.isArray(expression) || typeof expression[0] !== "string") {
1932
+ return { expression };
1933
+ }
1934
+ const [operator, ...args] = expression;
1935
+ if (operator === "and" || operator === "or") {
1936
+ const resolved = [];
1937
+ for (let index = 0; index < args.length; index += 1) {
1938
+ const result = resolveExpression(config, args[index], visiting, `${path}.${index + 1}`);
1939
+ if (result.issue) {
1940
+ return result;
1941
+ }
1942
+ resolved.push(result.expression);
1943
+ }
1944
+ return { expression: [operator, ...resolved] };
1945
+ }
1946
+ if (operator === "not") {
1947
+ const result = resolveExpression(config, args[0], visiting, `${path}.1`);
1948
+ if (result.issue) {
1949
+ return result;
1950
+ }
1951
+ return { expression: ["not", result.expression] };
1952
+ }
1953
+ return { expression };
1954
+ };
1955
+ var resolveGuards = (config) => {
1956
+ const issues = [];
1957
+ const resolveWhen = (when, path) => {
1958
+ if (when === void 0) {
1959
+ return void 0;
1960
+ }
1961
+ const result = resolveExpression(config, when, [], path);
1962
+ if (result.issue) {
1963
+ issues.push(result.issue);
1964
+ return when;
1965
+ }
1966
+ return result.expression;
1967
+ };
1968
+ const resolveNext = (next, prefix) => next.map((item, index) => {
1969
+ if (typeof item === "string" || !item || typeof item !== "object" || item.when === void 0) {
1970
+ return item;
1971
+ }
1972
+ const target = item;
1973
+ const when = resolveWhen(target.when, `${prefix}.${index}.when`);
1974
+ return when === void 0 ? item : { ...target, when };
1975
+ });
1976
+ const strategies = {};
1977
+ for (const [id, strategy] of Object.entries(config.strategies)) {
1978
+ const when = strategy.when === void 0 ? void 0 : resolveWhen(strategy.when, `${id}.when`);
1979
+ strategies[id] = {
1980
+ ...strategy,
1981
+ ...when !== void 0 ? { when } : {},
1982
+ ...strategy.then ? { then: resolveNext(strategy.then, `${id}.then`) } : {},
1983
+ ...strategy.catch ? { catch: resolveNext(strategy.catch, `${id}.catch`) } : {}
1984
+ };
1985
+ }
1986
+ return { config: { ...config, strategies }, issues };
1987
+ };
1988
+
1881
1989
  // src/helpers/validation/validateConfig.ts
1882
1990
  var validateConfig = (config, actionsRegistry, conditionsRegistry) => {
1883
1991
  const errors = [];
@@ -1896,6 +2004,22 @@ var validateConfig = (config, actionsRegistry, conditionsRegistry) => {
1896
2004
  warnings
1897
2005
  };
1898
2006
  }
2007
+ if (config.guards !== void 0) {
2008
+ if (typeof config.guards !== "object" || Array.isArray(config.guards)) {
2009
+ errors.push({ code: "GUARD_INVALID", message: "Config guards must be an object", path: "guards" });
2010
+ } else {
2011
+ for (const [name, expression] of Object.entries(config.guards)) {
2012
+ validateCondition(expression, name, `guards.${name}`, conditionsRegistry, errors);
2013
+ }
2014
+ }
2015
+ }
2016
+ for (const issue of resolveGuards(config).issues) {
2017
+ errors.push({
2018
+ code: issue.code,
2019
+ message: issue.message,
2020
+ ...issue.path ? { path: issue.path } : {}
2021
+ });
2022
+ }
1899
2023
  for (const [id, strategy] of Object.entries(config.strategies ?? {})) {
1900
2024
  if (!strategy || typeof strategy !== "object") {
1901
2025
  errors.push({ code: "STRATEGY_INVALID", message: "Strategy must be an object", strategy: id });
@@ -2015,10 +2139,10 @@ var createRunCancellation = (source) => {
2015
2139
  };
2016
2140
  };
2017
2141
 
2018
- // src/helpers/runner/createRunner.ts
2142
+ // src/createRunner.ts
2019
2143
  var createRunner = (options = {}) => {
2020
- const actionsRegistry = createActionsRegistry();
2021
- const conditionsRegistry = createConditionsRegistry();
2144
+ const actionsRegistry = new Map(BUILTIN_ACTIONS);
2145
+ const conditionsRegistry = new Map(BUILTIN_CONDITIONS);
2022
2146
  const configRef = {};
2023
2147
  const timeout = options.timeout ?? options.timeoutMs;
2024
2148
  const runnerOptions = timeout === void 0 ? options : { ...options, timeout };
@@ -2028,19 +2152,24 @@ var createRunner = (options = {}) => {
2028
2152
  console.warn("timeoutMs is deprecated; use timeout. It will be removed in a future major release.");
2029
2153
  }
2030
2154
  const environment = {
2031
- actionsRegistry,
2032
- conditionsRegistry,
2155
+ registry: { actions: actionsRegistry, conditions: conditionsRegistry },
2033
2156
  configRef,
2034
2157
  options: runnerOptions,
2035
2158
  mergeData
2036
2159
  };
2037
2160
  const registerAction = (name, action) => {
2161
+ if (BUILTIN_ACTION_NAMES.has(name)) {
2162
+ throw new Error(`Cannot override built-in action "${name}"`);
2163
+ }
2038
2164
  actionsRegistry.set(name, action);
2039
2165
  };
2040
2166
  const registerActions = (items) => {
2041
2167
  Object.entries(items).forEach(([name, action]) => registerAction(name, action));
2042
2168
  };
2043
2169
  const registerCondition = (name, condition) => {
2170
+ if (BUILTIN_CONDITION_NAMES.has(name)) {
2171
+ throw new Error(`Cannot override built-in condition "${name}"`);
2172
+ }
2044
2173
  conditionsRegistry.set(name, condition);
2045
2174
  };
2046
2175
  const registerConditions = (items) => {
@@ -2051,7 +2180,7 @@ var createRunner = (options = {}) => {
2051
2180
  return { ...result, warnings: [...result.warnings, ...runnerLimitWarnings(runnerOptions)] };
2052
2181
  };
2053
2182
  const loadConfig = (nextConfig) => {
2054
- configRef.current = nextConfig;
2183
+ configRef.current = resolveGuards(nextConfig).config;
2055
2184
  return validateConfig2(nextConfig);
2056
2185
  };
2057
2186
  const runInternal = (entrypoint, context, input, sync, runOptions) => {
@@ -2137,7 +2266,7 @@ var parseDomBinding = (binding, prefix) => {
2137
2266
  return separator <= 0 || separator === source.length - 1 ? void 0 : { selector: source.slice(0, separator), eventType: source.slice(separator + 1) };
2138
2267
  };
2139
2268
 
2140
- // src/flow.ts
2269
+ // src/createFlow.ts
2141
2270
  var busBindingPrefix = "[bus] ";
2142
2271
  var domBindingPrefix = "[dom] ";
2143
2272
  var defaultMaxQueueSize = 50;
@@ -2378,10 +2507,11 @@ var createFlow = (definition, options) => {
2378
2507
  return { runner, start, stop };
2379
2508
  };
2380
2509
 
2381
- // src/ws.ts
2510
+ // src/createWS.ts
2382
2511
  var openState = 1;
2383
2512
  var maxSeenEvents = 1e3;
2384
2513
  var createWS = (options) => {
2514
+ console.warn("[slapflow] createWS is deprecated and will be removed soon. Use createWebSocket instead.");
2385
2515
  const inboundTopics = new Set(options.inboundTopics ?? []);
2386
2516
  const outboundTopics = new Set(options.outboundTopics ?? []);
2387
2517
  const seenEventIds = /* @__PURE__ */ new Set();
@@ -2393,6 +2523,14 @@ var createWS = (options) => {
2393
2523
  let started = false;
2394
2524
  let currentStatus = "idle";
2395
2525
  const diagnosticsBus = options.bus;
2526
+ const isInboundTopic = (topic) => {
2527
+ for (const pattern of inboundTopics) {
2528
+ if (matchesTopic(topic, pattern)) {
2529
+ return true;
2530
+ }
2531
+ }
2532
+ return false;
2533
+ };
2396
2534
  const emitDiagnostic = (topic, payload) => {
2397
2535
  diagnosticsBus.emit(topic, payload, {
2398
2536
  ...options.origin ? { origin: options.origin } : {}
@@ -2470,7 +2608,7 @@ var createWS = (options) => {
2470
2608
  if (typeof data === "string") {
2471
2609
  try {
2472
2610
  const busEvent = JSON.parse(data);
2473
- if (busEvent.topic && inboundTopics.has(busEvent.topic)) {
2611
+ if (busEvent.topic && isInboundTopic(busEvent.topic)) {
2474
2612
  if (busEvent.id) {
2475
2613
  rememberEvent(busEvent.id);
2476
2614
  }
@@ -2537,7 +2675,117 @@ var createWS = (options) => {
2537
2675
  return { start, stop, reconnect, status: () => currentStatus };
2538
2676
  };
2539
2677
 
2540
- // src/catchError.ts
2678
+ // src/createWebSocket.ts
2679
+ var createWebSocket = (options) => {
2680
+ let socket;
2681
+ let retryTimer;
2682
+ let retryAttempt = 0;
2683
+ let started = false;
2684
+ let currentStatus = "idle";
2685
+ const emitSocketEvent = (topic, payload) => {
2686
+ options.bus.dispatch({
2687
+ id: createId(),
2688
+ topic,
2689
+ occurredAt: Date.now(),
2690
+ ...options.origin ? { origin: options.origin } : {},
2691
+ parsed: payload,
2692
+ serialized: JSON.stringify(payload)
2693
+ });
2694
+ };
2695
+ const scheduleRetry = () => {
2696
+ const delay = getRetryDelay(retryAttempt, options.reconnect ?? {});
2697
+ const attempt = retryAttempt + 1;
2698
+ currentStatus = "reconnecting";
2699
+ retryAttempt = attempt;
2700
+ retryTimer = setTimeout(() => {
2701
+ retryTimer = void 0;
2702
+ connect();
2703
+ }, delay);
2704
+ };
2705
+ const connect = () => {
2706
+ if (!started || socket) {
2707
+ return;
2708
+ }
2709
+ currentStatus = "connecting";
2710
+ try {
2711
+ const current = new WebSocket(options.url, options.protocols ?? []);
2712
+ socket = current;
2713
+ current.addEventListener("open", () => {
2714
+ if (socket === current) {
2715
+ retryAttempt = 0;
2716
+ currentStatus = "connected";
2717
+ emitSocketEvent("open", { url: options.url });
2718
+ }
2719
+ });
2720
+ current.addEventListener("message", (event) => {
2721
+ if (socket !== current) {
2722
+ return;
2723
+ }
2724
+ let parsed = event.data;
2725
+ if (typeof parsed === "string") {
2726
+ try {
2727
+ parsed = JSON.parse(parsed);
2728
+ } catch {
2729
+ parsed = event.data;
2730
+ }
2731
+ }
2732
+ emitSocketEvent("message", parsed);
2733
+ });
2734
+ current.addEventListener("close", (event) => {
2735
+ if (socket !== current) {
2736
+ return;
2737
+ }
2738
+ socket = void 0;
2739
+ emitSocketEvent("close", { code: event.code, reason: event.reason });
2740
+ if (started) {
2741
+ scheduleRetry();
2742
+ }
2743
+ });
2744
+ current.addEventListener("error", (event) => {
2745
+ emitSocketEvent("error", { error: event });
2746
+ });
2747
+ } catch (error) {
2748
+ socket = void 0;
2749
+ emitSocketEvent("error", { error });
2750
+ if (started) {
2751
+ scheduleRetry();
2752
+ }
2753
+ }
2754
+ };
2755
+ const start = () => {
2756
+ if (!started) {
2757
+ started = true;
2758
+ connect();
2759
+ }
2760
+ };
2761
+ const stop = () => {
2762
+ started = false;
2763
+ if (retryTimer) {
2764
+ clearTimeout(retryTimer);
2765
+ }
2766
+ retryTimer = void 0;
2767
+ const current = socket;
2768
+ socket = void 0;
2769
+ current?.close();
2770
+ currentStatus = "stopped";
2771
+ };
2772
+ const reconnect = () => {
2773
+ if (!started) {
2774
+ return;
2775
+ }
2776
+ if (retryTimer) {
2777
+ clearTimeout(retryTimer);
2778
+ retryTimer = void 0;
2779
+ }
2780
+ const current = socket;
2781
+ socket = void 0;
2782
+ current?.close();
2783
+ connect();
2784
+ };
2785
+ return { start, stop, reconnect, status: () => currentStatus };
2786
+ };
2787
+
2788
+ // src/helpers/catchError.ts
2541
2789
  var catchError = (callback) => new Promise((resolve, reject) => {
2542
2790
  try {
2543
2791
  resolve(callback());
@@ -2547,14 +2795,17 @@ var catchError = (callback) => new Promise((resolve, reject) => {
2547
2795
  });
2548
2796
  // Annotate the CommonJS export names for ESM import in node:
2549
2797
  0 && (module.exports = {
2798
+ BUILTIN_ACTIONS,
2799
+ BUILTIN_ACTION_NAMES,
2800
+ BUILTIN_CONDITIONS,
2801
+ BUILTIN_CONDITION_NAMES,
2550
2802
  PubSub,
2551
2803
  catchError,
2552
- createActionsRegistry,
2553
- createConditionsRegistry,
2554
2804
  createFlow,
2555
2805
  createMemoryTraceSink,
2556
2806
  createPubSub,
2557
2807
  createWS,
2808
+ createWebSocket,
2558
2809
  defineConfig,
2559
2810
  defineErrorReporter
2560
2811
  });