repos / starfx

a micro-mvc framework for react apps
git clone https://github.com/neurosnap/starfx.git

starfx / src
Vlad  ·  2025-06-15

matcher.ts

 1import type { AnyAction } from "./types.js";
 2
 3type ActionType = string;
 4type GuardPredicate<G extends T, T = unknown> = (arg: T) => arg is G;
 5type Predicate<Guard extends AnyAction = AnyAction> = (
 6  action: Guard,
 7) => boolean;
 8type StringableActionCreator<A extends AnyAction = AnyAction> = {
 9  (...args: any[]): A;
10  toString(): string;
11};
12type SubPattern<Guard extends AnyAction = AnyAction> =
13  | Predicate<Guard>
14  | StringableActionCreator
15  | ActionType;
16export type Pattern = SubPattern | SubPattern[];
17type ActionSubPattern<Guard extends AnyAction = AnyAction> =
18  | GuardPredicate<Guard, AnyAction>
19  | StringableActionCreator<Guard>
20  | Predicate<Guard>
21  | ActionType;
22export type ActionPattern<Guard extends AnyAction = AnyAction> =
23  | ActionSubPattern<Guard>
24  | ActionSubPattern<Guard>[];
25
26function isThunk(fn: any): boolean {
27  return (
28    typeof fn === "function" &&
29    typeof fn.run === "function" &&
30    typeof fn.use === "function" &&
31    typeof fn.name === "string" &&
32    typeof fn.toString === "function"
33  );
34}
35
36function isActionCreator(fn: any): boolean {
37  return !!fn && fn._starfx === true;
38}
39
40export function matcher(pattern: ActionPattern): Predicate {
41  if (pattern === "*") {
42    return (input) => !!input;
43  }
44
45  if (typeof pattern === "string") {
46    return (input) => pattern === input.type;
47  }
48
49  if (Array.isArray(pattern)) {
50    return (input) => pattern.some((p) => matcher(p)(input));
51  }
52
53  if (isThunk(pattern)) {
54    return (input) => pattern.toString() === input.type;
55  }
56
57  if (typeof pattern === "function" && !isActionCreator(pattern)) {
58    return (input) => pattern(input) as boolean;
59  }
60
61  if (isActionCreator(pattern)) {
62    return (input: AnyAction) => pattern.toString() === input.type;
63  }
64
65  throw new Error("invalid pattern");
66}