<commit_before>var express = require('express');
var monk = require('monk');
var bodyParser = require('body-parser');

var dbAPI = require('api/db.js');
var common = require('api/routing_common.js');

var Item = require('api/models/Item.js');
var Reservation = require('api/models/Reservation.js');

var router = express.Router();
router.use(bodyParser.json());

/* Method handlers: */

/* Return a listing of all inventory items. */
router.get('/inventory', function(req, res) {
    dbAPI.inventory.find({}, {}).then(
        (docs) => {
            promises = docs.map(
                (doc) => {
                    item = new Item(doc._id);
                    return item.summary();
                }
            );

            return Promise.all(promises);
        }
    ).then(common.jsonSuccess(res)).catch(common.apiErrorHandler(req, res));
});

/*
 Add a new inventory item.

 Send parameters as JSON:
  - 'name': name of item type
  - 'count': initial inventory count
 */
router.post('/inventory', function(req, res) {
    common.checkRequestParameters(req, 'name', 'count').then(
        () => { return dbAPI.inventory.count( { name: req.body.name } ); }
    ).then(
        (count) => {
            if(count > 0) {
                return Promise.reject("Item already exists.");
            } else {
                item = new Item();

                item.name(req.body.name);
                item.count(req.body.count);

                return item.save();
            }
        }
    ).then(common.sendJSON(res, 201)).catch(common.apiErrorHandler(req, res));
});

/* Get information on one inventory item. */
router.get('/inventory/:id', function(req, res) {
    var item = new Item(monk.id(req.params.id));

    item.exists().then(
        (exists) => {
            if(exists) {
                return item.summary();
            } else {
                return Promise.reject("Item does not exist.");
            }
        }
    ).then(common.jsonSuccess(res)).catch(common.apiErrorHandler(req, res));
});

router.delete('/inventory/:id', function(req, res) {
    item = new Item(monk.id(req.params.id));

    item.delete().then(common.emptySuccess(res)).catch(common.apiErrorHandler(req, res));
});

/* Update an inventory item. */
router.put('/inventory/:id', function(req, res) {
    var item = new Item(monk.id(req.params.id));

    common.checkRequestParameters(req, 'name', 'count').then(
        () => { return item.reserved(); }
    ).then(
        (rsvp_count) => {
            if(rsvp_count > req.body.count)
                return Promise.reject("Cannot satisfy reservations with lowered inventory count.");

            item.name(req.body.name);
            item.count(parseInt(req.body.count));

            return item.save();
        }
    ).then(common.jsonSuccess(res)).catch(common.apiErrorHandler(req, res));
});

/* Get info on part reservations. */
router.get('/inventory/:id/reservations', (req, res) => {
    var item = new Item(monk.id(req.params.id));

    item.reservations().then(
        (ids) => {
            /* Convert all RSVPs to (promises for) summaries */
            return Promise.all(ids.map(
                (id) => {
                    rsvp = new Reservation(id);
                    return rsvp.summary();
                }
            ));
        }
    ).then(common.jsonSuccess(res)).catch(common.apiErrorHandler(req, res));
});

/* Redirect all part-specific reservation requests to the reservation route */
router.all('/inventory/:id/reservations/:rid*', (req, res) => {
    // find subroute:
    subroute = req.path.split('/inventory/'+req.params.id+'/reservations/'+req.params.rid);

    if(subroute.length > 1) {
        res.redirect(307, req.baseUrl+'/reservations/'+req.params.rid+subroute[1]);
    } else {
        res.status(404).send("Could not split path.");
    }
});
router.post('/inventory/:id/reservations', (req, res) => {
    res.redirect(307, req.baseUrl+'/reservations');
});
router.put('/inventory/:id/reservations', (req, res) => {
    res.redirect(307, req.baseUrl+'/reservations');
});
router.delete('/inventory/:id/reservations', (req, res) => {
    res.redirect(307, req.baseUrl+'/reservations');
});

module.exports = router;
<commit_msg>Add CSV support for /inventory GET and PUT<commit_after>var express = require('express');
var monk = require('monk');
var bodyParser = require('body-parser');

var dbAPI = require('api/db.js');
var common = require('api/routing_common.js');

var Item = require('api/models/Item.js');
var Reservation = require('api/models/Reservation.js');

var router = express.Router();
router.use(bodyParser.json());
router.use(bodyParser.text({
    type: 'text/csv'
}));

/* Method handlers: */
router.get('/inventory', asyncMiddleware(
    async (req, res) => {
        var out_type = req.accepts(['json', 'text/csv']);
        if(!out_type)
            throw new common.APIClientError(406, "Request must Accept either CSV or JSON format data.");

        var docs = await dbAPI.inventory.find({}, {});
        var summaries = await Promise.all(docs.map(
            (doc) => {
                var item = new Item(doc._id);
                return item.summary();
            }
        ));

        if(out_type === 'json') {
            res.status(200).json(summaries);
        } else if(out_type === 'text/csv') {
            csv.stringify(
                summaries,
                {
                    columns: ['id', 'name', 'count', 'reserved', 'available', 'created', 'updated']
                },
                (err, data) => { res.status(200).send(data); }
            );
        }
    }
));

/* Completely replaces the inventory collection. */
router.put('/inventory', asyncMiddleware(
    async (req, res) => {
        var in_type = req.is(['json', 'text/csv']);
        if(!in_type)
            throw new common.APIClientError(415, "Request payload must either be in CSV or JSON format.");

        if(in_type === 'text/csv') {
            var data = await new Promise((resolve, reject) => {
                csv.parse(
                    req.body,
                    { columns: true, auto_parse: true },
                    (err, parsedData) => {
                        if(err) return reject(err);
                        return resolve(parsedData);
                    }
                );
            });
        } else {
            var data = req.body;
        }

        /* Delete all old items. */
        var oldDocs = await dbAPI.inventory.find({}, {});
        await Promise.all(oldDocs.map(
            (doc) => {
                var item = new Item(doc._id);
                return item.delete();
            }
        ));

        /* Create and save new items. */
        await Promise.all(data.map(async (userDoc) => {
            var userItem = new Item();
            await Promise.all([
                await userItem.name(userDoc.name),
                await userItem.count(userDoc.count)
            ]);

            return userItem.save();
        }));
    }
));

/*
 Add a new inventory item.

 Send parameters as JSON:
  - 'name': name of item type
  - 'count': initial inventory count
 */
router.post('/inventory', function(req, res) {
    common.checkRequestParameters(req, 'name', 'count').then(
        () => { return dbAPI.inventory.count( { name: req.body.name } ); }
    ).then(
        (count) => {
            if(count > 0) {
                return Promise.reject("Item already exists.");
            } else {
                item = new Item();

                item.name(req.body.name);
                item.count(req.body.count);

                return item.save();
            }
        }
    ).then(common.sendJSON(res, 201)).catch(common.apiErrorHandler(req, res));
});

/* Get information on one inventory item. */
router.get('/inventory/:id', function(req, res) {
    var item = new Item(monk.id(req.params.id));

    item.exists().then(
        (exists) => {
            if(exists) {
                return item.summary();
            } else {
                return Promise.reject("Item does not exist.");
            }
        }
    ).then(common.jsonSuccess(res)).catch(common.apiErrorHandler(req, res));
});

router.delete('/inventory/:id', function(req, res) {
    item = new Item(monk.id(req.params.id));

    item.delete().then(common.emptySuccess(res)).catch(common.apiErrorHandler(req, res));
});

/* Update an inventory item. */
router.put('/inventory/:id', function(req, res) {
    var item = new Item(monk.id(req.params.id));

    common.checkRequestParameters(req, 'name', 'count').then(
        () => { return item.reserved(); }
    ).then(
        (rsvp_count) => {
            if(rsvp_count > req.body.count)
                return Promise.reject("Cannot satisfy reservations with lowered inventory count.");

            item.name(req.body.name);
            item.count(parseInt(req.body.count));

            return item.save();
        }
    ).then(common.jsonSuccess(res)).catch(common.apiErrorHandler(req, res));
});

/* Get info on part reservations. */
router.get('/inventory/:id/reservations', (req, res) => {
    var item = new Item(monk.id(req.params.id));

    item.reservations().then(
        (ids) => {
            /* Convert all RSVPs to (promises for) summaries */
            return Promise.all(ids.map(
                (id) => {
                    rsvp = new Reservation(id);
                    return rsvp.summary();
                }
            ));
        }
    ).then(common.jsonSuccess(res)).catch(common.apiErrorHandler(req, res));
});

/* Redirect all part-specific reservation requests to the reservation route */
router.all('/inventory/:id/reservations/:rid*', (req, res) => {
    // find subroute:
    subroute = req.path.split('/inventory/'+req.params.id+'/reservations/'+req.params.rid);

    if(subroute.length > 1) {
        res.redirect(307, req.baseUrl+'/reservations/'+req.params.rid+subroute[1]);
    } else {
        res.status(404).send("Could not split path.");
    }
});
router.post('/inventory/:id/reservations', (req, res) => {
    res.redirect(307, req.baseUrl+'/reservations');
});
router.put('/inventory/:id/reservations', (req, res) => {
    res.redirect(307, req.baseUrl+'/reservations');
});
router.delete('/inventory/:id/reservations', (req, res) => {
    res.redirect(307, req.baseUrl+'/reservations');
});

module.exports = router;

{'fraction_non_alphanumeric': 0.16698804473582723, 'fraction_numerical': 0.00520632472040108, 'mean_word_length': 2.1433333333333335, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4353911', 'n_tokens_mistral': 3163, 'n_tokens_neox': 3060, 'n_words': 611}