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

hapipal / tandy / 102

pending completion
102

Pull #31

travis-ci-com

web-flow
Merge 71f19ecf9 into fc43360fe
Pull Request #31: Add support for giving back total count via header

55 of 55 new or added lines in 10 files covered. (100.0%)

284 of 288 relevant lines covered (98.61%)

201.71 hits per line

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

95.45
/lib/actions/populate.js
1
'use strict';
4✔
2

4✔
3
const Boom = require('@hapi/boom');
4✔
4
const Ref = require('objection').ref;
4✔
5
const Actions = require('../action-util');
4✔
6
/**
4✔
7
 * Populate an association
4✔
8
 *
4✔
9
 * get /model/:parentid/:relation
4✔
10
 * get /model/:parentid/:relation/count
4✔
11
 * get /model/:parentid/:relation/:id
4✔
12
 *
4✔
13
 * @param {Object} where       - the find criteria (passed directly to the ORM)
4✔
14
 * @param {Integer} limit      - the maximum number of records to send back (useful for pagination)
4✔
15
 * @param {Integer} skip       - the number of records to skip (useful for pagination)
4✔
16
 * @param {String} sort        - the order of returned records, e.g. `name ASC` or `age DESC`
4✔
17
 *
4✔
18
 */
4✔
19

4✔
20
module.exports = function expand(route, options) {
4✔
21

4✔
22
    return async (request, h) => {
4✔
23

4✔
24
        const actionUtil = Actions(request, options, h);
4✔
25

4✔
26
        const Model = actionUtil.modelFromParam(options.model);
56✔
27
        const relation  = options.associationAttr;
56✔
28
        const RelationModel = actionUtil.modelFromParam(options.associationAttr);
56✔
29

4✔
30
        if (!RelationModel) {
56✔
31
            return Boom.badImplementation('Invalid relation for populate');
8✔
32
        }
4✔
33

4✔
34
        const keys = actionUtil.getKeys();
48✔
35
        const limit = actionUtil.parseLimit();
48✔
36
        const sort = actionUtil.parseSort(Model);
48✔
37
        const rangeStart = actionUtil.parseSkip();
48✔
38
        const rangeEnd = rangeStart + limit;
48✔
39

4✔
40
        let total;
48✔
41

4✔
42
        const modelFullQuery = Model.query().findById(keys.parent.value)
48✔
43
            .withGraphFetched(relation)
4✔
44
            .modifyGraph(relation, (builder) => {
4✔
45

4✔
46
                if (keys.child?.value) {
4✔
47
                    builder.where(Ref(RelationModel.tableName + '.' + keys.child.key), '=', keys.child.value);
8✔
48
                }
4✔
49

4✔
50
                if (options.includeTotalCount) {
×
51
                    // we need to wrap this in an async iffe to trigger the query,
4✔
52
                    // as otherwise the main query gets borked
4✔
53
                    total = (async () => await builder.clone().count({ total: Ref(RelationModel.tableName + '.' + keys.child.key) }).first())();
×
54
                }
4✔
55

4✔
56
                builder.range(rangeStart, rangeEnd).limit(limit);
40✔
57

4✔
58
                if (sort) {
40✔
59
                    builder.orderByRaw(sort);
4✔
60
                }
4✔
61
            });
4✔
62

4✔
63
        const modelFull = await modelFullQuery;
48✔
64

4✔
65
        if (!modelFull) {
44✔
66
            return Boom.notFound('No record found with the specified id.');
4✔
67
        }
4✔
68

4✔
69
        if (keys.child?.value) {
40✔
70
            if (modelFull[options.associationAttr].length) {
8✔
71
                return h.response().code(204);
4✔
72
            }
4✔
73

4✔
74
            return Boom.notFound();
4✔
75
        }
4✔
76

4✔
77
        if (total) {
×
78
            return actionUtil.replyWithRange(options.associationAttr, rangeStart, rangeEnd, await total, modelFull[options.associationAttr]);
×
79
        }
4✔
80

4✔
81
        if (options._private.count) {
32✔
82
            return modelFull[options.associationAttr].length;
4✔
83
        }
4✔
84

4✔
85
        return modelFull[options.associationAttr];
28✔
86
    };
4✔
87
};
4✔
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

© 2025 Coveralls, Inc