From 1bc03457eff38a1ec39a803e5f4eafcdbded5be6 Mon Sep 17 00:00:00 2001 From: Duong Tran Date: Fri, 20 Jul 2018 17:49:29 +1000 Subject: [PATCH 1/6] throw error when env not found --- packages/mobx-state-tree/src/core/mst-operations.ts | 4 ++-- packages/mobx-state-tree/test/env.ts | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/mobx-state-tree/src/core/mst-operations.ts b/packages/mobx-state-tree/src/core/mst-operations.ts index 30cc08ae3..90c0fd777 100644 --- a/packages/mobx-state-tree/src/core/mst-operations.ts +++ b/packages/mobx-state-tree/src/core/mst-operations.ts @@ -718,8 +718,8 @@ export function getEnv(target: IStateTreeNode): T { } const node = getStateTreeNode(target) const env = node.root._environment - if (!!!env) return EMPTY_OBJECT as T - return env + + return env || fail(`Failed to find the environment of ${getStateTreeNode(target)}`) } /** diff --git a/packages/mobx-state-tree/test/env.ts b/packages/mobx-state-tree/test/env.ts index d05e3f4d8..44dda8a62 100644 --- a/packages/mobx-state-tree/test/env.ts +++ b/packages/mobx-state-tree/test/env.ts @@ -30,9 +30,11 @@ test("it should be possible to inherit environments", () => { env.useUppercase = false expect(store.todos[0].description).toBe("test") }) -test("getEnv returns empty object without environment", () => { +test("getEnv should throw error without environment", () => { const todo = Todo.create() - expect(getEnv(todo)).toEqual({}) + expect(() => getEnv(todo)).toThrowError( + "Failed to find the environment of AnonymousModel@" + ) }) test("detach should preserve environment", () => { const env = createEnvironment() @@ -103,7 +105,9 @@ test("clone preserves environnment", () => { } { const todo = clone(store.todos[0], false) - expect(getEnv(todo)).toEqual({}) + expect(() => { + getEnv(todo) + }).toThrowError("Failed to find the environment of AnonymousModel@") } { const env2 = createEnvironment() From 843caa103006e6207442b86407cc489c6d962cc0 Mon Sep 17 00:00:00 2001 From: Duong Tran Date: Thu, 26 Jul 2018 11:49:00 +1000 Subject: [PATCH 2/6] update undo manager to handle getEnv error --- packages/mst-middlewares/src/undo-manager.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/mst-middlewares/src/undo-manager.ts b/packages/mst-middlewares/src/undo-manager.ts index a1bc88b18..4c12c316b 100644 --- a/packages/mst-middlewares/src/undo-manager.ts +++ b/packages/mst-middlewares/src/undo-manager.ts @@ -135,7 +135,11 @@ const UndoManager = types self.undoIdx = self.history.length }, afterCreate() { - targetStore = getEnv(self).targetStore ? getEnv(self).targetStore : getRoot(self) + try { + targetStore = getEnv(self).targetStore + } catch { + targetStore = getRoot(self) + } if (!targetStore || targetStore === self) throw new Error( "UndoManager should be created as part of a tree, or with `targetStore` in it's environment" From 2accff299e8beccc92274b003c6a21959b89ff5c Mon Sep 17 00:00:00 2001 From: Duong Tran Date: Fri, 27 Jul 2018 10:40:56 +1000 Subject: [PATCH 3/6] update getEnv to include path in the error message --- packages/mobx-state-tree/src/core/mst-operations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mobx-state-tree/src/core/mst-operations.ts b/packages/mobx-state-tree/src/core/mst-operations.ts index f4818f63c..881a447f9 100644 --- a/packages/mobx-state-tree/src/core/mst-operations.ts +++ b/packages/mobx-state-tree/src/core/mst-operations.ts @@ -711,7 +711,7 @@ export function getEnv(target: IAnyStateTreeNode): T { const node = getStateTreeNode(target) const env = node.root._environment - return env || fail(`Failed to find the environment of ${getStateTreeNode(target)}`) + return env || fail(`Failed to find the environment of ${node} ${node.path}`) } /** From 3b11e978fb34ec95ae77cc7b91fb90d660a8f691 Mon Sep 17 00:00:00 2001 From: Duong Tran Date: Fri, 27 Jul 2018 11:03:57 +1000 Subject: [PATCH 4/6] introduce hasEnv function --- API.md | 292 +++++++++--------- README.md | 1 + .../src/core/mst-operations.ts | 20 ++ packages/mobx-state-tree/test/api.ts | 1 + packages/mobx-state-tree/test/env.ts | 5 +- 5 files changed, 177 insertions(+), 142 deletions(-) diff --git a/API.md b/API.md index ae9705434..4295576f9 100644 --- a/API.md +++ b/API.md @@ -37,6 +37,7 @@ _This reference guide lists all methods exposed by MST. Contributions like lingu - [getRoot](#getroot) - [getSnapshot](#getsnapshot) - [getType](#gettype) +- [hasEnv](#hasenv) - [hasParent](#hasparent) - [hasParentOfType](#hasparentoftype) - [IdentifierCache](#identifiercache) @@ -82,6 +83,7 @@ _This reference guide lists all methods exposed by MST. Contributions like lingu - [types.frozen](#typesfrozen) - [types.identifier](#typesidentifier) - [types.identifierNumber](#typesidentifiernumber) +- [types.integer](#typesinteger) - [types.late](#typeslate) - [types.literal](#typesliteral) - [types.map](#typesmap) @@ -90,7 +92,6 @@ _This reference guide lists all methods exposed by MST. Contributions like lingu - [types.model](#typesmodel) - [types.null](#typesnull) - [types.number](#typesnumber) -- [types.integer](#typesinteger) - [types.optional](#typesoptional) - [types.reference](#typesreference) - [types.refinement](#typesrefinement) @@ -109,8 +110,8 @@ cleanup methods yourself using the `beforeDestroy` hook. **Parameters** -- `target` **IStateTreeNode** -- `disposer` +- `target` **IStateTreeNode** +- `disposer` **Examples** @@ -139,11 +140,11 @@ For more details, see the [middleware docs](docs/middleware.md) **Parameters** -- `target` **IStateTreeNode** -- `handler` -- `includeHooks` +- `target` **IStateTreeNode** +- `handler` +- `includeHooks` -Returns **IDisposer** +Returns **IDisposer** ## applyAction @@ -153,9 +154,9 @@ Takes an action description as produced by the `onAction` middleware. **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** -- `actions` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<IActionCall>** -- `options` **IActionCallOptions?** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `actions` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<IActionCall>** +- `options` **IActionCallOptions?** ## applyPatch @@ -166,8 +167,8 @@ Can apply a single past, or an array of patches. **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** -- `patch` **IJsonPatch** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `patch` **IJsonPatch** ## applySnapshot @@ -175,8 +176,8 @@ Applies a snapshot to a given model instances. Patch and snapshot listeners will **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** -- `snapshot` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `snapshot` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** ## BaseReferenceType @@ -191,10 +192,10 @@ _Tip: clone will create a literal copy, including the same identifiers. To modif **Parameters** -- `source` **T** +- `source` **T** - `keepEnvironment` **([boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) | any)** indicates whether the clone should inherit the same environment (`true`, the default), or not have an environment (`false`). If an object is passed in as second argument, that will act as the environment for the cloned tree. -Returns **T** +Returns **T** ## ComplexType @@ -218,9 +219,9 @@ See the `atomic` middleware for an example **Parameters** -- `hooks` +- `hooks` -Returns **IMiddlewareHandler** +Returns **IMiddlewareHandler** ## decorate @@ -228,8 +229,8 @@ Binds middleware to a specific action **Parameters** -- `handler` **IMiddlewareHandler** -- `fn` +- `handler` **IMiddlewareHandler** +- `fn` - `Function` } fn **Examples** @@ -256,7 +257,7 @@ Removes a model element from the state tree, and mark it as end-of-life; the ele **Parameters** -- `target` +- `target` ## detach @@ -264,7 +265,7 @@ Removes a model element from the state tree, and let it live on as a new state t **Parameters** -- `target` +- `target` ## escapeJsonPath @@ -273,7 +274,7 @@ escape slashes and backslashes **Parameters** -- `str` +- `str` ## flow @@ -281,9 +282,9 @@ See [asynchronous actions](https://github.com/mobxjs/mobx-state-tree/blob/master **Parameters** -- `asyncAction` +- `asyncAction` -Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** +Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** ## getChildType @@ -291,8 +292,8 @@ Returns the _declared_ type of the given sub property of an object, array or map **Parameters** -- `object` **IStateTreeNode** -- `child` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** +- `object` **IStateTreeNode** +- `child` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** **Examples** @@ -303,7 +304,7 @@ const box = Box.create() console.log(getChildType(box, "x").name) // 'number' ``` -Returns **IAnyType** +Returns **IAnyType** ## getEnv @@ -317,9 +318,9 @@ Returns an empty environment if the tree wasn't initialized with an environment **Parameters** -- `target` **IStateTreeNode** +- `target` **IStateTreeNode** -Returns **any** +Returns **any** ## getIdentifier @@ -328,9 +329,9 @@ This is the _string normalized_ identifier, which might not match the type of th **Parameters** -- `target` **IStateTreeNode** +- `target` **IStateTreeNode** -Returns **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) | null)** +Returns **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) | null)** ## getMembers @@ -338,9 +339,9 @@ Returns a reflection of the node **Parameters** -- `target` **IStateTreeNode** +- `target` **IStateTreeNode** -Returns **IModelReflectionData** +Returns **IModelReflectionData** ## getParent @@ -354,10 +355,10 @@ once the `afterAttach` hook has fired **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** - `depth` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** = 1, how far should we look upward? -Returns **any** +Returns **any** ## getParentOfType @@ -365,10 +366,10 @@ Returns the target's parent of a given type, or throws. **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** -- `type` **IAnyType** +- `target` **IStateTreeNode** +- `type` **IType<any, any, T>** -Returns **any** +Returns **T** ## getPath @@ -376,9 +377,9 @@ Returns the path of the given object in the model tree **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** -Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** +Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** ## getPathParts @@ -386,9 +387,9 @@ Returns the path of the given object as unescaped string array **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** -Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** +Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** ## getRelativePath @@ -397,10 +398,10 @@ returns the shortest jsonpath needed to navigate from the one to the other **Parameters** -- `base` **IStateTreeNode** -- `target` **IStateTreeNode** +- `base` **IStateTreeNode** +- `target` **IStateTreeNode** -Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** +Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** ## getRoot @@ -411,9 +412,9 @@ once the `afterAttach` hook has fired **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** -Returns **any** +Returns **any** ## getSnapshot @@ -422,10 +423,10 @@ structural sharing where possible. Doesn't require MobX transactions to be compl **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** - `applyPostProcess` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** = true, by default the postProcessSnapshot gets applied -Returns **any** +Returns **any** ## getType @@ -433,9 +434,19 @@ Returns the _actual_ type of the given tree node. (Or throws) **Parameters** -- `object` **IStateTreeNode** +- `object` **IStateTreeNode** + +Returns **IAnyType** -Returns **IAnyType** +## hasEnv + +Returns whether the current state tree has environment or not. + +**Parameters** + +- `target` **IStateTreeNode** + +Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** ## hasParent @@ -443,10 +454,10 @@ Given a model instance, returns `true` if the object has a parent, that is, is p **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** - `depth` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** = 1, how far should we look upward? -Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** +Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** ## hasParentOfType @@ -454,10 +465,10 @@ Given a model instance, returns `true` if the object has a parent of given type, **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** -- `type` **IAnyType** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `type` **IAnyType** -Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** +Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** ## IdentifierCache @@ -472,9 +483,9 @@ is requesting it's last path and snapshot **Parameters** -- `target` **IStateTreeNode** +- `target` **IStateTreeNode** -Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** +Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** ## isProtected @@ -482,7 +493,7 @@ Returns true if the object is in protected mode, @see protect **Parameters** -- `target` +- `target` ## isRoot @@ -490,9 +501,9 @@ Returns true if the given object is the root of a model tree **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** -Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** +Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** ## isStateTreeNode @@ -502,7 +513,7 @@ More precisely, that is, if the value is an instance of a **Parameters** -- `value` **any** +- `value` **any** ## joinJsonPath @@ -510,9 +521,9 @@ Generates a json-path compliant json path from path parts **Parameters** -- `path` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** +- `path` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** -Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** +Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** ## ObjectNode @@ -530,8 +541,8 @@ Rather, when using `onAction` middleware, one should consider in passing argumen **Parameters** -- `target` **IStateTreeNode** -- `listener` +- `target` **IStateTreeNode** +- `listener` - `attachAfter` {boolean} (default false) fires the listener _after_ the action has executed instead of before. **Examples** @@ -559,7 +570,7 @@ s.add({ task: "Grab a coffee" }) // Logs: { name: "add", path: "", args: [{ task: "Grab a coffee" }] } ``` -Returns **IDisposer** +Returns **IDisposer** ## onPatch @@ -570,8 +581,7 @@ Patches can be used to deep observe a model tree. **Parameters** - `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** the model instance from which to receive patches -- `callback` -- `boolean` **includeOldValue** if oldValue is included in the patches, they can be inverted. However patches will become much bigger and might not be suitable for efficient transport +- `callback` Returns **IDisposer** function to remove the listener @@ -583,18 +593,18 @@ See [snapshots](https://github.com/mobxjs/mobx-state-tree#snapshots) for more de **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** -- `callback` +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `callback` -Returns **IDisposer** +Returns **IDisposer** ## process **Parameters** -- `asyncAction` +- `asyncAction` -Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** +Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** **Meta** @@ -609,7 +619,7 @@ The inverse of `unprotect` **Parameters** -- `target` **IStateTreeNode** +- `target` **IStateTreeNode** ## recordActions @@ -618,7 +628,7 @@ Returns an recorder object with the following signature: **Parameters** -- `subject` **IStateTreeNode** +- `subject` **IStateTreeNode** **Examples** @@ -633,7 +643,7 @@ export interface IActionRecorder { } ``` -Returns **IPatchRecorder** +Returns **IPatchRecorder** ## recordPatches @@ -642,7 +652,7 @@ Returns an recorder object with the following signature: **Parameters** -- `subject` **IStateTreeNode** +- `subject` **IStateTreeNode** **Examples** @@ -664,7 +674,7 @@ export interface IPatchRecorder { } ``` -Returns **IPatchRecorder** +Returns **IPatchRecorder** ## resolveIdentifier @@ -673,11 +683,11 @@ Returns undefined if no value can be found. **Parameters** -- `type` **IAnyType** -- `target` **IStateTreeNode** -- `identifier` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number))** +- `type` **IAnyType** +- `target` **IStateTreeNode** +- `identifier` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number))** -Returns **any** +Returns **any** ## resolvePath @@ -686,10 +696,10 @@ Returns undefined if no value can be found. **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** - `path` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** escaped json path -Returns **any** +Returns **any** ## ScalarNode @@ -703,7 +713,7 @@ Possible values: `"warn"`, `"error"` and `"ignore"` **Parameters** -- `mode` **LivelynessMode** +- `mode` **LivelynessMode** ## splitJsonPath @@ -711,9 +721,9 @@ Splits and decodes a json path into several parts **Parameters** -- `path` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** +- `path` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** -Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** +Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** ## StoredReference @@ -721,10 +731,10 @@ Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refere **Parameters** -- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** -- `path` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** +- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `path` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** -Returns **any** +Returns **any** ## Type @@ -754,8 +764,8 @@ Use this if you need typechecks even in a production build (by default all autom **Parameters** -- `type` **IAnyType** -- `value` **any** +- `type` **IAnyType** +- `value` **any** ## types.array @@ -765,7 +775,7 @@ This type will always produce [observable arrays](https://mobx.js.org/refguide/a **Parameters** -- `subtype` **IType<S, T>** +- `subtype` **IType<S, T>** **Examples** @@ -784,7 +794,7 @@ s.todos.push({ task: "Grab coffee" }) console.log(s.todos[0]) // prints: "Grab coffee" ``` -Returns **IComplexType<[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<S>, IObservableArray<T>>** +Returns **IComplexType<[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<S>, IObservableArray<T>>** ## types.boolean @@ -831,7 +841,7 @@ export type CustomTypeOptions = { **Parameters** -- `options` +- `options` **Examples** @@ -890,7 +900,7 @@ const TrafficLight = types.model({ }) ``` -Returns **ISimpleType<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** +Returns **ISimpleType<[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** ## types.frozen @@ -909,8 +919,8 @@ Frozen properties can be defined in three different ways **Parameters** -- `arg` -- `defaultValueOrType` **([Type](#type) | value)** +- `arg` +- `defaultValueOrType` **([Type](#type) | value)** **Examples** @@ -936,7 +946,7 @@ type Point = { x: number, y: number } }) ``` -Returns **[Type](#type)** +Returns **[Type](#type)** ## types.identifier @@ -955,7 +965,7 @@ const Todo = types.model("Todo", { }) ``` -Returns **IType<T, T>** +Returns **IType<T, T>** ## types.identifierNumber @@ -970,7 +980,21 @@ const Todo = types.model("Todo", { }) ``` -Returns **IType<T, T>** +Returns **IType<T, T>** + +## types.integer + +Creates a type that can only contain an integer value. +This type is used for integer values by default + +**Examples** + +```javascript +const Size = types.model({ + width: types.integer, + height: 10 +}) +``` ## types.late @@ -980,8 +1004,8 @@ You need to declare an interface to explicit the return type of the late paramet **Parameters** -- `nameOrType` -- `maybeType` +- `nameOrType` +- `maybeType` - `name` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The name to use for the type that will be returned. - `type` **ILateType<S, T>** A function that returns the type that will be defined. @@ -998,7 +1022,7 @@ interface INode { }) ``` -Returns **IType<S, T>** +Returns **IType<S, T>** ## types.literal @@ -1019,7 +1043,7 @@ const Person = types.model({ }) ``` -Returns **ISimpleType<S>** +Returns **ISimpleType<S>** ## types.map @@ -1030,7 +1054,7 @@ This type will always produce [observable maps](https://mobx.js.org/refguide/map **Parameters** -- `subtype` **IType<S, T>** +- `subtype` **IType<S, T>** **Examples** @@ -1051,7 +1075,7 @@ s.todos.put({ task: "Grab cookie", id: 18 }) // put will infer key from the iden console.log(s.todos.get(17).task) // prints: "Grab coffee" ``` -Returns **IComplexType<[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<S>, IObservableArray<T>>** +Returns **IComplexType<[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<S>, IObservableArray<T>>** ## types.maybe @@ -1060,9 +1084,9 @@ The value `undefined` will be used to represent nullability. **Parameters** -- `type` **IType<S, T>** The type to make nullable +- `type` **IType<C, S, M>** The type to make nullable -Returns **(IType<(S | [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)), (T | [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined))>)** +Returns **(IType<(C | [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)), (S | [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)), (T | [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined))>)** ## types.maybeNull @@ -1071,9 +1095,9 @@ The value `null` will be used to represent no value. **Parameters** -- `type` **IType<S, T>** The type to make nullable +- `type` **IType<C, S, M>** The type to make nullable -Returns **(IType<(S | null), (T | null)>)** +Returns **(IType<(C | null | [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)), (S | null), (T | null)>)** ## types.model @@ -1099,20 +1123,6 @@ const Vector = types.model({ }) ``` -## types.integer - -Creates a type that can only contain an integer value. -This type is used for integer values by default - -**Examples** - -```javascript -const Size = types.model({ - width: types.integer, - height: 10 -}) -``` - ## types.optional `types.optional` can be used to create a property with a default value. @@ -1122,8 +1132,8 @@ Applying a snapshot in which the optional value is _not_ present, causes the val **Parameters** -- `type` -- `defaultValueOrFunction` +- `type` +- `defaultValueOrFunction` **Examples** @@ -1145,8 +1155,8 @@ See also the [reference and identifiers](https://github.com/mobxjs/mobx-state-tr **Parameters** -- `subType` -- `options` +- `subType` +- `options` ## types.refinement @@ -1154,10 +1164,10 @@ See also the [reference and identifiers](https://github.com/mobxjs/mobx-state-tr **Parameters** -- `name` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** -- `type` **IType<T, T>** +- `name` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** +- `type` **IType<T, T>** -Returns **IType<T, T>** +Returns **IType<T, T>** ## types.string @@ -1183,10 +1193,10 @@ types.union(dispatcher?, types...) create a union of multiple types. If the corr **Parameters** -- `optionsOrType` **(ITypeDispatcher | IAnyType)** -- `otherTypes` **...[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<IAnyType>** +- `optionsOrType` **(ITypeDispatcher | IAnyType)** +- `otherTypes` **...[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<IAnyType>** -Returns **IAnyType** +Returns **IAnyType** ## unescapeJsonPath @@ -1194,7 +1204,7 @@ unescape slashes and backslashes **Parameters** -- `str` +- `str` ## unprotect @@ -1206,7 +1216,7 @@ In that case you can disable this protection by calling `unprotect` on the root **Parameters** -- `target` +- `target` **Examples** @@ -1232,5 +1242,5 @@ Performs a depth first walk through a tree **Parameters** -- `target` -- `processor` +- `target` +- `processor` diff --git a/README.md b/README.md index 979563fd5..e55f959b1 100644 --- a/README.md +++ b/README.md @@ -979,6 +979,7 @@ See the [full API docs](API.md) for more details. | [`getIdentifier(node)`](API.md#getidentifier) | Returns the identifier of the given element | | [`getSnapshot(node, applyPostProcess)`](API.md#getsnapshot) | Returns the snapshot of the `node`. See [snapshots](#snapshots) | | [`getType(node)`](API.md#gettype) | Returns the type of `node` | +| [`hasEnv(node)`](API.md#hasenv) | Returns `true` if `node` has environment, , see [environments](#environments) | | [`hasParent(node, depth=1)`](API.md#hasparent) | Returns `true` if `node` has a parent at `depth` | | [`hasParentOfType(node, type)`](API.md#hasparentoftype) | Returns `true` if the `node` has a parent that satisfies the provided type | | [`isAlive(node)`](API.md#isalive) | Returns `true` if `node` is alive | diff --git a/packages/mobx-state-tree/src/core/mst-operations.ts b/packages/mobx-state-tree/src/core/mst-operations.ts index 881a447f9..965bcab59 100644 --- a/packages/mobx-state-tree/src/core/mst-operations.ts +++ b/packages/mobx-state-tree/src/core/mst-operations.ts @@ -714,6 +714,26 @@ export function getEnv(target: IAnyStateTreeNode): T { return env || fail(`Failed to find the environment of ${node} ${node.path}`) } +/** + * Returns whether the current state tree has environment or not. + * + * @export + * @param {IStateTreeNode} target + * @return {boolean} + */ +export function hasEnv(target: IAnyStateTreeNode): boolean { + // check all arguments + if (process.env.NODE_ENV !== "production") { + if (!isStateTreeNode(target)) + fail("expected first argument to be a mobx-state-tree node, got " + target + " instead") + } + + const node = getStateTreeNode(target) + const env = node.root._environment + + return !!env +} + /** * Performs a depth first walk through a tree */ diff --git a/packages/mobx-state-tree/test/api.ts b/packages/mobx-state-tree/test/api.ts index 35a187632..bd92f7a8c 100644 --- a/packages/mobx-state-tree/test/api.ts +++ b/packages/mobx-state-tree/test/api.ts @@ -24,6 +24,7 @@ const METHODS = [ "getIdentifier", "getSnapshot", "getType", + "hasEnv", "hasParent", "hasParentOfType", "isAlive", diff --git a/packages/mobx-state-tree/test/env.ts b/packages/mobx-state-tree/test/env.ts index 44dda8a62..bbfaa9394 100644 --- a/packages/mobx-state-tree/test/env.ts +++ b/packages/mobx-state-tree/test/env.ts @@ -1,4 +1,4 @@ -import { types, getEnv, clone, detach, unprotect } from "../src" +import { types, getEnv, clone, detach, unprotect, hasEnv } from "../src" const Todo = types .model({ title: "test" @@ -19,6 +19,7 @@ function createEnvironment() { test("it should be possible to use environments", () => { const env = createEnvironment() const todo = Todo.create({}, env) + expect(hasEnv(todo)).toBe(true) expect(todo.description).toBe("TEST") env.useUppercase = false expect(todo.description).toBe("test") @@ -26,12 +27,14 @@ test("it should be possible to use environments", () => { test("it should be possible to inherit environments", () => { const env = createEnvironment() const store = Store.create({ todos: [{}] }, env) + expect(hasEnv(store.todos[0])).toBe(true) expect(store.todos[0].description).toBe("TEST") env.useUppercase = false expect(store.todos[0].description).toBe("test") }) test("getEnv should throw error without environment", () => { const todo = Todo.create() + expect(hasEnv(todo)).toBe(false) expect(() => getEnv(todo)).toThrowError( "Failed to find the environment of AnonymousModel@" ) From 27da8c8c220b8a21fc8cf7e08faf7e3cb2ce26c8 Mon Sep 17 00:00:00 2001 From: Duong Tran Date: Fri, 27 Jul 2018 11:10:00 +1000 Subject: [PATCH 5/6] update UndoManager to use hasEnv --- packages/mst-middlewares/src/undo-manager.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/mst-middlewares/src/undo-manager.ts b/packages/mst-middlewares/src/undo-manager.ts index 4c12c316b..a6f18298a 100644 --- a/packages/mst-middlewares/src/undo-manager.ts +++ b/packages/mst-middlewares/src/undo-manager.ts @@ -2,6 +2,7 @@ import { types, flow, getEnv, + hasEnv, recordPatches, addMiddleware, applyPatch, @@ -135,11 +136,7 @@ const UndoManager = types self.undoIdx = self.history.length }, afterCreate() { - try { - targetStore = getEnv(self).targetStore - } catch { - targetStore = getRoot(self) - } + targetStore = hasEnv(self) ? getEnv(self).targetStore : getRoot(self) if (!targetStore || targetStore === self) throw new Error( "UndoManager should be created as part of a tree, or with `targetStore` in it's environment" From 8ed47bc05587c3f65f194ed565d1f34d90abb292 Mon Sep 17 00:00:00 2001 From: Duong Tran Date: Fri, 19 Oct 2018 14:36:11 +1100 Subject: [PATCH 6/6] update test, doc and middleware after merge with master --- API.md | 610 +++++++++--------- README.md | 1 + .../__tests__/core/api.test.ts | 1 + .../__tests__/core/env.test.ts | 2 +- packages/mobx-state-tree/src/index.ts | 2 + packages/mst-middlewares/src/undo-manager.ts | 5 +- 6 files changed, 316 insertions(+), 305 deletions(-) diff --git a/API.md b/API.md index daaabb4c0..4a626ec30 100644 --- a/API.md +++ b/API.md @@ -69,81 +69,81 @@ _This reference guide lists all methods exposed by MST. Contributions like lingu - [Parameters][61] - [getType][62] - [Parameters][63] -- [hasParent][64] +- [hasEnv][64] - [Parameters][65] -- [hasParentOfType][66] +- [hasParent][66] - [Parameters][67] -- [IdentifierCache][68] -- [IdentifierType][69] -- [isAlive][70] - - [Parameters][71] -- [isArrayType][72] +- [hasParentOfType][68] + - [Parameters][69] +- [IdentifierCache][70] +- [IdentifierType][71] +- [isAlive][72] - [Parameters][73] -- [isFrozenType][74] +- [isArrayType][74] - [Parameters][75] -- [isIdentifierType][76] +- [isFrozenType][76] - [Parameters][77] -- [isLateType][78] +- [isIdentifierType][78] - [Parameters][79] -- [isLiteralType][80] +- [isLateType][80] - [Parameters][81] -- [isMapType][82] +- [isLiteralType][82] - [Parameters][83] -- [isModelType][84] +- [isMapType][84] - [Parameters][85] -- [isOptionalType][86] +- [isModelType][86] - [Parameters][87] -- [isPrimitiveType][88] +- [isOptionalType][88] - [Parameters][89] -- [isProtected][90] +- [isPrimitiveType][90] - [Parameters][91] -- [isReferenceType][92] +- [isProtected][92] - [Parameters][93] -- [isRefinementType][94] +- [isReferenceType][94] - [Parameters][95] -- [isRoot][96] +- [isRefinementType][96] - [Parameters][97] -- [isStateTreeNode][98] +- [isRoot][98] - [Parameters][99] -- [isType][100] +- [isStateTreeNode][100] - [Parameters][101] -- [isUnionType][102] +- [isType][102] - [Parameters][103] -- [joinJsonPath][104] +- [isUnionType][104] - [Parameters][105] -- [ObjectNode][106] -- [ObservableMap][107] -- [onAction][108] - - [Parameters][109] - - [Examples][110] -- [onPatch][111] - - [Parameters][112] -- [onSnapshot][113] +- [joinJsonPath][106] + - [Parameters][107] +- [ObjectNode][108] +- [ObservableMap][109] +- [onAction][110] + - [Parameters][111] + - [Examples][112] +- [onPatch][113] - [Parameters][114] -- [process][115] +- [onSnapshot][115] - [Parameters][116] -- [protect][117] +- [process][117] - [Parameters][118] -- [recordActions][119] +- [protect][119] - [Parameters][120] - - [Examples][121] -- [recordPatches][122] - - [Parameters][123] - - [Examples][124] -- [resolveIdentifier][125] - - [Parameters][126] -- [resolvePath][127] +- [recordActions][121] + - [Parameters][122] + - [Examples][123] +- [recordPatches][124] + - [Parameters][125] + - [Examples][126] +- [resolveIdentifier][127] - [Parameters][128] -- [ScalarNode][129] -- [setLivelynessChecking][130] - - [Parameters][131] -- [splitJsonPath][132] +- [resolvePath][129] + - [Parameters][130] +- [ScalarNode][131] +- [setLivelynessChecking][132] - [Parameters][133] -- [StoredReference][134] -- [tryResolve][135] - - [Parameters][136] -- [Type][137] -- [Type][138] +- [splitJsonPath][134] + - [Parameters][135] +- [StoredReference][136] +- [tryResolve][137] + - [Parameters][138] - [Type][139] - [Type][140] - [Type][141] @@ -152,67 +152,69 @@ _This reference guide lists all methods exposed by MST. Contributions like lingu - [Type][144] - [Type][145] - [Type][146] -- [typecheck][147] - - [Parameters][148] -- [types.array][149] +- [Type][147] +- [Type][148] +- [typecheck][149] - [Parameters][150] - - [Examples][151] -- [types.boolean][152] +- [types.array][151] + - [Parameters][152] - [Examples][153] -- [types.compose][154] -- [types.custom][155] - - [Parameters][156] - - [Examples][157] -- [types.Date][158] +- [types.boolean][154] + - [Examples][155] +- [types.compose][156] +- [types.custom][157] + - [Parameters][158] - [Examples][159] -- [types.enumeration][160] - - [Parameters][161] - - [Examples][162] -- [types.frozen][163] - - [Parameters][164] - - [Examples][165] -- [types.identifier][166] +- [types.Date][160] + - [Examples][161] +- [types.enumeration][162] + - [Parameters][163] + - [Examples][164] +- [types.frozen][165] + - [Parameters][166] - [Examples][167] -- [types.identifierNumber][168] +- [types.identifier][168] - [Examples][169] -- [types.integer][170] +- [types.identifierNumber][170] - [Examples][171] -- [types.late][172] - - [Parameters][173] - - [Examples][174] -- [types.literal][175] - - [Parameters][176] - - [Examples][177] -- [types.map][178] - - [Parameters][179] - - [Examples][180] -- [types.maybe][181] - - [Parameters][182] -- [types.maybeNull][183] +- [types.integer][172] + - [Examples][173] +- [types.late][174] + - [Parameters][175] + - [Examples][176] +- [types.literal][177] + - [Parameters][178] + - [Examples][179] +- [types.map][180] + - [Parameters][181] + - [Examples][182] +- [types.maybe][183] - [Parameters][184] -- [types.model][185] -- [types.null][186] -- [types.number][187] - - [Examples][188] -- [types.optional][189] - - [Parameters][190] - - [Examples][191] -- [types.reference][192] - - [Parameters][193] -- [types.refinement][194] +- [types.maybeNull][185] + - [Parameters][186] +- [types.model][187] +- [types.null][188] +- [types.number][189] + - [Examples][190] +- [types.optional][191] + - [Parameters][192] + - [Examples][193] +- [types.reference][194] - [Parameters][195] -- [types.string][196] - - [Examples][197] -- [types.undefined][198] -- [types.union][199] - - [Parameters][200] -- [unescapeJsonPath][201] +- [types.refinement][196] + - [Parameters][197] +- [types.string][198] + - [Examples][199] +- [types.undefined][200] +- [types.union][201] - [Parameters][202] -- [unprotect][203] +- [unescapeJsonPath][203] - [Parameters][204] - - [Examples][205] -- [walk][206] - - [Parameters][207] +- [unprotect][205] + - [Parameters][206] + - [Examples][207] +- [walk][208] + - [Parameters][209] ## addDisposer @@ -248,7 +250,7 @@ const Todo = types.model({ Middleware can be used to intercept any action is invoked on the subtree where it is attached. If a tree is protected (by default), this means that any mutation of the tree will pass through your middleware. -For more details, see the [middleware docs][208] +For more details, see the [middleware docs][210] ### Parameters @@ -266,19 +268,19 @@ Takes an action description as produced by the `onAction` middleware. ### Parameters -- `target` **[Object][209]** -- `actions` **[Array][210]<IActionCall>** +- `target` **[Object][211]** +- `actions` **[Array][212]<IActionCall>** ## applyPatch Applies a JSON-patch to the given model instance or bails out if the patch couldn't be applied -See [patches][211] for more details. +See [patches][213] for more details. Can apply a single past, or an array of patches. ### Parameters -- `target` **[Object][209]** +- `target` **[Object][211]** - `patch` **IJsonPatch** ## applySnapshot @@ -287,8 +289,8 @@ Applies a snapshot to a given model instances. Patch and snapshot listeners will ### Parameters -- `target` **[Object][209]** -- `snapshot` **[Object][209]** +- `target` **[Object][211]** +- `snapshot` **[Object][211]** ## BaseReferenceType @@ -339,7 +341,7 @@ _Tip: clone will create a literal copy, including the same identifiers. To modif ### Parameters - `source` **T** -- `keepEnvironment` **([boolean][212] | any)** indicates whether the clone should inherit the same environment (`true`, the default), or not have an environment (`false`). If an object is passed in as second argument, that will act as the environment for the cloned tree. +- `keepEnvironment` **([boolean][214] | any)** indicates whether the clone should inherit the same environment (`true`, the default), or not have an environment (`false`). If an object is passed in as second argument, that will act as the environment for the cloned tree. Returns **T** @@ -416,7 +418,7 @@ Removes a model element from the state tree, and let it live on as a new state t ## escapeJsonPath escape slashes and backslashes -[http://tools.ietf.org/html/rfc6901][213] +[http://tools.ietf.org/html/rfc6901][215] ### Parameters @@ -424,13 +426,13 @@ escape slashes and backslashes ## flow -See [asynchronous actions][214]. +See [asynchronous actions][216]. ### Parameters - `asyncAction` -Returns **[Promise][215]** +Returns **[Promise][217]** ## getChildType @@ -439,7 +441,7 @@ Returns the _declared_ type of the given sub property of an object, array or map ### Parameters - `object` **IStateTreeNode** -- `child` **[string][216]** +- `child` **[string][218]** ### Examples @@ -455,7 +457,7 @@ Returns **IAnyType** ## getEnv Returns the environment of the current state tree. For more info on environments, -see [Dependency injection][217] +see [Dependency injection][219] Please note that in child nodes access to the root is only possible once the `afterAttach` hook has fired @@ -477,7 +479,7 @@ This is the _string normalized_ identifier, which might not match the type of th - `target` **IStateTreeNode** -Returns **([string][216] | null)** +Returns **([string][218] | null)** ## getMembers @@ -501,8 +503,8 @@ once the `afterAttach` hook has fired ### Parameters -- `target` **[Object][209]** -- `depth` **[number][218]** = 1, how far should we look upward? +- `target` **[Object][211]** +- `depth` **[number][220]** = 1, how far should we look upward? Returns **any** @@ -523,9 +525,9 @@ Returns the path of the given object in the model tree ### Parameters -- `target` **[Object][209]** +- `target` **[Object][211]** -Returns **[string][216]** +Returns **[string][218]** ## getPathParts @@ -533,9 +535,9 @@ Returns the path of the given object as unescaped string array ### Parameters -- `target` **[Object][209]** +- `target` **[Object][211]** -Returns **[Array][210]<[string][216]>** +Returns **[Array][212]<[string][218]>** ## getPropertyMembers @@ -557,7 +559,7 @@ returns the shortest jsonpath needed to navigate from the one to the other - `base` **IStateTreeNode** - `target` **IStateTreeNode** -Returns **[string][216]** +Returns **[string][218]** ## getRoot @@ -568,7 +570,7 @@ once the `afterAttach` hook has fired ### Parameters -- `target` **[Object][209]** +- `target` **[Object][211]** Returns **any** @@ -579,8 +581,8 @@ structural sharing where possible. Doesn't require MobX transactions to be compl ### Parameters -- `target` **[Object][209]** -- `applyPostProcess` **[boolean][212]** = true, by default the postProcessSnapshot gets applied +- `target` **[Object][211]** +- `applyPostProcess` **[boolean][214]** = true, by default the postProcessSnapshot gets applied Returns **any** @@ -598,11 +600,11 @@ Returns **IAnyType** Returns whether the current state tree has environment or not. -**Parameters** +### Parameters - `target` **IStateTreeNode** -Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** +Returns **[boolean][214]** ## hasParent @@ -610,10 +612,10 @@ Given a model instance, returns `true` if the object has a parent, that is, is p ### Parameters -- `target` **[Object][209]** -- `depth` **[number][218]** = 1, how far should we look upward? +- `target` **[Object][211]** +- `depth` **[number][220]** = 1, how far should we look upward? -Returns **[boolean][212]** +Returns **[boolean][214]** ## hasParentOfType @@ -621,10 +623,10 @@ Given a model instance, returns `true` if the object has a parent of given type, ### Parameters -- `target` **[Object][209]** +- `target` **[Object][211]** - `type` **IAnyType** -Returns **[boolean][212]** +Returns **[boolean][214]** ## IdentifierCache @@ -641,7 +643,7 @@ is requesting it's last path and snapshot - `target` **IStateTreeNode** -Returns **[boolean][212]** +Returns **[boolean][214]** ## isArrayType @@ -745,9 +747,9 @@ Returns true if the given object is the root of a model tree ### Parameters -- `target` **[Object][209]** +- `target` **[Object][211]** -Returns **[boolean][212]** +Returns **[boolean][214]** ## isStateTreeNode @@ -781,9 +783,9 @@ Generates a json-path compliant json path from path parts ### Parameters -- `path` **[Array][210]<[string][216]>** +- `path` **[Array][212]<[string][218]>** -Returns **[string][216]** +Returns **[string][218]** ## ObjectNode @@ -792,7 +794,7 @@ Returns **[string][216]** ## onAction Registers a function that will be invoked for each action that is called on the provided model instance, or to any of its children. -See [actions][219] for more details. onAction events are emitted only for the outermost called action in the stack. +See [actions][221] for more details. onAction events are emitted only for the outermost called action in the stack. Action can also be intercepted by middleware using addMiddleware to change the function call before it will be run. Not all action arguments might be serializable. For unserializable arguments, a struct like `{ $MST_UNSERIALIZABLE: true, type: "someType" }` will be generated. @@ -835,12 +837,12 @@ Returns **IDisposer** ## onPatch Registers a function that will be invoked for each mutation that is applied to the provided model instance, or to any of its children. -See [patches][211] for more details. onPatch events are emitted immediately and will not await the end of a transaction. +See [patches][213] for more details. onPatch events are emitted immediately and will not await the end of a transaction. Patches can be used to deep observe a model tree. ### Parameters -- `target` **[Object][209]** the model instance from which to receive patches +- `target` **[Object][211]** the model instance from which to receive patches - `callback` Returns **IDisposer** function to remove the listener @@ -849,11 +851,11 @@ Returns **IDisposer** function to remove the listener Registers a function that is invoked whenever a new snapshot for the given model instance is available. The listener will only be fire at the and of the current MobX (trans)action. -See [snapshots][220] for more details. +See [snapshots][222] for more details. ### Parameters -- `target` **[Object][209]** +- `target` **[Object][211]** - `callback` Returns **IDisposer** @@ -864,12 +866,12 @@ Returns **IDisposer** - `asyncAction` -Returns **[Promise][215]** +Returns **[Promise][217]** **Meta** - **deprecated**: has been renamed to `flow()`. - See [https://github.com/mobxjs/mobx-state-tree/issues/399][221] for more information. + See [https://github.com/mobxjs/mobx-state-tree/issues/399][223] for more information. Note that the middleware event types starting with `process` now start with `flow`. @@ -945,7 +947,7 @@ Returns undefined if no value can be found. - `type` **IAnyType** - `target` **IStateTreeNode** -- `identifier` **([string][216] \| [number][218])** +- `identifier` **([string][218] \| [number][220])** Returns **any** @@ -956,8 +958,8 @@ Returns undefined if no value can be found. ### Parameters -- `target` **[Object][209]** -- `path` **[string][216]** escaped json path +- `target` **[Object][211]** +- `path` **[string][218]** escaped json path Returns **any** @@ -981,9 +983,9 @@ Splits and decodes a json path into several parts ### Parameters -- `path` **[string][216]** +- `path` **[string][218]** -Returns **[Array][210]<[string][216]>** +Returns **[Array][212]<[string][218]>** ## StoredReference @@ -991,8 +993,8 @@ Returns **[Array][210]<[string][216]>** ### Parameters -- `target` **[Object][209]** -- `path` **[string][216]** +- `target` **[Object][211]** +- `path` **[string][218]** Returns **any** @@ -1031,7 +1033,7 @@ Use this if you need typechecks even in a production build (by default all autom Creates an index based collection type who's children are all of a uniform declared type. -This type will always produce [observable arrays][222] +This type will always produce [observable arrays][224] ### Parameters @@ -1054,7 +1056,7 @@ s.todos.push({ task: "Grab coffee" }) console.log(s.todos[0]) // prints: "Grab coffee" ``` -Returns **IComplexType<[Array][210]<S>, IObservableArray<T>>** +Returns **IComplexType<[Array][212]<S>, IObservableArray<T>>** ## types.boolean @@ -1151,8 +1153,8 @@ Can be used to create an string based enumeration. ### Parameters -- `name` **[string][216]** descriptive name of the enumeration (optional) -- `options` **[Array][210]<[string][216]>** possible values this enumeration can have +- `name` **[string][218]** descriptive name of the enumeration (optional) +- `options` **[Array][212]<[string][218]>** possible values this enumeration can have ### Examples @@ -1162,7 +1164,7 @@ const TrafficLight = types.model({ }) ``` -Returns **ISimpleType<[string][216]>** +Returns **ISimpleType<[string][218]>** ## types.frozen @@ -1182,7 +1184,7 @@ Frozen properties can be defined in three different ways ### Parameters - `arg` -- `defaultValueOrType` **([Type][223] | value)** +- `defaultValueOrType` **([Type][225] | value)** ### Examples @@ -1208,7 +1210,7 @@ type Point = { x: number, y: number } }) ``` -Returns **[Type][223]** +Returns **[Type][225]** ## types.identifier @@ -1268,7 +1270,7 @@ You need to declare an interface to explicit the return type of the late paramet - `nameOrType` - `maybeType` -- `name` **[string][216]?** The name to use for the type that will be returned. +- `name` **[string][218]?** The name to use for the type that will be returned. - `type` **ILateType<S, T>** A function that returns the type that will be defined. ### Examples @@ -1312,7 +1314,7 @@ Returns **ISimpleType<S>** Creates a key based collection type who's children are all of a uniform declared type. If the type stored in a map has an identifier, it is mandatory to store the child under that identifier in the map. -This type will always produce [observable maps][224] +This type will always produce [observable maps][226] ### Parameters @@ -1337,7 +1339,7 @@ s.todos.put({ task: "Grab cookie", id: 18 }) // put will infer key from the iden console.log(s.todos.get(17).task) // prints: "Grab coffee" ``` -Returns **IComplexType<[Array][210]<S>, IObservableArray<T>>** +Returns **IComplexType<[Array][212]<S>, IObservableArray<T>>** ## types.maybe @@ -1348,7 +1350,7 @@ The value `undefined` will be used to represent nullability. - `type` **IType<C, S, M>** The type to make nullable -Returns **(IType<(C | [undefined][225]), (S | [undefined][225]), (T | [undefined][225])>)** +Returns **(IType<(C | [undefined][227]), (S | [undefined][227]), (T | [undefined][227])>)** ## types.maybeNull @@ -1359,13 +1361,13 @@ The value `null` will be used to represent no value. - `type` **IType<C, S, M>** The type to make nullable -Returns **(IType<(C | null | [undefined][225]), (S | null), (T | null)>)** +Returns **(IType<(C | null | [undefined][227]), (S | null), (T | null)>)** ## types.model Creates a new model type by providing a name, properties, volatile state and actions. -See the [model type][226] description or the [getting started][227] tutorial. +See the [model type][228] description or the [getting started][229] tutorial. ## types.null @@ -1413,7 +1415,7 @@ const todo = Todo.create({ title: "Get coffee "}) ## types.reference Creates a reference to another type, which should have defined an identifier. -See also the [reference and identifiers][228] section. +See also the [reference and identifiers][230] section. ### Parameters @@ -1426,7 +1428,7 @@ See also the [reference and identifiers][228] section. ### Parameters -- `name` **[string][216]** +- `name` **[string][218]** - `type` **IType<T, T>** Returns **IType<T, T>** @@ -1456,7 +1458,7 @@ types.union(dispatcher?, types...) create a union of multiple types. If the corr ### Parameters - `optionsOrType` **(ITypeDispatcher | IAnyType)** -- `otherTypes` **...[Array][210]<IAnyType>** +- `otherTypes` **...[Array][212]<IAnyType>** Returns **IAnyType** @@ -1633,332 +1635,336 @@ Performs a depth first walk through a tree [63]: #parameters-25 -[64]: #hasparent +[64]: #hasenv [65]: #parameters-26 -[66]: #hasparentoftype +[66]: #hasparent [67]: #parameters-27 -[68]: #identifiercache +[68]: #hasparentoftype -[69]: #identifiertype +[69]: #parameters-28 -[70]: #isalive +[70]: #identifiercache -[71]: #parameters-28 +[71]: #identifiertype -[72]: #isarraytype +[72]: #isalive [73]: #parameters-29 -[74]: #isfrozentype +[74]: #isarraytype [75]: #parameters-30 -[76]: #isidentifiertype +[76]: #isfrozentype [77]: #parameters-31 -[78]: #islatetype +[78]: #isidentifiertype [79]: #parameters-32 -[80]: #isliteraltype +[80]: #islatetype [81]: #parameters-33 -[82]: #ismaptype +[82]: #isliteraltype [83]: #parameters-34 -[84]: #ismodeltype +[84]: #ismaptype [85]: #parameters-35 -[86]: #isoptionaltype +[86]: #ismodeltype [87]: #parameters-36 -[88]: #isprimitivetype +[88]: #isoptionaltype [89]: #parameters-37 -[90]: #isprotected +[90]: #isprimitivetype [91]: #parameters-38 -[92]: #isreferencetype +[92]: #isprotected [93]: #parameters-39 -[94]: #isrefinementtype +[94]: #isreferencetype [95]: #parameters-40 -[96]: #isroot +[96]: #isrefinementtype [97]: #parameters-41 -[98]: #isstatetreenode +[98]: #isroot [99]: #parameters-42 -[100]: #istype +[100]: #isstatetreenode [101]: #parameters-43 -[102]: #isuniontype +[102]: #istype [103]: #parameters-44 -[104]: #joinjsonpath +[104]: #isuniontype [105]: #parameters-45 -[106]: #objectnode +[106]: #joinjsonpath -[107]: #observablemap +[107]: #parameters-46 -[108]: #onaction +[108]: #objectnode -[109]: #parameters-46 +[109]: #observablemap -[110]: #examples-4 +[110]: #onaction -[111]: #onpatch +[111]: #parameters-47 -[112]: #parameters-47 +[112]: #examples-4 -[113]: #onsnapshot +[113]: #onpatch [114]: #parameters-48 -[115]: #process +[115]: #onsnapshot [116]: #parameters-49 -[117]: #protect +[117]: #process [118]: #parameters-50 -[119]: #recordactions +[119]: #protect [120]: #parameters-51 -[121]: #examples-5 +[121]: #recordactions -[122]: #recordpatches +[122]: #parameters-52 -[123]: #parameters-52 +[123]: #examples-5 -[124]: #examples-6 +[124]: #recordpatches -[125]: #resolveidentifier +[125]: #parameters-53 -[126]: #parameters-53 +[126]: #examples-6 -[127]: #resolvepath +[127]: #resolveidentifier [128]: #parameters-54 -[129]: #scalarnode +[129]: #resolvepath -[130]: #setlivelynesschecking +[130]: #parameters-55 -[131]: #parameters-55 +[131]: #scalarnode -[132]: #splitjsonpath +[132]: #setlivelynesschecking [133]: #parameters-56 -[134]: #storedreference +[134]: #splitjsonpath -[135]: #tryresolve +[135]: #parameters-57 -[136]: #parameters-57 +[136]: #storedreference -[137]: #type +[137]: #tryresolve -[138]: #type-1 +[138]: #parameters-58 -[139]: #type-2 +[139]: #type -[140]: #type-3 +[140]: #type-1 -[141]: #type-4 +[141]: #type-2 -[142]: #type-5 +[142]: #type-3 -[143]: #type-6 +[143]: #type-4 -[144]: #type-7 +[144]: #type-5 -[145]: #type-8 +[145]: #type-6 -[146]: #type-9 +[146]: #type-7 -[147]: #typecheck +[147]: #type-8 -[148]: #parameters-58 +[148]: #type-9 -[149]: #typesarray +[149]: #typecheck [150]: #parameters-59 -[151]: #examples-7 +[151]: #typesarray -[152]: #typesboolean +[152]: #parameters-60 -[153]: #examples-8 +[153]: #examples-7 -[154]: #typescompose +[154]: #typesboolean -[155]: #typescustom +[155]: #examples-8 -[156]: #parameters-60 +[156]: #typescompose -[157]: #examples-9 +[157]: #typescustom -[158]: #typesdate +[158]: #parameters-61 -[159]: #examples-10 +[159]: #examples-9 -[160]: #typesenumeration +[160]: #typesdate -[161]: #parameters-61 +[161]: #examples-10 -[162]: #examples-11 +[162]: #typesenumeration -[163]: #typesfrozen +[163]: #parameters-62 -[164]: #parameters-62 +[164]: #examples-11 -[165]: #examples-12 +[165]: #typesfrozen -[166]: #typesidentifier +[166]: #parameters-63 -[167]: #examples-13 +[167]: #examples-12 -[168]: #typesidentifiernumber +[168]: #typesidentifier -[169]: #examples-14 +[169]: #examples-13 -[170]: #typesinteger +[170]: #typesidentifiernumber -[171]: #examples-15 +[171]: #examples-14 -[172]: #typeslate +[172]: #typesinteger -[173]: #parameters-63 +[173]: #examples-15 -[174]: #examples-16 +[174]: #typeslate -[175]: #typesliteral +[175]: #parameters-64 -[176]: #parameters-64 +[176]: #examples-16 -[177]: #examples-17 +[177]: #typesliteral -[178]: #typesmap +[178]: #parameters-65 -[179]: #parameters-65 +[179]: #examples-17 -[180]: #examples-18 +[180]: #typesmap -[181]: #typesmaybe +[181]: #parameters-66 -[182]: #parameters-66 +[182]: #examples-18 -[183]: #typesmaybenull +[183]: #typesmaybe [184]: #parameters-67 -[185]: #typesmodel +[185]: #typesmaybenull -[186]: #typesnull +[186]: #parameters-68 -[187]: #typesnumber +[187]: #typesmodel -[188]: #examples-19 +[188]: #typesnull -[189]: #typesoptional +[189]: #typesnumber -[190]: #parameters-68 +[190]: #examples-19 -[191]: #examples-20 +[191]: #typesoptional -[192]: #typesreference +[192]: #parameters-69 -[193]: #parameters-69 +[193]: #examples-20 -[194]: #typesrefinement +[194]: #typesreference [195]: #parameters-70 -[196]: #typesstring +[196]: #typesrefinement -[197]: #examples-21 +[197]: #parameters-71 -[198]: #typesundefined +[198]: #typesstring -[199]: #typesunion +[199]: #examples-21 -[200]: #parameters-71 +[200]: #typesundefined -[201]: #unescapejsonpath +[201]: #typesunion [202]: #parameters-72 -[203]: #unprotect +[203]: #unescapejsonpath [204]: #parameters-73 -[205]: #examples-22 +[205]: #unprotect + +[206]: #parameters-74 + +[207]: #examples-22 -[206]: #walk +[208]: #walk -[207]: #parameters-74 +[209]: #parameters-75 -[208]: docs/middleware.md +[210]: docs/middleware.md -[209]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object +[211]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object -[210]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array +[212]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array -[211]: https://github.com/mobxjs/mobx-state-tree#patches +[213]: https://github.com/mobxjs/mobx-state-tree#patches -[212]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[214]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean -[213]: http://tools.ietf.org/html/rfc6901 +[215]: http://tools.ietf.org/html/rfc6901 -[214]: https://github.com/mobxjs/mobx-state-tree/blob/master/docs/async-actions.md +[216]: https://github.com/mobxjs/mobx-state-tree/blob/master/docs/async-actions.md -[215]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise +[217]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise -[216]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String +[218]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String -[217]: https://github.com/mobxjs/mobx-state-tree#dependency-injection +[219]: https://github.com/mobxjs/mobx-state-tree#dependency-injection -[218]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number +[220]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number -[219]: https://github.com/mobxjs/mobx-state-tree#actions +[221]: https://github.com/mobxjs/mobx-state-tree#actions -[220]: https://github.com/mobxjs/mobx-state-tree#snapshots +[222]: https://github.com/mobxjs/mobx-state-tree#snapshots -[221]: https://github.com/mobxjs/mobx-state-tree/issues/399 +[223]: https://github.com/mobxjs/mobx-state-tree/issues/399 -[222]: https://mobx.js.org/refguide/array.html +[224]: https://mobx.js.org/refguide/array.html -[223]: #type +[225]: #type -[224]: https://mobx.js.org/refguide/map.html +[226]: https://mobx.js.org/refguide/map.html -[225]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined +[227]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined -[226]: https://github.com/mobxjs/mobx-state-tree#creating-models +[228]: https://github.com/mobxjs/mobx-state-tree#creating-models -[227]: https://github.com/mobxjs/mobx-state-tree/blob/master/docs/getting-started.md#getting-started-1 +[229]: https://github.com/mobxjs/mobx-state-tree/blob/master/docs/getting-started.md#getting-started-1 -[228]: https://github.com/mobxjs/mobx-state-tree#references-and-identifiers +[230]: https://github.com/mobxjs/mobx-state-tree#references-and-identifiers diff --git a/README.md b/README.md index fedc4f90a..872bb3135 100644 --- a/README.md +++ b/README.md @@ -1004,6 +1004,7 @@ See the [full API docs](API.md) for more details. | [`getIdentifier(node)`](API.md#getidentifier) | Returns the identifier of the given element | | [`getSnapshot(node, applyPostProcess)`](API.md#getsnapshot) | Returns the snapshot of the `node`. See [snapshots](#snapshots) | | [`getType(node)`](API.md#gettype) | Returns the type of `node` | +| [`hasEnv(node)`](API.md#hasenv) | Returns `true` if `node` has environment, see [environments](#environments) | | [`hasParent(node, depth=1)`](API.md#hasparent) | Returns `true` if `node` has a parent at `depth` | | [`hasParentOfType(node, type)`](API.md#hasparentoftype) | Returns `true` if the `node` has a parent that satisfies the provided type | | [`isAlive(node)`](API.md#isalive) | Returns `true` if `node` is alive | diff --git a/packages/mobx-state-tree/__tests__/core/api.test.ts b/packages/mobx-state-tree/__tests__/core/api.test.ts index da37db6d5..263e41001 100644 --- a/packages/mobx-state-tree/__tests__/core/api.test.ts +++ b/packages/mobx-state-tree/__tests__/core/api.test.ts @@ -50,6 +50,7 @@ const METHODS_AND_INTERNAL_TYPES = stringToArray(` destroy, isAlive, addDisposer, + hasEnv, getEnv, walk, getMembers, diff --git a/packages/mobx-state-tree/__tests__/core/env.test.ts b/packages/mobx-state-tree/__tests__/core/env.test.ts index 57cbc1231..050e15cc7 100644 --- a/packages/mobx-state-tree/__tests__/core/env.test.ts +++ b/packages/mobx-state-tree/__tests__/core/env.test.ts @@ -1,4 +1,4 @@ -import { types, getEnv, clone, detach, unprotect } from "../../src" +import { types, getEnv, clone, detach, unprotect, hasEnv } from "../../src" const Todo = types .model({ diff --git a/packages/mobx-state-tree/src/index.ts b/packages/mobx-state-tree/src/index.ts index 3d3e41219..d9a408061 100644 --- a/packages/mobx-state-tree/src/index.ts +++ b/packages/mobx-state-tree/src/index.ts @@ -152,6 +152,7 @@ import { destroy, isAlive, addDisposer, + hasEnv, getEnv, walk, IModelReflectionData, @@ -273,6 +274,7 @@ export { destroy, isAlive, addDisposer, + hasEnv, getEnv, walk, IModelReflectionData, diff --git a/packages/mst-middlewares/src/undo-manager.ts b/packages/mst-middlewares/src/undo-manager.ts index 493261efd..79fd76a2e 100644 --- a/packages/mst-middlewares/src/undo-manager.ts +++ b/packages/mst-middlewares/src/undo-manager.ts @@ -7,6 +7,7 @@ import { IPatchRecorder, createActionTrackingMiddleware, getEnv, + hasEnv, getRoot, applyPatch, flow, @@ -58,7 +59,7 @@ const UndoManager = types recordingActionId = null if (!skipping) { if (grouping) return cachePatchForGroup(recorder) - ; (self as any).addUndoState(recorder) + ;(self as any).addUndoState(recorder) } skipping = flagSkipping } @@ -163,7 +164,7 @@ const UndoManager = types } }, withoutUndoFlow(generatorFn: () => any) { - return flow(function* () { + return flow(function*() { skipping = true flagSkipping = true const result = yield* generatorFn()