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,125 +1,127 @@
1
- /*
2
- function* promiseGenerator<T>(
3
- this: Promise<T>
4
- ) {
5
- const ret: T = yield this
6
- return ret
7
- }
8
- */
9
-
10
- // above code but compiled by TS for ES5
11
- // so we don't include a dependency to regenerator runtime
12
-
13
- const __generator = function (thisArg: any, body: any) {
14
- let _: any = {
15
- label: 0,
16
- sent: function () {
17
- if (t[0] & 1) throw t[1]
18
- return t[1]
19
- },
20
- trys: [],
21
- ops: [],
22
- },
23
- f: any,
24
- y: any,
25
- t: any,
26
- g: any
27
- return (
28
- (g = { next: verb(0), throw: verb(1), return: verb(2) }),
29
- typeof Symbol === "function" &&
30
- (g[Symbol.iterator] = function () {
31
- return this
32
- }),
33
- g
34
- )
35
- function verb(n: any) {
36
- return function (v: any) {
37
- return step([n, v])
38
- }
39
- }
40
- function step(op: any) {
41
- if (f) throw new TypeError("Generator is already executing.")
42
- while (_)
43
- try {
44
- if (
45
- ((f = 1),
46
- y &&
47
- (t =
48
- op[0] & 2
49
- ? y["return"]
50
- : op[0]
51
- ? y["throw"] || ((t = y["return"]) && t.call(y), 0)
52
- : y.next) &&
53
- !(t = t.call(y, op[1])).done)
54
- )
55
- return t
56
- if (((y = 0), t)) op = [op[0] & 2, t.value]
57
- switch (op[0]) {
58
- case 0:
59
- case 1:
60
- t = op
61
- break
62
- case 4:
63
- _.label++
64
- return { value: op[1], done: false }
65
- case 5:
66
- _.label++
67
- y = op[1]
68
- op = [0]
69
- continue
70
- case 7:
71
- op = _.ops.pop()
72
- _.trys.pop()
73
- continue
74
- default:
75
- if (
76
- !((t = _.trys), (t = t.length > 0 && t[t.length - 1])) &&
77
- (op[0] === 6 || op[0] === 2)
78
- ) {
79
- _ = 0
80
- continue
81
- }
82
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
83
- _.label = op[1]
84
- break
85
- }
86
- if (op[0] === 6 && _.label < t[1]) {
87
- _.label = t[1]
88
- t = op
89
- break
90
- }
91
- if (t && _.label < t[2]) {
92
- _.label = t[2]
93
- _.ops.push(op)
94
- break
95
- }
96
- if (t[2]) _.ops.pop()
97
- _.trys.pop()
98
- continue
99
- }
100
- op = body.call(thisArg, _)
101
- } catch (e) {
102
- op = [6, e]
103
- y = 0
104
- } finally {
105
- f = t = 0
106
- }
107
- if (op[0] & 5) throw op[1]
108
- return { value: op[0] ? op[1] : void 0, done: true }
109
- }
110
- }
111
-
112
- export function promiseGenerator(this: Promise<any>) {
113
- let ret
114
- return __generator(this, function (this: any, _a: any) {
115
- switch (_a.label) {
116
- case 0:
117
- return [4 /*yield*/, this]
118
- case 1:
119
- ret = _a.sent()
120
- return [2 /*return*/, ret]
121
- default:
122
- return
123
- }
124
- })
125
- }
1
+ // biome-ignore-all lint: transpiled TypeScript ES5 helper kept verbatim; its generated shape intentionally violates style and complexity rules.
2
+
3
+ /*
4
+ function* promiseGenerator<T>(
5
+ this: Promise<T>
6
+ ) {
7
+ const ret: T = yield this
8
+ return ret
9
+ }
10
+ */
11
+
12
+ // above code but compiled by TS for ES5
13
+ // so we don't include a dependency to regenerator runtime
14
+
15
+ const __generator = function (thisArg: any, body: any) {
16
+ let _: any = {
17
+ label: 0,
18
+ sent: function () {
19
+ if (t[0] & 1) throw t[1]
20
+ return t[1]
21
+ },
22
+ trys: [],
23
+ ops: [],
24
+ },
25
+ f: any,
26
+ y: any,
27
+ t: any,
28
+ g: any
29
+ return (
30
+ (g = { next: verb(0), throw: verb(1), return: verb(2) }),
31
+ typeof Symbol === "function" &&
32
+ (g[Symbol.iterator] = function () {
33
+ return this
34
+ }),
35
+ g
36
+ )
37
+ function verb(n: any) {
38
+ return function (v: any) {
39
+ return step([n, v])
40
+ }
41
+ }
42
+ function step(op: any) {
43
+ if (f) throw new TypeError("Generator is already executing.")
44
+ while (_)
45
+ try {
46
+ if (
47
+ ((f = 1),
48
+ y &&
49
+ (t =
50
+ op[0] & 2
51
+ ? y["return"]
52
+ : op[0]
53
+ ? y["throw"] || ((t = y["return"]) && t.call(y), 0)
54
+ : y.next) &&
55
+ !(t = t.call(y, op[1])).done)
56
+ )
57
+ return t
58
+ if (((y = 0), t)) op = [op[0] & 2, t.value]
59
+ switch (op[0]) {
60
+ case 0:
61
+ case 1:
62
+ t = op
63
+ break
64
+ case 4:
65
+ _.label++
66
+ return { value: op[1], done: false }
67
+ case 5:
68
+ _.label++
69
+ y = op[1]
70
+ op = [0]
71
+ continue
72
+ case 7:
73
+ op = _.ops.pop()
74
+ _.trys.pop()
75
+ continue
76
+ default:
77
+ if (
78
+ !((t = _.trys), (t = t.length > 0 && t[t.length - 1])) &&
79
+ (op[0] === 6 || op[0] === 2)
80
+ ) {
81
+ _ = 0
82
+ continue
83
+ }
84
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
85
+ _.label = op[1]
86
+ break
87
+ }
88
+ if (op[0] === 6 && _.label < t[1]) {
89
+ _.label = t[1]
90
+ t = op
91
+ break
92
+ }
93
+ if (t && _.label < t[2]) {
94
+ _.label = t[2]
95
+ _.ops.push(op)
96
+ break
97
+ }
98
+ if (t[2]) _.ops.pop()
99
+ _.trys.pop()
100
+ continue
101
+ }
102
+ op = body.call(thisArg, _)
103
+ } catch (e) {
104
+ op = [6, e]
105
+ y = 0
106
+ } finally {
107
+ f = t = 0
108
+ }
109
+ if (op[0] & 5) throw op[1]
110
+ return { value: op[0] ? op[1] : void 0, done: true }
111
+ }
112
+ }
113
+
114
+ export function promiseGenerator(this: Promise<any>) {
115
+ let ret
116
+ return __generator(this, function (this: any, _a: any) {
117
+ switch (_a.label) {
118
+ case 0:
119
+ return [4 /*yield*/, this]
120
+ case 1:
121
+ ret = _a.sent()
122
+ return [2 /*return*/, ret]
123
+ default:
124
+ return
125
+ }
126
+ })
127
+ }
@@ -1,42 +1,42 @@
1
- import { getCurrentActionContext } from "./context"
2
- import { getActionProtection } from "./protection"
3
-
4
- const pendingActions: (() => void)[] = []
5
-
6
- function isActionRunning(): boolean {
7
- return !getActionProtection() || !!getCurrentActionContext()
8
- }
9
-
10
- /**
11
- * @internal
12
- */
13
- export function enqueuePendingAction(action: () => void): void {
14
- // delay action until all current actions are finished
15
- if (isActionRunning()) {
16
- pendingActions.push(action)
17
- } else {
18
- action()
19
- }
20
- }
21
-
22
- let pendingActionsRunning = false
23
-
24
- /**
25
- * @internal
26
- */
27
- export function tryRunPendingActions(): void {
28
- if (isActionRunning() || pendingActionsRunning) {
29
- return
30
- }
31
-
32
- pendingActionsRunning = true
33
-
34
- try {
35
- while (pendingActions.length > 0) {
36
- const nextAction = pendingActions.shift()!
37
- nextAction()
38
- }
39
- } finally {
40
- pendingActionsRunning = false
41
- }
42
- }
1
+ import { getCurrentActionContext } from "./context"
2
+ import { getActionProtection } from "./protection"
3
+
4
+ const pendingActions: (() => void)[] = []
5
+
6
+ function isActionRunning(): boolean {
7
+ return !getActionProtection() || !!getCurrentActionContext()
8
+ }
9
+
10
+ /**
11
+ * @internal
12
+ */
13
+ export function enqueuePendingAction(action: () => void): void {
14
+ // delay action until all current actions are finished
15
+ if (isActionRunning()) {
16
+ pendingActions.push(action)
17
+ } else {
18
+ action()
19
+ }
20
+ }
21
+
22
+ let pendingActionsRunning = false
23
+
24
+ /**
25
+ * @internal
26
+ */
27
+ export function tryRunPendingActions(): void {
28
+ if (isActionRunning() || pendingActionsRunning) {
29
+ return
30
+ }
31
+
32
+ pendingActionsRunning = true
33
+
34
+ try {
35
+ while (pendingActions.length > 0) {
36
+ const nextAction = pendingActions.shift()!
37
+ nextAction()
38
+ }
39
+ } finally {
40
+ pendingActionsRunning = false
41
+ }
42
+ }
@@ -1,156 +1,156 @@
1
- import { action } from "mobx"
2
- import type { O } from "ts-toolbelt"
3
- import type { AnyDataModel } from "../dataModel/BaseDataModel"
4
- import type { AnyModel } from "../model/BaseModel"
5
- import { AnyFunction } from "../utils/AnyFunction"
6
- import { copyFunctionMetadata } from "../utils/decorators"
7
- import {
8
- ActionContext,
9
- ActionContextActionType,
10
- getCurrentActionContext,
11
- setCurrentActionContext,
12
- } from "./context"
13
- import { isModelAction, modelActionSymbol } from "./isModelAction"
14
- import { getPerObjectActionMiddlewares } from "./middleware"
15
- import type { FlowFinisher } from "./modelFlow"
16
- import { tryRunPendingActions } from "./pendingActions"
17
-
18
- /**
19
- * @internal
20
- */
21
- export type WrapInActionOverrideContextFn = (ctx: O.Writable<ActionContext>, self: AnyModel) => void
22
-
23
- /**
24
- * @internal
25
- */
26
- export function wrapInAction<T extends Function>({
27
- nameOrNameFn,
28
- fn,
29
- actionType,
30
- overrideContext,
31
- isFlowFinisher = false,
32
- }: {
33
- nameOrNameFn: string | (() => string)
34
- fn: T
35
- actionType: ActionContextActionType
36
- overrideContext?: WrapInActionOverrideContextFn
37
- isFlowFinisher?: boolean
38
- }): T {
39
- let fnInAction = false
40
-
41
- const wrappedAction = function (this: AnyModel, ...args: unknown[]) {
42
- const name = typeof nameOrNameFn === "function" ? nameOrNameFn() : nameOrNameFn
43
-
44
- if (!fnInAction) {
45
- fnInAction = true
46
-
47
- // we need to make only inner actions actual mobx actions
48
- // so reactions (e.g. reference detaching) are picked up in the
49
- // right context
50
- fn = action(name, fn)
51
- }
52
-
53
- const parentContext = getCurrentActionContext()
54
-
55
- const context: O.Writable<ActionContext> = {
56
- actionName: name,
57
- type: actionType,
58
- target: this,
59
- args,
60
- parentContext,
61
- data: {},
62
- rootContext: undefined as never, // will be set after the override
63
- }
64
- if (overrideContext) {
65
- overrideContext(context, this)
66
- }
67
- if (!context.rootContext) {
68
- if (context.previousAsyncStepContext) {
69
- context.rootContext = context.previousAsyncStepContext.rootContext
70
- } else if (context.parentContext) {
71
- context.rootContext = context.parentContext.rootContext
72
- } else {
73
- context.rootContext = context
74
- }
75
- }
76
-
77
- setCurrentActionContext(context)
78
-
79
- const perObjectMiddlewares = getPerObjectActionMiddlewares(context.target)
80
-
81
- let objectIndex = perObjectMiddlewares.length - 1 // from topmost parent to the object itself
82
- let objectMwareIndex = 0
83
-
84
- const runNextMiddleware = (): unknown => {
85
- const objectMwares = perObjectMiddlewares[objectIndex]
86
- if (!objectMwares) {
87
- // no more middlewares, run base action
88
- return fn.apply(this, args)
89
- }
90
- const mwareData = objectMwares[objectMwareIndex]
91
-
92
- // advance to the next middleware
93
- objectMwareIndex++
94
- if (objectMwareIndex >= objectMwares.length) {
95
- objectMwareIndex = 0
96
- objectIndex--
97
- }
98
-
99
- const filterPassed = mwareData.filter ? mwareData.filter(context) : true
100
- return filterPassed ? mwareData.middleware(context, runNextMiddleware) : runNextMiddleware()
101
- }
102
-
103
- try {
104
- const ret = runNextMiddleware()
105
-
106
- if (isFlowFinisher) {
107
- const flowFinisher = ret as FlowFinisher
108
- const value = flowFinisher.value
109
- if (flowFinisher.resolution === "accept") {
110
- flowFinisher.accepter(value)
111
- } else {
112
- flowFinisher.rejecter(value)
113
- }
114
- return value // not sure if this is even needed
115
- } else {
116
- return ret
117
- }
118
- } finally {
119
- setCurrentActionContext(context.parentContext)
120
-
121
- tryRunPendingActions()
122
- }
123
- }
124
- ;(wrappedAction as unknown as { [modelActionSymbol]: true })[modelActionSymbol] = true
125
-
126
- copyFunctionMetadata(fn, wrappedAction)
127
-
128
- return wrappedAction as unknown as T
129
- }
130
-
131
- /**
132
- * @internal
133
- */
134
- export function wrapModelMethodInActionIfNeeded<M extends AnyModel | AnyDataModel>(
135
- model: M,
136
- propertyKey: keyof M,
137
- name: string
138
- ): void {
139
- const fn = model[propertyKey] as AnyFunction
140
- if (isModelAction(fn)) {
141
- return
142
- }
143
-
144
- const wrappedFn = wrapInAction({
145
- nameOrNameFn: name,
146
- fn,
147
- actionType: ActionContextActionType.Sync,
148
- })
149
- const proto = Object.getPrototypeOf(model)
150
- const protoFn = proto[propertyKey]
151
- if (protoFn === fn) {
152
- proto[propertyKey] = wrappedFn
153
- } else {
154
- model[propertyKey] = wrappedFn as M[typeof propertyKey]
155
- }
156
- }
1
+ import { action } from "mobx"
2
+ import type { O } from "ts-toolbelt"
3
+ import type { AnyDataModel } from "../dataModel/BaseDataModel"
4
+ import type { AnyModel } from "../model/BaseModel"
5
+ import type { AnyFunction } from "../utils/AnyFunction"
6
+ import { copyFunctionMetadata } from "../utils/decorators"
7
+ import {
8
+ type ActionContext,
9
+ ActionContextActionType,
10
+ getCurrentActionContext,
11
+ setCurrentActionContext,
12
+ } from "./context"
13
+ import { isModelAction, modelActionSymbol } from "./isModelAction"
14
+ import { getPerObjectActionMiddlewares } from "./middleware"
15
+ import type { FlowFinisher } from "./modelFlow"
16
+ import { tryRunPendingActions } from "./pendingActions"
17
+
18
+ /**
19
+ * @internal
20
+ */
21
+ export type WrapInActionOverrideContextFn = (ctx: O.Writable<ActionContext>, self: AnyModel) => void
22
+
23
+ /**
24
+ * @internal
25
+ */
26
+ export function wrapInAction<T extends Function>({
27
+ nameOrNameFn,
28
+ fn,
29
+ actionType,
30
+ overrideContext,
31
+ isFlowFinisher = false,
32
+ }: {
33
+ nameOrNameFn: string | (() => string)
34
+ fn: T
35
+ actionType: ActionContextActionType
36
+ overrideContext?: WrapInActionOverrideContextFn
37
+ isFlowFinisher?: boolean
38
+ }): T {
39
+ let fnInAction = false
40
+
41
+ const wrappedAction = function (this: AnyModel, ...args: unknown[]) {
42
+ const name = typeof nameOrNameFn === "function" ? nameOrNameFn() : nameOrNameFn
43
+
44
+ if (!fnInAction) {
45
+ fnInAction = true
46
+
47
+ // we need to make only inner actions actual mobx actions
48
+ // so reactions (e.g. reference detaching) are picked up in the
49
+ // right context
50
+ fn = action(name, fn)
51
+ }
52
+
53
+ const parentContext = getCurrentActionContext()
54
+
55
+ const context: O.Writable<ActionContext> = {
56
+ actionName: name,
57
+ type: actionType,
58
+ target: this,
59
+ args,
60
+ parentContext,
61
+ data: {},
62
+ rootContext: undefined as never, // will be set after the override
63
+ }
64
+ if (overrideContext) {
65
+ overrideContext(context, this)
66
+ }
67
+ if (!context.rootContext) {
68
+ if (context.previousAsyncStepContext) {
69
+ context.rootContext = context.previousAsyncStepContext.rootContext
70
+ } else if (context.parentContext) {
71
+ context.rootContext = context.parentContext.rootContext
72
+ } else {
73
+ context.rootContext = context
74
+ }
75
+ }
76
+
77
+ setCurrentActionContext(context)
78
+
79
+ const perObjectMiddlewares = getPerObjectActionMiddlewares(context.target)
80
+
81
+ let objectIndex = perObjectMiddlewares.length - 1 // from topmost parent to the object itself
82
+ let objectMwareIndex = 0
83
+
84
+ const runNextMiddleware = (): unknown => {
85
+ const objectMwares = perObjectMiddlewares[objectIndex]
86
+ if (!objectMwares) {
87
+ // no more middlewares, run base action
88
+ return fn.apply(this, args)
89
+ }
90
+ const mwareData = objectMwares[objectMwareIndex]
91
+
92
+ // advance to the next middleware
93
+ objectMwareIndex++
94
+ if (objectMwareIndex >= objectMwares.length) {
95
+ objectMwareIndex = 0
96
+ objectIndex--
97
+ }
98
+
99
+ const filterPassed = mwareData.filter ? mwareData.filter(context) : true
100
+ return filterPassed ? mwareData.middleware(context, runNextMiddleware) : runNextMiddleware()
101
+ }
102
+
103
+ try {
104
+ const ret = runNextMiddleware()
105
+
106
+ if (isFlowFinisher) {
107
+ const flowFinisher = ret as FlowFinisher
108
+ const value = flowFinisher.value
109
+ if (flowFinisher.resolution === "accept") {
110
+ flowFinisher.accepter(value)
111
+ } else {
112
+ flowFinisher.rejecter(value)
113
+ }
114
+ return value // not sure if this is even needed
115
+ } else {
116
+ return ret
117
+ }
118
+ } finally {
119
+ setCurrentActionContext(context.parentContext)
120
+
121
+ tryRunPendingActions()
122
+ }
123
+ }
124
+ ;(wrappedAction as unknown as { [modelActionSymbol]: true })[modelActionSymbol] = true
125
+
126
+ copyFunctionMetadata(fn, wrappedAction)
127
+
128
+ return wrappedAction as unknown as T
129
+ }
130
+
131
+ /**
132
+ * @internal
133
+ */
134
+ export function wrapModelMethodInActionIfNeeded<M extends AnyModel | AnyDataModel>(
135
+ model: M,
136
+ propertyKey: keyof M,
137
+ name: string
138
+ ): void {
139
+ const fn = model[propertyKey] as AnyFunction
140
+ if (isModelAction(fn)) {
141
+ return
142
+ }
143
+
144
+ const wrappedFn = wrapInAction({
145
+ nameOrNameFn: name,
146
+ fn,
147
+ actionType: ActionContextActionType.Sync,
148
+ })
149
+ const proto = Object.getPrototypeOf(model)
150
+ const protoFn = proto[propertyKey]
151
+ if (protoFn === fn) {
152
+ proto[propertyKey] = wrappedFn
153
+ } else {
154
+ model[propertyKey] = wrappedFn as M[typeof propertyKey]
155
+ }
156
+ }
@@ -4,7 +4,7 @@ import { assertTweakedObject } from "../../tweaker/core"
4
4
  import { failure, isJSONPrimitive, isPlainObject } from "../../utils"
5
5
  import type { JSONPrimitiveValue } from "../../utils/types"
6
6
  import { arraySerializer } from "./arraySerializer"
7
- import { ActionCallArgumentSerializer, cannotSerialize } from "./core"
7
+ import { type ActionCallArgumentSerializer, cannotSerialize } from "./core"
8
8
  import { dateSerializer } from "./dateSerializer"
9
9
  import { mapSerializer } from "./mapSerializer"
10
10
  import { objectPathSerializer } from "./objectPathSerializer"