Skip to content

Commit

Permalink
Added 'getIdentifier' function
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Hollies committed Feb 27, 2018
1 parent 688e3e0 commit 10808ff
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 3 deletions.
12 changes: 10 additions & 2 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,11 +347,19 @@ Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer

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

## getIdentifier(node, property?)

Returns the identifier of the given node. If a property is given returns the identifier of that property. If the node or property
does not have an identifier, returns null

**Parameters**

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

Returns **any**


Returns **string | null**

## getSnapshot

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,7 @@ See the [full API docs](API.md) for more details.
| [`getPathParts(node)`](API.md#getpathparts) | Returns the path of `node` in the tree, unescaped as separate parts |
| [`getRelativePath(base, target)`](API.md#getrelativepath) | Returns the short path, which one could use to walk from node `base` to node `target`, assuming they are in the same tree. Up is represented as `../` |
| [`getRoot(node)`](API.md#getroot) | Returns the root element of the tree containing `node` |
| [`getIdentifier(node, property?)`](API.md#getidentifier) | Returns the identifier of the given element, or of the given property` |
| [`getSnapshot(node)`](API.md#getsnapshot) | Returns the snapshot of the `node`. See [snapshots](#snapshots) |
| [`getType(node)`](API.md#gettype) | Returns the type of `node` |
| [`hasParent(node, depth=1)`](API.md#hasparent) | Returns `true` if `node` has a parent at `depth` |
Expand Down
41 changes: 40 additions & 1 deletion packages/mobx-state-tree/src/core/mst-operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,44 @@ export function resolveIdentifier(
return node ? node.value : undefined
}

/**
* Returns the identifier of the target node. If a property is supplied returns the identifier
* of the property even if it is a reference to a missing object.
*
* @export
* @param {IStateTreeNode} target
* @param {string} property
* @returns {(string | null)}
*/
export function getIdentifier<T>(target: T, property?: keyof T): string | null {
// 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")
}

if (property === "$treenode") {
return null
}

if (!property) {
return getStateTreeNode(target).identifier
} else {
const propertyNode: INode = getStateTreeNode(target).getChildNode(property)
if (!isReferenceType(propertyNode.type)) {
return null
} else {
// if mode is 'object' then the value is a node
if (propertyNode.storedValue.mode === "identifier") {
return propertyNode.storedValue.value
} else {
return getStateTreeNode(propertyNode.storedValue.value).identifier
}
}
}
}

/**
*
*
Expand Down Expand Up @@ -662,5 +700,6 @@ import {
IType,
isType,
resolveNodeByPath,
getRelativePathBetweenNodes
getRelativePathBetweenNodes,
isReferenceType
} from "../internal"
1 change: 1 addition & 0 deletions packages/mobx-state-tree/test/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const METHODS = [
"getPathParts",
"getRelativePath",
"getRoot",
"getIdentifier",
"getSnapshot",
"getType",
"hasParent",
Expand Down
56 changes: 56 additions & 0 deletions packages/mobx-state-tree/test/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
getParent,
hasParent,
getRoot,
getIdentifier,
getPathParts,
isAlive,
clone,
Expand Down Expand Up @@ -69,6 +70,61 @@ test("it should resolve to the root of an object", t => {
doc.rows.push(row)
t.is(getRoot(row), doc)
})

// getIdentifier

test("it should resolve to the identifier of the object", t => {
const Person = types.model("Person", {
id: types.identifier(types.string)
})
const Document = types.model("Document", {
author: types.reference(Person),
id: types.identifier(types.string),
pageCount: types.number
})
const doc = Document.create({
author: "person_1",
id: "document_1",
pageCount: 32
})

// direct access throws
t.throws(() => {
const authorId = doc.author
})

// unfortunatly '$treenode' is accepted by the compile-time type checks
t.is(getIdentifier(doc, "$treenode"), null)

// get identifier of object
t.is(getIdentifier(doc), "document_1")

// get identifier of non-existent reference
t.is(getIdentifier(doc, "author"), "person_1")

// attempt to get identifier of scalar type
t.is(getIdentifier(doc, "pageCount"), null)

const Container = types.model("Container", {
person: Person,
doc: Document
})

const container = Container.create({
doc: Document.create({
author: "person_2",
id: "document_2",
pageCount: 12
}),
person: Person.create({
id: "person_2"
})
})

// get identifier of existing reference
t.is(getIdentifier(container.doc, "author"), "person_2")
})

// getPath

test("it should resolve the path of an object", t => {
Expand Down

0 comments on commit 10808ff

Please sign in to comment.