mirror of
https://github.com/bckelley/cgm-remote-monitor.git
synced 2026-08-24 03:14:12 -05:00
Handle UUID treatment ids in v1 API
This commit is contained in:
+25
-3
@@ -3,6 +3,7 @@
|
||||
const traverse = require('traverse');
|
||||
const ObjectID = require('mongodb-legacy').ObjectId;
|
||||
const moment = require('moment');
|
||||
const OBJECT_ID_HEX_RE = /^[0-9a-fA-F]{24}$/;
|
||||
|
||||
const TWO_DAYS = 172800000;
|
||||
/**
|
||||
@@ -90,9 +91,30 @@ function enforceDateFilter (query, opts) {
|
||||
* Forces anything named `_id` to be the `ObjectID` type.
|
||||
*/
|
||||
function updateIdQuery (query) {
|
||||
if (query._id && query._id.length) {
|
||||
query._id = ObjectID(query._id);
|
||||
if (!Object.prototype.hasOwnProperty.call(query, '_id')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof query._id === 'string') {
|
||||
query._id = normalizeIdValue(query._id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (query._id && typeof query._id === 'object') {
|
||||
traverse(query._id).forEach(function (x) {
|
||||
if (this.isLeaf) {
|
||||
this.update(normalizeIdValue(x));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeIdValue (value) {
|
||||
if (typeof value === 'string' && OBJECT_ID_HEX_RE.test(value)) {
|
||||
return new ObjectID(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,7 +235,7 @@ walker.walk_prop = walk_prop;
|
||||
create.walker = walker;
|
||||
create.parseRegEx = parseRegEx;
|
||||
create.default_options = default_options;
|
||||
create.normalizeIdValue = normalizeIdValue;
|
||||
|
||||
// expose module as single high level function
|
||||
exports = module.exports = create;
|
||||
|
||||
|
||||
+38
-12
@@ -7,6 +7,7 @@ var find_options = require('./query');
|
||||
|
||||
function storage (env, ctx) {
|
||||
var ObjectID = require('mongodb-legacy').ObjectId;
|
||||
var OBJECT_ID_HEX_RE = /^[0-9a-fA-F]{24}$/;
|
||||
|
||||
function create (objOrArray, fn) {
|
||||
|
||||
@@ -49,10 +50,11 @@ function storage (env, ctx) {
|
||||
// Build bulkWrite operations for regular docs (no preBolus)
|
||||
// Prepare data and build bulk ops together
|
||||
var bulkOps = objOrArray.map(function(obj) {
|
||||
normalizeTreatmentId(obj);
|
||||
var results = prepareData(obj);
|
||||
return {
|
||||
replaceOne: {
|
||||
filter: { created_at: results.created_at, eventType: obj.eventType },
|
||||
filter: upsertQueryFor(obj, results),
|
||||
replacement: obj,
|
||||
upsert: true
|
||||
}
|
||||
@@ -90,13 +92,10 @@ function storage (env, ctx) {
|
||||
}
|
||||
|
||||
function upsert (obj, fn) {
|
||||
normalizeTreatmentId(obj);
|
||||
|
||||
var results = prepareData(obj);
|
||||
|
||||
var query = {
|
||||
created_at: results.created_at
|
||||
, eventType: obj.eventType
|
||||
};
|
||||
var query = upsertQueryFor(obj, results);
|
||||
|
||||
api( ).replaceOne(query, obj, {upsert: true}, function complete (err, updateResults) {
|
||||
|
||||
@@ -121,8 +120,11 @@ function storage (env, ctx) {
|
||||
pbTreat.notes = obj.notes;
|
||||
}
|
||||
|
||||
query.created_at = pbTreat.created_at;
|
||||
api( ).replaceOne(query, pbTreat, {upsert: true}, function pbComplete (err, updateResults) {
|
||||
var pbQuery = {
|
||||
created_at: pbTreat.created_at,
|
||||
eventType: pbTreat.eventType
|
||||
};
|
||||
api( ).replaceOne(pbQuery, pbTreat, {upsert: true}, function pbComplete (err, updateResults) {
|
||||
|
||||
if (updateResults) {
|
||||
if (updateResults.upsertedCount == 1) {
|
||||
@@ -191,11 +193,14 @@ function storage (env, ctx) {
|
||||
}
|
||||
|
||||
function save (obj, fn) {
|
||||
obj._id = new ObjectID(obj._id);
|
||||
normalizeTreatmentId(obj);
|
||||
prepareData(obj);
|
||||
|
||||
function saved (err, created) {
|
||||
function saved (err, updateResults) {
|
||||
if (!err) {
|
||||
if (updateResults && updateResults.upsertedCount == 1) {
|
||||
obj._id = updateResults.upsertedId;
|
||||
}
|
||||
// console.log('Treatment updated', created);
|
||||
|
||||
ctx.ddata.processRawDataForRuntime(obj);
|
||||
@@ -209,10 +214,10 @@ function storage (env, ctx) {
|
||||
}
|
||||
if (err) console.error('Problem saving treating', err);
|
||||
|
||||
fn(err, created);
|
||||
fn(err, obj);
|
||||
}
|
||||
|
||||
api().save(obj, saved);
|
||||
api().replaceOne(upsertQueryFor(obj, { created_at: obj.created_at }), obj, {upsert: true}, saved);
|
||||
|
||||
ctx.bus.emit('data-received');
|
||||
}
|
||||
@@ -221,6 +226,27 @@ function storage (env, ctx) {
|
||||
return ctx.store.collection(env.treatments_collection);
|
||||
}
|
||||
|
||||
function upsertQueryFor (obj, results) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, '_id') && obj._id !== null && obj._id !== '') {
|
||||
return { _id: obj._id };
|
||||
}
|
||||
|
||||
return {
|
||||
created_at: results.created_at
|
||||
, eventType: obj.eventType
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeTreatmentId (obj) {
|
||||
if (!Object.prototype.hasOwnProperty.call(obj, '_id') || obj._id === null || obj._id === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof obj._id === 'string' && OBJECT_ID_HEX_RE.test(obj._id)) {
|
||||
obj._id = new ObjectID(obj._id);
|
||||
}
|
||||
}
|
||||
|
||||
api.list = list;
|
||||
api.create = create;
|
||||
api.query_for = query_for;
|
||||
|
||||
@@ -246,4 +246,113 @@ describe('Treatment API', function ( ) {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('supports UUID treatment ids for post, put, and delete', function (done) {
|
||||
var treatmentId = '69F15FD2-8075-4DEB-AEA3-4352F455840D';
|
||||
var originalCreatedAt = '2026-02-17T02:00:16.000Z';
|
||||
var repostedCreatedAt = '2026-02-17T02:05:16.000Z';
|
||||
var updatedCreatedAt = '2026-02-17T02:10:16.000Z';
|
||||
|
||||
self.ctx.treatments.remove({ find: { created_at: { '$gte': '1999-01-01T00:00:00.000Z' } } }, function () {
|
||||
request(self.app)
|
||||
.post('/api/treatments/')
|
||||
.set('api-secret', api_secret_hash || '')
|
||||
.send({
|
||||
_id: treatmentId,
|
||||
eventType: 'Temporary Override',
|
||||
created_at: originalCreatedAt,
|
||||
durationType: 'indefinite',
|
||||
correctionRange: [90, 110],
|
||||
insulinNeedsScaleFactor: 1.2,
|
||||
reason: 'test override'
|
||||
})
|
||||
.expect(200)
|
||||
.end(function (err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
request(self.app)
|
||||
.post('/api/treatments/')
|
||||
.set('api-secret', api_secret_hash || '')
|
||||
.send({
|
||||
_id: treatmentId,
|
||||
eventType: 'Temporary Override',
|
||||
created_at: repostedCreatedAt,
|
||||
duration: 60,
|
||||
correctionRange: [90, 110],
|
||||
insulinNeedsScaleFactor: 1.2,
|
||||
reason: 'reposted override'
|
||||
})
|
||||
.expect(200)
|
||||
.end(function (err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
self.ctx.treatments.list({ find: { _id: treatmentId } }, function (err, list) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
list.length.should.equal(1);
|
||||
list[0]._id.should.equal(treatmentId);
|
||||
list[0].created_at.should.equal(repostedCreatedAt);
|
||||
list[0].duration.should.equal(60);
|
||||
should.not.exist(list[0].durationType);
|
||||
|
||||
request(self.app)
|
||||
.put('/api/treatments/')
|
||||
.set('api-secret', api_secret_hash || '')
|
||||
.send({
|
||||
_id: treatmentId,
|
||||
eventType: 'Temporary Override',
|
||||
created_at: updatedCreatedAt,
|
||||
duration: 30,
|
||||
correctionRange: [90, 110],
|
||||
insulinNeedsScaleFactor: 1.2,
|
||||
reason: 'updated override'
|
||||
})
|
||||
.expect(200)
|
||||
.end(function (err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
self.ctx.treatments.list({ find: { _id: treatmentId } }, function (err, updatedList) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
updatedList.length.should.equal(1);
|
||||
updatedList[0]._id.should.equal(treatmentId);
|
||||
updatedList[0].created_at.should.equal(updatedCreatedAt);
|
||||
updatedList[0].duration.should.equal(30);
|
||||
updatedList[0].reason.should.equal('updated override');
|
||||
|
||||
request(self.app)
|
||||
.delete('/api/treatments/' + encodeURIComponent(treatmentId))
|
||||
.set('api-secret', api_secret_hash || '')
|
||||
.expect(200)
|
||||
.end(function (err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
self.ctx.treatments.list({ find: { _id: treatmentId } }, function (err, deletedList) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
deletedList.length.should.equal(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,4 +35,18 @@ describe('query', function ( ) {
|
||||
|
||||
(typeof opts.date).should.equal('undefined')
|
||||
});
|
||||
|
||||
it('should keep non-ObjectId _id queries as strings', function ( ) {
|
||||
var uuid = '69F15FD2-8075-4DEB-AEA3-4352F455840D';
|
||||
var opts = query({ find: { _id: uuid } });
|
||||
|
||||
opts._id.should.equal(uuid);
|
||||
});
|
||||
|
||||
it('should convert ObjectId-shaped _id queries', function ( ) {
|
||||
var objectId = '55cbd4e47e726599048a3f91';
|
||||
var opts = query({ find: { _id: objectId } });
|
||||
|
||||
opts._id.toString().should.equal(objectId);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user