diff --git a/lib/schema/uuid.js b/lib/schema/uuid.js index b621fa942d8..6b5793fd3ee 100644 --- a/lib/schema/uuid.js +++ b/lib/schema/uuid.js @@ -67,7 +67,7 @@ function stringToBinary(uuidStr) { function binaryToString(uuidBin) { // i(hasezoey) dont quite know why, but "uuidBin" may sometimes also be the already processed string let hex; - if (typeof uuidBin !== 'string') { + if (typeof uuidBin !== 'string' && uuidBin != null) { hex = binary2hex(uuidBin); const uuidStr = hex.substring(0, 8) + '-' + hex.substring(8, 8 + 4) + '-' + hex.substring(12, 12 + 4) + '-' + hex.substring(16, 16 + 4) + '-' + hex.substring(20, 20 + 12); return uuidStr; diff --git a/test/schema.uuid.test.js b/test/schema.uuid.test.js index ee06af9b3b7..8292c233d35 100644 --- a/test/schema.uuid.test.js +++ b/test/schema.uuid.test.js @@ -10,6 +10,8 @@ const assert = require('assert'); const mongoose = start.mongoose; const Schema = mongoose.Schema; +const { v4: uuidv4 } = require('uuid'); + describe('SchemaUUID', function() { let Model; let TestSchema; @@ -101,6 +103,32 @@ describe('SchemaUUID', function() { assert.strictEqual(foundDocAll[0].y[2], '5b544b71-8988-422b-a4df-bf691939fe4e'); }); + it('should not convert to string nullish UUIDs (gh-13032)', async function() { + const schema = new Schema({ + _id: { + type: Schema.Types.UUID, + default: uuidv4(), + immutable: true + }, + name: { + type: String, + required: true + }, + organization: { + type: Schema.Types.UUID, + ref: 'Organization', + index: true + } + }, { _id: false }); + + const Test = db.model('gh_13032', schema); + + const { name, organization } = await Test.create({ name: 'test' }); + + assert.equal(name, 'test'); + assert.equal(organization, undefined); + }); + // the following are TODOs based on SchemaUUID.prototype.$conditionalHandlers which are not tested yet it('should work with $bits* operators'); it('should work with $all operator');