• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mobxjs / serializr / 14498102528

16 Apr 2025 04:49PM UTC coverage: 90.687% (+0.4%) from 90.257%
14498102528

push

github

web-flow
Decrease tech debt  (#191)

* Decrease tech debt by updating babel and switching to jest testing framework
* Removed node 12.x from the testing matrix as the typescript compiler doesn't run on it anymore.

687 of 885 branches covered (77.63%)

1003 of 1106 relevant lines covered (90.69%)

42.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.1
/src/types/reference.ts
1
import {
2
    invariant,
2✔
3
    isModelSchema,
2!
4
    getIdentifierProp,
5
    processAdditionalPropArgs,
2✔
6
} from "../utils/utils";
2✔
7
import getDefaultModelSchema from "../api/getDefaultModelSchema";
2✔
8
import {
2✔
9
    ClazzOrModelSchema,
10
    RefLookupFunction,
1✔
11
    AdditionalPropArgs,
1✔
12
    PropSchema,
13
    ModelSchema,
14
} from "../api/types";
15
import Context from "../core/Context";
4✔
16

4!
17
function createDefaultRefLookup(modelSchema: ModelSchema<any>) {
18
    return function resolve(
8✔
19
        uuid: string,
12✔
20
        cb: (err?: any, result?: any) => any,
8✔
21
        context: Context<any>
4!
22
    ) {
12✔
23
        context.rootContext.await(modelSchema, uuid, cb);
20✔
24
    };
25
}
1✔
26

1!
27
/**
1!
28
 * `reference` can be used to (de)serialize references that point to other models.
1!
29
 *
×
30
 * The first parameter should be either a ModelSchema that has an `identifier()` property (see identifier)
31
 * or a string that represents which attribute in the target object represents the identifier of the object.
32
 *
1✔
33
 * The second parameter is a lookup function that is invoked during deserialization to resolve an identifier to
1✔
34
 * an object. Its signature should be as follows:
1✔
35
 *
1✔
36
 * `lookupFunction(identifier, callback, context)` where:
1✔
37
 * 1. `identifier` is the identifier being resolved
38
 * 2. `callback` is a node style calblack function to be invoked with the found object (as second arg) or an error (first arg)
39
 * 3. `context` see context.
4✔
40
 *
41
 * The lookupFunction is optional. If it is not provided, it will try to find an object of the expected type and required identifier within the same JSON document
1!
42
 *
×
43
 * N.B. mind issues with circular dependencies when importing model schemas from other files! The module resolve algorithm might expose classes before `createModelSchema` is executed for the target class.
1!
44
 *
45
 * @example
46
 * class User {}
1!
47
 * class Post {}
1✔
48
 *
1!
49
 * createModelSchema(User, {
×
50
 *     uuid: identifier(),
51
 *     displayname: primitive(),
1✔
52
 * })
53
 *
54
 * createModelSchema(Post, {
4✔
55
 *     author: reference(User, findUserById),
4✔
56
 *     message: primitive(),
57
 * })
58
 *
59
 * function findUserById(uuid, callback) {
60
 *     fetch('http://host/user/' + uuid)
61
 *         .then(userData => {
62
 *             deserialize(User, userData, callback)
63
 *         })
64
 *         .catch(callback)
65
 * }
66
 *
67
 * deserialize(
68
 *     Post,
69
 *     {
70
 *         message: 'Hello World',
71
 *         author: 234,
72
 *     },
73
 *     (err, post) => {
74
 *         console.log(post)
75
 *     }
76
 * )
77
 *
78
 * @param target: ModelSchema or string
79
 * @param lookupFn optional function or additionalArgs object
80
 * @param additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
81
 */
82
export default function reference(
83
    modelSchema: ClazzOrModelSchema<any>,
84
    lookupFn?: RefLookupFunction,
85
    additionalArgs?: AdditionalPropArgs
86
): PropSchema;
87
export default function reference(
88
    modelSchema: ClazzOrModelSchema<any>,
89
    additionalArgs?: AdditionalPropArgs
90
): PropSchema;
91
export default function reference(
92
    identifierAttr: string,
93
    lookupFn: RefLookupFunction,
94
    additionalArgs?: AdditionalPropArgs
95
): PropSchema;
96
export default function reference(
97
    target: ClazzOrModelSchema<any> | string,
98
    lookupFnOrAdditionalPropArgs?: RefLookupFunction | AdditionalPropArgs,
99
    additionalArgs?: AdditionalPropArgs
100
) {
101
    invariant(
13✔
102
        !!target,
103
        "No modelSchema provided. If you are importing it from another file be aware of circular dependencies."
104
    );
105
    let lookupFn =
106
        "function" === typeof lookupFnOrAdditionalPropArgs
13✔
107
            ? lookupFnOrAdditionalPropArgs
108
            : undefined;
109
    additionalArgs =
13✔
110
        additionalArgs ||
26✔
111
        (lookupFn ? undefined : (lookupFnOrAdditionalPropArgs as AdditionalPropArgs | undefined));
13✔
112
    let initialized = false;
13✔
113
    let childIdentifierAttribute: string | undefined;
114
    function initialize() {
115
        initialized = true;
13✔
116
        invariant(
13✔
117
            typeof target !== "string" || typeof lookupFn === "function",
17✔
118
            "if the reference target is specified by attribute name, a lookup function is required"
119
        );
120
        invariant(
13✔
121
            !lookupFn || typeof lookupFn === "function",
18✔
122
            "second argument should be a lookup function or additional arguments object"
123
        );
124
        if (typeof target === "string") {
13✔
125
            childIdentifierAttribute = target;
4✔
126
        } else {
127
            const modelSchema = getDefaultModelSchema(target)!;
9✔
128
            invariant(
9✔
129
                isModelSchema(modelSchema),
130
                `expected model schema or string as first argument for 'ref', got ${modelSchema}`
131
            );
132
            lookupFn = lookupFn || createDefaultRefLookup(modelSchema);
9✔
133
            childIdentifierAttribute = getIdentifierProp(modelSchema);
9✔
134
            invariant(
9✔
135
                !!childIdentifierAttribute,
136
                "provided model schema doesn't define an identifier() property and cannot be used by 'ref'."
137
            );
138
        }
139
    }
140
    let result: PropSchema = {
13✔
141
        serializer: function (item) {
142
            if (!initialized) initialize();
7✔
143
            return item ? item[childIdentifierAttribute!] : null;
7!
144
        },
145
        deserializer: function (identifierValue, done, context) {
146
            if (!initialized) initialize();
31✔
147
            if (identifierValue === null || identifierValue === undefined)
31!
148
                done(null, identifierValue);
×
149
            else lookupFn!(identifierValue, done, context);
31✔
150
        },
151
    };
152
    result = processAdditionalPropArgs(result, additionalArgs);
13✔
153
    return result;
13✔
154
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc