mobx-keystone 1.20.0 → 1.22.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 (174) hide show
  1. package/CHANGELOG.md +864 -853
  2. package/README.md +61 -61
  3. package/dist/mobx-keystone.esm.js +11336 -11148
  4. package/dist/mobx-keystone.esm.mjs +11336 -11148
  5. package/dist/mobx-keystone.umd.js +12229 -11738
  6. package/dist/types/actionMiddlewares/undoMiddleware.d.ts +1 -1
  7. package/dist/types/modelShared/prop.d.ts +5 -0
  8. package/dist/types/redux/connectReduxDevTools.d.ts +17 -4
  9. package/dist/types/ref/Ref.d.ts +1 -1
  10. package/dist/types/treeUtils/sandbox.d.ts +1 -1
  11. package/dist/types/types/TypeChecker.d.ts +1 -1
  12. package/dist/types/types/arrayBased/typesArray.d.ts +1 -1
  13. package/dist/types/types/arrayBased/typesTuple.d.ts +1 -1
  14. package/dist/types/types/objectBased/typesArraySet.d.ts +1 -1
  15. package/dist/types/types/objectBased/typesDataModelData.d.ts +1 -1
  16. package/dist/types/types/objectBased/typesModel.d.ts +1 -1
  17. package/dist/types/types/objectBased/typesObject.d.ts +3 -3
  18. package/dist/types/types/objectBased/typesObjectMap.d.ts +1 -1
  19. package/dist/types/types/objectBased/typesRecord.d.ts +1 -1
  20. package/dist/types/types/primitiveBased/typesPrimitive.d.ts +1 -1
  21. package/dist/types/types/types.d.ts +3 -3
  22. package/dist/types/types/utility/typesCodec.d.ts +1 -6
  23. package/dist/types/types/utility/typesCodecCore.d.ts +1 -1
  24. package/dist/types/types/utility/typesOr.d.ts +1 -1
  25. package/dist/types/types/utility/typesRefinement.d.ts +1 -1
  26. package/dist/types/types/utility/typesSkipCheck.d.ts +1 -1
  27. package/dist/types/types/utility/typesTag.d.ts +1 -1
  28. package/dist/types/wrappers/ObjectMap.d.ts +2 -0
  29. package/dist/types/wrappers/asMap.d.ts +10 -6
  30. package/package.json +14 -12
  31. package/src/action/applyAction.ts +125 -114
  32. package/src/action/applyMethodCall.ts +37 -37
  33. package/src/action/isModelAction.ts +16 -16
  34. package/src/action/middleware.ts +137 -137
  35. package/src/action/modelFlow.ts +240 -240
  36. package/src/action/modelFlowPromiseGenerator.ts +127 -125
  37. package/src/action/pendingActions.ts +42 -42
  38. package/src/action/wrapInAction.ts +156 -156
  39. package/src/actionMiddlewares/actionSerialization/actionSerialization.ts +1 -1
  40. package/src/actionMiddlewares/actionSerialization/applySerializedAction.ts +172 -172
  41. package/src/actionMiddlewares/actionSerialization/arraySerializer.ts +20 -20
  42. package/src/actionMiddlewares/actionSerialization/dateSerializer.ts +17 -17
  43. package/src/actionMiddlewares/actionSerialization/mapSerializer.ts +42 -42
  44. package/src/actionMiddlewares/actionSerialization/objectPathSerializer.ts +50 -50
  45. package/src/actionMiddlewares/actionSerialization/objectSnapshotSerializer.ts +21 -21
  46. package/src/actionMiddlewares/actionSerialization/plainObjectSerializer.ts +24 -32
  47. package/src/actionMiddlewares/actionSerialization/primitiveSerializer.ts +51 -51
  48. package/src/actionMiddlewares/actionSerialization/setSerializer.ts +37 -37
  49. package/src/actionMiddlewares/actionTrackingMiddleware.ts +3 -3
  50. package/src/actionMiddlewares/onActionMiddleware.ts +2 -2
  51. package/src/actionMiddlewares/readonlyMiddleware.ts +2 -2
  52. package/src/actionMiddlewares/transactionMiddleware.ts +4 -4
  53. package/src/actionMiddlewares/undoMiddleware.ts +804 -796
  54. package/src/actionMiddlewares/utils.ts +2 -2
  55. package/src/computedTree/computedTree.ts +143 -143
  56. package/src/context/context.ts +1 -1
  57. package/src/dataModel/BaseDataModel.ts +194 -192
  58. package/src/dataModel/actions.ts +1 -1
  59. package/src/dataModel/newDataModel.ts +57 -57
  60. package/src/deepChange/index.ts +1 -1
  61. package/src/deepChange/onDeepChange.ts +244 -244
  62. package/src/frozen/Frozen.ts +146 -146
  63. package/src/globalConfig/globalConfig.ts +107 -107
  64. package/src/index.ts +24 -24
  65. package/src/model/BaseModel.ts +275 -273
  66. package/src/model/ModelConstructorOptions.ts +15 -15
  67. package/src/model/getModelMetadata.ts +51 -51
  68. package/src/model/index.ts +6 -6
  69. package/src/model/mixins.ts +288 -288
  70. package/src/model/newModel.ts +301 -301
  71. package/src/model/utils.ts +249 -249
  72. package/src/modelShared/modelDecorator.ts +260 -253
  73. package/src/modelShared/modelInfo.ts +50 -50
  74. package/src/modelShared/modelSymbols.ts +3 -3
  75. package/src/modelShared/newModel.ts +25 -25
  76. package/src/modelShared/prop.ts +713 -684
  77. package/src/modelShared/sharedInternalModel.ts +427 -417
  78. package/src/modelShared/utils.ts +24 -24
  79. package/src/parent/core.ts +65 -65
  80. package/src/parent/coreObjectChildren.ts +180 -180
  81. package/src/parent/detach.ts +47 -47
  82. package/src/parent/findParent.ts +1 -1
  83. package/src/parent/getChildrenObjects.ts +25 -25
  84. package/src/parent/path.ts +386 -381
  85. package/src/parent/setParent.ts +149 -149
  86. package/src/parent/walkTree.ts +1 -1
  87. package/src/patch/applyPatches.ts +187 -187
  88. package/src/patch/jsonPatch.ts +108 -108
  89. package/src/patch/patchRecorder.ts +6 -1
  90. package/src/redux/connectReduxDevTools.ts +39 -7
  91. package/src/redux/redux.ts +6 -2
  92. package/src/ref/Ref.ts +1 -1
  93. package/src/ref/core.ts +339 -345
  94. package/src/ref/customRef.ts +3 -3
  95. package/src/ref/rootRef.ts +100 -100
  96. package/src/rootStore/attachDetach.ts +89 -89
  97. package/src/rootStore/rootStore.ts +1 -1
  98. package/src/snapshot/SnapshotOf.ts +104 -104
  99. package/src/snapshot/SnapshotProcessingError.ts +45 -45
  100. package/src/snapshot/applySnapshot.ts +177 -181
  101. package/src/snapshot/cloneTreeValue.ts +30 -30
  102. package/src/snapshot/fromArraySnapshot.ts +27 -33
  103. package/src/snapshot/fromModelSnapshot.ts +70 -70
  104. package/src/snapshot/fromPlainObjectSnapshot.ts +47 -42
  105. package/src/snapshot/fromSnapshot.ts +198 -198
  106. package/src/snapshot/getSnapshot.ts +80 -79
  107. package/src/snapshot/index.ts +8 -8
  108. package/src/snapshot/internal.ts +230 -230
  109. package/src/snapshot/reconcileArraySnapshot.ts +70 -70
  110. package/src/snapshot/reconcileModelSnapshot.ts +155 -150
  111. package/src/snapshot/reconcilePlainObjectSnapshot.ts +72 -72
  112. package/src/snapshot/reconcileSnapshot.ts +88 -88
  113. package/src/standardActions/actions.ts +64 -64
  114. package/src/standardActions/objectActions.ts +60 -60
  115. package/src/transforms/ImmutableDate.ts +93 -93
  116. package/src/transforms/asMap.ts +50 -50
  117. package/src/transforms/asSet.ts +22 -22
  118. package/src/transforms/bigint.ts +20 -20
  119. package/src/transforms/date.ts +40 -40
  120. package/src/treeUtils/deepEquals.ts +55 -55
  121. package/src/treeUtils/sandbox.ts +6 -3
  122. package/src/tweaker/TweakerPriority.ts +9 -9
  123. package/src/tweaker/tweak.ts +4 -3
  124. package/src/tweaker/tweakArray.ts +530 -475
  125. package/src/tweaker/tweakFrozen.ts +42 -42
  126. package/src/tweaker/tweakModel.ts +1 -1
  127. package/src/tweaker/tweakPlainObject.ts +355 -355
  128. package/src/tweaker/typeChecking.ts +101 -101
  129. package/src/types/SnapshotTypeMismatchError.ts +46 -46
  130. package/src/types/TypeCheckError.ts +183 -184
  131. package/src/types/TypeChecker.ts +202 -185
  132. package/src/types/arrayBased/typesArray.ts +136 -137
  133. package/src/types/arrayBased/typesTuple.ts +138 -139
  134. package/src/types/createPerEntryCachedCheck.ts +166 -160
  135. package/src/types/index.ts +6 -6
  136. package/src/types/objectBased/typesArraySet.ts +133 -134
  137. package/src/types/objectBased/typesDataModelData.ts +203 -204
  138. package/src/types/objectBased/typesModel.ts +220 -221
  139. package/src/types/objectBased/typesObject.ts +308 -310
  140. package/src/types/objectBased/typesObjectMap.ts +142 -143
  141. package/src/types/objectBased/typesRecord.ts +156 -157
  142. package/src/types/objectBased/typesRef.ts +89 -89
  143. package/src/types/primitiveBased/typesEnum.ts +63 -63
  144. package/src/types/primitiveBased/typesPrimitive.ts +219 -220
  145. package/src/types/registerDefaultStandardTypeResolvers.ts +21 -21
  146. package/src/types/resolveTypeChecker.ts +78 -78
  147. package/src/types/schemas.ts +208 -208
  148. package/src/types/tProp.ts +277 -268
  149. package/src/types/typeCheck.ts +21 -21
  150. package/src/types/typeCheckErrorUtils.ts +23 -23
  151. package/src/types/types.ts +142 -142
  152. package/src/types/utility/typeToStoredData.ts +37 -37
  153. package/src/types/utility/typesBigInt.ts +15 -15
  154. package/src/types/utility/typesCodec.ts +41 -38
  155. package/src/types/utility/typesCodecCore.ts +178 -178
  156. package/src/types/utility/typesCodecSupport.ts +806 -806
  157. package/src/types/utility/typesDate.ts +27 -27
  158. package/src/types/utility/typesMap.ts +253 -222
  159. package/src/types/utility/typesOr.ts +263 -259
  160. package/src/types/utility/typesRefinement.ts +131 -125
  161. package/src/types/utility/typesSet.ts +110 -110
  162. package/src/types/utility/typesSkipCheck.ts +69 -70
  163. package/src/types/utility/typesTag.ts +88 -82
  164. package/src/types/utility/typesUnchecked.ts +40 -40
  165. package/src/utils/AnyFunction.ts +4 -4
  166. package/src/utils/ModelPool.ts +59 -59
  167. package/src/utils/chainFns.ts +18 -18
  168. package/src/utils/decorators.ts +274 -274
  169. package/src/utils/errorDiagnostics.ts +204 -204
  170. package/src/utils/index.ts +443 -372
  171. package/src/wrappers/ArraySet.ts +156 -156
  172. package/src/wrappers/ObjectMap.ts +155 -136
  173. package/src/wrappers/asMap.ts +65 -30
  174. package/src/wrappers/asSet.ts +3 -3
@@ -1,240 +1,240 @@
1
- import type { O } from "ts-toolbelt"
2
- import { failure } from "../utils"
3
- import { copyFunctionMetadata, decorateWrapMethodOrField } from "../utils/decorators"
4
- import { ActionContext, ActionContextActionType, ActionContextAsyncStepType } from "./context"
5
- import { promiseGenerator } from "./modelFlowPromiseGenerator"
6
- import { WrapInActionOverrideContextFn, wrapInAction } from "./wrapInAction"
7
-
8
- const modelFlowSymbol = Symbol("modelFlow")
9
-
10
- /**
11
- * @internal
12
- */
13
- export function flow<R, Args extends any[]>({
14
- nameOrNameFn,
15
- generator,
16
- overrideContext,
17
- }: {
18
- nameOrNameFn: string | (() => string)
19
- generator: (...args: Args) => IterableIterator<any>
20
- overrideContext?: WrapInActionOverrideContextFn
21
- }): (...args: Args) => Promise<any> {
22
- // Implementation based on https://github.com/tj/co/blob/master/index.js
23
- const flowFn = function (this: any, ...args: any[]) {
24
- const name = typeof nameOrNameFn === "function" ? nameOrNameFn() : nameOrNameFn
25
-
26
- const target = this
27
-
28
- let previousAsyncStepContext: ActionContext | undefined
29
-
30
- const ctxOverride = (stepType: ActionContextAsyncStepType): WrapInActionOverrideContextFn => {
31
- return (ctx: O.Writable<ActionContext>, self) => {
32
- if (overrideContext) {
33
- overrideContext(ctx, self)
34
- }
35
-
36
- ctx.previousAsyncStepContext = previousAsyncStepContext
37
- ctx.spawnAsyncStepContext = previousAsyncStepContext
38
- ? previousAsyncStepContext.spawnAsyncStepContext
39
- : ctx
40
- ctx.asyncStepType = stepType
41
- ctx.args = args
42
-
43
- previousAsyncStepContext = ctx
44
- }
45
- }
46
-
47
- let generatorRun = false
48
- const gen = wrapInAction({
49
- nameOrNameFn: name,
50
- fn: () => {
51
- generatorRun = true
52
- return generator.apply(target, args as Args)
53
- },
54
- actionType: ActionContextActionType.Async,
55
- overrideContext: ctxOverride(ActionContextAsyncStepType.Spawn),
56
- }).apply(target)
57
-
58
- if (!generatorRun) {
59
- // maybe it got overridden into a sync action
60
-
61
- return gen instanceof Promise ? gen : Promise.resolve(gen)
62
- }
63
-
64
- // use bound functions to fix es6 compilation
65
- const genNext = gen.next.bind(gen)
66
- const genThrow = gen.throw!.bind(gen)
67
-
68
- const promise = new Promise<R>((resolve, reject) => {
69
- function onFulfilled(res: any): void {
70
- let ret: unknown
71
- try {
72
- ret = wrapInAction({
73
- nameOrNameFn: name,
74
- fn: genNext,
75
- actionType: ActionContextActionType.Async,
76
- overrideContext: ctxOverride(ActionContextAsyncStepType.Resume),
77
- }).call(target, res)
78
- } catch (e) {
79
- wrapInAction({
80
- nameOrNameFn: name,
81
- fn: (err: any) => {
82
- // we use a flow finisher to allow middlewares to tweak the return value before resolution
83
- return {
84
- value: err,
85
- resolution: "reject",
86
-
87
- accepter: resolve,
88
- rejecter: reject,
89
- } as FlowFinisher
90
- },
91
- actionType: ActionContextActionType.Async,
92
- overrideContext: ctxOverride(ActionContextAsyncStepType.Throw),
93
- isFlowFinisher: true,
94
- }).call(target, e)
95
- return
96
- }
97
-
98
- next(ret)
99
- }
100
-
101
- function onRejected(err: unknown): void {
102
- let ret: unknown
103
- try {
104
- ret = wrapInAction({
105
- nameOrNameFn: name,
106
- fn: genThrow,
107
- actionType: ActionContextActionType.Async,
108
- overrideContext: ctxOverride(ActionContextAsyncStepType.ResumeError),
109
- }).call(target, err)
110
- } catch (e) {
111
- wrapInAction({
112
- nameOrNameFn: name,
113
- fn: (err: any) => {
114
- // we use a flow finisher to allow middlewares to tweak the return value before resolution
115
- return {
116
- value: err,
117
- resolution: "reject",
118
-
119
- accepter: resolve,
120
- rejecter: reject,
121
- } as FlowFinisher
122
- },
123
- actionType: ActionContextActionType.Async,
124
- overrideContext: ctxOverride(ActionContextAsyncStepType.Throw),
125
- isFlowFinisher: true,
126
- }).call(target, e)
127
- return
128
- }
129
-
130
- next(ret)
131
- }
132
-
133
- function next(ret: any): void {
134
- if (ret && typeof ret.then === "function") {
135
- // an async iterator
136
- ret.then(next, reject)
137
- } else if (ret.done) {
138
- // done
139
- wrapInAction({
140
- nameOrNameFn: name,
141
- fn: (val: any) => {
142
- // we use a flow finisher to allow middlewares to tweak the return value before resolution
143
- return {
144
- value: val,
145
- resolution: "accept",
146
-
147
- accepter: resolve,
148
- rejecter: reject,
149
- } as FlowFinisher
150
- },
151
- actionType: ActionContextActionType.Async,
152
- overrideContext: ctxOverride(ActionContextAsyncStepType.Return),
153
- isFlowFinisher: true,
154
- }).call(target, ret.value)
155
- } else {
156
- // continue
157
- Promise.resolve(ret.value).then(onFulfilled, onRejected)
158
- }
159
- }
160
-
161
- onFulfilled(undefined) // kick off the process
162
- })
163
-
164
- return promise
165
- }
166
- ;(flowFn as any)[modelFlowSymbol] = true
167
-
168
- copyFunctionMetadata(generator, flowFn)
169
-
170
- return flowFn
171
- }
172
-
173
- /**
174
- * @internal
175
- */
176
- export interface FlowFinisher {
177
- value: any
178
- resolution: "accept" | "reject"
179
-
180
- accepter(value: any): void
181
- rejecter(value: any): void
182
- }
183
-
184
- /**
185
- * Returns if the given function is a model flow or not.
186
- *
187
- * @param fn Function to check.
188
- * @returns
189
- */
190
- export function isModelFlow(fn: unknown) {
191
- return typeof fn === "function" && modelFlowSymbol in fn
192
- }
193
-
194
- /**
195
- * Decorator that turns a function generator into a model flow.
196
- */
197
- export function modelFlow(...args: any[]): void {
198
- // biome-ignore lint/correctness/noVoidTypeReturn: proper way to declare a decorator
199
- return decorateWrapMethodOrField("modelFlow", args, (data, fn) => {
200
- if (isModelFlow(fn)) {
201
- return fn
202
- } else {
203
- if (typeof fn !== "function") {
204
- throw failure("modelFlow has to be used over functions")
205
- }
206
-
207
- return flow({
208
- nameOrNameFn: data.actionName,
209
- generator: fn,
210
- overrideContext: data.overrideContext,
211
- })
212
- }
213
- })
214
- }
215
-
216
- /**
217
- * Tricks the TS compiler into thinking that a model flow generator function can be awaited
218
- * (is a promise).
219
- *
220
- * @template A Function arguments.
221
- * @template R Return value.
222
- * @param fn Flow function.
223
- * @returns
224
- */
225
- export function _async<A extends any[], R>(
226
- fn: (...args: A) => Generator<any, R, any>
227
- ): (...args: A) => Promise<R> {
228
- return fn as any
229
- }
230
-
231
- /**
232
- * Makes a promise a flow, so it can be awaited with yield*.
233
- *
234
- * @template T Promise return type.
235
- * @param promise Promise.
236
- * @returns
237
- */
238
- export function _await<T>(promise: Promise<T>): Generator<Promise<T>, T, unknown> {
239
- return promiseGenerator.call(promise)
240
- }
1
+ import type { O } from "ts-toolbelt"
2
+ import { failure } from "../utils"
3
+ import { copyFunctionMetadata, decorateWrapMethodOrField } from "../utils/decorators"
4
+ import { type ActionContext, ActionContextActionType, ActionContextAsyncStepType } from "./context"
5
+ import { promiseGenerator } from "./modelFlowPromiseGenerator"
6
+ import { type WrapInActionOverrideContextFn, wrapInAction } from "./wrapInAction"
7
+
8
+ const modelFlowSymbol = Symbol("modelFlow")
9
+
10
+ /**
11
+ * @internal
12
+ */
13
+ export function flow<R, Args extends any[]>({
14
+ nameOrNameFn,
15
+ generator,
16
+ overrideContext,
17
+ }: {
18
+ nameOrNameFn: string | (() => string)
19
+ generator: (...args: Args) => IterableIterator<any>
20
+ overrideContext?: WrapInActionOverrideContextFn
21
+ }): (...args: Args) => Promise<any> {
22
+ // Implementation based on https://github.com/tj/co/blob/master/index.js
23
+ const flowFn = function (this: any, ...args: any[]) {
24
+ const name = typeof nameOrNameFn === "function" ? nameOrNameFn() : nameOrNameFn
25
+
26
+ const target = this
27
+
28
+ let previousAsyncStepContext: ActionContext | undefined
29
+
30
+ const ctxOverride = (stepType: ActionContextAsyncStepType): WrapInActionOverrideContextFn => {
31
+ return (ctx: O.Writable<ActionContext>, self) => {
32
+ if (overrideContext) {
33
+ overrideContext(ctx, self)
34
+ }
35
+
36
+ ctx.previousAsyncStepContext = previousAsyncStepContext
37
+ ctx.spawnAsyncStepContext = previousAsyncStepContext
38
+ ? previousAsyncStepContext.spawnAsyncStepContext
39
+ : ctx
40
+ ctx.asyncStepType = stepType
41
+ ctx.args = args
42
+
43
+ previousAsyncStepContext = ctx
44
+ }
45
+ }
46
+
47
+ let generatorRun = false
48
+ const gen = wrapInAction({
49
+ nameOrNameFn: name,
50
+ fn: () => {
51
+ generatorRun = true
52
+ return generator.apply(target, args as Args)
53
+ },
54
+ actionType: ActionContextActionType.Async,
55
+ overrideContext: ctxOverride(ActionContextAsyncStepType.Spawn),
56
+ }).apply(target)
57
+
58
+ if (!generatorRun) {
59
+ // maybe it got overridden into a sync action
60
+
61
+ return gen instanceof Promise ? gen : Promise.resolve(gen)
62
+ }
63
+
64
+ // use bound functions to fix es6 compilation
65
+ const genNext = gen.next.bind(gen)
66
+ const genThrow = gen.throw!.bind(gen)
67
+
68
+ const promise = new Promise<R>((resolve, reject) => {
69
+ function onFulfilled(res: any): void {
70
+ let ret: unknown
71
+ try {
72
+ ret = wrapInAction({
73
+ nameOrNameFn: name,
74
+ fn: genNext,
75
+ actionType: ActionContextActionType.Async,
76
+ overrideContext: ctxOverride(ActionContextAsyncStepType.Resume),
77
+ }).call(target, res)
78
+ } catch (e) {
79
+ wrapInAction({
80
+ nameOrNameFn: name,
81
+ fn: (err: any) => {
82
+ // we use a flow finisher to allow middlewares to tweak the return value before resolution
83
+ return {
84
+ value: err,
85
+ resolution: "reject",
86
+
87
+ accepter: resolve,
88
+ rejecter: reject,
89
+ } as FlowFinisher
90
+ },
91
+ actionType: ActionContextActionType.Async,
92
+ overrideContext: ctxOverride(ActionContextAsyncStepType.Throw),
93
+ isFlowFinisher: true,
94
+ }).call(target, e)
95
+ return
96
+ }
97
+
98
+ next(ret)
99
+ }
100
+
101
+ function onRejected(err: unknown): void {
102
+ let ret: unknown
103
+ try {
104
+ ret = wrapInAction({
105
+ nameOrNameFn: name,
106
+ fn: genThrow,
107
+ actionType: ActionContextActionType.Async,
108
+ overrideContext: ctxOverride(ActionContextAsyncStepType.ResumeError),
109
+ }).call(target, err)
110
+ } catch (e) {
111
+ wrapInAction({
112
+ nameOrNameFn: name,
113
+ fn: (err: any) => {
114
+ // we use a flow finisher to allow middlewares to tweak the return value before resolution
115
+ return {
116
+ value: err,
117
+ resolution: "reject",
118
+
119
+ accepter: resolve,
120
+ rejecter: reject,
121
+ } as FlowFinisher
122
+ },
123
+ actionType: ActionContextActionType.Async,
124
+ overrideContext: ctxOverride(ActionContextAsyncStepType.Throw),
125
+ isFlowFinisher: true,
126
+ }).call(target, e)
127
+ return
128
+ }
129
+
130
+ next(ret)
131
+ }
132
+
133
+ function next(ret: any): void {
134
+ if (ret && typeof ret.then === "function") {
135
+ // an async iterator
136
+ ret.then(next, reject)
137
+ } else if (ret.done) {
138
+ // done
139
+ wrapInAction({
140
+ nameOrNameFn: name,
141
+ fn: (val: any) => {
142
+ // we use a flow finisher to allow middlewares to tweak the return value before resolution
143
+ return {
144
+ value: val,
145
+ resolution: "accept",
146
+
147
+ accepter: resolve,
148
+ rejecter: reject,
149
+ } as FlowFinisher
150
+ },
151
+ actionType: ActionContextActionType.Async,
152
+ overrideContext: ctxOverride(ActionContextAsyncStepType.Return),
153
+ isFlowFinisher: true,
154
+ }).call(target, ret.value)
155
+ } else {
156
+ // continue
157
+ Promise.resolve(ret.value).then(onFulfilled, onRejected)
158
+ }
159
+ }
160
+
161
+ onFulfilled(undefined) // kick off the process
162
+ })
163
+
164
+ return promise
165
+ }
166
+ ;(flowFn as any)[modelFlowSymbol] = true
167
+
168
+ copyFunctionMetadata(generator, flowFn)
169
+
170
+ return flowFn
171
+ }
172
+
173
+ /**
174
+ * @internal
175
+ */
176
+ export interface FlowFinisher {
177
+ value: any
178
+ resolution: "accept" | "reject"
179
+
180
+ accepter(value: any): void
181
+ rejecter(value: any): void
182
+ }
183
+
184
+ /**
185
+ * Returns if the given function is a model flow or not.
186
+ *
187
+ * @param fn Function to check.
188
+ * @returns
189
+ */
190
+ export function isModelFlow(fn: unknown) {
191
+ return typeof fn === "function" && modelFlowSymbol in fn
192
+ }
193
+
194
+ /**
195
+ * Decorator that turns a function generator into a model flow.
196
+ */
197
+ export function modelFlow(...args: any[]): void {
198
+ // biome-ignore lint/correctness/noVoidTypeReturn: proper way to declare a decorator
199
+ return decorateWrapMethodOrField("modelFlow", args, (data, fn) => {
200
+ if (isModelFlow(fn)) {
201
+ return fn
202
+ } else {
203
+ if (typeof fn !== "function") {
204
+ throw failure("modelFlow has to be used over functions")
205
+ }
206
+
207
+ return flow({
208
+ nameOrNameFn: data.actionName,
209
+ generator: fn,
210
+ overrideContext: data.overrideContext,
211
+ })
212
+ }
213
+ })
214
+ }
215
+
216
+ /**
217
+ * Tricks the TS compiler into thinking that a model flow generator function can be awaited
218
+ * (is a promise).
219
+ *
220
+ * @template A Function arguments.
221
+ * @template R Return value.
222
+ * @param fn Flow function.
223
+ * @returns
224
+ */
225
+ export function _async<A extends any[], R>(
226
+ fn: (...args: A) => Generator<any, R, any>
227
+ ): (...args: A) => Promise<R> {
228
+ return fn as any
229
+ }
230
+
231
+ /**
232
+ * Makes a promise a flow, so it can be awaited with yield*.
233
+ *
234
+ * @template T Promise return type.
235
+ * @param promise Promise.
236
+ * @returns
237
+ */
238
+ export function _await<T>(promise: Promise<T>): Generator<Promise<T>, T, unknown> {
239
+ return promiseGenerator.call(promise)
240
+ }