@xmachines/play-xstate 2.0.0-alpha.1 → 2.0.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.
Files changed (84) hide show
  1. package/README.md +90 -91
  2. package/dist/define-player.d.ts +3 -3
  3. package/dist/define-player.js +3 -3
  4. package/dist/errors.d.ts +46 -70
  5. package/dist/errors.d.ts.map +1 -1
  6. package/dist/errors.js +69 -77
  7. package/dist/errors.js.map +1 -1
  8. package/dist/guards/compose.d.ts +49 -59
  9. package/dist/guards/compose.d.ts.map +1 -1
  10. package/dist/guards/compose.js +68 -95
  11. package/dist/guards/compose.js.map +1 -1
  12. package/dist/guards/helpers.d.ts +6 -2
  13. package/dist/guards/helpers.d.ts.map +1 -1
  14. package/dist/guards/helpers.js +6 -2
  15. package/dist/guards/helpers.js.map +1 -1
  16. package/dist/guards/index.d.ts +7 -0
  17. package/dist/guards/index.d.ts.map +1 -1
  18. package/dist/guards/index.js +7 -0
  19. package/dist/guards/index.js.map +1 -1
  20. package/dist/guards/types.d.ts +4 -5
  21. package/dist/guards/types.d.ts.map +1 -1
  22. package/dist/index.d.ts +3 -4
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +2 -4
  25. package/dist/index.js.map +1 -1
  26. package/dist/player-actor.d.ts +112 -44
  27. package/dist/player-actor.d.ts.map +1 -1
  28. package/dist/player-actor.js +311 -327
  29. package/dist/player-actor.js.map +1 -1
  30. package/dist/routing/build-url.d.ts +2 -7
  31. package/dist/routing/build-url.d.ts.map +1 -1
  32. package/dist/routing/build-url.js +21 -25
  33. package/dist/routing/build-url.js.map +1 -1
  34. package/dist/routing/derive-current-route.d.ts +32 -0
  35. package/dist/routing/derive-current-route.d.ts.map +1 -1
  36. package/dist/routing/derive-current-route.js +20 -19
  37. package/dist/routing/derive-current-route.js.map +1 -1
  38. package/dist/routing/derive-initial-route.d.ts +1 -4
  39. package/dist/routing/derive-initial-route.d.ts.map +1 -1
  40. package/dist/routing/derive-initial-route.js +1 -4
  41. package/dist/routing/derive-initial-route.js.map +1 -1
  42. package/dist/routing/format-play-route-transitions.d.ts +11 -54
  43. package/dist/routing/format-play-route-transitions.d.ts.map +1 -1
  44. package/dist/routing/format-play-route-transitions.js +65 -125
  45. package/dist/routing/format-play-route-transitions.js.map +1 -1
  46. package/dist/routing/index.d.ts +1 -5
  47. package/dist/routing/index.d.ts.map +1 -1
  48. package/dist/routing/index.js +1 -3
  49. package/dist/routing/index.js.map +1 -1
  50. package/dist/types.d.ts +87 -14
  51. package/dist/types.d.ts.map +1 -1
  52. package/dist/view/derive-current-view.d.ts +49 -0
  53. package/dist/view/derive-current-view.d.ts.map +1 -0
  54. package/dist/view/derive-current-view.js +115 -0
  55. package/dist/view/derive-current-view.js.map +1 -0
  56. package/package.json +22 -22
  57. package/dist/define-player.typecheck.d.ts +0 -2
  58. package/dist/define-player.typecheck.d.ts.map +0 -1
  59. package/dist/define-player.typecheck.js +0 -48
  60. package/dist/define-player.typecheck.js.map +0 -1
  61. package/dist/guards/compose.typecheck.d.ts +0 -2
  62. package/dist/guards/compose.typecheck.d.ts.map +0 -1
  63. package/dist/guards/compose.typecheck.js +0 -22
  64. package/dist/guards/compose.typecheck.js.map +0 -1
  65. package/dist/player-actor.typecheck.d.ts +0 -2
  66. package/dist/player-actor.typecheck.d.ts.map +0 -1
  67. package/dist/player-actor.typecheck.js +0 -30
  68. package/dist/player-actor.typecheck.js.map +0 -1
  69. package/dist/routing/create-routed-machine.d.ts +0 -71
  70. package/dist/routing/create-routed-machine.d.ts.map +0 -1
  71. package/dist/routing/create-routed-machine.js +0 -71
  72. package/dist/routing/create-routed-machine.js.map +0 -1
  73. package/dist/routing/play-route-event.typecheck.d.ts +0 -2
  74. package/dist/routing/play-route-event.typecheck.d.ts.map +0 -1
  75. package/dist/routing/play-route-event.typecheck.js +0 -43
  76. package/dist/routing/play-route-event.typecheck.js.map +0 -1
  77. package/dist/routing/schemas.d.ts +0 -99
  78. package/dist/routing/schemas.d.ts.map +0 -1
  79. package/dist/routing/schemas.js +0 -30
  80. package/dist/routing/schemas.js.map +0 -1
  81. package/dist/schemas.d.ts +0 -28
  82. package/dist/schemas.d.ts.map +0 -1
  83. package/dist/schemas.js +0 -29
  84. package/dist/schemas.js.map +0 -1
package/dist/errors.js CHANGED
@@ -1,4 +1,24 @@
1
1
  import { PlayError } from "@xmachines/play";
2
+ /**
3
+ * Stringify a thrown value without trusting it: `String()` itself throws for
4
+ * a null-prototype object or a value whose `toString`/`Symbol.toPrimitive`
5
+ * throw, and this runs inside the error path — a second throw here would
6
+ * replace the machine's real failure with a `TypeError` and bypass `onError`.
7
+ */
8
+ const safeString = (value) => {
9
+ try {
10
+ return String(value);
11
+ }
12
+ catch {
13
+ try {
14
+ return Object.prototype.toString.call(value);
15
+ }
16
+ catch {
17
+ // A revoked Proxy throws even on brand inspection.
18
+ return "[unrepresentable value]";
19
+ }
20
+ }
21
+ };
2
22
  /**
3
23
  * Thrown by `buildRouteUrl()` when a required route parameter is absent from the
4
24
  * actor's context.
@@ -8,16 +28,17 @@ import { PlayError } from "@xmachines/play";
8
28
  *
9
29
  * **Error code:** `PLAY_XSTATE_ROUTE_PARAM_MISSING`
10
30
  *
31
+ * Note: `actor.currentRoute.get()` never surfaces this error — route
32
+ * derivation catches it and returns `null` for the transient mid-transition
33
+ * case. It only escapes direct `buildRouteUrl()` calls.
34
+ *
11
35
  * @example
12
36
  * ```typescript
37
+ * import { buildRouteUrl } from "@xmachines/play-xstate";
13
38
  * import { MissingRouteParamError } from "@xmachines/play-xstate/errors";
14
39
  *
15
- * // The route template "/profile/:userId" requires "userId" in context.
16
- * // If userId is absent, MissingRouteParamError is thrown when the
17
- * // actor.currentRoute signal is read.
18
- *
19
40
  * try {
20
- * actor.currentRoute.get();
41
+ * buildRouteUrl("/profile/:userId", { params: {}, query: {} });
21
42
  * } catch (err) {
22
43
  * if (err instanceof MissingRouteParamError) {
23
44
  * console.error(
@@ -40,36 +61,18 @@ export class MissingRouteParamError extends PlayError {
40
61
  }
41
62
  }
42
63
  /**
43
- * Thrown by `buildRouteUrl()` when the context has a `params` field (indicating a
44
- * routing-aware machine context) but no `query` field.
45
- *
46
- * The `params` field signals the context was set up for routing (either manually or via
47
- * `formatPlayRouteTransitions`). A routing-aware context without `query` will silently
48
- * drop any query parameters carried by `play.route` events, producing incorrect URLs.
64
+ * @deprecated Never thrown any more. `buildRouteUrl` treats a missing `query`
65
+ * field as `query: {}` — the generated `play.route` transitions assign
66
+ * `query` on every navigation, so the loss this error guarded against cannot
67
+ * occur through route derivation. Machines that handle `play.route` by hand
68
+ * and want query forwarding must assign `event.query` to context themselves.
69
+ * Kept exported so existing `instanceof` handlers keep compiling; remove them
70
+ * at leisure.
49
71
  *
50
- * **Fix:** Ensure the machine context type includes `query: Record<string, string>`
51
- * and that the context initializer sets `query: {}` (or a populated value).
52
- * If using `formatPlayRouteTransitions`, the field is assigned automatically on each
53
- * `play.route` event — but the machine's initial context must still declare it.
72
+ * Formerly thrown by `buildRouteUrl()` when the context had a `params` field
73
+ * (a routing-aware machine context) but no `query` field.
54
74
  *
55
75
  * **Error code:** `PLAY_XSTATE_MISSING_QUERY_CONTEXT`
56
- *
57
- * @example
58
- * ```typescript
59
- * import { MissingQueryContextError } from "@xmachines/play-xstate/errors";
60
- *
61
- * try {
62
- * // params present but no query field — throws
63
- * buildRouteUrl("/profile/:userId", { params: { userId: "42" } });
64
- * } catch (err) {
65
- * if (err instanceof MissingQueryContextError) {
66
- * console.error("Machine context missing query field");
67
- * }
68
- * }
69
- *
70
- * // Correct — both params and query declared
71
- * buildRouteUrl("/profile/:userId", { params: { userId: "42" }, query: {} });
72
- * ```
73
76
  */
74
77
  export class MissingQueryContextError extends PlayError {
75
78
  constructor() {
@@ -165,51 +168,6 @@ export class EmptyGuardArrayError extends PlayError {
165
168
  this.combinator = combinator;
166
169
  }
167
170
  }
168
- /**
169
- * Thrown when a composed guard cannot resolve a string guard name at call time.
170
- *
171
- * String names in `composeGuards`/`composeGuardsOr`/`negateGuard` resolve
172
- * against `args.guards` — the named guards from `setup({ guards })` that
173
- * XState v6 provides to transition functions, `always`, entry/exit actions
174
- * (since 6.0.0-alpha.20), and function-form route resolvers. Resolution fails
175
- * when the name was never declared or when the composed guard is called
176
- * without transition arguments.
177
- *
178
- * **Error code:** `PLAY_XSTATE_UNRESOLVABLE_GUARD_NAME`
179
- */
180
- export class UnresolvableGuardNameError extends PlayError {
181
- /** The guard name that could not be resolved. */
182
- guardName;
183
- constructor(guardName, origin) {
184
- super(origin, "PLAY_XSTATE_UNRESOLVABLE_GUARD_NAME", `Guard "${guardName}" is not a function. Either the name was never declared ` +
185
- `in setup({ guards }) or the composed guard was called without ` +
186
- `transition arguments.`);
187
- this.name = "UnresolvableGuardNameError";
188
- this.guardName = guardName;
189
- }
190
- }
191
- /**
192
- * Thrown when a composed guard evaluates an entry that is neither a predicate
193
- * function nor a guard name — typically `null`/`undefined` from a typo'd
194
- * import or an optional lookup.
195
- *
196
- * XState v5 failed loudly when evaluating such entries; silently treating them
197
- * as never-passing would turn `negateGuard(undefined)` into an always-allow.
198
- * Composition stays lazy (no throw at compose time); evaluation throws.
199
- *
200
- * **Error code:** `PLAY_XSTATE_INVALID_GUARD_ENTRY`
201
- */
202
- export class InvalidGuardEntryError extends PlayError {
203
- /** `typeof` of the invalid entry (e.g. `"undefined"`, `"object"` for null). */
204
- entryType;
205
- constructor(entryType, origin) {
206
- super(origin, "PLAY_XSTATE_INVALID_GUARD_ENTRY", `Guard entry of type "${entryType}" is neither a predicate function nor a ` +
207
- `guard name. Check for typo'd imports or optional lookups that resolved ` +
208
- `to null/undefined.`);
209
- this.name = "InvalidGuardEntryError";
210
- this.entryType = entryType;
211
- }
212
- }
213
171
  /**
214
172
  * Thrown by `PlayerActor.send()` when the event argument is not a plain object.
215
173
  *
@@ -244,4 +202,38 @@ export class InvalidEventError extends PlayError {
244
202
  this.detail = detail;
245
203
  }
246
204
  }
205
+ /**
206
+ * Passed to `PlayerOptions.onError` when the actor failed with a value that is
207
+ * not an `Error` — e.g. a machine action ran `throw { code: 42 }`.
208
+ *
209
+ * An actor error that *is* an `Error` reaches `onError` untouched, keeping the
210
+ * identity the machine gave it. Only this case constructs a new error, so it
211
+ * carries a matchable code instead of a `String(value)` message such as
212
+ * `"[object Object]"`. The thrown value is preserved on `cause`.
213
+ *
214
+ * **Error code:** `PLAY_XSTATE_NON_ERROR_THROWN`
215
+ *
216
+ * @example
217
+ * ```typescript
218
+ * import { ActorThrewNonErrorError } from "@xmachines/play-xstate/errors";
219
+ *
220
+ * definePlayer({
221
+ * machine,
222
+ * options: {
223
+ * onError: (actor, err) => {
224
+ * if (err instanceof ActorThrewNonErrorError) {
225
+ * // err.cause is the value the machine actually threw
226
+ * console.error("Machine threw a non-Error:", err.cause);
227
+ * }
228
+ * },
229
+ * },
230
+ * });
231
+ * ```
232
+ */
233
+ export class ActorThrewNonErrorError extends PlayError {
234
+ constructor(value) {
235
+ super("PlayerActor", "PLAY_XSTATE_NON_ERROR_THROWN", `PlayerActor failed with a non-Error value: ${safeString(value)}.`, { cause: value });
236
+ this.name = "ActorThrewNonErrorError";
237
+ }
238
+ }
247
239
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
@@ -1,50 +1,35 @@
1
+ import type { GuardPredicate } from "xstate";
1
2
  import type { Guard, GuardArray } from "./types.js";
3
+ import type { MachineContext, EventObject, ParameterizedObject } from "xstate";
2
4
  /**
3
- * Composed guard: a plain predicate over transition arguments.
5
+ * Narrowest public return type for guard composition helpers.
4
6
  *
5
- * XState v6 removed guard objects and the `and()`/`or()`/`not()` creators —
6
- * guards are now plain functions evaluated inside transition functions. A
7
- * composed guard is therefore just another predicate with the same shape as
8
- * {@link Guard}, callable anywhere transition args are available.
9
- *
10
- * String guard names are resolved against `args.guards` (the named guards
11
- * declared in `setup({ guards })`, which XState v6 passes to every transition
12
- * function). Resolving a name outside a transition function — or a name that
13
- * was never declared — throws `UnresolvableGuardNameError` immediately.
14
- *
15
- * String names work in `on` transitions, `always`, entry/exit actions (since
16
- * xstate 6.0.0-alpha.20 populates `guards` there), and function-form route
17
- * resolvers.
7
+ * `GuardPredicate<MachineContext, EventObject, unknown, ParameterizedObject>` is the
8
+ * widest-compatible concrete XState guard type that does not use `any`.
18
9
  *
19
10
  * @public
11
+ * @deprecated The guard utilities will be removed in the next major — use
12
+ * XState's own combinator types directly.
20
13
  */
21
- export type ComposedGuard = (args: unknown) => boolean;
14
+ export type ComposedGuard = GuardPredicate<MachineContext, EventObject, unknown, ParameterizedObject>;
22
15
  /**
23
- * Compose guards with AND logic.
16
+ * Compose guards with AND logic using XState's and() helper
24
17
  *
25
18
  * Combines multiple guard predicates using AND semantics—all guards must pass for
26
- * the composition to succeed. Evaluation is short-circuiting, left to right.
19
+ * the composition to succeed. Uses XState's built-in `and()` helper to ensure proper
20
+ * type inference and machine serialization.
27
21
  *
28
22
  * **Architectural Context:** Supports **Actor Authority (INV-01)** by enabling
29
23
  * declarative guard composition in state machine transitions. Guards enforce business
30
24
  * logic rules that determine whether navigation or actions are valid.
31
25
  *
32
- * **XState v6:** the composed value is a plain predicate. Call it inside a
33
- * transition function and return early to block the transition:
34
- *
35
- * @typeParam TContext - State machine context type (defaults to `any` so the
36
- * documented inline-predicate examples compile without annotations)
37
- * @typeParam TEvent - Event type
38
- *
39
- * @typeParam TContext - State machine context type (defaults to `any` so the
40
- * documented inline-predicate examples compile without annotations)
26
+ * @typeParam TContext - State machine context type
41
27
  * @typeParam TEvent - Event type
42
28
  *
43
- * @param guards - Array of guard predicates or guard names (string references
44
- * resolved against `args.guards` from `setup({ guards })`)
45
- * @returns Predicate returning `true` only when every guard passes
29
+ * @param guards - Array of guard predicates or guard names (string references)
30
+ * @returns XState and() guard composition
46
31
  *
47
- * @throws {EmptyGuardArrayError} If guards array is empty
32
+ * @throws {Error} If guards array is empty
48
33
  *
49
34
  * @example
50
35
  * AND composition with named guards
@@ -52,8 +37,6 @@ export type ComposedGuard = (args: unknown) => boolean;
52
37
  * import { setup } from "xstate";
53
38
  * import { composeGuards } from "@xmachines/play-xstate";
54
39
  *
55
- * const canAccessAdmin = composeGuards(['isLoggedIn', 'hasPermission']);
56
- *
57
40
  * const machine = setup({
58
41
  * guards: {
59
42
  * isLoggedIn: ({ context }) => !!context.userId,
@@ -61,9 +44,10 @@ export type ComposedGuard = (args: unknown) => boolean;
61
44
  * }
62
45
  * }).createMachine({
63
46
  * on: {
64
- * accessAdmin: (args) => {
65
- * if (!canAccessAdmin(args)) return;
66
- * return { target: 'adminPanel' };
47
+ * accessAdmin: {
48
+ * // Both guards must pass
49
+ * guard: composeGuards(['isLoggedIn', 'hasPermission']),
50
+ * target: 'adminPanel'
67
51
  * }
68
52
  * }
69
53
  * });
@@ -74,27 +58,32 @@ export type ComposedGuard = (args: unknown) => boolean;
74
58
  * ```typescript
75
59
  * import { composeGuards } from "@xmachines/play-xstate";
76
60
  *
77
- * const isEligible = composeGuards([
61
+ * guard: composeGuards([
78
62
  * ({ context }) => context.age >= 18,
79
63
  * ({ context }) => context.verified
80
- * ]);
64
+ * ])
81
65
  * ```
82
66
  *
83
67
  * @see {@link composeGuardsOr} for OR composition
84
68
  * @see {@link negateGuard} for NOT logic
69
+ * @deprecated Use XState's own `and()`/`or()`/`not()` directly — this helper does not
70
+ * compose with `setup()`-typed guard slots and will be removed in the next major.
85
71
  */
86
72
  export declare const composeGuards: <TContext = any, TEvent = any>(guards: GuardArray<TContext, TEvent>) => ComposedGuard;
87
73
  /**
88
- * Compose guards with OR logic.
74
+ * Compose guards with OR logic using XState's or() helper
89
75
  *
90
76
  * Combines multiple guard predicates using OR semantics—at least one guard must pass
91
- * for the composition to succeed. Evaluation is short-circuiting, left to right.
77
+ * for the composition to succeed. Uses XState's built-in `or()` helper for proper
78
+ * type inference.
79
+ *
80
+ * @typeParam TContext - State machine context type
81
+ * @typeParam TEvent - Event type
92
82
  *
93
- * @param guards - Array of guard predicates or guard names (string references
94
- * resolved against `args.guards` from `setup({ guards })`)
95
- * @returns Predicate returning `true` when any guard passes
83
+ * @param guards - Array of guard predicates or guard names
84
+ * @returns XState or() guard composition
96
85
  *
97
- * @throws {EmptyGuardArrayError} If guards array is empty
86
+ * @throws {Error} If guards array is empty
98
87
  *
99
88
  * @example
100
89
  * OR composition with named guards
@@ -102,8 +91,6 @@ export declare const composeGuards: <TContext = any, TEvent = any>(guards: Guard
102
91
  * import { setup } from "xstate";
103
92
  * import { composeGuardsOr } from "@xmachines/play-xstate";
104
93
  *
105
- * const canDelete = composeGuardsOr(['isOwner', 'isAdmin']);
106
- *
107
94
  * const machine = setup({
108
95
  * guards: {
109
96
  * isOwner: ({ context }) => context.role === 'owner',
@@ -111,9 +98,10 @@ export declare const composeGuards: <TContext = any, TEvent = any>(guards: Guard
111
98
  * }
112
99
  * }).createMachine({
113
100
  * on: {
114
- * deleteResource: (args, enq) => {
115
- * if (!canDelete(args)) return;
116
- * enq(() => deleteIt());
101
+ * deleteResource: {
102
+ * // Either guard can pass
103
+ * guard: composeGuardsOr(['isOwner', 'isAdmin']),
104
+ * actions: 'delete'
117
105
  * }
118
106
  * }
119
107
  * });
@@ -121,20 +109,21 @@ export declare const composeGuards: <TContext = any, TEvent = any>(guards: Guard
121
109
  *
122
110
  * @see {@link composeGuards} for AND composition
123
111
  * @see {@link negateGuard} for NOT logic
112
+ * @deprecated Use XState's own `and()`/`or()`/`not()` directly — this helper does not
113
+ * compose with `setup()`-typed guard slots and will be removed in the next major.
124
114
  */
125
115
  export declare const composeGuardsOr: <TContext = any, TEvent = any>(guards: GuardArray<TContext, TEvent>) => ComposedGuard;
126
116
  /**
127
- * Negate a guard.
117
+ * Negate a guard using XState's not() helper
128
118
  *
129
119
  * Inverts a guard's result—if the guard passes, NOT fails; if guard fails, NOT passes.
120
+ * Uses XState's built-in `not()` helper for proper serialization.
130
121
  *
131
- * @typeParam TContext - State machine context type (defaults to `any` so
132
- * inline predicates compile without annotations)
122
+ * @typeParam TContext - State machine context type
133
123
  * @typeParam TEvent - Event type
134
124
  *
135
- * @param guard - Guard predicate or guard name (resolved against `args.guards`
136
- * from `setup({ guards })`) to negate
137
- * @returns Predicate returning the inverted guard result
125
+ * @param guard - Guard predicate or guard name to negate
126
+ * @returns XState not() guard negation
138
127
  *
139
128
  * @example
140
129
  * NOT composition with named guard
@@ -142,17 +131,16 @@ export declare const composeGuardsOr: <TContext = any, TEvent = any>(guards: Gua
142
131
  * import { setup } from "xstate";
143
132
  * import { negateGuard } from "@xmachines/play-xstate";
144
133
  *
145
- * const isAuthenticated = negateGuard('isGuest');
146
- *
147
134
  * const machine = setup({
148
135
  * guards: {
149
136
  * isGuest: ({ context }) => !context.userId
150
137
  * }
151
138
  * }).createMachine({
152
139
  * on: {
153
- * accessDashboard: (args) => {
154
- * if (!isAuthenticated(args)) return;
155
- * return { target: 'dashboard' };
140
+ * accessDashboard: {
141
+ * // Allow if NOT a guest (i.e., authenticated)
142
+ * guard: negateGuard('isGuest'),
143
+ * target: 'dashboard'
156
144
  * }
157
145
  * }
158
146
  * });
@@ -160,6 +148,8 @@ export declare const composeGuardsOr: <TContext = any, TEvent = any>(guards: Gua
160
148
  *
161
149
  * @see {@link composeGuards} for AND composition
162
150
  * @see {@link composeGuardsOr} for OR composition
151
+ * @deprecated Use XState's own `and()`/`or()`/`not()` directly — this helper does not
152
+ * compose with `setup()`-typed guard slots and will be removed in the next major.
163
153
  */
164
154
  export declare const negateGuard: <TContext = any, TEvent = any>(guard: Guard<TContext, TEvent> | string) => ComposedGuard;
165
155
  //# sourceMappingURL=compose.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/guards/compose.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAQpD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;AAqCvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAEH,eAAO,MAAM,aAAa,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EACzD,QAAQ,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAClC,aAgBF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,eAAO,MAAM,eAAe,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAC3D,QAAQ,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAClC,aAgBF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,eAAO,MAAM,WAAW,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EACvD,OAAO,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,KACrC,aAGF,CAAC"}
1
+ {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/guards/compose.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAkB/E;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG,cAAc,CACzC,cAAc,EACd,WAAW,EACX,OAAO,EACP,mBAAmB,CACnB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAEH,eAAO,MAAM,aAAa,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EACzD,QAAQ,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAClC,aAYF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,eAAO,MAAM,eAAe,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAC3D,QAAQ,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,KAClC,aAYF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,eAAO,MAAM,WAAW,GAAI,QAAQ,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EACvD,OAAO,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,KACrC,aAIF,CAAC"}