├── .gitignore ├── .npmrc ├── History.md ├── LICENSE ├── Makefile ├── README.md ├── index.d.ts ├── index.js ├── lib └── index.js ├── package.json └── test └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.swo 2 | *.swp 3 | *.swn 4 | node_modules/ 5 | .c9revisions/* -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 0.8.0 / 2023-10-31 2 | ================== 3 | * feat: support Mongoose 8 4 | 5 | 0.7.1 / 2023-08-22 6 | ================== 7 | * fix: allow undefined #22 [WhatCats](https://github.com/WhatCats) 8 | 9 | 0.7.0 / 2023-06-01 10 | ================== 11 | * feat: support Mongoose 7 [yincrash](https://github.com/yincrash) 12 | 13 | 0.6.0 / 2022-10-24 14 | ================== 15 | * feat: change base type of Long to mongodb.Long #19 [d3m3vilurr](https://github.com/d3m3vilurr) 16 | 17 | 0.5.1 / 2022-01-05 18 | ================== 19 | * fix: add `fromString()` and `fromNumber()` for Long type #17 [mkadirtan](https://github.com/mkadirtan) 20 | 21 | 0.5.0 / 2021-10-21 22 | ================== 23 | * feat: add support for Mongoose 6 24 | 25 | 0.4.1 / 2021-08-10 26 | ================== 27 | * fix(index.d.ts): add return type to default export #14 28 | 29 | 0.4.0 / 2021-05-21 30 | ================== 31 | * feat: add `index.d.ts` file for TypeScript support #13 32 | 33 | 0.3.2 / 2020-09-19 34 | ================== 35 | * docs: use const instead of var in README #12 [adamreisnz](https://github.com/adamreisnz) 36 | 37 | 0.3.1 / 2020-07-18 38 | ================== 39 | * fix: correct inheritance so `Long.set()` and `Long.get()` work as expected #10 40 | 41 | 0.3.0 / 2020-04-18 42 | ================== 43 | * feat: support new Mongoose global schema type configs: `cast()`, `get()`, `set()` #10 44 | 45 | 0.2.1 / 2018-05-17 46 | ================== 47 | * fix: support bitsAnySet and bitsAllSet #6 [MichelLiu](https://github.com/MichelLiu) 48 | 49 | 0.2.0 / 2018-02-26 50 | ================== 51 | * feat: added support for mongoose 5.x 52 | 53 | 0.0.2 / 2012-10-18 54 | ================== 55 | 56 | * fixed; Incorrect variable reference #1 [ofShard](https://github.com/ofShard) 57 | * tests; add failing test for #1 58 | 59 | 0.0.1 / 2012-08-01 60 | ==================== 61 | 62 | * initial release 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2012 [Aaron Heckmann](aaron.heckmann+github@gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | test: 3 | @./node_modules/.bin/mocha --reporter list $(T) 4 | 5 | .PHONY: test 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #mongoose-long 2 | =============== 3 | 4 | Provides Number Long support for [Mongoose](http://mongoosejs.com). 5 | 6 | [![Build Status](https://secure.travis-ci.org/aheckmann/mongoose-long.png)](http://travis-ci.org/mongoosejs/mongoose-long) 7 | 8 | Example: 9 | 10 | ```js 11 | const mongoose = require('mongoose') 12 | require('mongoose-long')(mongoose); 13 | const {Types: {Long}} = mongoose; 14 | 15 | const partSchema = new Schema({ 16 | long: { 17 | type: Long, 18 | } 19 | }); 20 | 21 | const Part = db.model('Part', partSchema); 22 | const part = new Part({long: '9223372036854775806'}); 23 | 24 | part.long = part.long.divide(Long.fromString('2')); 25 | part.save() 26 | ``` 27 | 28 | ### install 29 | 30 | ``` 31 | npm install mongoose-long 32 | ``` 33 | 34 | See [node-mongodb-native](https://mongodb.github.io/node-mongodb-native/4.2/classes/Long.html) docs on all the `Long` methods available. 35 | 36 | [LICENSE](https://github.com/aheckmann/mongoose-long/blob/master/LICENSE) 37 | 38 | ### TypeScript Usage 39 | 40 | Make sure you enable both `compilerOptions.allowSyntheticDefaultImports` and `compilerOptions.esModuleInterop` in your `tsconfig.json`. 41 | 42 | ```typescript 43 | import mongoose from 'mongoose'; 44 | import mongooseLong from 'mongoose-long'; 45 | 46 | mongooseLong(mongoose); 47 | 48 | const Long = mongoose.Schema.Types.Long; 49 | ``` -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import mongodb from "mongodb"; 2 | import { Mongoose } from "mongoose"; 3 | import { SchemaType } from "mongoose"; 4 | import mongooseLong from "."; 5 | 6 | export default function(mongoose?: Mongoose): SchemaType; 7 | 8 | declare module 'mongoose' { 9 | namespace Schema { 10 | namespace Types { 11 | class Long extends SchemaType {} 12 | } 13 | } 14 | 15 | namespace Types { 16 | class Long extends mongodb.Long { 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = exports = require('./lib'); 2 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | // mongoose-long 2 | 3 | module.exports = exports = function NumberLong (mongoose) { 4 | var Schema = mongoose.Schema 5 | , SchemaType = mongoose.SchemaType 6 | , Types = mongoose.Types 7 | , mongo = mongoose.mongo; 8 | 9 | /** 10 | * Long constructor 11 | * 12 | * @inherits SchemaType 13 | * @param {String} key 14 | * @param {Object} [options] 15 | */ 16 | 17 | function Long (key, options) { 18 | SchemaType.call(this, key, options); 19 | } 20 | 21 | /*! 22 | * inherits 23 | */ 24 | 25 | Long.prototype = Object.create(SchemaType.prototype); 26 | Long.prototype.constructor = Long; 27 | Long.cast = SchemaType.cast; 28 | Long.set = SchemaType.set; 29 | Long.get = SchemaType.get; 30 | 31 | /** 32 | * Implement checkRequired method. 33 | * 34 | * @param {any} val 35 | * @return {Boolean} 36 | */ 37 | 38 | Long.prototype.checkRequired = function (val) { 39 | return null != val; 40 | }; 41 | 42 | 43 | Long.set = SchemaType.set; 44 | 45 | /** 46 | * Implement casting. 47 | * 48 | * @param {any} val 49 | * @param {Object} [scope] 50 | * @param {Boolean} [init] 51 | * @return {mongo.Long|null} 52 | */ 53 | 54 | Long.prototype.cast = function (val, scope, init) { 55 | if (null === val || undefined === val) return val; 56 | if ('' === val) return null; 57 | 58 | if (val instanceof mongo.Long) { 59 | return val; 60 | } 61 | 62 | if (val instanceof Number || 'number' == typeof val) { 63 | return mongo.Long.fromNumber(val); 64 | } 65 | 66 | if (!Array.isArray(val) && val.toString) { 67 | return mongo.Long.fromString(val.toString()); 68 | } 69 | 70 | throw new SchemaType.CastError('Long', val, this.path); 71 | } 72 | 73 | /*! 74 | * ignore 75 | */ 76 | 77 | function handleSingle (val) { 78 | return this.cast(val) 79 | } 80 | 81 | function handleArray (val) { 82 | var self = this; 83 | return val.map( function (m) { 84 | return self.cast(m) 85 | }); 86 | } 87 | 88 | Long.prototype.$conditionalHandlers.$lt = handleSingle; 89 | Long.prototype.$conditionalHandlers.$lte = handleSingle; 90 | Long.prototype.$conditionalHandlers.$gt = handleSingle; 91 | Long.prototype.$conditionalHandlers.$gte = handleSingle; 92 | Long.prototype.$conditionalHandlers.$ne = handleSingle; 93 | Long.prototype.$conditionalHandlers.$in = handleArray; 94 | Long.prototype.$conditionalHandlers.$nin = handleArray; 95 | Long.prototype.$conditionalHandlers.$mod = handleArray; 96 | Long.prototype.$conditionalHandlers.$all = handleArray; 97 | Long.prototype.$conditionalHandlers.$bitsAnySet = handleArray; 98 | Long.prototype.$conditionalHandlers.$bitsAllSet = handleArray; 99 | 100 | /** 101 | * Implement query casting, for mongoose 3.0 102 | * 103 | * @param {String} $conditional 104 | * @param {*} [value] 105 | */ 106 | 107 | Long.prototype.castForQuery = function ($conditional, value, context) { 108 | var handler; 109 | if (3 === arguments.length) { 110 | // mongoose 7 111 | if ($conditional != null) { 112 | handler = this.$conditionalHandlers[$conditional]; 113 | if (!handler) { 114 | throw new Error("Can't use " + $conditional + " with Long."); 115 | } 116 | return handler.call(this, value); 117 | } else { 118 | return this.cast(value); 119 | } 120 | } 121 | if (2 === arguments.length) { 122 | handler = this.$conditionalHandlers[$conditional]; 123 | if (!handler) { 124 | throw new Error("Can't use " + $conditional + " with Long."); 125 | } 126 | return handler.call(this, value); 127 | } else { 128 | return this.cast($conditional); 129 | } 130 | } 131 | 132 | /** 133 | * Expose 134 | */ 135 | 136 | Schema.Types.Long = Long; 137 | Types.Long = mongo.Long; 138 | return Long; 139 | } 140 | 141 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mongoose-long", 3 | "version": "0.8.0", 4 | "description": "Long number type for Mongoose", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "make test" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git://github.com/aheckmann/mongoose-long.git" 15 | }, 16 | "keywords": [ 17 | "mongoose", 18 | "long", 19 | "number", 20 | "type", 21 | "schematype", 22 | "schema" 23 | ], 24 | "author": "Aaron Heckmann ", 25 | "license": "MIT", 26 | "devDependencies": { 27 | "mocha": "*", 28 | "mongoose": "8.x" 29 | }, 30 | "peerDependencies": { 31 | "mongoose": "4.x || 5.x || 6.x || 7.x || 8.x" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert') 2 | var LongModule = require('../') 3 | var mongoose = require('mongoose') 4 | var Schema = mongoose.Schema; 5 | var Long; 6 | 7 | describe('Long', function(){ 8 | before(function(){ 9 | Long = LongModule(mongoose); 10 | }) 11 | 12 | it('is a function', function(){ 13 | assert.equal('function', typeof Long); 14 | }) 15 | 16 | it('extends mongoose.Schema.Types', function(){ 17 | assert.ok(Schema.Types.Long); 18 | assert.equal(Long, Schema.Types.Long); 19 | }) 20 | 21 | it('extends mongoose.Types', function(){ 22 | assert.ok(mongoose.Types.Long); 23 | assert.equal(mongoose.mongo.Long, mongoose.Types.Long); 24 | }) 25 | 26 | it('can be used in schemas', function(){ 27 | var s = new Schema({ long: Long }); 28 | var long = s.path('long') 29 | assert.ok(long instanceof mongoose.SchemaType); 30 | assert.equal('function', typeof long.get); 31 | 32 | var s = new Schema({ long: 'long' }); 33 | var long = s.path('long') 34 | assert.ok(long instanceof mongoose.SchemaType); 35 | assert.equal('function', typeof long.get); 36 | }) 37 | 38 | describe('integration', function(){ 39 | var db, S, schema, id; 40 | 41 | before(function(done){ 42 | db = mongoose.createConnection('mongodb://localhost:27017/mlong'); 43 | db.once('open', function () { 44 | schema = new Schema({ long: Long, name: 'string' }); 45 | S = db.model('Long', schema); 46 | done(); 47 | }); 48 | }) 49 | 50 | after(function(done) { 51 | db.close().then(() => { done(); }); 52 | }); 53 | 54 | describe('casts', function(){ 55 | it('numbers', function(){ 56 | var v = 200000000; 57 | var s = new S({ long: v }); 58 | assert.ok(s.long instanceof mongoose.Types.Long); 59 | assert.equal(v, s.long.toNumber()); 60 | 61 | v = new Number(200000000); 62 | s = new S({ long: v }); 63 | assert.ok(s.long instanceof mongoose.Types.Long); 64 | assert.equal(+v, s.long.toNumber()); 65 | }) 66 | 67 | it('strings', function(){ 68 | var v = '200000000'; 69 | var s = new S({ long: v}); 70 | assert.ok(s.long instanceof mongoose.Types.Long); 71 | assert.equal(v, s.long.toString()); 72 | }) 73 | 74 | it('null', function(){ 75 | var s = new S({ long: null }); 76 | assert.equal(null, s.long); 77 | }) 78 | 79 | it('mongo.Long', function(){ 80 | var s = new S({ long: new mongoose.Types.Long("90") }); 81 | assert.ok(s.long instanceof mongoose.Types.Long); 82 | assert.equal(90, s.long.toNumber()); 83 | }) 84 | 85 | it('non-castables produce _saveErrors', function(done){ 86 | var schema = new Schema({ long: Long }, { strict: 'throw' }); 87 | var M = db.model('throws', schema); 88 | var m = new M({ long: [] }); 89 | m.save().then(function () { 90 | done("Promise should be rejected."); 91 | }).catch(function (err) { 92 | assert.ok(err); 93 | assert.equal('ValidationError', err.name); 94 | assert.equal(err.errors['long'].name, 'CastError'); 95 | done(); 96 | }); 97 | }) 98 | }) 99 | 100 | it('can be saved', function(done){ 101 | var s = new S({ long: 20 }); 102 | id = s.id; 103 | s.save().then(function () { 104 | done(); 105 | }).catch(function (err) { 106 | done(err); 107 | }) 108 | }) 109 | 110 | it('is queryable', function(done){ 111 | S.findById(id).then(function (doc) { 112 | assert.ok(doc.long instanceof mongoose.Types.Long); 113 | assert.equal(20, doc.long.toNumber()); 114 | done(); 115 | }).catch(function(err) { 116 | done(err); 117 | }); 118 | }) 119 | 120 | it('can be updated', function(done){ 121 | S.findById(id).then(function (doc) { 122 | doc.long = doc.long.add(mongoose.Types.Long.fromString("10")); 123 | doc.save().then(function () { 124 | S.findById(id).then(function (doc) { 125 | assert.equal(30, doc.long.toNumber()); 126 | done(); 127 | }).catch(function (err) { 128 | done(err); 129 | }); 130 | }).catch(function (err) { 131 | done(err); 132 | }) 133 | }).catch(function (err) { 134 | done(err); 135 | }) 136 | }) 137 | 138 | it('can be required', function(done){ 139 | var s = new Schema({ long: { type: Long, required: true }}); 140 | var M = db.model('required', s); 141 | var m = new M; 142 | m.save().then(function () { 143 | done("Field should be required."); 144 | }).catch(function(err) { 145 | assert.ok(err); 146 | m.long = 10; 147 | m.validate().then(function () { 148 | done(); 149 | }).catch(function(err) { 150 | done(err); 151 | }); 152 | }) 153 | }) 154 | 155 | it('works with update', function(done){ 156 | S.create({ long: 99999 }).then(function (s) { 157 | S.updateOne({ long: s.long, _id: s._id }, { name: 'changed' }, { upsert: true }).then(function () { 158 | S.findById(s._id).then(function (doc) { 159 | assert.equal(99999, doc.long); 160 | assert.equal('changed', doc.name); 161 | done(); 162 | }).catch(function (err) { 163 | done(err); 164 | }); 165 | }).catch(function (err) { 166 | done(err); 167 | }) 168 | }).catch(function (err) { 169 | done(err); 170 | }) 171 | 172 | }) 173 | }) 174 | }) 175 | --------------------------------------------------------------------------------