Skip to content

Commit

Permalink
fix #233
Browse files Browse the repository at this point in the history
  • Loading branch information
mattiamanzati committed Jul 5, 2017
1 parent 70db681 commit fc6e5ff
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 48 deletions.
164 changes: 159 additions & 5 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,28 @@
- [detach](#detach)
- [escapeJsonPath](#escapejsonpath)
- [getChildType](#getchildtype)
- [getParent](#getparent)
- [getPath](#getpath)
- [getPathParts](#getpathparts)
- [getRoot](#getroot)
- [getSnapshot](#getsnapshot)
- [getType](#gettype)
- [hasParent](#hasparent)
- [isProtected](#isprotected)
- [isRoot](#isroot)
- [maybe](#maybe)
- [onAction](#onaction)
- [onPatch](#onpatch)
- [onSnapshot](#onsnapshot)
- [protect](#protect)
- [recordActions](#recordactions)
- [recordPatches](#recordpatches)
- [resolveIdentifier](#resolveidentifier)
- [resolvePath](#resolvepath)
- [tryResolve](#tryresolve)
- [types.identifier](#typesidentifier)
- [types.late](#typeslate)
- [types.literal](#typesliteral)
- [types.maybe](#typesmaybe)
- [unescapeJsonPath](#unescapejsonpath)
- [unprotect](#unprotect)
- [walk](#walk)
Expand Down Expand Up @@ -162,6 +171,20 @@ Returns the _declared_ type of the given sub property of an object, array or map

Returns **IType<any, any>**

## getParent

Returns the immediate parent of this object, or null.

Note that the immediate parent can be either an object, map or array, and
doesn't necessarily refer to the parent model

**Parameters**

- `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**

## getPath

Returns the path of the given object in the model tree
Expand All @@ -182,6 +205,27 @@ Returns the path of the given object as unescaped string array

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)>**

## getRoot

Given an object in a model tree, returns the root object of that tree

**Parameters**

- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**

Returns **any**

## getSnapshot

Calculates a snapshot from the given model instance. The snapshot will always reflect the latest state but use
structural sharing where possible. Doesn't require MobX transactions to be completed.

**Parameters**

- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**

Returns **any**

## getType

Returns the _actual_ type of the given tree node. (Or throws)
Expand Down Expand Up @@ -221,15 +265,18 @@ Returns true if the given object is the root of a model tree

Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**

## maybe
## onAction

Maybe will make a type nullable, and also null by default.
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](https://github.com/mobxjs/mobx-state-tree#actions) 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.

**Parameters**

- `type` **IType<S, T>** The type to make nullable
- `target` **IStateTreeNode**
- `listener`

Returns **(IType<(S | null | [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)), (T | null)>)**
Returns **IDisposer**

## onPatch

Expand All @@ -244,6 +291,19 @@ Patches can be used to deep observe a model tree.

Returns **IDisposer** function to remove the listener

## onSnapshot

Registeres 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](https://github.com/mobxjs/mobx-state-tree#snapshots) for more details.

**Parameters**

- `target` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
- `callback`

Returns **IDisposer**

## protect

The inverse of `unprotect`
Expand Down Expand Up @@ -296,9 +356,23 @@ export interface IPatchRecorder {

Returns **IPatchRecorder**

## resolveIdentifier

Resolves a model instance given a root target, the type and the identifier you are searching for.
Returns undefined if no value can be found.

**Parameters**

- `type` **IType<any, any>**
- `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**

## resolvePath

Resolves a path relatively to a given object.
Returns undefined if no value can be found.

**Parameters**

Expand All @@ -316,6 +390,86 @@ Returns **any**

Returns **any**

## types.identifier

Identifier are used to make references, lifecycle events and reconciling works.
Inside a state tree, for each type can exist only one instance for each given identifier.
For example there could'nt be 2 instances of user with id 1. If you need more, consider using references.
Identifier can be used only as type property of a model.
This type accepts as parameter the value type of the identifier field that can be either string or number.

**Parameters**

- `baseType` **IType<T, T>**

**Examples**

```javascript
const Todo = types.model("Todo", {
id: types.identifier(types.string),
title: types.string
})
```

Returns **IType<T, T>**

## types.late

Defines a type that gets implemented later. This is usefull when you have to deal with circular dependencies.
Please notice that when defining circular dependencies TypeScript is'nt smart enought to inference them.
You need to declare an interface to explicit the return type of the late parameter function.

```typescript
interface INode {
childs: INode[]
}

// TypeScript is'nt smart enough to infer self referencing types.
const Node = types.model({
childs: types.optional(types.array(types.late<any, INode>(() => Node)), [])
})
```

**Parameters**

- `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&lt;S, T>** A function that returns the type that will be defined.

Returns **IType&lt;S, T>**

## types.literal

The literal type will return a type that will match only the exact given type.
The given value must be a primitive, in order to be serialized to a snapshot correctly.
You can use literal to match exact strings for example the exact male or female string.

**Parameters**

- `value` **S** The value to use in the strict equal check

**Examples**

```javascript
const Person = types.model({
name: types.string,
gender: types.union(types.literal('male'), types.literal('female'))
})
```

Returns **ISimpleType&lt;S>**

## types.maybe

Maybe will make a type nullable, and also null by default.

**Parameters**

- `type` **IType&lt;S, T>** The type to make nullable

Returns **(IType&lt;(S | null | [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined)), (T | null)>)**

## unescapeJsonPath

unescape slashes and backslashes
Expand Down
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

* Applying a snapshot or patches will now emit an action as well. The name of the emitted action will be `@APPLY_PATCHES`resp `@APPLY_SNAPSHOT`. See [#107](https://github.com/mobxjs/mobx-state-tree/issues/107)
* Fixed issue where same Date instance could'nt be used two times in the same state tree [#229](https://github.com/mobxjs/mobx-state-tree/issues/229)
* Fixed issue with reapplying snapshots to Date field resulting in snapshot typecheck error[#233](https://github.com/mobxjs/mobx-state-tree/issues/233)
* Declaring `types.maybe(types.frozen)` will now result into an error [#224](https://github.com/mobxjs/mobx-state-tree/issues/224)
* Added support for Mobx observable arrays in type checks [#221](https://github.com/mobxjs/mobx-state-tree/issues/221) (from [alessioscalici](https://github.com/alessioscalici))

Expand Down
12 changes: 11 additions & 1 deletion src/core/action.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { action as mobxAction, isObservable } from "mobx"
import { isArray } from '../utils'
import { isArray } from "../utils"

export type ISerializedActionCall = {
name: string
Expand Down Expand Up @@ -136,6 +136,16 @@ export function applyAction(target: IStateTreeNode, action: ISerializedActionCal
)
}

/**
* 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](https://github.com/mobxjs/mobx-state-tree#actions) 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.
*
* @export
* @param {IStateTreeNode} target
* @param {(call: ISerializedActionCall) => void} listener
* @returns {IDisposer}
*/
export function onAction(
target: IStateTreeNode,
listener: (call: ISerializedActionCall) => void
Expand Down
43 changes: 27 additions & 16 deletions src/core/mst-operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ export function onPatch(target: IStateTreeNode, callback: (patch: IJsonPatch) =>
return getStateTreeNode(target).onPatch(callback)
}

export function onSnapshot<S>(
target: ObservableMap<S>,
callback: (snapshot: { [key: string]: S }) => void
): IDisposer
export function onSnapshot<S>(
target: IObservableArray<S>,
callback: (snapshot: S[]) => void
): IDisposer
export function onSnapshot<S>(target: ISnapshottable<S>, callback: (snapshot: S) => void): IDisposer
/**
* Registeres 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.
Expand All @@ -104,15 +113,6 @@ export function onPatch(target: IStateTreeNode, callback: (patch: IJsonPatch) =>
* @param {(snapshot: any) => void} callback
* @returns {IDisposer}
*/
export function onSnapshot<S>(
target: ObservableMap<S>,
callback: (snapshot: { [key: string]: S }) => void
): IDisposer
export function onSnapshot<S>(
target: IObservableArray<S>,
callback: (snapshot: S[]) => void
): IDisposer
export function onSnapshot<S>(target: ISnapshottable<S>, callback: (snapshot: S) => void): IDisposer
export function onSnapshot<S>(
target: ISnapshottable<S>,
callback: (snapshot: S) => void
Expand Down Expand Up @@ -289,6 +289,9 @@ export function applySnapshot<S, T>(target: IStateTreeNode, snapshot: S) {
return getStateTreeNode(target).applySnapshot(snapshot)
}

export function getSnapshot<S>(target: ObservableMap<S>): { [key: string]: S }
export function getSnapshot<S>(target: IObservableArray<S>): S[]
export function getSnapshot<S>(target: ISnapshottable<S>): S
/**
* Calculates a snapshot from the given model instance. The snapshot will always reflect the latest state but use
* structural sharing where possible. Doesn't require MobX transactions to be completed.
Expand All @@ -297,9 +300,6 @@ export function applySnapshot<S, T>(target: IStateTreeNode, snapshot: S) {
* @param {Object} target
* @returns {*}
*/
export function getSnapshot<S>(target: ObservableMap<S>): { [key: string]: S }
export function getSnapshot<S>(target: IObservableArray<S>): S[]
export function getSnapshot<S>(target: ISnapshottable<S>): S
export function getSnapshot<S>(target: ISnapshottable<S>): S {
return getStateTreeNode(target).snapshot
}
Expand All @@ -322,6 +322,8 @@ export function hasParent(target: IStateTreeNode, depth: number = 1): boolean {
return false
}

export function getParent(target: IStateTreeNode, depth?: number): (any & IStateTreeNode)
export function getParent<T>(target: IStateTreeNode, depth?: number): (T & IStateTreeNode)
/**
* Returns the immediate parent of this object, or null.
*
Expand All @@ -333,8 +335,6 @@ export function hasParent(target: IStateTreeNode, depth: number = 1): boolean {
* @param {number} depth = 1, how far should we look upward?
* @returns {*}
*/
export function getParent(target: IStateTreeNode, depth?: number): (any & IStateTreeNode)
export function getParent<T>(target: IStateTreeNode, depth?: number): (T & IStateTreeNode)
export function getParent<T>(target: IStateTreeNode, depth = 1): (T & IStateTreeNode) {
if (depth < 0) fail(`Invalid depth: ${depth}, should be >= 1`)
let d = depth
Expand All @@ -346,15 +346,15 @@ export function getParent<T>(target: IStateTreeNode, depth = 1): (T & IStateTree
return fail(`Failed to find the parent of ${getStateTreeNode(target)} at depth ${depth}`)
}

export function getRoot(target: IStateTreeNode): any & IStateTreeNode
export function getRoot<T>(target: IStateTreeNode): T & IStateTreeNode
/**
* Given an object in a model tree, returns the root object of that tree
*
* @export
* @param {Object} target
* @returns {*}
*/
export function getRoot(target: IStateTreeNode): any & IStateTreeNode
export function getRoot<T>(target: IStateTreeNode): T & IStateTreeNode
export function getRoot(target: IStateTreeNode): IStateTreeNode {
return getStateTreeNode(target).root.storedValue
}
Expand Down Expand Up @@ -394,6 +394,7 @@ export function isRoot(target: IStateTreeNode): boolean {

/**
* Resolves a path relatively to a given object.
* Returns undefined if no value can be found.
*
* @export
* @param {Object} target
Expand All @@ -405,6 +406,16 @@ export function resolvePath(target: IStateTreeNode, path: string): IStateTreeNod
return node ? node.value : undefined
}

/**
* Resolves a model instance given a root target, the type and the identifier you are searching for.
* Returns undefined if no value can be found.
*
* @export
* @param {IType<any, any>} type
* @param {IStateTreeNode} target
* @param {(string | number)} identifier
* @returns {*}
*/
export function resolveIdentifier(
type: IType<any, any>,
target: IStateTreeNode,
Expand Down
Loading

0 comments on commit fc6e5ff

Please sign in to comment.