forked from mobxjs/serializr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
list.ts
116 lines (111 loc) · 3.54 KB
/
list.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import { SKIP } from "../constants"
import {
invariant,
isPropSchema,
isAliasedPropSchema,
parallel,
processAdditionalPropArgs
} from "../utils/utils"
import { onAfterDeserialize, onBeforeDeserialize } from "../core/deserialize"
import { _defaultPrimitiveProp } from "../constants"
import { AdditionalPropArgs, PropSchema } from "../api/types"
/**
* List indicates that this property contains a list of things.
* Accepts a sub model schema to serialize the contents
*
* @example
* class SubTask {}
* class Task {}
* class Todo {}
*
* createModelSchema(SubTask, {
* title: true,
* })
* createModelSchema(Todo, {
* title: true,
* subTask: list(object(SubTask)),
* })
*
* const todo = deserialize(Todo, {
* title: 'Task',
* subTask: [
* {
* title: 'Sub task 1',
* },
* ],
* })
*
* @param propSchema to be used to (de)serialize the contents of the array
* @param additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
*/
export default function list(
propSchema: PropSchema,
additionalArgs?: AdditionalPropArgs
): PropSchema {
propSchema = propSchema || _defaultPrimitiveProp
invariant(isPropSchema(propSchema), "expected prop schema as first argument")
invariant(
!isAliasedPropSchema(propSchema),
"provided prop is aliased, please put aliases first"
)
let result: PropSchema = {
serializer: function(ar) {
if (ar === undefined) {
return SKIP
}
invariant(ar && "length" in ar && "map" in ar, "expected array (like) object")
return ar.map(propSchema.serializer)
},
deserializer: function(jsonArray, done, context) {
if (!Array.isArray(jsonArray)) return void done("[serializr] expected JSON array")
function processItem(
jsonValue: any,
onItemDone: (err?: any, value?: any) => void,
itemIndex: number
) {
function callbackBefore(err: any, value: any) {
if (!err) {
propSchema.deserializer(value, deserializeDone, context)
} else {
onItemDone(err)
}
}
function deserializeDone(err: any, value: any) {
if (typeof propSchema.afterDeserialize === "function") {
onAfterDeserialize(
onItemDone,
err,
value,
jsonValue,
jsonArray,
itemIndex,
context,
propSchema
)
} else {
onItemDone(err, value)
}
}
onBeforeDeserialize(
callbackBefore,
jsonValue,
jsonArray,
itemIndex,
context,
propSchema
)
}
parallel(jsonArray, processItem, (err, result) => {
if (err) {
return void done(err)
}
done(
undefined,
result!.filter(x => SKIP !== x)
)
})
}
}
result = processAdditionalPropArgs(result, additionalArgs)
return result
}